Add binary PCK orientation kernel support#80
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds first-class support for binary PCK (DAF/PCK) orientation kernels alongside existing SPK support, exposing Euler-angle orientation (+ optional rates) and a reference→body rotation matrix API, while also improving Chebyshev evaluation performance and fixing batched differentiation correctness.
Changes:
- Introduce
Ephem::PCKplus orientation segment/group types to readDAF/PCKtype-2 orientation kernels and queryangles_at,orientation_at, andmatrix_at. - Refactor Chebyshev type-2 segment evaluation into shared machinery and add a fused value+derivative evaluator for improved performance.
- Add segment grouping (SPK center/target, PCK body) to route queries across time-split segments; extend CLI/Excerpt/Download/Docs/Benchmarks and add extensive specs.
Reviewed changes
Copilot reviewed 35 out of 37 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| spec/support/test_spk_helper.rb | Add binary PCK fixture path helpers for specs. |
| spec/ephem/spk_spec.rb | Ensure SPK rejects PCK files with a helpful error. |
| spec/ephem/segments/segment_spec.rb | Regression test for correct pairing of array times with velocities. |
| spec/ephem/segments/segment_group_spec.rb | New tests for routing/group behavior for position + orientation groups. |
| spec/ephem/segments/orientation_segment_spec.rb | New unit tests for OrientationSegment API and behavior. |
| spec/ephem/pck_spec.rb | End-to-end PCK open/query/routing and accuracy vs jplephem reference. |
| spec/ephem/io/daf_spec.rb | New tests for DAF file type detection (SPK vs PCK). |
| spec/ephem/download_spec.rb | Add coverage for downloading NAIF .bpc kernels. |
| spec/ephem/core/rotation_spec.rb | Add tests for rotation matrix helpers (passive convention). |
| spec/ephem/core/orientation_spec.rb | Add tests for Orientation value object, rates, matrix composition. |
| spec/ephem/computation/chebyshev_polynomial_spec.rb | Add tests for fused evaluate_with_derivative. |
| spec/ephem/cli_spec.rb | Update help text expectation + add PCK excerpt/open-kernel tests. |
| README.md | Document binary PCK orientation kernel usage and matrix application. |
| lib/ephem/tasks/validate_accuracy.rb | Correct velocity unit label to km/day. |
| lib/ephem/spk.rb | Reject PCK in SPK.open; use Registry + PositionGroup wrapping for split segments. |
| lib/ephem/segments/segment.rb | Move type-2 evaluation into shared module; register SPK types via Registry. |
| lib/ephem/segments/segment_group.rb | New base routing class for multi-segment keys (batch + scalar). |
| lib/ephem/segments/registry.rb | Replace SPK-only registry with kind-aware registry (spk/pck). |
| lib/ephem/segments/position_group.rb | New group wrapper routing position/state queries across segments. |
| lib/ephem/segments/orientation_source.rb | Shared “reject position/state APIs” mixin for orientation sources. |
| lib/ephem/segments/orientation_segment.rb | New PCK type-2 orientation segment (angles/rates/matrix). |
| lib/ephem/segments/orientation_group.rb | New group wrapper routing orientation queries across segments. |
| lib/ephem/segments/chebyshev_type2.rb | Shared loader/evaluator for DAF type-2 Chebyshev segments + fused eval use. |
| lib/ephem/segments/base_segment.rb | Add start_jd/end_jd, covers?, and descriptor parsing hook for PCK. |
| lib/ephem/pck.rb | New Ephem::PCK kernel reader, grouping by body, excerpt support. |
| lib/ephem/io/daf.rb | Add file_type detection for SPK vs PCK (including legacy fallback). |
| lib/ephem/excerpt.rb | Generalize excerpting to SPK or PCK and reopen matching kernel type. |
| lib/ephem/download.rb | Add NAIF PCK download support and include .bpc in supported kernels. |
| lib/ephem/core/rotation.rb | New kernel-agnostic rotation matrix helpers (about_*, multiply, apply). |
| lib/ephem/core/orientation.rb | New Orientation value object with optional rates and 3-1-3 matrix composition. |
| lib/ephem/computation/chebyshev_polynomial.rb | Add fused value+derivative evaluation for performance. |
| lib/ephem/cli.rb | Update excerpt CLI to auto-detect SPK vs PCK and add open_kernel. |
| lib/ephem.rb | Wire new core + segment + kernel files into the main require graph. |
| CHANGELOG.md | Document 0.5.0 features/improvements including PCK support and perf/bug fixes. |
| benchmarks/run.rb | Add benchmark coverage for fused evaluator and PCK orientation queries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Completes the binary PCK (DAF/PCK) orientation work on top of the draft. - Add Core::Rotation (kernel-agnostic 3x3 helpers) and Orientation#to_matrix / OrientationSegment#matrix_at, centralizing the 3-1-3 (Z-X-Z), reference->body convention where the kernel knowledge lives. - Route queries to the covering segment when a body/pair spans multiple time intervals (Position/OrientationGroup via SegmentGroup.wrap), with zero overhead for the common single-segment case. - Share the compute/compute_and_differentiate rejection across orientation sources (Segments::OrientationSource). - Excerpt, the excerpt CLI, and Download now handle binary PCK; kernel kind is auto-detected. - Fix compute_and_differentiate returning mismatched velocities for an array of times; document the velocity/rate unit as km/day (rad/day). - Tests: Orientation, Rotation, OrientationSegment, group routing, PCK, plus committed .bpc fixtures (2000-2030 accuracy gate + a boundary excerpt exercising real multi-segment routing). Validated against jplephem (SPK output unchanged, PCK angles exact).
State queries previously ran two full Clenshaw passes over the same coefficients: one for position (evaluate) and one for velocity (evaluate_derivative). Profiling showed those two passes were ~80% of compute_and_differentiate. Add ChebyshevPolynomial.evaluate_with_derivative, which fuses the value and derivative recurrences into one loop so the coefficient fetch and loop control are shared. The arithmetic of each recurrence is unchanged, so results are bit-for-bit identical to calling the two methods separately (verified across real and random coefficients; SPK position and velocity still match jplephem exactly). generate_single now uses it, speeding up every state/orientation query (compute_and_differentiate, state_at, orientation_at): ~13% faster for scalar state queries; the corrected batch path is now faster than it was before the array-velocity fix.
Merged
rhannequin
added a commit
that referenced
this pull request
Jun 22, 2026
## [0.5.0] - 2026-06-23 ### Features - Read binary PCK (`DAF/PCK`) orientation kernels via `Ephem::PCK`, exposing a body's Euler angles and rates over time (`angles_at`, `orientation_at`), the foundation for DE440-grade lunar libration ([#76], [#80]) - Add `Ephem::Core::Orientation` (Euler angles + optional rates) and `Ephem::Core::Rotation` (kernel-agnostic rotation-matrix helpers), plus `Orientation#to_matrix` / `OrientationSegment#matrix_at` for the built-in 3-1-3 (Z-X-Z) reference→body convention - Excerpt and the `excerpt` CLI now support binary PCK kernels, detecting the kernel kind automatically - Download binary PCK lunar orientation kernels from NAIF via `Ephem::Download` - Add `#inspect` and `#to_s` to `State` for easier debugging ([#67]) ### Improvements - Route queries to the covering segment when a body/pair spans multiple time-split segments (SPK and PCK), with no overhead for single-segment keys - Share the type-2 Chebyshev machinery between SPK and PCK segments - Evaluate position and velocity in a single Chebyshev pass (`ChebyshevPolynomial.evaluate_with_derivative`), speeding up every state / orientation query (`compute_and_differentiate`, `state_at`, `orientation_at`) with bit-for-bit identical results - Correct the documented velocity unit to km/day (the actual, validated value) - Remove the `numo-narray` dependency ([#65]) - Skip derivative evaluation in `Segment#compute` ([#57]) - Hoist loop-invariant `t2` computation in Chebyshev evaluation ([#58]) - Cache the `RecordParser` instance in `SummaryManager` ([#63]) - Eliminate a redundant `read_record` call in `SummaryManager` ([#62]) - Replace duplicated endianness format lookups with shared constants ([#64]) - Replace `instance_variable_get` with proper `attr_reader`s in `Excerpt` ([#66]) - Use separate error margins for position and velocity validation ([#61]) - Add a comprehensive benchmark suite ([#68]) - Upgrade default Ruby to 4.0.5 ([#81]) - Match SPICE last-loaded-wins precedence for overlapping segments ([#83]) - Add a dedicated spec for the shared type-2 Chebyshev evaluation ([#84]) - Bump standard from 1.50.0 to 1.55.0 by @dependabot ([#45], [#46], [#56], [#78]) - Bump actions/checkout from 4 to 7 by @dependabot ([#44], [#52], [#79]) - Bump rake from 13.3.0 to 13.4.2 by @dependabot ([#48], [#73]) - Bump zlib from 3.2.1 to 3.2.3 by @dependabot ([#49], [#70]) - Bump rspec from 3.13.1 to 3.13.2 by @dependabot ([#47]) - Bump parallel from 1.27.0 to 1.28.0 by @dependabot ([#71]) - Bump benchmark-ips from 2.14.0 to 2.15.1 by @dependabot ([#75]) - Bump json from 2.18.1 to 2.19.2 by @dependabot ([#77]) ### Bug fixes - Fix `compute_and_differentiate` returning mismatched velocities for an array of times - Fix precision loss in `time_to_seconds` for dates far from J2000 ([#60]) [#44]: #44 [#45]: #45 [#46]: #46 [#47]: #47 [#48]: #48 [#49]: #49 [#52]: #52 [#56]: #56 [#57]: #57 [#58]: #58 [#60]: #60 [#61]: #61 [#62]: #62 [#63]: #63 [#64]: #64 [#65]: #65 [#66]: #66 [#67]: #67 [#68]: #68 [#70]: #70 [#71]: #71 [#73]: #73 [#75]: #75 [#76]: #76 [#77]: #77 [#78]: #78 [#79]: #79 [#80]: #80 [#81]: #81 [#83]: #83 [#84]: #84 **Full Changelog**: v0.4.1...v0.5.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds support for reading binary PCK (
DAF/PCK) orientation kernels, a body frame's orientation over time as Euler angles.Notable
state_at/orientation_at, bit-identical results.compute_and_differentiatewith an array of times returned wrong velocities; now correct..bpctoo.Fixes #76