3.6 KiB
SpaceBook
Category: Astronomy, Astrophysics, Astrometry, Astrodynamics, AAAA Points (final): 75 points Solves: 56
Hah, yeah we're going to do the hard part anyways! Glue all previous parts together by identifying these stars based on the provided catalog. Match the provided boresight refence vectors to the catalog refence vectors and tell us our attitude.
Note: The catalog format is unit vector (X,Y,Z) in a celestial reference frame and the magnitude (relative brightness)
Given files: spacebook-golf56788echo.tar.bz2
Writeup
by erin (barzamin
).
SpaceBook is a very similar problem to Attitude Adjustment; we still need to solve an orthogonal Procrustes problem to align a set of stars to a catalog. However, we don't know which stars in the unknown set match to which stars in the catalog, unlike in Attitude Adjustment.
We're given a boresight vector \vec{v}\in\mathbb{R}^3
for each star, and a magnitude m
. The vectors in the catalog set are off by some rotation from the vectors in the unknown set; the magnitudes match. Looking at the distribution of magnitudes, we see that there is a significant outlier population in both the catalog and reference sets, and that these outlier populations match:
Note that code from here on in this report is reconstructed, since I accidentally overwrote the original copy. I took the chance to use scipy for Kabsch this time instead of the original package I used, rmsd
.
My immediate suspicion was that we could take the outliers (simply by thresholding for stars with $m>500$) and, for each, directly match it to the catalog by finding the star with closest magnitude in the catalog:
def match_brightest_stars(unknown, catalog):
brightest = []
catalog_matches = []
for star in unknown:
if star['m'] < 500:
continue
# find closest magnitude in catalog
match = np.argmin(np.abs(np.array([s['m'] for s in catalog]) - star['m']))
print(f'[+] matched {star} to {catalog[match]}')
brightest.append(star)
catalog_matches.append(catalog[match])
return brightest, catalog_matches
We can then align those brightest stars to their closest magnitude matches using the Kabsch algorithm:
def orient(ref, catalog):
P = [s['v'] for s in catalog]
Q = [s['v'] for s in ref]
rot, rmsd = Rotation.align_vectors(P, Q)
print(f'[+] aligned; rmsd = {rmsd}')
return rot
Then for each unknown star with vector \vec{v}
, we can find its catalog index by evaluating
\arg\min_{\vec{u}\in\text{catalog}} \norm{\vec{u}-\vec{v}}_2
for every challenge:
for _ in range(5):
unknown_stars = read_starfile(r.recvuntil('\n\n').decode())
# find pairs
unknown_ref, catalog_ref = match_brightest_stars(unknown_stars, catalog)
# get attitude
attitude = orient(unknown_ref, catalog_ref)
# rotate each star to catalog-referenced coordinates and match by L2 norm
index_guesses = []
for star in unknown_stars:
v = attitude.apply(star['v'])
index_guesses.append(np.argmin([np.linalg.norm(catalog_star['v'] - v)
for catalog_star in catalog]))
r.send(','.join(map(str, index_guesses))+'\n')
r.recvuntil('Left...\n')
print(r.clean())
Full code