Skip to content

feat(viz): LiDAR sensor mount offset - #84

Merged
WomB0ComB0 merged 2 commits into
mainfrom
feat/lidar-mount-offset
Apr 29, 2026
Merged

WomB0ComB0 merged 2 commits into
mainfrom
feat/lidar-mount-offset

Conversation

@WomB0ComB0

@WomB0ComB0 WomB0ComB0 commented Apr 29, 2026 •

Copy link
Copy Markdown
Member

Summary

LidarScan.scan(origin, rot?, mountOffset?) now accepts an optional drone-local mount offset (e.g. [0, 0.5, 0] for a sensor on a 0.5 m mast). The offset is rotated into world space by rot and added to origin to produce the actual scan origin.

Mechanics

  • Hoists the q→3x3 rotation matrix outside the existing per-ray loop so it can be reused for both the mount-offset transform and the direction rotation. No new compute cost on the scan side — the matrix already needed to exist; offset application is one matrix-vector multiply per scan.
  • Hit positions now derive from this._origin (the post-offset scan origin) rather than the raw origin parameter — without this, a mast-mounted sensor would report hits as if rays started at the drone center but ended at the mast tip.
  • Backward-compatible. Existing effects.ts:_updateLidar keeps passing two args; mountOffset defaults to undefined and the bare drone-origin path stays bit-identical to PR feat(viz): per-drone LiDAR scans #80.

Tests

Three new cases in client/__tests__/lidar.test.ts:

  • World-axis-aligned offset (no rot)
  • Rotation of offset by quaternion (yaw 90° → +X local maps to −Z world)
  • Bare-origin path unchanged

Suite goes 14 → 17 tests, runtime unchanged (~380 ms).

Bundle

Main 756.4 → 756.6 KB (+200 B; 92 % of cap).

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added mount offset support for LIDAR scans, enabling accurate hit position reporting from sensors positioned off-axis from the origin point. Mount offsets can be configured with optional rotation transformations for proper world-space alignment.
  • Tests

    • Added comprehensive test coverage for mount offset behavior with and without rotational transformations.

`LidarScan.scan(origin, rot?, mountOffset?)` now accepts an optional
drone-local mount offset (e.g. `[0, 0.5, 0]` for a sensor on a 0.5 m
mast). The offset is rotated into world space by `rot` and added to
`origin` to produce the actual scan origin.

Mechanics:
- Hoists the q→3x3 rotation matrix outside the existing per-ray
  loop so it can be reused for both the mount-offset transform and
  the direction rotation. No new compute cost on the scan side
  (matrix already needed to be built); offset application is a
  single matrix-vector multiply per scan.
- Hit positions now derive from `this._origin` (the post-offset scan
  origin) rather than the raw `origin` parameter — without this, a
  mast-mounted sensor would report hits as if rays started at the
  drone center but ended at the mast tip, drifting by the offset
  length.
- Backward-compatible: existing `effects.ts:_updateLidar` keeps
  passing two args; `mountOffset` defaults to undefined and the bare
  drone-origin path stays bit-identical to PR #80.

Tests:
- World-axis-aligned offset application (no rot)
- Rotation of offset by quaternion (yaw 90° → +X local maps to −Z world)
- Bare-origin path unchanged

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Apr 29, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 66e7a6e2-a645-4f77-af62-f5abf2f2883b

📥 Commits

Reviewing files that changed from the base of the PR and between a9f32a9 and 2ed332e.

📒 Files selected for processing (2)
  • src/ResQ.Viz.Web/client/__tests__/lidar.test.ts
  • src/ResQ.Viz.Web/client/webgpu/lidar.ts

📝 Walkthrough

Walkthrough

Introduces an optional mountOffset parameter to the LidarScan.scan() method, enabling mast-mounted LIDAR sensors to report hits relative to an effective scan origin. The offset can be applied as world-axis-aligned or rotated via a quaternion, with corresponding test coverage validating both application modes.

Changes

Cohort / File(s) Summary
Mount Offset Tests
src/ResQ.Viz.Web/client/__tests__/lidar.test.ts
New test suite for LidarScan mount-offset behavior: validates hit positioning with no offset, world-axis-aligned offset, and rotation-aware offset application.
Mount Offset Implementation
src/ResQ.Viz.Web/client/webgpu/lidar.ts
Extended scan() signature with optional mountOffset parameter; hoists quaternion→matrix computation for reuse in both offset rotation and per-ray direction transformation; snapshots mutable this._origin to ensure hit positions use the effective scan origin.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A sensor mounted high, with offset and care,
Quaternions spin, vectors rotate in air,
The LIDAR now knows where it truly sits—
No more mast confusion, each scan precisely hits! 🎯

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(viz): LiDAR sensor mount offset' directly summarizes the main change: adding mount offset support to LidarScan with world-axis-aligned and quaternion-rotated offset handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/lidar-mount-offset

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

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

Copy link
Copy Markdown
Contributor

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 adds support for a mountOffset in the LidarScan.scan method, allowing hit positions to be calculated relative to a sensor's local position on a drone. The changes include logic to rotate the offset into world space and new unit tests to verify the coordinate math. A potential race condition was identified where the scan origin is read from a shared mutable buffer after an asynchronous operation, which could lead to incorrect results if multiple scans are performed concurrently.

Comment thread src/ResQ.Viz.Web/client/webgpu/lidar.ts Outdated
Address Gemini review on PR #84: capture `ox/oy/oz` from
`this._origin` BEFORE the `await this.los.query(rays)` rather than
after. The tuple is shared mutable state; if another scan() landed
on the same instance while the query was in flight, the post-await
read would see the next scan's origin and the hit-position math
would silently produce wrong world-space positions.

The current consumer gates per-drone via the in-flight flag in
effects.ts, so the race isn't reachable today — this just makes
LidarScan robust to other call patterns and future mistakes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@WomB0ComB0
WomB0ComB0 merged commit 1a2e59e into main Apr 29, 2026
37 checks passed
@WomB0ComB0
WomB0ComB0 deleted the feat/lidar-mount-offset branch April 29, 2026 06:16
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