Skip to content

feat: add non-sidereal tracking for solar system objects#130

Open
dgegen wants to merge 5 commits intoppp-one:mainfrom
dgegen:feature/non-sidereal-tracking
Open

feat: add non-sidereal tracking for solar system objects#130
dgegen wants to merge 5 commits intoppp-one:mainfrom
dgegen:feature/non-sidereal-tracking

Conversation

@dgegen
Copy link
Copy Markdown
Collaborator

@dgegen dgegen commented Mar 20, 2026

Pull Request

Description
Adds non-sidereal (differential) tracking support for solar system objects. A NonSiderealManager 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.

I have locally tested integration with JPL Horizons via astroquery to 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: New NonSiderealManager class encapsulating setup, rate application, re-centering, and cleanup
  • utils.py: Add is_solar_system_body, precompute_ephemeris, compute_nonsidereal_rates_from_interp; cache _SOLAR_SYSTEM_BODIES and _SOLAR_TO_SIDEREAL at module level
  • observatory.py: Integrate NonSiderealManager into the imaging sequence loop with guiding-incompatibility warning and guaranteed rate reset in a finally block
  • action_configs.py: Add nonsidereal_recenter_interval field; update guiding field description; add usage documentation with a Saturn scheduling example
  • tests/test_utils.py: Fix monkeypatch targets for get_body; add full test suite for the three new utility functions

How to Test

  1. Schedule an object action with a solar system body (e.g. "lookup_name": "saturn") and "nonsidereal_recenter_interval": 300
  2. Verify tracking rates are applied at the start of each exposure
  3. Verify the telescope re-slews to the updated ephemeris position every 300 s
  4. Verify that enabling guiding: true alongside non-sidereal tracking logs a warning and disables guiding
  5. Run pytest tests/test_utils.py — all non-sidereal utility tests should pass

Checklist

  • Code follows project style guidelines
  • Tests added/updated
  • Documentation updated (if needed)
  • All checks pass

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 NonSiderealManager to encapsulate ephemeris setup, rate application, periodic re-centering, and cleanup/reset.
  • Extends astra.utils with 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.

Comment thread src/astra/nonsidereal.py Outdated
Comment thread src/astra/nonsidereal.py Outdated
Comment thread src/astra/utils.py Outdated
Comment thread src/astra/observatory.py
Comment thread src/astra/observatory.py Outdated
@dgegen
Copy link
Copy Markdown
Collaborator Author

dgegen commented Mar 23, 2026

Following a discussion with @ppp-one, I've now included the JPL Horizons integration via astroquery that I previously held back.

The implementation raises NotMovingBodyError when a lookup_name can't be resolved as a known solar system body, which triggers a fallback to Horizons for comets and asteroids. This does introduce a network dependency at schedule load time for minor bodies.

For field mode / offline scenarios, the current behaviour is: if the Horizons query fails with anything other than a ConnectionError, it raises NotMovingBodyError and the object is treated as a fixed target (sidereal tracking and lookup). A bare ConnectionError propagates so the operator knows the schedule couldn't be validated. It might be worth to consider a softer fallback (e.g. warn and skip the action rather than abort).

dgegen added 5 commits May 5, 2026 22:56
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
@dgegen dgegen force-pushed the feature/non-sidereal-tracking branch from 08544a6 to 5d39104 Compare May 5, 2026 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Solar system sequence

2 participants