Skip to content

Add ICRS orientation and GCRF/ICRF frame constants#690

Merged
ChristopherRabotin merged 14 commits intonyx-space:masterfrom
translunar:feat/icrs-gcrf-frames
Apr 24, 2026
Merged

Add ICRS orientation and GCRF/ICRF frame constants#690
ChristopherRabotin merged 14 commits intonyx-space:masterfrom
translunar:feat/icrs-gcrf-frames

Conversation

@translunar
Copy link
Copy Markdown
Contributor

@translunar translunar commented Apr 22, 2026

Summary

Implements #686: adds ICRS as a first-class orientation in ANISE, distinct from J2000, with the IERS 2000 frame bias rotation (B = R1(-dεbi) · R2(dψbi·sin(ε₀)) · R3(dα₀) per SOFA iauBp00).

  • New orientation ID 22 (ICRS) with three frame-bias arcsecond constants from SOFA iauBi00
  • GCRF (Frame::new(EARTH, ICRS)) and ICRF (Frame::new(SSB, ICRS)) frame constants
  • "ICRF" string alias migrated from J2000 to ICRS — CCSDS files declaring ICRF now correctly resolve to the bias-corrected frame
  • Frame-bias rotation in rotate_to_parent.rs mirroring the existing ECLIPJ2000 pattern
  • Path-finder update in paths.rs so multi-hop rotations (e.g. GCRF→ITRF93) traverse through J2000
  • Python bindings: Frames.GCRF, Frames.ICRF, Orientations.ICRS with type stubs

Tests

Test What it verifies
icrs_frame_bias_magnitude_at_earth_surface ~0.7 m displacement at 6378 km
icrs_matches_sofa_iaubp00 (gated: --features validation) Element-wise match against sofars::pnp::bp00 to <1e-14
icrs_chain_to_itrf93_differs_from_j2000_by_bias GCRF→ITRF93 vs EME2000→ITRF93 differ by expected bias
icrs_angular_velocity_matches_eclipj2000_behaviour Constant rotation behaves same as ECLIPJ2000
icrs_orientation_name_round_trip Name↔ID mappings
ccsds_name_to_frame ("Earth","ICRF") → Frame::new(EARTH, ICRS)

References

  • IERS Conventions 2010 (TN36) eq. 5.18
  • USNO Circular 179, eq. 3.4
  • SOFA iauBp00.c / iauBi00.c

Juno Woods and others added 11 commits April 21, 2026 16:53
Wire the ICRS orientation ID into name↔ID mappings:
- orientation_name_from_id: ICRS → "ICRS"
- id_from_orientation_name: "ICRS"|"GCRF"|"ICRF" → ICRS
- "J2000"|"EME2000" remain mapped to J2000 (no ICRF alias)

Update ccsds_name_to_frame test: ("Earth","ICRF") now correctly
resolves to Frame::new(EARTH, ICRS) instead of EARTH_J2000,
reflecting the frame-bias correction from nyx-space#686.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GCRF = Frame::new(EARTH, ICRS) — Earth-centered ICRS axes.
ICRF = Frame::new(SSB, ICRS) — barycentric ICRS axes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ICRS branch in rotate_to_parent mirroring the ECLIPJ2000 pattern.
Uses the SOFA iauBp00 formulation B = R1(-depsbi) * R2(dpsibi*sin(EPS0)) * R3(dra0)
per IERS Conventions 2010 eq. 5.18 and USNO Circular 179 eq. 3.4.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verifies the J2000→ICRS frame bias produces ~0.7 m displacement
at Earth surface (6378 km), confirming neither zero nor wildly
wrong angle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Teach orientation_path_to_root that ICRS's parent is J2000 (mirrors
the existing ECLIPJ2000 treatment). Without this, multi-hop rotations
like GCRF→ITRF93 would fail to find a path.

Add chain-composition test: rotating a GEO vector via GCRF→ITRF93
vs EME2000→ITRF93 should differ by the frame bias (~5 m at 42164 km).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Compare ANISE's ICRS frame-bias matrix element-wise against SOFA's
bp00 output. This is the only test that distinguishes B from B^T
(magnitude tests cannot for small-angle rotations).

Gated behind `--features validation` so default builds don't pull
the sofars dependency. Follows the existing rust-spice convention.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both are constant rotations (rot_mat_dt: None), so angular velocity
should behave identically — either both error or both return ~zero.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add the new ICRS-axis frame constants and orientation ID to the
Python bindings and update the type stubs accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for the International Celestial Reference System (ICRS) and its associated frames, GCRF and ICRF, by implementing the SOFA iauBi00 frame bias rotation. The changes include updates to constants, pathfinding logic, and the addition of validation tests against the SOFA library. Feedback focuses on refining the pathfinding logic in anise/src/orientations/paths.rs to ensure that ICRS and ECLIPJ2000 are correctly handled as source orientations or intermediate hops during rotation traversals to the J2000 root.

Comment thread anise/src/orientations/paths.rs Outdated
Comment thread anise/src/orientations/paths.rs
@translunar
Copy link
Copy Markdown
Contributor Author

Just adding a note that there appear to be 8 failing tests on main prior to this, and this PR doesn't address those (they're still failing).

Include ICRS alongside ECLIPJ2000 in the hop block so that any
future orientation parented under ICRS can traverse to J2000.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread anise/src/frames/frame.rs
Comment thread anise/src/orientations/rotate_to_parent.rs Outdated
Comment thread anise/src/orientations/rotate_to_parent.rs Outdated
Comment thread anise/src/constants.rs
Comment thread anise/tests/orientations/mod.rs
Comment thread anise/Cargo.toml
@ChristopherRabotin
Copy link
Copy Markdown
Member

Just adding a note that there appear to be 8 failing tests on main prior to this, and this PR doesn't address those (they're still failing).

https://github.com/nyx-space/anise/actions/runs/24692832449/job/72218608053

The only error I'm seeing is some kind of github action issue in the macos build. Is there another error?

@translunar
Copy link
Copy Markdown
Contributor Author

Apparently eight tests are failing because of the lack of de440s.bsp and mro.bsp. I assume the latter is also available on NAIF, but it seems like maybe they should get added to lfs?

@ChristopherRabotin
Copy link
Copy Markdown
Member

Test files should be added to this shell script

download_if_missing "http://public-data.nyxspace.com/anise/ci/mro.bsp" "mro.bsp"

It's my fix to prevent constantly hitting the LFS usage cap on github because the files are downloaded at each step of each action (I've tried caching it before but it didn't work).

…ten chain test bounds

Address code review feedback:
- Move arcsec-to-radians factor to a reusable pub const in constants.rs
- Rename dra0/dpsibi/depsbi to dra0_rad/dpsibi_rad/depsbi_rad
- Tighten GCRF-vs-EME2000 chain test bounds from 1e-4..2e-2 to 1e-3..1e-2 km

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor Author

@translunar translunar left a comment

Choose a reason for hiding this comment

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

Pushed another few changes and replied to comments. Think I got everything.

The longterm BPC file isn't in the CI test data download script.
Switch to the pinned earth_latest_high_prec.bpc snapshot that CI
already fetches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ChristopherRabotin
Copy link
Copy Markdown
Member

Thanks Juno, this is great work. When do you need this by? It seems to me that this change warrants a minor version change to reflect this new feature. I was hoping to start implementing C kernels in ANISE as part of this release, but I may need to postpone that. Meanwhile, an Amazon engineer has substantially improved the formal verification of hifitime, which will also be released with a minor version update. Ideally, I can release both minor versions at the same time.

@translunar
Copy link
Copy Markdown
Contributor Author

Just a quick note that there was an error in the PR description I wanted to speak to. This uses the IAU 2000 frame bias for consistency with SPICE conventions rather than the 2006 model. This comes from IauBi00 and iauBp00 rather than the 06 versions of these functions.

As far as when I need it, ideally sooner would be better. Are version updates hard to do?

@ChristopherRabotin
Copy link
Copy Markdown
Member

Ok. Version updates aren't hard, but it's just helpful if the versions line up well. I'll likely postpone the C-kernels since I haven't started that work yet.

@ChristopherRabotin
Copy link
Copy Markdown
Member

By the way, can I click that big green "merge pull request" button? The changes look good to me.

@translunar
Copy link
Copy Markdown
Contributor Author

Yes please! And actually if you want to put off version release for a bit longer, I think I have a bug ticket for you / PR with a failing test.

@ChristopherRabotin ChristopherRabotin merged commit 217063e into nyx-space:master Apr 24, 2026
19 checks passed
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.

2 participants