Skip to main content

Crate tetra3

Crate tetra3 

Source
Expand description

§tetra3

A fast, robust lost-in-space star plate solver written in Rust.

Status: Alpha — The core solver is based on well-vetted algorithms but has only been tested against a limited set of images. The API is not yet stable and may change between releases. Having said that, it has been made to work on both low-SNR images taken with a backyard camera and high-star-density images from more complex telescopes.

Given a set of star centroids extracted from a camera image, tetra3 identifies the stars against a catalog and returns the camera’s pointing direction as a quaternion — no prior attitude estimate required.

Documentation: For tutorials, concept guides, and Python API reference, see the tetra3rs documentation.

§Features

  • Lost-in-space solving — determines attitude from star patterns with no initial guess
  • Fast — geometric hashing of 4-star patterns with breadth-first (brightest-first) search
  • Robust — statistical verification via binomial false-positive probability
  • Multiscale — supports a range of field-of-view scales in a single database
  • Proper motion — propagates Hipparcos catalog positions to any observation epoch
  • Zero-copy deserialization — databases serialize with rkyv for instant loading
  • Centroid extraction — detect stars from images with local background subtraction, connected-component labeling, and quadratic sub-pixel peak refinement (image feature)
  • Camera model — unified CameraModel struct (focal length, optical center, parity, distortion) used throughout the solve and calibration pipeline
  • Distortion calibration — fit SIP polynomial or radial distortion models from one or more solved images via calibrate_camera
  • WCS output — solve results include FITS-standard WCS fields (CD matrix, CRVAL) and SolveResult::pixel_to_world / SolveResult::world_to_pixel methods
  • Stellar aberration — optional correction for the ~20″ apparent shift in star positions caused by the observer’s barycentric velocity; set SolveConfig::observer_velocity_km_s (use earth_barycentric_velocity for ground-based / Earth-orbiting observers)
  • Tested on real spacecraft imagery — successfully solves NASA TESS Full Frame Images (~12° FOV, significant optical distortion). Multi-image calibration across 10 TESS sectors achieves RMSE <15″ and <10″ agreement with FITS WCS solutions

§Example

use tetra3::{GenerateDatabaseConfig, SolverDatabase, SolveConfig, Centroid, SolveStatus};

// Generate a database from the Hipparcos catalog
let config = GenerateDatabaseConfig {
    max_fov_deg: 20.0,
    epoch_proper_motion_year: Some(2025.0),
    ..Default::default()
};
let db = SolverDatabase::generate_from_hipparcos("data/hip2.dat", &config).unwrap();

// Save for fast loading later, or load a previously saved database
db.save_to_file("data/my_database.rkyv").unwrap();
let db = SolverDatabase::load_from_file("data/my_database.rkyv").unwrap();

// Solve from image centroids (pixel coordinates, origin at image center)
let centroids = vec![
    Centroid { x: 100.0, y: 200.0, mass: Some(50.0), cov: None },
    Centroid { x: -50.0, y: -10.0, mass: Some(45.0), cov: None },
    // ... more centroids ...
];

let solve_config = SolveConfig {
    fov_estimate_rad: (15.0_f32).to_radians(), // horizontal FOV
    image_width: 1024,
    image_height: 1024,
    fov_max_error_rad: Some((2.0_f32).to_radians()),
    ..Default::default()
};

let result = db.solve_from_centroids(&centroids, &solve_config);
if result.status == SolveStatus::MatchFound {
    let q = result.qicrs2cam.unwrap();
    println!("Attitude: {q}");
    println!("Matched {} stars in {:.1} ms",
        result.num_matches.unwrap(), result.solve_time_ms);
}

§Stellar aberration

Stellar aberration shifts apparent star positions by up to ~20″ due to the observer’s barycentric velocity (~30 km/s for Earth). The pattern-matching step is unaffected (inter-star angular separations are invariant to first order in v/c), but the final attitude quaternion is biased by ~20″ unless corrected.

Pass the observer’s barycentric velocity (ICRS, km/s) via SolveConfig::observer_velocity_km_s. The solver applies a first-order correction to all catalog vectors before matching and refinement.

For Earth-based or Earth-orbiting observers, earth_barycentric_velocity provides an approximate velocity from a circular-orbit model:

use tetra3::{earth_barycentric_velocity, SolveConfig};

let v = earth_barycentric_velocity(9321.0); // days since J2000.0
let config = SolveConfig {
    observer_velocity_km_s: Some(v),
    ..SolveConfig::new((10.0_f32).to_radians(), 1024, 1024)
};

§Algorithm overview

  1. Pattern generation — select combinations of 4 bright centroids; compute 6 pairwise angular separations and normalize into 5 edge ratios (a geometric invariant)
  2. Hash lookup — quantize the edge ratios into a key and probe a precomputed hash table for matching catalog patterns
  3. Attitude estimation — solve Wahba’s problem via SVD to find the rotation from catalog (ICRS) to camera frame
  4. Verification — project nearby catalog stars into the camera frame, count matches, and accept only if the false-positive probability (binomial CDF) is below threshold
  5. Refinement — re-estimate the rotation using all matched star pairs via iterative SVD passes
  6. WCS fit — constrained 3-DOF tangent-plane refinement (rotation angle θ + CRVAL offset) with sigma-clipping, producing FITS-standard WCS output

§Credits

This crate is a Rust implementation of the tetra3 / cedar-solve algorithm:

  • tetra3 — the original Python implementation by Gustav Pettersson at ESA
  • cedar-solve — Steven Rosenthal’s C++/Rust star plate solver, which this implementation closely follows
  • Paper: G. Pettersson, “Tetra3: a fast and robust star identification algorithm,” ESA GNC Conference, 2023

This Rust implementation was developed by Steven Michael with assistance from Claude Code (Anthropic).

Re-exports§

pub use camera_model::CameraModel;
pub use distortion::calibrate_camera;
pub use distortion::CalibrateConfig;
pub use distortion::CalibrateResult;
pub use distortion::Distortion;
pub use distortion::PolynomialDistortion;
pub use distortion::RadialDistortion;
pub use solver::DatabaseProperties;
pub use solver::GenerateDatabaseConfig;
pub use solver::SolveConfig;
pub use solver::SolveResult;
pub use solver::SolveStatus;
pub use solver::SolverDatabase;
pub use aberration::earth_barycentric_velocity;
pub use star::*;
pub use starcatalog::*;

Modules§

aberration
Stellar aberration utilities.
camera_model
Camera intrinsics model: focal length, optical center, parity, and distortion.
distortion
Lens distortion models for correcting optical distortion in star images.
rkyv_nalgebra
rkyv wrappers for nalgebra types that don’t natively support rkyv 0.8.
solver
Star plate solver based on the tetra3/cedar-solve algorithm.
star
starcatalog
Spatial star catalog optimized for fast cone (angular-radius) searches.

Structs§

ArchivedCentroid
An archived Centroid
Centroid
CentroidResolver
The resolver for an archived Centroid

Type Aliases§

Matrix2
Quaternion
Vector3