LOST 0.0.1
LOST: Open-source Star Tracker
Loading...
Searching...
No Matches
star-id.cpp
Go to the documentation of this file.
1#include <stdlib.h>
2#include <math.h>
3#include <assert.h>
4#include <vector>
5#include <algorithm>
6#include <chrono>
7#include <unordered_map>
8
9#include "star-id.hpp"
10#include "star-id-private.hpp"
11#include "databases.hpp"
12#include "attitude-utils.hpp"
13
14namespace lost {
15
17 const unsigned char *, const Stars &stars, const Catalog &catalog, const Camera &) const {
18
20
21 unsigned int randomSeed = 123456;
22 for (int i = 0; i < (int)stars.size(); i++) {
23 result.push_back(StarIdentifier(i, rand_r(&randomSeed) % catalog.size()));
24 }
25
26 return result;
27}
28
30 const unsigned char *database, const Stars &stars, const Catalog &catalog, const Camera &camera) const {
31
34 const unsigned char *databaseBuffer = multiDatabase.SubDatabasePointer(PairDistanceKVectorDatabase::kMagicValue);
35 if (databaseBuffer == NULL) {
36 return identified;
37 }
40
41 for (int i = 0; i < (int)stars.size(); i++) {
42 std::vector<int16_t> votes(catalog.size(), 0);
43 Vec3 iSpatial = camera.CameraToSpatial(stars[i].position).Normalize();
44 for (int j = 0; j < (int)stars.size(); j++) {
45 if (i != j) {
46 // TODO: find a faster way to do this:
47 std::vector<bool> votedInPair(catalog.size(), false);
48 Vec3 jSpatial = camera.CameraToSpatial(stars[j].position).Normalize();
50 //give a greater range for min-max Query for bigger radius (GreatCircleDistance)
54 const int16_t *lowerBoundSearch = vectorDatabase.FindPairsLiberal(
56 //loop from lowerBoundSearch till numReturnedPairs, add one vote to each star in the pairs in the datastructure
57 for (const int16_t *k = lowerBoundSearch; k != upperBoundSearch; k++) {
58 if ((k - lowerBoundSearch) % 2 == 0) {
59 decimal actualAngle = AngleUnit(catalog[*k].spatial, catalog[*(k+1)].spatial);
60 assert(actualAngle <= greatCircleDistance + tolerance * 2);
61 assert(actualAngle >= greatCircleDistance - tolerance * 2);
62 }
63 if (!votedInPair[*k] || true) {
64 // if (i == 542 && *k == 9085) {
65 // printf("INC, distance %f from query %f to %f\n", greatCircleDistance,
66 // lowerBoundRange, upperBoundRange);
67 // }
68 votes[*k]++;
69 votedInPair[*k] = true;
70 }
71 }
72 // US voting system
73 }
74 }
75 // Find star w most votes
77 int indexOfMax = 0;
78 for (int v = 1; v < (int)votes.size(); v++) {
79 if (votes[v] > maxVotes) {
80 maxVotes = votes[v];
81 indexOfMax = v;
82 }
83 }
84 // if (i == 542) {
85 // for (decimal dist : vectorDatabase.StarDistances(9085, catalog)) {
86 // printf("Actual 9085 distance: %f\n", dist);
87 // }
88 // puts("Debug star.");
89 // for (int i = 0; i < (int)votes.size(); i++) {
90 // if (votes[i] > maxVotes/2) {
91 // printf("Star %4d received %d votes.\n", catalog[i].name, votes[i]);
92 // }
93 // }
94 // printf("Debug star: Actually voted for %d with %d votes\n",
95 // catalog[indexOfMax].name, maxVotes);
96 // }
97 // printf("Max votes: %d\n", maxVotes);
98 //starIndex = i, catalog index = indexOfMax
100 // Set identified[i] to value of catalog index of star w most votesr
101 identified.push_back(newStar);
102 }
103 //optimizations? N^2
104 //https://www.researchgate.net/publication/3007679_Geometric_voting_algorithm_for_star_trackers
105 //
106 // Do we have a metric for localization uncertainty? Star brighntess?
107 //loop i from 1 through n
108 std::vector<int16_t> verificationVotes(identified.size(), 0);
109 for (int i = 0; i < (int)identified.size(); i++) {
110 //loop j from i+1 through n
111 for (int j = i + 1; j < (int)identified.size(); j++) {
112 // Calculate distance between catalog stars
113 CatalogStar first = catalog[identified[i].catalogIndex];
114 CatalogStar second = catalog[identified[j].catalogIndex];
115 decimal cDist = AngleUnit(first.spatial, second.spatial);
116
117 Star firstIdentified = stars[identified[i].starIndex];
118 Star secondIdentified = stars[identified[j].starIndex];
122
123 //if sDist is in the range of (distance between stars in the image +- R)
124 //add a vote for the match
125 if (DECIMAL_ABS(sDist - cDist) < tolerance) {
128 }
129 }
130 }
131 // Find star w most votes
132 int maxVotes = verificationVotes.size() > 0 ? verificationVotes[0] : 0;
133 for (int v = 1; v < (int)verificationVotes.size(); v++) {
136 }
137 }
138
139 // If the stars are within a certain range of the maximal number of votes,
140 // we consider it correct.
141 // maximal votes = maxVotes
143 int thresholdVotes = maxVotes * 3 / 4;
144 printf("Verification threshold: %d\n", thresholdVotes);
145 for (int i = 0; i < (int)verificationVotes.size(); i++) {
147 verified.push_back(identified[i]);
148 }
149 }
150
151 return verified;
152}
153
154/*
155 * Strategies:
156 * 1. For each star, enumerate all stars which have the same combination of distances to some
157 * other stars, getting down to a hopefully small (<10) list of candidates for each star, then
158 * do a quad-nested loop to correlate them.
159 * 2. Loop through all possible stars in the catalog for star i. Then look at edge ij, using
160 * this to select possible j-th stars. If ever there is not a possible j-th star, continue the
161 * i-loop. When a possible ij combination is found, loop through k stars according to ik. IF
162 * none are found, continue the outer i loop. If some are found, check jk for each one. For each possible ijk triangle,
163 */
164
170public:
176 : pairs(NULL), end(NULL) { };
177
184 PairDistanceInvolvingIterator(const int16_t *pairs, const int16_t *end, int16_t involving)
185 : pairs(pairs), end(end), involving(involving) {
186
187 assert((end-pairs)%2 == 0);
188 ForwardUntilInvolving();
189 };
190
191 // PairDistanceInvolvingIterator operator++() {
192 // PairDistanceInvolvingIterator result(*this);
193 // ++(*this);
194 // return result;
195 // }
196
199 assert(HasValue());
200 pairs += 2;
201 ForwardUntilInvolving();
202 return *this;
203 }
204
207 return curValue;
208 }
209
211 bool HasValue() {
212 return pairs != end;
213 }
214
215 // bool operator==(const PairDistanceInvolvingIterator &other) const {
216 // return ()other.pairs == pairs;
217 // }
218
219 // bool operator!=(const PairDistanceInvolvingIterator &other) const {
220 // return !(*this == other);
221 // }
222private:
223 const int16_t *pairs;
224 const int16_t *end;
225 int16_t involving;
226 int16_t curValue;
227
229 void ForwardUntilInvolving() {
230 while (pairs != end) {
231 if (pairs[0] == involving) {
232 curValue = pairs[1];
233 return;
234 }
235 if (pairs[1] == involving) {
236 curValue = pairs[0];
237 return;
238 }
239 pairs += 2;
240 }
241 }
242};
243
245 std::vector<int16_t> result;
246 for (; it.HasValue(); ++it) {
247 result.push_back(*it);
248 }
249 return result;
250}
251
259std::unordered_multimap<int16_t, int16_t> PairDistanceQueryToMap(const int16_t *pairs, const int16_t *end) {
260 std::unordered_multimap<int16_t, int16_t> result;
261 for (const int16_t *p = pairs; p != end; p += 2) {
262 result.emplace(p[0], p[1]);
263 result.emplace(p[1], p[0]);
264 }
265 return result;
266}
267
268decimal IRUnidentifiedCentroid::VerticalAnglesToAngleFrom90(decimal v1, decimal v2) {
270}
271
277 const Star &otherStar = stars[starId.starIndex];
280
281 for (const auto &otherPair : identifiedStarsInRange) {
282 decimal curAngleFrom90 = VerticalAnglesToAngleFrom90(otherPair.first, angleFromVertical);
286 bestStar2 = otherPair.second;
287 }
288 }
289
290 identifiedStarsInRange.emplace_back(angleFromVertical, starId);
291}
292
299std::vector<std::vector<IRUnidentifiedCentroid *>::iterator> FindUnidentifiedCentroidsInRange(
300 std::vector<IRUnidentifiedCentroid *> *centroids, const Star &star, const Camera &camera,
302
304
307
308 std::vector<std::vector<IRUnidentifiedCentroid *>::iterator> result;
309 for (auto it = centroids->begin(); it != centroids->end(); ++it) {
310 Vec3 theirSpatial = camera.CameraToSpatial((*it)->star->position).Normalize();
312 if (angleCos >= minCos && angleCos <= maxCos) {
313 result.push_back(it);
314 }
315 }
316
317 return result;
318
319 // TODO: optimize by sorting on x-coordinate (like in tracking), or maybe even kd-tree
320
321 // // Find the first centroid that is within range of the given centroid.
322 // auto firstInRange = std::lower_bound(centroids->begin(), centroids->end(), star.position.x - maxDistance,
323 // [](const IRUnidentifiedCentroid &centroid, decimal x) {
324 // return centroid.star.position.x < x;
325 // });
326
327 // // Find the first centroid that is not within range of the given centroid.
328 // auto firstNotInRange = std::lower_bound(firstInRange, centroids->end(), star.position.x + maxDistance,
329 // [](const IRUnidentifiedCentroid &centroid, decimal x) {
330 // return centroid.star.position.x <= x;
331 // });
332
333 // // Copy the pointers to the stars into the result vector.
334 // for (auto it = firstInRange; it != firstNotInRange; ++it) {
335 // decimal distance = Distance(star.position, it->star.position);
336 // if (distance >= minDistance && distance <= maxDistance) {
337 // result.push_back(&*it);
338 // }
339 // }
340}
341
351 std::vector<IRUnidentifiedCentroid *> *aboveThresholdCentroids,
352 std::vector<IRUnidentifiedCentroid *> *belowThresholdCentroids,
355 const Camera &camera) {
356
357 std::vector<int16_t> nowBelowThreshold; // centroid indices newly moved above the threshold
358 // don't need to iterate through the centroids that are already below the threshold, for performance.
360 (*centroidIt)->AddIdentifiedStar(starId, stars);
361 if ((*centroidIt)->bestAngleFrom90 <= angleFrom90Threshold) {
363 nowBelowThreshold.push_back((*centroidIt)->index);
364 }
365 }
366 // remove all centroids with indices in nowBelowThreshold from aboveThresholdCentroids
367 aboveThresholdCentroids->erase(std::remove_if(aboveThresholdCentroids->begin(), aboveThresholdCentroids->end(),
369 return std::find(nowBelowThreshold.begin(), nowBelowThreshold.end(), centroid->index) != nowBelowThreshold.end();
370 }), aboveThresholdCentroids->end());
371}
372
385 const Catalog &catalog,
388 decimal tolerance) {
389
390 const int16_t *query1End;
391 const int16_t *query1 = db.FindPairsExact(catalog, distance1-tolerance, distance1+tolerance, &query1End);
392
393 const Vec3 &spatial1 = catalog[catalogIndex1].spatial;
394 const Vec3 &spatial2 = catalog[catalogIndex2].spatial;
396
397 // Use PairDistanceInvolvingIterator to find catalog candidates for the unidentified centroid from both sides.
398
399 std::vector<int16_t> result;
400 // find all the catalog stars that are in both annuli
403 ++candidateIt) {
404
405 Vec3 candidateSpatial = catalog[*candidateIt].spatial;
406
408
409 // check distance to second star
410 if (!(angle2 >= distance2-tolerance && angle2 <= distance2+tolerance)) {
411 continue;
412 }
413
414 // check spectrality
416 // if they are nearly coplanar, don't need to check spectrality
417 // TODO: Implement ^^. Not high priority, since always checking spectrality is conservative.
418 if (spectralTorch <= 0) {
419 continue;
420 }
421
422 // we've made it through the gauntlet!
423 result.push_back(*candidateIt);
424 }
425
426 return result;
427}
428
430 std::vector<IRUnidentifiedCentroid *> *belowThresholdCentroids) {
431 if (!belowThresholdCentroids->empty()) {
432 auto result = belowThresholdCentroids->back();
433 belowThresholdCentroids->pop_back();
434 return result;
435 }
436
437 // need to find the best in aboveThreshold, if any
438 auto bestAboveThreshold = std::min_element(aboveThresholdCentroids->begin(), aboveThresholdCentroids->end(),
440 return a->bestAngleFrom90 < b->bestAngleFrom90;
441 });
442
443 // 10 is arbitrary; but really it should be less than DECIMAL_M_PI_2 when set
444 if (bestAboveThreshold != aboveThresholdCentroids->end() && (*bestAboveThreshold)->bestAngleFrom90 < 10) {
447 return result;
448 }
449
450 return NULL;
451}
452
454
462 const Stars &stars,
464 const Catalog &catalog,
465 const Camera &camera,
466 decimal tolerance) {
467#ifdef LOST_DEBUG_PERFORMANCE
468 auto startTimestamp = std::chrono::steady_clock::now();
469#endif
470 // initialize all unidentified centroids
471 std::vector<IRUnidentifiedCentroid> allUnidentifiedCentroids;
472 std::vector<IRUnidentifiedCentroid *> aboveThresholdUnidentifiedCentroids;
473 std::vector<IRUnidentifiedCentroid *> belowThresholdUnidentifiedCentroids;
474 allUnidentifiedCentroids.reserve(stars.size());
475 for (size_t i = 0; i < stars.size(); i++) {
476 allUnidentifiedCentroids.push_back(IRUnidentifiedCentroid(stars[i], i));
477 }
478 // add everything from allUnidentifiedCentroids to above threshold
480 for (size_t i = 0; i < allUnidentifiedCentroids.size(); i++) {
481 // only add if index is not equal to any starIndex in identifiers already
482 if (std::find_if(identifiers->begin(), identifiers->end(),
484 return identifier.starIndex == allUnidentifiedCentroids[i].index;
485 }) == identifiers->end()) {
486
488 }
489 }
490
491 // sort unidentified centroids by x coordinate
492 // Don't need this until we fix the Find thing
493 // std::sort(unidentifiedCentroids.begin(), unidentifiedCentroids.end(),
494 // [](const IRUnidentifiedCentroid &a, const IRUnidentifiedCentroid &b) {
495 // return a.star->position.x < b.star->position.x;
496 // });
497
498 // for each identified star, add it to the list of identified stars for each unidentified centroid within range
499 for (const auto &starId : *identifiers) {
502 db.MinDistance(), db.MaxDistance(),
504 camera);
505 }
506
508
509 // keep getting the best unidentified centroid and identifying it
514 break;
515 }
516
517 // Project next stars to 3d, find angle between them and current unidentified centroid
519 Vec3 spatial1 = camera.CameraToSpatial(stars[nextUnidentifiedCentroid->bestStar1.starIndex].position);
520 Vec3 spatial2 = camera.CameraToSpatial(stars[nextUnidentifiedCentroid->bestStar2.starIndex].position);
524
525 // find all the catalog stars that are in both annuli
526 // flip arguments for appropriate spectrality.
527 std::vector<int16_t> candidates =
528 spectralTorch > 0
530 catalog,
531 nextUnidentifiedCentroid->bestStar1.catalogIndex,
532 nextUnidentifiedCentroid->bestStar2.catalogIndex,
533 d1, d2, tolerance)
535 catalog,
536 nextUnidentifiedCentroid->bestStar2.catalogIndex,
537 nextUnidentifiedCentroid->bestStar1.catalogIndex,
538 d2, d1, tolerance);
539
540 if (candidates.size() != 1) { // if there is not exactly one candidate, we can't identify the star. Just remove it from the list.
541 if (candidates.size() > 1) {
542 std::cerr << "WARNING: Multiple catalog stars matched during identify remaining stars. This should be rare." << std::endl;
543 }
544 } else {
545 // identify the centroid
546 identifiers->emplace_back(nextUnidentifiedCentroid->index, candidates[0]);
547
548 // update nearby unidentified centroids with the new identified star
551 db.MinDistance(), db.MaxDistance(),
552 // TODO should probably tune this:
554 camera);
555
557 }
558 }
559
560 // Select() should always empty out this list
562
563#ifdef LOST_DEBUG_PERFORMANCE
564 auto endTimestamp = std::chrono::steady_clock::now();
565 std::cout << "IdentifyRemainingStarsPairDistance took " << std::chrono::duration_cast<std::chrono::microseconds>(endTimestamp - startTimestamp).count() << "us" << std::endl;
566#endif
567
569}
570
572 const unsigned char *database, const Stars &stars, const Catalog &catalog, const Camera &camera) const {
573
576 const unsigned char *databaseBuffer = multiDatabase.SubDatabasePointer(PairDistanceKVectorDatabase::kMagicValue);
577 if (databaseBuffer == NULL || stars.size() < 4) {
578 std::cerr << "Not enough stars, or database missing." << std::endl;
579 return identified;
580 }
583
584 // smallest normal single-precision decimal is around 10^-38 so we should be all good. See
585 // Analytic_Star_Pattern_Probability on the HSL wiki for details.
586 decimal expectedMismatchesConstant = DECIMAL_POW(numFalseStars, 4) * DECIMAL_POW(tolerance, 5) / 2 / DECIMAL_POW(DECIMAL_M_PI, 2);
587
588 // this iteration technique is described in the Pyramid paper. Briefly: i will always be the
589 // lowest index, then dj and dk are how many indexes ahead the j-th star is from the i-th, and
590 // k-th from the j-th. In addition, we here add some other numbers so that the pyramids are not
591 // weird lines in wide FOV images. TODO: Select the starting points to ensure that the first pyramids are all within measurement tolerance.
592 int numStars = (int)stars.size();
593 // the idea is that the square root is about across the FOV horizontally
594 int across = floor(sqrt(numStars))*2;
595 int halfwayAcross = floor(sqrt(numStars)/2);
596 long totalIterations = 0;
597
598 int jMax = numStars - 3;
599 for (int jIter = 0; jIter < jMax; jIter++) {
600 int dj = 1+(jIter+halfwayAcross)%jMax;
601
602 int kMax = numStars-dj-2;
603 for (int kIter = 0; kIter < kMax; kIter++) {
604 int dk = 1+(kIter+across)%kMax;
605
606 int rMax = numStars-dj-dk-1;
607 for (int rIter = 0; rIter < rMax; rIter++) {
608 int dr = 1+(rIter+halfwayAcross)%rMax;
609
610 int iMax = numStars-dj-dk-dr-1;
611 for (int iIter = 0; iIter <= iMax; iIter++) {
612 int i = (iIter + iMax/2)%(iMax+1); // start near the center of the photo
613
614 // identification failure due to cutoff
615 if (++totalIterations > cutoff) {
616 std::cerr << "Cutoff reached." << std::endl;
617 return identified;
618 }
619
620 int j = i+dj;
621 int k = j+dk;
622 int r = k+dr;
623
624 assert(i != j && j != k && k != r && i != k && i != r && j != r);
625
626 // TODO: move this out of the loop?
627 Vec3 iSpatial = camera.CameraToSpatial(stars[i].position).Normalize();
628 Vec3 jSpatial = camera.CameraToSpatial(stars[j].position).Normalize();
629 Vec3 kSpatial = camera.CameraToSpatial(stars[k].position).Normalize();
630
632
636
637 // if we made it this far, all 6 angles are confirmed! Now check
638 // that this match would not often occur due to chance.
639 // See Analytic_Star_Pattern_Probability on the HSL wiki for details
642 / kSinInner
643 / std::max(std::max(iSinInner, jSinInner), kSinInner);
644
645 if (expectedMismatches > maxMismatchProbability) {
646 std::cout << "skip: mismatch prob." << std::endl;
647 continue;
648 }
649
650 Vec3 rSpatial = camera.CameraToSpatial(stars[r].position).Normalize();
651
652 // sign of determinant, to detect flipped patterns
654
659 decimal krDist = AngleUnit(kSpatial, rSpatial); // TODO: we don't really need to
660 // check krDist, if k has been
661 // verified by i and j it's fine.
662
663 // we check the distances with the extra tolerance requirement to ensure that
664 // there isn't some pyramid that's just outside the database's bounds, but
665 // within measurement tolerance of the observed pyramid, since that would
666 // possibly cause a non-unique pyramid to be identified as unique.
667#define _CHECK_DISTANCE(_dist) if (_dist < vectorDatabase.MinDistance() + tolerance || _dist > vectorDatabase.MaxDistance() - tolerance) { continue; }
673#undef _CHECK_DISTANCE
674
675 const int16_t *ijEnd, *ikEnd, *irEnd;
676 const int16_t *const ijQuery = vectorDatabase.FindPairsLiberal(ijDist - tolerance, ijDist + tolerance, &ijEnd);
677 const int16_t *const ikQuery = vectorDatabase.FindPairsLiberal(ikDist - tolerance, ikDist + tolerance, &ikEnd);
678 const int16_t *const irQuery = vectorDatabase.FindPairsLiberal(irDist - tolerance, irDist + tolerance, &irEnd);
679
680 std::unordered_multimap<int16_t, int16_t> ikMap = PairDistanceQueryToMap(ikQuery, ikEnd);
681 std::unordered_multimap<int16_t, int16_t> irMap = PairDistanceQueryToMap(irQuery, irEnd);
682
683 int iMatch = -1, jMatch = -1, kMatch = -1, rMatch = -1;
686 // depending on parity, the first or second star in the pair is the "other" one
687 int jCandidate = (iCandidateQuery - ijQuery) % 2 == 0
688 ? iCandidateQuery[1]
689 : iCandidateQuery[-1];
690
691 const Vec3 &iCandidateSpatial = catalog[iCandidate].spatial;
692 const Vec3 &jCandidateSpatial = catalog[jCandidate].spatial;
693
695
696 for (auto kCandidateIt = ikMap.equal_range(iCandidate); kCandidateIt.first != kCandidateIt.second; kCandidateIt.first++) {
697 // kCandidate.first is iterator, then ->second is the value (other star)
698 int kCandidate = kCandidateIt.first->second;
699 Vec3 kCandidateSpatial = catalog[kCandidate].spatial;
701 // checking the spectral-ity early to fail fast
703 continue;
704 }
705
706 // small optimization: We can calculate jk before iterating through r, so we will!
709 continue;
710 }
711
712 // TODO: if there are no jr matches, there's no reason to
713 // continue iterating through all the other k-s. Possibly
714 // enumarete all r matches, according to ir, before this loop
715 for (auto rCandidateIt = irMap.equal_range(iCandidate); rCandidateIt.first != rCandidateIt.second; rCandidateIt.first++) {
716 int rCandidate = rCandidateIt.first->second;
717 const Vec3 &rCandidateSpatial = catalog[rCandidate].spatial;
721 continue;
722 }
725 continue;
726 }
727
728 // we have a match!
729
730 if (iMatch == -1) {
735 } else {
736 // uh-oh, stinky!
737 // TODO: test duplicate detection, it's hard to cause it in the real catalog...
738 std::cerr << "Pyramid not unique, skipping..." << std::endl;
739 goto sensorContinue;
740 }
741 }
742 }
743
744
745 }
746
747 if (iMatch != -1) {
748 std::cout.precision(6);
749 std::cout << "Matched unique pyramid!" << std::endl << "Expected mismatches: " << std::scientific << expectedMismatches << std::endl << std::fixed;
750 identified.push_back(StarIdentifier(i, iMatch));
751 identified.push_back(StarIdentifier(j, jMatch));
752 identified.push_back(StarIdentifier(k, kMatch));
753 identified.push_back(StarIdentifier(r, rMatch));
754
756 printf("Identified an additional %d stars.\n", numAdditionallyIdentified);
758
759 return identified;
760 }
761
763 }
764 }
765 }
766 }
767
768 std::cerr << "Tried all pyramids; none matched." << std::endl;
769 return identified;
770}
771
772}
A full description of a camera. Enough information to reconstruct the camera matrix and then some.
Definition camera.hpp:9
Vec3 CameraToSpatial(const Vec2 &) const
Gives a point in 3d space that could correspond to the given vector, using the same coordinate system...
Definition camera.cpp:35
A star from the Bright Star Catalog.
StarIdentifiers Go(const unsigned char *database, const Stars &, const Catalog &, const Camera &) const
Actualy perform the star idenification. This is the "main" function for StarIdAlgorithm.
Definition star-id.cpp:16
StarIdentifiers Go(const unsigned char *database, const Stars &, const Catalog &, const Camera &) const
Actualy perform the star idenification. This is the "main" function for StarIdAlgorithm.
Definition star-id.cpp:29
unidentified centroid used in IdentifyRemainingStarsPairDistance The "angles" through here are "trian...
const Star * star
Index into list of all centroids.
StarIdentifier bestStar1
For the pair of other centroids forming the triangular angle closest to 90 degrees,...
void AddIdentifiedStar(const StarIdentifier &starId, const Stars &stars)
When a centroid within range of this centroid is identified, call this function.
Definition star-id.cpp:276
StarIdentifier bestStar2
One star corresponding to bestAngleFrom90.
Given a list of star pairs, finds all those pairs which involve a certain star.
Definition star-id.cpp:169
PairDistanceInvolvingIterator(const int16_t *pairs, const int16_t *end, int16_t involving)
The main constructor.
Definition star-id.cpp:184
PairDistanceInvolvingIterator & operator++()
Move to the next matching pair.
Definition star-id.cpp:198
int16_t operator*() const
Access the curent pair.
Definition star-id.cpp:206
bool HasValue()
Whether the iterator is currently on a value. (false if iteration is complete)
Definition star-id.cpp:211
PairDistanceInvolvingIterator()
Create a "past-the-end" iterator.
Definition star-id.cpp:175
A database storing distances between pairs of stars.
Definition databases.hpp:54
static const int32_t kMagicValue
Magic value to use when storing inside a MultiDatabase.
Definition databases.hpp:70
StarIdentifiers Go(const unsigned char *database, const Stars &, const Catalog &, const Camera &) const
Actualy perform the star idenification. This is the "main" function for StarIdAlgorithm.
Definition star-id.cpp:571
A "centroid" detected in an image.
Vec2 position
The (x,y) pixel coordinates in the image (top left is 0,0)
Records that a certain Star (detected in the image) corresponds to a certain CatalogStar.
Three dimensional vector with decimaling point components.
Vec3 Normalize() const
Create a vector pointing in the same direction with magnitude 1.
Vec3 CrossProduct(const Vec3 &) const
Usual vector cross product.
double decimal
Definition decimal.hpp:11
#define DECIMAL_POW(base, power)
Definition decimal.hpp:39
#define DECIMAL_M_PI
Definition decimal.hpp:29
#define DECIMAL_M_PI_4
Definition decimal.hpp:31
#define DECIMAL_SIN(x)
Definition decimal.hpp:52
#define DECIMAL_ABS(x)
Definition decimal.hpp:49
#define DECIMAL_M_PI_2
Definition decimal.hpp:30
#define DECIMAL_ATAN2(x, y)
Definition decimal.hpp:58
#define DECIMAL_COS(x)
Definition decimal.hpp:53
LOST starting point.
std::vector< std::vector< IRUnidentifiedCentroid * >::iterator > FindUnidentifiedCentroidsInRange(std::vector< IRUnidentifiedCentroid * > *centroids, const Star &star, const Camera &camera, decimal minDistance, decimal maxDistance)
Return all the unidentified centroids within the requested distance bounds from star
Definition star-id.cpp:299
const decimal kAngleFrom90SoftThreshold
Definition star-id.cpp:453
std::vector< StarIdentifier > StarIdentifiers
IRUnidentifiedCentroid * SelectNextUnidentifiedCentroid(std::vector< IRUnidentifiedCentroid * > *aboveThresholdCentroids, std::vector< IRUnidentifiedCentroid * > *belowThresholdCentroids)
Definition star-id.cpp:429
std::vector< Star > Stars
decimal AngleUnit(const Vec3 &vec1, const Vec3 &vec2)
Calculate the inner angle, in radians, between two /unit/ vectors.
decimal Angle(const Vec3 &vec1, const Vec3 &vec2)
Calculate the inner angle, in radians, between two vectors.
std::vector< int16_t > ConsumeInvolvingIterator(PairDistanceInvolvingIterator it)
Definition star-id.cpp:244
int IdentifyRemainingStarsPairDistance(StarIdentifiers *, const Stars &, const PairDistanceKVectorDatabase &, const Catalog &, const Camera &, decimal tolerance)
Given some identified stars, attempt to identify the rest.
Definition star-id.cpp:461
decimal DecimalModulo(decimal x, decimal mod)
Given a decimal, find it "modulo" another decimal, in the true mathematical sense (not remainder).
std::vector< int16_t > IdentifyThirdStar(const PairDistanceKVectorDatabase &db, const Catalog &catalog, int16_t catalogIndex1, int16_t catalogIndex2, decimal distance1, decimal distance2, decimal tolerance)
Given two already-identified centroids, and the distance from each to an as-yet unidentified third ce...
Definition star-id.cpp:384
void SerializePrimitive(SerializeContext *ser, const T &val)
std::unordered_multimap< int16_t, int16_t > PairDistanceQueryToMap(const int16_t *pairs, const int16_t *end)
Given the result of a pair-distance kvector query, build a hashmultimap of stars to other stars that ...
Definition star-id.cpp:259
std::vector< CatalogStar > Catalog
void AddToAllUnidentifiedCentroids(const StarIdentifier &starId, const Stars &stars, std::vector< IRUnidentifiedCentroid * > *aboveThresholdCentroids, std::vector< IRUnidentifiedCentroid * > *belowThresholdCentroids, decimal minDistance, decimal maxDistance, decimal angleFrom90Threshold, const Camera &camera)
Given a list of unidentified centroids not yet at the soft threshold, and a list of unidentified cent...
Definition star-id.cpp:350
#define _CHECK_DISTANCE(_dist)
A two dimensional vector with decimaling point components.