feat: add non-sidereal tracking for solar system objects#130
feat: add non-sidereal tracking for solar system objects#130dgegen wants to merge 5 commits intoppp-one:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds non-sidereal (differential) tracking support aimed at enabling solar system object imaging by precomputing ephemerides and applying ASCOM RA/Dec tracking rates during sequences, with optional periodic re-centering slews.
Changes:
- Introduces
NonSiderealManagerto encapsulate ephemeris setup, rate application, periodic re-centering, and cleanup/reset. - Extends
astra.utilswith solar-system body detection, ephemeris precomputation, and nonsidereal rate computation from interpolators. - Integrates non-sidereal tracking into the main imaging sequence loop, including guiding incompatibility handling and cleanup in
finally.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/astra/nonsidereal.py |
New manager implementing nonsidereal tracking workflow for a sequence. |
src/astra/utils.py |
Adds helpers for solar-system body lookup, ephemeris interpolation, and rate computation. |
src/astra/observatory.py |
Wires the manager into image_sequence (initial rates, re-centering, cleanup/reset). |
src/astra/action_configs.py |
Adds nonsidereal_recenter_interval config field and documents usage. |
tests/test_utils.py |
Updates get_body monkeypatch target and adds tests for new utils helpers. |
uv.lock |
Lockfile change (greenlet wheel entry adjustment). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Following a discussion with @ppp-one, I've now included the JPL Horizons integration via astroquery that I previously held back. The implementation raises For field mode / offline scenarios, the current behaviour is: if the Horizons query fails with anything other than a |
Pre-computes a cubic-interpolated ephemeris at sequence start so that ASCOM RightAscensionRate/DeclinationRate can be refreshed each exposure without repeated get_body() calls. Periodic re-centering slews correct long-term drift. Guiding is automatically disabled when non-sidereal tracking is active. - utils: add is_solar_system_body, precompute_ephemeris, compute_nonsidereal_rates_from_interp; cache _SOLAR_SYSTEM_BODIES and _SOLAR_TO_SIDEREAL at module level - nonsidereal: new NonSiderealManager class encapsulating setup, rate application, re-centering, and cleanup - observatory: integrate NonSiderealManager into the imaging sequence loop with guiding-incompatibility warning and guaranteed rate reset in a finally block - action_configs: add nonsidereal_recenter_interval field and update guiding field description - tests: fix monkeypatch targets for get_body; add full test suite for the three new utility functions
- Future-proof logic selecting non-sidereal tracking - Add updated uv.lock file
- Activate NonSiderealManager on lookup_name alone; recenter_interval=0 now means "track without periodic re-slews" rather than "disabled" - Use np.unwrap for continuous RA interpolation to avoid discontinuities at the 0°/360° boundary - Re-apply tracking rates after a pointing correction in the exposure loop - Add test_nonsidereal_object_action: verifies a Mars sequence completes, takes images, and resets RA/Dec rates on teardown - Add set_location_for_body_visibility helper to position the simulator at the target's meridian so the visibility check passes at any time - Fix action config: nonsidereal_object test case uses action_type=object with both object and lookup_name keys, allowing create_schedule_data to support an action_type override independent of the config key name
Move ephemeris computation from sequence start (NonSiderealManager._setup) to schedule validation (ObjectActionConfig._resolve_lookup_name), so the interpolators are built once when the schedule is loaded rather than re-computed at runtime. Key changes: - Add NotMovingBodyError to distinguish solar system / minor bodies from fixed targets in precompute_ephemeris - Extend precompute_ephemeris to query JPL Horizons via astroquery for comets and asteroids not in astropy's built-in ephemeris - Store _nonsidereal flag and interpolators as private fields on ObjectActionConfig; NonSiderealManager reads them directly instead of repeating network calls - Remove obs_location parameter from NonSiderealManager (no longer needed at runtime) - Add astroquery>=0.4.11 dependency - Add unit tests for NonSiderealManager and a network-marked integration test for minor-body ephemeris lookup
08544a6 to
5d39104
Compare
Pull Request
Description
Adds non-sidereal (differential) tracking support for solar system objects. A
NonSiderealManagerpre-computes a cubic-interpolated ephemeris at sequence start so that ASCOMRightAscensionRate/DeclinationRatecan be refreshed each exposure without repeatedget_body()calls. Periodic re-centering slews correct long-term drift.I have locally tested integration with JPL Horizons via
astroqueryto allow the tracking of comets and asteroids. However, to maintain Astra’s "Offline-First" philosophy and avoid mandatory network dependencies, I have not yet included this in the current PR. That said, I am happy to do so following a discussion on Astra’s connectivity requirements and how to handle offline 'field mode' scenarios for minor body lookups gracefully.Let me know what you think!
Related Issue
Closes #91
Changes Made
nonsidereal.py: NewNonSiderealManagerclass encapsulating setup, rate application, re-centering, and cleanuputils.py: Addis_solar_system_body,precompute_ephemeris,compute_nonsidereal_rates_from_interp; cache_SOLAR_SYSTEM_BODIESand_SOLAR_TO_SIDEREALat module levelobservatory.py: IntegrateNonSiderealManagerinto the imaging sequence loop with guiding-incompatibility warning and guaranteed rate reset in afinallyblockaction_configs.py: Addnonsidereal_recenter_intervalfield; updateguidingfield description; add usage documentation with a Saturn scheduling exampletests/test_utils.py: Fix monkeypatch targets forget_body; add full test suite for the three new utility functionsHow to Test
objectaction with a solar system body (e.g."lookup_name": "saturn") and"nonsidereal_recenter_interval": 300guiding: truealongside non-sidereal tracking logs a warning and disables guidingpytest tests/test_utils.py— all non-sidereal utility tests should passChecklist