Skip to content

Integrate wheel odometry over the real capture interval - #9

Merged
JaidenAGrimminck merged 1 commit into
mainfrom
fix-wheel-odometry-interval
Oct 16, 2026
Merged

JaidenAGrimminck merged 1 commit into
mainfrom
fix-wheel-odometry-interval

Conversation

@clmazzac

@clmazzac clmazzac commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Problem

wheelTravelFromBicycle computed each sample's travel as speed × (1 / rateHz). The fixed-step schedule rounds the sensor period to whole steps (periodSteps = round(periodNs / stepNs)), so captures can arrive more often than rateHz.

Example: 50 Hz wheel odometry on the default 60 Hz step. periodSteps rounds 1.2 to 1, so the sensor captures every 16.67 ms. Each capture still integrated 20 ms of travel. Distance came out 20% too long.

Measured at 3 m/s for 30 s: 107.7 m reported against 90.0 m true.

Fix

Travel uses the time since the previous capture, from state.lastCaptureTimeNs. The IMU and GNSS models already do this. The first capture has no previous one and still uses 1 / rateHz.

wheelTravelFromBicycle takes dt as an argument. It no longer reads snapshot.rateHz, and buildWheelOdometryMeasurement no longer writes rateHz onto the shared snapshot.

Tests

  • New test in tests/localization-sensors.test.js: 50 Hz odometry on a 16.67 ms step at 3 m/s for 180 captures. Distance is within 1% of truth. Without the fix it reports 10.78 m against 9.01 m.
  • npm test on a clean checkout: all pass except Python decodes retained RGB, depth, and CameraInfo SFLog messages, which also fails on main.

Related

#10 fixes tick rounding in the same function. The two PRs merge cleanly in either order; I checked the combined result with npm test.

The measured wheel odometry values change for affected runs. deterministic-state-sensors stays at version 1. Bump it if recorded runs must reproduce exactly across this change.

🤖 Generated with Claude Code

Wheel odometry computed travel over 1 / rateHz. The fixed-step schedule
rounds the sensor period to whole steps, so captures can arrive more often
than that. A 50 Hz sensor on the default 60 Hz step captures every
16.67 ms but integrated 20 ms each time, which overstated distance by 20%.

Travel now uses the time since the previous capture, as the IMU and GNSS
models already do. The first capture still uses 1 / rateHz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@JaidenAGrimminck JaidenAGrimminck left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

for the built in model i think this is fine but since we're adjusting to dynamics package might need to do some later adjusting

@JaidenAGrimminck
JaidenAGrimminck merged commit 8e36c57 into main Oct 16, 2026
7 of 8 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