Skip to main content

zenith: Automated Celestial Navigation

zenith answers one question without GPS: where am I on Earth? Given a photograph of the night sky, an IMU gravity vector, and a UTC timestamp, it returns latitude, longitude, and a rigorous 2-sigma uncertainty ellipse.

The engine is validated end to end against an independent reference implementation (astropy) using the real Yale Bright Star Catalog: position fixes land within 0.1 to 0.2 nautical miles of truth on noise-free synthetic imagery, and within 5 nautical miles under realistic sensor noise (3 arcminutes of star-position error plus IMU tilt noise).

How it works

This is automated celestial navigation: the same idea sailors used with a sextant and star charts for centuries, now done by a computer from a single photograph in a fraction of a second.

Consider the night sky is a ceiling covered in dots, and every dot has a known name and a known place. If you can work out which dots you photographed and which way the camera was pointing, you can work backwards to the one spot on Earth where the sky would look exactly like that. Zenith needs only three things to do it: the photo, which way is down (gravity, from an IMU), and the exact time.

Zenith pipeline
architecture: an attitude subsystem (image, centroids, camera vectors, star
identification, attitude) feeds a position subsystem (direct zenith fix,
altitude sights, Gauss-Newton least squares) that outputs the position fix and
2-sigma ellipse, with external inputs for camera intrinsics, the star
catalogue, UTC, and the refraction model.

It runs in seven steps:

  1. Start with the photo. One raw night-sky frame is all Zenith needs to begin.
  2. Find the dots. Pinpoint each star in the photo to within a fraction of a pixel.
  3. Find a matching triangle. The angles between three stars stay the same however the camera is tilted, so a triangle of dots is enough to search the catalogue of about 9,100 real stars for a candidate match.
  4. Name every dot. Confirm that triangle against the rest of the field. If the field is ambiguous, Zenith refuses to guess and raises an error rather than risk a wrong fix.
  5. Find where the camera pointed. Turn the named stars into the camera's orientation in the sky.
  6. Fix the position, with uncertainty. Gravity tells it which way is straight up, and the star directly overhead is, in effect, your latitude and longitude. That first estimate is then polished and reported with a 2-sigma uncertainty ellipse, "you are within this small patch", all from a single frame, with no prior position and no dead reckoning.
  7. Show it on Earth. The fix lands on one real patch of the globe, the same spot the opening question asked about.

Steps 3 to 5 are the heart of it: the angles between stars stay fixed however the camera is tilted, so a triangle of dots identifies the stars, and a single rotation then recovers where the camera pointed.

Two panels. Left:
three dots forming a triangle with its three side-angles labelled, captioned
'three angles identify which stars they are'. Right: the same rigid triangle
drawn in a camera frame and a catalogue frame, one rotation R apart, captioned
'same rigid triangle, one rotation aligns them'.

For a runnable, illustrated walkthrough of these two steps (with diagrams and animations), see examples/how-it-works.ipynb.

It also works by day. Daytime sky brightness is scattered sunlight, and scattering falls off steeply toward longer wavelengths, so in the short-wave infrared (about 0.9 to 1.7 micron) the sky background drops away while the brightest stars still shine. Zenith ships a separate infrared catalogue (real 2MASS J/H photometry) and a solar-disc detector, so a SWIR camera can fix position in daylight, resolving within about a nautical mile at the validation sites. The Sun itself can be added as an extra sight: a known body needs no identification, only an ephemeris, and it contributes one more line of position that strengthens a star fix or fills in when stars are sparse. See docs/how-it-works.md for the reasoning and docs/algorithms.md for the equations.

The deeper story lives in the docs. For the conceptual walkthrough (why each stage is built the way it is, the arcminute-level accuracy budget, and the refusal properties that make a fix with errors), see docs/how-it-works.md. For the full equations, the formal method names (subpixel centroiding, the k-vector lost-in-space match, Wahba's problem solved by SVD, the Marcq St. Hilaire intercept method), and code references, see docs/algorithms.md. For carrying a fix through motion on a moving platform (the orientation MEKF and the position INS Kalman filter, with the maths and worked examples), see docs/fusion.md. For the camera-mount and optics study (which camera, lens, and catalogue to carry, and what an end-to-end flight reveals that a single frame cannot), see docs/camera-and-optics.md.

Documentation

Start here and read in order; each page builds on the one before.

  1. This README: the public API, the validation results, the browser demo, and the desktop app.
  2. docs/how-it-works.md: the conceptual walkthrough, stage by stage, with the accuracy budget and the refusal properties.
  3. docs/algorithms.md: every equation, with the code excerpt that evaluates it and the embedded catalogue format.
  4. docs/fusion.md: carrying a fix through motion, the orientation MEKF and the position PosKf, with maths and worked examples.
  5. docs/camera-and-optics.md: the camera-mount and optics trade study (which camera, lens, and catalogue to carry).
  6. docs/real-sky-validation.md: the attitude pipeline validated on real night-sky data (the EBS-EKF public dataset), method and caveats.
  7. crates/zenith-autopilot/README.md: plugging the engine into an ArduPilot flight stack, the GPS_INPUT contract, and the live SITL demo.
  8. docs/python-api.md: the full Python API reference.
  9. docs/pipeline-testing.md: running the M0 Pi rig's star-capture-to-fix test yourself (SSH access, daylight-check and exposure-ladder modes).
  10. docs/cube-to-pi-wiring.md: wiring a Cube Orange+ TELEM port to the Raspberry Pi 5 GPIO header (pinouts, board settings, link checks, and the two faults found on the bench).

For runnable walkthroughs see the notebooks under examples/ (quickstart.ipynb, how-it-works.ipynb, camera-system-trade-study.ipynb).

Architecture

Cargo workspaces are used to decouple the main resolver engine from other aspects of the system.

Project structure

zenith/
├── Cargo.toml                  # workspace
├── pyproject.toml              # Python package metadata (maturin)
├── crates/
│   ├── zenith-core/            # pure Rust engine, pixels to fix (MSRV 1.88)
│   ├── zenith-fusion/          # MEKF + PosKf Kalman filters for motion
│   ├── zenith-hal/             # sensor-source traits (camera + IMU) + codec
│   ├── zenith-autopilot/       # ArduPilot companion daemon (GPS_INPUT + MEKF)
│   ├── zenith-drivers/         # real hardware drivers (GenICam/Aravis, V4L2, libcamera)
│   ├── zenith-sim/             # motion/mount/optics simulation study
│   ├── zenith-py/              # PyO3 bindings (lib name: zenith)
│   ├── zenith-wasm/            # wasm-bindgen bindings + scene synthesis
│   └── zenith-desktop/         # native Tauri desktop app (reuses web UI)
├── python/
│   ├── zenith/
│   │   ├── pipeline/           # Polars BSC5 builder + binary writers
│   │   └── simulate/           # astropy sky renderer + demo plots
│   └── tests/                  # bindings, pipeline, simulate, e2e suites
├── scripts/                    # node wasm/globe tests, figure generators, rig-run + demo-frame pipeline scripts
├── web/                        # browser tactical demo (no bundler)
├── packaging/                  # demo bundle README + macOS launcher
├── docs/images/                # rendered demonstration plots
├── data/                       # generated artefacts (gitignored)
└── .github/workflows/ci-cd.yml # fmt + clippy + cargo test + pytest + wasm
Crate / package Role
crates/zenith-core The full runtime path from pixels to position fix. Only dependency: nalgebra.
crates/zenith-fusion The MEKF orientation filter and PosKf position filter that carry a fix through motion on a moving platform (see docs/fusion.md).
crates/zenith-hal Hardware-abstraction layer: sensor-source traits, shared sensor data types, the session record/replay codec, and the two capture interfaces. Cameras: the CameraBackend capture trait, timestamp accuracy classes and the CameraSource adapter. Inertial: the ImuBackend capture trait and the ImuSource adapter, on the session's shared timeline. Plus MergedSource, which merges any number of sources into one time-ordered stream. No engine dependency and no hardware dependency.
crates/zenith-autopilot The companion daemon that makes any stock ArduPilot vehicle navigate on zenith fixes: engine fixes stream out as MAVLink GPS_INPUT, and an onboard orientation MEKF serves the solve a fused up vector through manoeuvres. See its README.
crates/zenith-drivers Every real hardware driver, behind the pure zenith-hal interfaces. Cameras: per-camera calibration files, a backend conformance suite, and feature-gated GenICam (Aravis), V4L2, and libcamera drivers, so any camera plugs in without touching the pipeline. Inertial and GPS: the Sense HAT (LSM9DS1/LSM6DSL) and Cube Orange IMU (MAVLink) drivers, and raw-GPS seed capture for tie-breaking.
crates/zenith-sim The motion, mount, and optics simulation study behind docs/fusion.md and docs/camera-and-optics.md. Study and development only; not shipped in any wheel.
crates/zenith-py PyO3 bindings exposing resolve_fix, Catalog, FixTracker (stateful tie-breaking with set_last_known_position), detect_centroids, covariance_ellipse, and time/frame helpers as the zenith Python module.
crates/zenith-wasm wasm-bindgen bindings and in-engine scene synthesis powering the browser tactical demo.
crates/zenith-desktop Native desktop app: a Tauri wrapper that runs the same engine and browser UI natively over zenith-core. Run with cargo run -p zenith-desktop.
python/zenith/pipeline Offline catalog builder: downloads the real BSC5, parses it with Polars, writes catalog.parquet plus the binary artefacts the engine embeds.
python/zenith/simulate astropy-driven synthetic sky renderer (independent ground truth for testing) and the demonstration plot scripts.

The embedded star catalog

The pipeline produces two compact little-endian artefacts consumed by the Rust core (formats documented in crates/zenith-core/src/catalog.rs):

  • catalog.bin: all ~9,100 BSC5 stars (HR number, magnitude, J2000 RA/Dec, precomputed unit vector), 48 bytes per star.
  • pairs.bin: every pair of bright stars (magnitude 4.5 or brighter, about 30,000 pairs within 30 degrees) sorted by angular separation, ready for binary search. Matching only ever needs bright stars; sight reduction uses the full table.

For daytime SWIR fixes the pipeline also writes catalog_ir.bin and pairs_ir.bin in the identical formats, built from real 2MASS J/H photometry cross-matched to the BSC5, with a brighter pair-index cut (J 4.0 or brighter).

There is no database engine at runtime. Polars does the heavy lifting offline, and the derived-column stage runs through the Polars lazy API, so it can execute on an NVIDIA GPU via the RAPIDS cudf-polars engine (parse(raw, engine="gpu")). At BSC5 scale that is architectural headroom for future Tycho-2 or Gaia subsets rather than a present-day speedup.

Roadmap

Delivered beyond the core engine: the motion-fusion filters and their study (docs/fusion.md), the mount and optics trade study (docs/camera-and-optics.md), real-sky attitude validation (docs/real-sky-validation.md), the ArduPilot integration (SITL-proven, see Navigate on it), a camera-agnostic hardware seam (any camera satisfying the zenith-hal backend contract plugs into the daemon, with GenICam and V4L2 drivers proven against protocol-true test rigs in CI, and a third, libcamera, driver proven on real Pi rig hardware, 5/5 conformance on a mono IMX296), and the first real-photon position fixes: frames from the public LenghuSky-8 all-sky dataset resolve to 35-67 nm of the surveyed site on two independent nights (93 and 110 matched stars), via mesh-background detection and a calibrated degree-9 fisheye model (issues #39, #40), and last-known-position tie-breaking: an ambiguous two-candidate identification is now resolved by a tracked history (the last healthy fix, or an autopilot GPS seed) instead of always refusing, while the untracked path still raises MatchAmbiguous.

In progress and next, tracked as GitHub issues:

  • Real-sky position validation from a surveyed ground site on our own hardware, closing the loop from camera to fix end to end (#26).
  • Replacing the assumed per-star measurement noise with a value measured on real hardware, and tightening the reported uncertainty (#36).
  • The physical deployment path: companion-computer link, mounting, and power on a real airframe (#35).
  • Celestial yaw injection (a drift-free, magnetometer-free heading) and a real camera/IMU sensor backend (#31).

Further out: cloud-masked degraded-sky operation, and a Gaia-scale catalogue with quad-code hashing for the lost-in-space match.

Quickstart

Install and use

The distribution is zenith-fixer; the import is zenith. The star catalogue ships inside the wheel, so a fix needs no download or build step.

pip install "zenith-fixer[viz]"   # [viz] adds matplotlib, plotly and astropy for the plots
import zenith

catalog = zenith.bundled_catalog()  # bundled with the wheel; no external files
fix = zenith.resolve_fix(
    image,                      # numpy uint16 array (uint8 also accepted), shape (height, width)
    1500.0, 512.0, 512.0,       # focal length and principal point, pixels
    (ux, uy, uz),               # unit vector toward the zenith, camera frame
    (2026, 1, 15, 2, 0, 0.0),   # UTC tuple, or a timezone-aware datetime
    catalog,
    sigma_arcmin=1.0,           # assumed 1-sigma altitude noise; defaults to half a pixel
)
print(fix.latitude_deg, fix.longitude_deg)
print(fix.ellipse_2sigma_nm)    # (semi-major nm, semi-minor nm, orientation deg)
print(fix.matched_hr_ids)       # which catalog stars were identified

The full Python API is documented in docs/python-api.md. For an end-to-end walkthrough with plots (synthesised sky, all-sky skymap, an interactive globe of the fix, and the uncertainty ellipse), see examples/quickstart.ipynb. For a conceptual companion that explains how the matcher names the dots and how Wahba's problem recovers the camera's orientation (with diagrams and animations), see examples/how-it-works.ipynb. For the executive trade study that recommends what camera and mount to carry (the mount and optics findings, a hardware shortlist, and what is ready for a field test), see examples/camera-system-trade-study.ipynb.

Develop from source

Requirements: Rust 1.88+, Python 3.10+, uv.

uv sync   # builds the extension and installs the full dev toolchain
# after changing Rust, rebuild the extension into the venv:
.venv/bin/maturin develop --manifest-path crates/zenith-py/Cargo.toml

# the catalogue is vendored under python/zenith/data; to rebuild it from the
# real BSC5/2MASS sources and refresh that copy:
make pkg-data

# run the tests
cargo test --workspace --exclude zenith-desktop
.venv/bin/pytest python/tests/

Validation

The synthetic test harness places stars with astropy (its own precession, aberration, and refraction models), renders them onto a sensor frame with Gaussian point-spread functions, and perturbs the IMU vector. Because the generator shares no transform code with the engine, the acceptance tests are a genuine cross-implementation check:

Scenario Requirement Achieved
Noise-free, 3 sites (35N 40W, 34S 18E, 60N 11E) < 0.5 nm 0.10 to 0.20 nm
3 arcmin star noise + 1 arcmin IMU tilt < 5 nm passes at all sites
Covariance calibration (Mahalanobis 2σ, ≥100 realisations) 0.70 to 0.97 inside ~0.92 inside (ideal 0.865)

The covariance-calibration row is a true elliptical (Mahalanobis) containment test: each noisy fix's offset from truth is projected onto the principal axes of its own 2-sigma ellipse and counted inside when it lands within the ellipse, not within a circle of the semi-major radius. For a well-calibrated 2D Gaussian the expected containment is 1 - exp(-2) = 0.865; the harness measures about 0.92 over at least 100 deterministic realisations (the covariance runs slightly conservative), and the test asserts the fraction stays in the band 0.70 to 0.97.

The matcher's refusal property is tested directly: a congruent star pattern duplicated on the opposite side of the sky must raise MatchAmbiguous rather than guess, while catalogued close doubles (Alnitak, Mintaka) must not trigger false ambiguity.

Real photons, not just synthetic ones. The attitude pipeline (centroiding, star identification, Wahba attitude) is additionally validated on real night-sky data: run blind over all 15 science tracks of the public EBS-EKF release with an independent per-collect lens calibration, zenith agrees with the authors' astrometry.net solutions to a median boresight of 73 arcseconds, in the neighbourhood of their own ~100 arcsecond headline. See docs/real-sky-validation.md for the method, the gating, and the caveats. This validates attitude only; the full real-sky lat/lon campaign is tracked as issue #26.

Navigate on it: ArduPilot integration

The engine plugs into a stock ArduPilot flight stack with no firmware change: a companion daemon (zenith-autopilot) resolves fixes from a sensor stream and sends them as MAVLink GPS_INPUT, so the autopilot's EKF3 fuses starlight exactly as it would a GNSS receiver. This is proven live against ArduPilot SITL, captured output:

STATUS: GPS 1: detected MAV
STATUS: EKF3 IMU0 origin set
STATUS: EKF3 IMU0 is using GPS
STATUS: EKF3 IMU1 is using GPS
engine fixes produced and sent: 264
test engine_fixes_drive_sitl_to_convergence ... ok

Every fix carries its own solve-derived 1-sigma accuracy in GPS_INPUT.horiz_accuracy, so EKF3 weights celestial fixes honestly, and a refused frame sends nothing (the EKF coasts, as through a GPS dropout). An onboard orientation MEKF fuses gyro samples with accepted star fixes to keep the solve's up vector honest through manoeuvres, behind conservative trust gates. The daemon compiles to a single static aarch64-musl binary (~2.5 MB stripped, star catalogue embedded) that drops onto a Raspberry Pi or i.MX class companion computer. Demo recipe, SITL parameters, and the full contract: crates/zenith-autopilot/README.md.

Demonstration plots

Generate with .venv/bin/python -m zenith.simulate.covariance_plot and .venv/bin/python -m zenith.simulate.zero_crossing.

Sight geometry drives uncertainty. Two stars separated by only 30 degrees of azimuth give nearly parallel lines of position; the 2-sigma ellipse (computed by the Rust engine, not re-derived in Python) stretches across the weakly constrained direction:

Uncertainty ellipse for a 30 degree sight separation

Shoot on the roll. At sea the camera cannot be stabilised, but it can be triggered. Sampling the IMU at high rate and firing the shutter as the hull rolls through zero removes the platform tilt from the measurement; the zero-crossing fixes cluster on the true position while randomly timed exposures smear with the roll angle:

Zero-crossing trigger strategy versus random triggering

Browser demo

The Zenith browser tactical demo: synthesised sky, tactical fix, and globe

The engine compiles to WebAssembly unchanged and ships with a fully client-side tactical display: pick a position, time, and noise level; the page synthesises the night sky that would be photographed there from the real BSC5 catalog, identifies the stars, and resolves the fix in the browser. No server-side computation is involved. Alongside the sky view, a 3D orthographic globe panel renders real Natural Earth coastlines that you can drag to rotate, with a pulsing pinpoint that recentres on every resolved fix.

The demo defaults to the fisheye all-sky lens; the LENS toggle also offers PINHOLE, and the projection is selectable from the fisheye_fov_deg parameter on resolve_fix in Python and on the WASM bindings. An all-sky field spreads the stars across the whole sky, which strengthens the fix geometry and yields a noticeably tighter uncertainty ellipse on a noiseless single frame (the dilution-of-precision picture), and it gives the wide field of view a daytime fix needs, at the cost of lower per-star angular resolution. At a realistic 16-bit sensor depth the two lenses fix equally well through real motion and centroiding noise, so that single-frame star-spread edge does not open a measurable end-to-end accuracy gap. An earlier 8-bit render had made the pinhole look the more precise lens, but that was a dynamic-range artefact (the 8-bit sensor saturated the bright stars and buried the faint ones), corrected once the study was regenerated at the depth a real star camera delivers; see camera-and-optics.md (sub-project G). The demo uses the ideal equidistant projection; a real fisheye lens uses the calibrated degree-9 distortion model (k1..k4 on resolve_fix), which is what the LenghuSky-8 real-photon fixes required.

Real recorded frames

The SOURCE control switches the page off the synthesised sky and onto real photographs. RIG (PURLEY) is a night on this project's own Pi rig: two sessions of 16-bit exposures through a calibrated 130-degree lens, all twelve of which the offline pipeline fixed. Measured from the fixes the manifest archives, the twelve run from 174 m to 2.5 km off the surveyed site, a median of 0.7 nm; the six frames of the later session all land inside 750 m, and the six of the earlier one between 1.8 and 2.5 km. LENGHU ALL-SKY is the public LenghuSky-8 all-sky dataset. Nothing is replayed: the page decodes the PNG, hands the pixels to the same WebAssembly engine, and solves them in the browser, so the readout's SOLVE TIME is a real measurement and its REFERENCE line is the browser's fix compared against the one this repository's offline solver archived for that frame. The frames are exported pre-masked (trees and rooflines removed) and the manifest beside them carries the session's lens calibration, each exposure's UTC epoch and zenith vector, and the solver settings, because a real lens and a real star field need settings the synthetic demo never has to state. Two faint rings, at 30 and 60 degrees from the zenith, are drawn over each frame through that session's own calibrated lens: the rig frames are a rectangular crop of a fisheye whose image circle is wider than the sensor, and without them the picture reads as an ordinary shot of a small patch of sky rather than the 130-degree field it is. How the rig frames were captured, and what the rig is, are in pipeline-testing.md; the manifests and one sample frame per source are committed, and scripts/pipeline/prepare_demo_frames.py regenerates the full sessions from the raw captures.

The Lenghu preset resolves 30 to 46 nm from the published site, and that offset is a systematic rather than scatter: the fixes land consistently west of the site, by a longitude bias equivalent to a clock error of 149 to 232 s, which is that dataset's own recorded timing limitation and not a property of the solver. The rig frames carry the camera's own exposure stamps, and the later of the two sessions shows nothing on that scale: its east-west component runs from 223 m west to 494 m east, at most a second or two of clock. The earlier session does show a bias of the same shape, two orders of magnitude smaller than the Lenghu one but consistent across all six frames: every fix sits east of the site, by 1836 to 2431 m, while the north components scatter around zero. That is 6.4 to 8.4 s of clock on a run whose exposures were 8 s apart, so the exposure timestamps are the first suspect rather than the optics. It is an open question, not a property of the dataset the way the Lenghu offset is, and the next rig run is set up to test it directly by varying the recorded epoch.

UPLOAD YOUR OWN solves a frame you supply, and it will not solve one without the metadata that pixels do not carry: the exposure instant in UTC, the focal length and principal point in pixels, the fisheye field of view if the lens is one, and the up direction at the moment of exposure. SOLVE UPLOAD stays disabled until all of them are present. The conventions are the engine's own, the same ones resolve_fix documents: focal length and principal point in pixels of the frame as supplied, and the up vector expressed in the camera frame (0, 0, 1 when the camera points at the zenith), not in any world frame. Metadata that is wrong but plausible is answered with a refusal rather than a warning, because a lens or an up vector that does not describe the picture puts the stars where no catalogue pattern matches them, and the engine declines to claim a position instead of returning a confident wrong one.

Both presets are held to their archived fixes by two checks. The engine half runs headlessly against the committed samples, and the page half drives the real browser:

node scripts/web/real_frames_smoke.mjs   # both samples through the wasm engine
make test-browser                    # the page itself, in headless Chrome

The browser check needs Chrome (it looks for puppeteer where npx leaves it) and skips with a printed reason where it cannot launch one; the engine check needs nothing beyond the checkout and the wasm build.

Run it

A Makefile wraps the build and serve steps. With the toolchain installed (see Quickstart):

make serve
# then open http://localhost:8123/web/

make serve rebuilds the WebAssembly package and the catalog artefacts when they are missing, then serves the repository root. In the page, RESOLVE FIX runs a fix, RANDOM SKY picks a random position and time, and the LENS toggle switches between the pinhole and fisheye all-sky models.

The equivalent manual steps:

.venv/bin/python -m zenith.pipeline   # catalog + coastline artefacts (one-time)
wasm-pack build crates/zenith-wasm --target web --out-dir ../../web/pkg
.venv/bin/python -m http.server 8123  # then visit http://localhost:8123/web/

Share it

To give the demo to someone with no toolchain, package it into one self-contained zip:

make bundle
# writes dist/zenith-demo.zip

The zip holds the web app, the compiled WebAssembly engine, the real catalog and coastline data, a plain-English README, and a double-click launcher for macOS. The recipient unzips it and runs a local static server (the bundled instructions cover macOS, Linux, and Windows); nothing is installed and nothing leaves their machine. Because the demo is fully static and client-side, it can equally be hosted on any static host (GitHub Pages, Netlify) and shared as a link; the host only needs to serve .wasm with the application/wasm MIME type, which those services do by default.

The same engine path is exercised headlessly by the smoke test:

make test          # full suite, including the wasm smoke test
# or just the wasm smoke test:
wasm-pack build crates/zenith-wasm --target nodejs --out-dir ../../build/wasm-node
node scripts/web/wasm_smoke.mjs

References

  • Yale Bright Star Catalogue, 5th revised edition: http://tdc-www.harvard.edu/catalogs/bsc5.html
  • Bennett, G. G. (1982). The calculation of astronomical refraction in marine navigation. Journal of Navigation, 35(2).
  • Markley, F. L. (1988). Attitude determination using vector observations and the singular value decomposition. Journal of the Astronautical Sciences, 36(3).
  • Mortari, D. et al. (2004). The pyramid star identification technique. Navigation, 51(3).
  • RAPIDS cuDF Polars GPU engine: https://docs.rapids.ai/api/cudf/stable/cudf_polars/

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

zenith_fixer-0.20.0-cp310-abi3-win_amd64.whl (9.7 MB view details)

Uploaded CPython 3.10+Windows x86-64

zenith_fixer-0.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (9.9 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

zenith_fixer-0.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (9.9 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

zenith_fixer-0.20.0-cp310-abi3-macosx_11_0_arm64.whl (9.8 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

zenith_fixer-0.20.0-cp310-abi3-macosx_10_12_x86_64.whl (9.8 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file zenith_fixer-0.20.0-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for zenith_fixer-0.20.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 5ee164f9af36dd699f9d287460d1ae74ac2f15a0810b0b2c1f233da33fd9d248
MD5 5c6ffbb0c1b8473e00424e62e75c344c
BLAKE2b-256 40f8a5e031c9788b43c67b5ca2e296f2cad6aea6a85b65e6813d379f9ff9f7eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for zenith_fixer-0.20.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on tallamjr/zenith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zenith_fixer-0.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for zenith_fixer-0.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 370720a2d352248a140f24b89d7b835b4934f82de49cc44c9fbcd0bb4967aa02
MD5 d6b903cee4dd4c2e007f37b38cc24acf
BLAKE2b-256 85d06b7aa8eae7c1a7b95843fe4be8f719a4b0b49b67a49c28a84fe2cd218544

See more details on using hashes here.

Provenance

The following attestation bundles were made for zenith_fixer-0.20.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on tallamjr/zenith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zenith_fixer-0.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for zenith_fixer-0.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 3d43f2f9ab0e096bda94fcefc5b2f4d5af5f2afdb4582b35cb01cde265093cca
MD5 454b1d64134025c0de6c4e2de3ee561a
BLAKE2b-256 15e39997db820afcf1514c44d6db0a3b37063e8833c532f07e4f5c4dab5c6a9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for zenith_fixer-0.20.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on tallamjr/zenith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zenith_fixer-0.20.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for zenith_fixer-0.20.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 213925f7e6ed888b5f27034cfecf7f240fd8a479e1b88053664dfdd40b87f1bb
MD5 9864657073e43108634fbf9a83895046
BLAKE2b-256 29a230a80b2d5d833ebbaffd807272b8889b4fd671b431030261e4a771a17fcf

See more details on using hashes here.

Provenance

The following attestation bundles were made for zenith_fixer-0.20.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on tallamjr/zenith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zenith_fixer-0.20.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for zenith_fixer-0.20.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b1c700e5500757079ed3b32e715fac074357b162b6a979e6842393b7a97e99b3
MD5 a69e2d2a1a3de06bca0a192be8d3c4fa
BLAKE2b-256 2424188453e73a9d2ec5fdfa4386fc3a337b06ecef8b6f4bd1e2ba73487bd1b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for zenith_fixer-0.20.0-cp310-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on tallamjr/zenith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.20.0 This release

5 files

0.19.0

5 files

0.18.0

5 files

0.17.0

5 files

0.16.0

5 files

0.14.0

5 files

0.13.0

5 files

0.12.0

5 files

0.11.0

5 files

0.10.0

5 files

0.9.1

5 files

0.9.0

5 files

0.8.1

5 files

0.8.0

5 files

0.7.0

5 files

0.6.0

5 files

0.5.0

5 files

0.4.0

5 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page