Skip to content

feat(transformations): configurable anchor frame + self-describing compensation result#147

Merged
janickm merged 1 commit into
NVIDIA:mainfrom
janickm:compensator-anchor-frame
Jun 11, 2026
Merged

feat(transformations): configurable anchor frame + self-describing compensation result#147
janickm merged 1 commit into
NVIDIA:mainfrom
janickm:compensator-anchor-frame

Conversation

@janickm

@janickm janickm commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to the reference-timestamp work (#146). Make the motion-compensation anchor frame an explicit parameter and expose the frame IDs in the result so a compensation is fully self-describing.

Changes

  • MotionCompensator.motion_compensate_points / motion_decompensate_points gain anchor_frame_id: str = "world". The anchor is the common frame the per-point transforms are composed through; the default preserves the previous hard-coded "world" behavior. Decompensation must use the same anchor as compensation (documented in both docstrings).
  • MotionCompensationResult now carries:
    • reference_frame_id -- the sensor frame the compensated points are expressed in (equals the sensor_id)
    • anchor_frame_id -- the common anchor frame used to compose the transforms
    • alongside the existing xyz_s_reftime / xyz_e_reftime / reference_timestamp_us.
  • MotionCompensator.from_sensor_rig gains anchor_frame_id: str = "world" and rig_frame_id: str = "rig" so the pose-graph node names are no longer hard-coded.

All existing callers keep the defaults, so behavior is unchanged.

Note on valid anchors

A valid anchor must be a frame the sensor actually moves relative to within the frame -- i.e. the dynamic/global frame, or one related to it by a static transform (e.g. world / world_global). The rig frame is not a valid anchor, because the sensor->rig extrinsic is static, so compensation through it would see no motion. This is reflected in the tests.

Testing

bazel test //ncore/impl/common:test_3_11 \
            //ncore/impl/data/v4:pytest_compat_3_11 \
            //ncore/impl/sensors:pytest_lidar_3_11

New tests:

  • test_result_exposes_frame_ids -- result records the reference (sensor) and anchor frame IDs, including on the empty-input path.
  • test_compensation_independent_of_static_anchor_choice -- anchors related by a static transform (world / world_global) yield identical compensated points; round-trip with the non-default anchor recovers the input.
  • test_from_sensor_rig_custom_frame_names -- from_sensor_rig honors custom anchor/rig node names with a clean compensate/decompensate round-trip.

All of //ncore/... and the affected //tools/... packages build and type-lint cleanly; the existing compensator/compat/lidar tests still pass.

…mpensation result

Follow-up to the reference-timestamp work. Make the common anchor frame an
explicit parameter and expose the frame IDs in the result so a compensation
is fully self-describing.

- `MotionCompensator.motion_compensate_points` / `motion_decompensate_points`
  gain `anchor_frame_id: str = "world"`. The anchor is the common frame the
  per-point transforms are composed through; the default preserves the
  previous hard-coded "world" behavior. Decompensation must use the same
  anchor as compensation (documented).
- `MotionCompensationResult` now carries `reference_frame_id` (the sensor frame
  the compensated points are expressed in, i.e. the sensor_id) and
  `anchor_frame_id`, alongside the existing points and `reference_timestamp_us`.
- `MotionCompensator.from_sensor_rig` gains `anchor_frame_id: str = "world"` and
  `rig_frame_id: str = "rig"` so the pose-graph node names are no longer
  hard-coded. All existing callers keep the defaults, so behavior is unchanged.

Note: a valid anchor must be a frame the sensor moves relative to within the
frame (the dynamic/global frame or one related to it by a static transform).
The rig frame is not a valid anchor because the sensor->rig extrinsic is static.

Tests: result exposes the expected frame IDs (incl. the empty-input path);
compensation is invariant to anchors related by a static transform
(world / world_global); and from_sensor_rig honors custom node names with a
clean compensate/decompensate round-trip.
@copy-pr-bot

copy-pr-bot Bot commented Jun 11, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@janickm janickm marked this pull request as ready for review June 11, 2026 09:12
@janickm

janickm commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

/ok to test a5263b9

@janickm janickm self-assigned this Jun 11, 2026
@janickm janickm enabled auto-merge June 11, 2026 09:16
@janickm janickm added this pull request to the merge queue Jun 11, 2026
Merged via the queue into NVIDIA:main with commit b134328 Jun 11, 2026
5 checks passed
@janickm janickm deleted the compensator-anchor-frame branch June 11, 2026 09:33
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.

1 participant