Star Refinement (StarRefineNav)
Overview
StarRefineNav is the pass-2 star
refinement technique: given a prior offset produced by the
pass-1 ensemble, it polishes that offset by re-centroiding every predicted catalog star against
the image and averaging the per-star residuals. Each predicted catalog star is shifted by the
prior offset, re-detected inside a tight refinement window, and its sub-pixel centroid compared
to the shifted prediction; the inverse-variance weighted average of the per-star residuals is
the refined delta the technique reports. When the per-instrument camera-rotation flag is on
and at least two stars survive the per-star quality gates, a Procrustes / similarity-transform
refit recovers a translation plus rotation instead of a translation alone.
Feasibility passes when at least one
STAR feature survives the shared usability
gates — predictable and not occluded by a body silhouette or ring annulus. Feasibility
fails when no usable star is offered.
Theory
The technique is a per-star centroid average rather than a global pattern-matcher. Pass-1 has already aligned the catalog to the image to within a few pixels (the prior offset); the remaining task is to extract the residual misalignment plus, on instruments that support it, the camera rotation.
Per-star centroid model
For a single predicted catalog star at position \(x_{\mathrm{pred}}\) with covariance \(\Sigma_{i}\) (the Cramer-Rao lower bound carried on the feature), the refinement step takes the brightness-weighted moment of a small box around the predicted brightness peak in a search window centred on \(x_{\mathrm{pred}} + \mathbf{p}\) (where \(\mathbf{p}\) is the prior offset). The centroid is rejected when the brightest pixel in the window is below the detection threshold or the implied per-star residual exceeds a configured cap; the surviving correspondences are the inlier set.
Translation-only fit
For each surviving star \(i\) the per-star residual is
The reported delta is the inverse-variance weighted mean
where \(\mathrm{tr}(\Sigma_{i})\) is the trace of the per-star feature covariance; a zero-or-missing covariance falls back to a unit weight. The reported translation on the result is \(\mathbf{p} + \Delta\) (absolute, not delta-from-prior); the orchestrator’s ensemble combine treats every per-technique offset as absolute.
Rotation-aware fit
When fit_camera_rotation is true and the inlier count is at least two, the technique runs
a weighted Kabsch / orthogonal-Procrustes solve on the catalog-vs-detection point clouds to
extract a rotation about the catalog-side weighted centroid plus a translation. The
similarity-transform fitter computes the weighted cross-covariance, decomposes it via SVD, and
applies a determinant correction so that one cohort being a numerical mirror image of the other
cannot produce a reflection masquerading as a rotation. The translation read off the
similarity-transform output is the reported absolute offset for the rotation-fitting
branch; the inverse-variance-weighted mean is used only when rotation fitting is
disabled or there are too few inliers to fit a rotation.
The rotation variance is derived from the inlier residual scatter scaled by the catalog spread:
with \(\sigma_{r}^{2}\) the per-axis-averaged weighted residual variance. A vanishing catalog spread (every inlier on top of the centroid) collapses \(S\) to zero and the rotation is reported with the project-wide rotation-unobservable sigma sentinel; the ensemble combine treats that variance as effectively unconstrained.
Restrictions and assumptions
The technique requires a prior offset on the per-image
NavContext; absent that, it returns a spurious zero-confidence result rather than running the per-star centroid loop.Predicted catalog positions are assumed to be in the same extended-FOV pixel frame the image uses; a SPICE pose error larger than the refinement window radius pushes the prediction outside the search window and the per-star detection misses.
The per-star CRLB covariance carried on each feature is taken at face value as the inlier weight; an over-confident CRLB will tighten the reported confidence. The pass-1 model is responsible for grounding the CRLB physically.
The 1-inlier path provides no independent cross-check beyond the prior it was handed: the same single observation that drove the pass-1 fit just gets polished. A documented post-sigmoid cap (default 0.5) prevents the technique from outranking
StarUniqueMatchNavon the same one-star scene.
Sources of uncertainty
The reported translation covariance is one of two forms:
Single inlier. The (2, 2) covariance is the inlier feature’s CRLB (a copy of
position_cov_px). A missing CRLB falls back to the identity matrix.Multi-inlier. The (2, 2) covariance is a diagonal of the per-axis weighted residual variances about the converged delta, floored at the inverse total weight so the diagonals do not collapse to zero on a coincidentally-tight inlier set.
When camera rotation is fit, the (2, 2) translation block is embedded in a (3, 3) covariance whose rotation diagonal is the variance derived above; with a single inlier the rotation diagonal is the project-wide rotation-unobservable sentinel and the rotation angle is reported as zero. At-edge and spurious flags hard-zero the confidence on top of the linear formula.
Configuration
All numeric tunables for this technique live in techniques.StarRefineNav.tuning in
src/nav/config_files/config_510_techniques.yaml.
refine_window_px— float, default6.0px. Half-width of the per-star refinement window centred on each shifted prediction. Tighter than the unique-match search window because the pass-1 prior already put the prediction within a few pixels of the brightness peak.centroid_box_half_px— int, default3px. Half-width of the brightness-weighted-moment box around each accepted peak.max_per_star_residual_px— float, default4.0px. A star whose detected centroid sits more than this many pixels from the shifted prediction is dropped before the average; almost certainly a wrong peak.detection_sigma— float, default4.0(dimensionless). Detection-threshold multiplier on the per-image noise sigma; the brightest pixel in the refinement window must cleardetection_sigma * image_noise_sigmato be accepted.min_inliers— int, default1(count). Below this many surviving inliers the technique reports a spurious zero-confidence result instead of attempting the average.at_edge_tolerance_px— float, default1.0px. The reported absolute translation is flaggedat_edgewhen its absolute distance from any search-window axis bound falls within this tolerance.single_inlier_confidence_cap— float, default0.5(dimensionless). Post-sigmoid confidence cap when the refine fit had only one inlier. A 1-star refine carries no independent cross-check beyond the prior it was handed; the cap keeps the technique from outranking a 1-star unique-match on the same observation.rotation_at_edge_fraction— float, default0.95(dimensionless). Fraction ofmax_rotation_degat which the converged rotation magnitude tripsat_edge. Only the multi-inlier Procrustes path uses this threshold; a 1-inlier refine always reports rotation as unobservable.
Per-instrument overrides
The eight keys above are global; the per-instrument YAML files in
src/nav/config_files/config_4N0_inst_*.yaml do not override any of them. The
camera-rotation flag (fit_camera_rotation) and the rotation cap (max_rotation_deg)
that this technique reads off the per-image
NavContext come from the per-instrument
InstrumentSettings.
Confidence formula
The technique reports a calibrated confidence in \([0, 1]\) produced by the shared sigmoid
combination, see DT Fitting (Shared Polyline-vs-Image Fitter) for the per-term arithmetic and
Navigation Techniques for the family-level overview. The formula spec is
techniques.StarRefineNav in the same YAML file and consumes attributes off
StarRefineDiagnostics plus at_edge and spurious.
n_stars_used— alpha = 1.0, offset = 0.0, divisor = 5.0, cap at 1.0. Number of stars that survived the per-star quality gates. More inliers earn confidence up to a five-star saturation point.median_pos_err_px— alpha = -1.0, offset = 0.0, divisor = 1.0, no cap. Median per-star Euclidean residual (observed centroid vs. shifted prediction). Larger residuals pull confidence down.residual_scatter_px— alpha = -1.0, offset = 0.0, divisor = 1.0, no cap. Per-axis weighted RMS of the per-star residuals about the fitted delta. Internally inconsistent inlier sets pull confidence down.
Hard-zero gate: at_edge and spurious either firing forces confidence to zero before the
sigmoid is evaluated. The constant baseline is \(\alpha_{0} = -1.0\). No post-sigmoid
hard_cap is applied at the spec level; the single_inlier_confidence_cap above is
applied by the technique itself only when exactly one inlier survived.
Implementation
Source files:
src/nav/nav_technique/nav_technique_star_refine.py—StarRefineNavand its private collect-residuals / build-covariance / Procrustes-refit / fail-shape helpers.src/nav/nav_technique/_star_helpers.py— shared star-feature helpers (usable_stars,local_centroid,similarity_transform_fit). The leading underscore marks the module as package-private; every star technique imports it.src/nav/nav_technique/confidence.py— the shared sigmoid-combination evaluator.src/nav/nav_technique/diagnostics.py—StarRefineDiagnostics.
Public class StarRefineNav, base
NavTechnique.
Class attributes:
name—'StarRefineNav'.accepts_feature_types—frozenset({STAR}).requires_prior—True. The orchestrator only invokes this technique on pass 2, after the pass-1 ensemble has produced a prior offset.confidence_attributes—{'at_edge', 'spurious', 'n_stars_used', 'median_pos_err_px', 'residual_scatter_px'}.
Public methods (autodocumented at nav.nav_technique):
is_feasible() and
navigate().
Diagnostics
n_stars_used— count of stars that survived the per-star quality gates. Consumed by the confidence formula and by the single-inlier confidence cap.median_pos_err_px— median per-star Euclidean residual. Consumed by the confidence formula.residual_scatter_px— per-axis weighted RMS of the per-star residuals about the fitted delta. Consumed by the confidence formula.
Call path traced through
navigate():
Open a logged section. Filter the offered features down to
usable_stars(predictable and not occluded by a body silhouette or ring annulus).No prior on the context. Return early with a spurious zero-confidence result via the private
_failhelper, withreason='no_prior_offset_on_context'.Read the prior offset, the extfov image, and the per-image noise sigma off the context. Loop over the usable stars: for each, call
local_centroidagainst the shifted prediction; drop stars with no peak above the detection threshold or whose centroid sits more thanmax_per_star_residual_pxfrom the shifted prediction. Compute the per-star residuals and inverse-trace weights.Too few inliers. When the surviving inlier count is below
min_inliers, return a spurious zero-confidence result via_fail.Compute the inverse-variance weighted delta, the median per-star residual distance, and the per-axis weighted scatter about the delta. Build a
StarRefineDiagnostics.Read the search-window margin via
search_window_for_obs()and apply the at-edge test to the absolute offset (prior + delta). Evaluate the confidence spec viaevaluate_sigmoid_combination()and log the per-term breakdown.Single-inlier post-sigmoid cap. When exactly one inlier survived and the raw confidence exceeds
single_inlier_confidence_cap, the confidence is clipped to the cap and a log line records the clamp.Build the (2, 2) translation covariance via the private
_build_covariancehelper: single-inlier returns the feature’s CRLB; multi-inlier returns the diagonal of per-axis residual variances floored at the inverse total weight.Result-shape branches on the rotation flag and the inlier count:
Translation only (
fit_camera_rotationfalse). The reported covariance is the (2, 2) block;rotation_radandsigma_rotation_radareNone.Rotation fit, two or more inliers. Call the private
_fit_rotation_3dofhelper, which reconstructs the per-star detection and shifted-prediction positions from the residuals and runssimilarity_transform_fitto extract the rotation and translation. The Procrustes refit can pull the absolute offset outside the search window even when the delta-only path was inside, soat_edgeis re-evaluated against the updated absolute offset and the rotation magnitude. The reported covariance is the (3, 3) block with the per-axis translation variances on the leading diagonal and the rotation variance on the bottom-right.Rotation fit, single inlier. No rotation evidence exists; the technique embeds the (2, 2) translation block in a (3, 3) covariance via
embed_rotation_unobservable(), setsrotation_radto0.0, and reportsrotation_unobservable_sigma_rad()as the sigma.
Assemble and return the
NavTechniqueResult.feature_idspreserves the inlier set; the orchestrator’s curator uses it to attribute per-star contributions at audit time.
Examples
one_bright_star_no_body(Cassini ISS WAC, imageW1449079117_1)Single bright star (Vega) in an otherwise empty field. The pass-1 ensemble’s
StarUniqueMatchNavrecovers a 1-star prior;StarRefineNavruns on pass 2, finds that single star at the shifted prediction, and reports a polished offset within sub-pixel of the prior. The result fires the single-inlier confidence cap (one inlier, no cross-check) and is reported with confidence at most 0.5. Operator-verified ground-truth offset is \((\Delta v, \Delta u) = (3.06, -0.02)\) px.star_dominated(Cassini ISS WAC, imageW1580760393_1)Dense star field, no body in FOV. When the pass-1
StarFieldFromCatalogNavproduces a multi-star prior,StarRefineNavre-centroids every predicted catalog star against the image and averages the per-star residuals. Multi-inlier inputs do not fire the single-inlier cap; the reported covariance is the diagonal of per-axis weighted residual variances rather than the CRLB floor. Operator-verified ground-truth offset is \((\Delta v, \Delta u) = (-2.68, -3.68)\) px.