fix(retargeting): derive locomotion hip-height dt from graph_time#477
fix(retargeting): derive locomotion hip-height dt from graph_time#477
Conversation
The hip-height integration in LocomotionRootCmdRetargeter used a hardcoded config.dt=1/60 regardless of the actual control rate, so any deployment running at 90/120 Hz integrated 1.5x/2x too slowly. Read dt from ComputeContext.graph_time.real_time_ns instead, with a fallback_dt for the first frame after init/reset. Add a rate-invariance test that drives the retargeter at 60/90/120 Hz with the same stick value over the same wall duration and asserts the hip delta matches across rates. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR refactors the locomotion retargeter to compute integration timesteps dynamically from the simulation graph clock rather than using a fixed configured value. The key change replaces the Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
There was a problem hiding this comment.
Pull request overview
Fixes locomotion hip-height integration so it uses actual elapsed wall-clock time from ComputeContext.graph_time.real_time_ns, making behavior invariant to control loop rate (e.g., 60/90/120 Hz) and clarifying configuration intent by renaming dt to fallback_dt.
Changes:
- Derive per-step
dtfromComputeContext.graph_time.real_time_nswith a first-frame/reset fallback tofallback_dt. - Rename config field
dt→fallback_dtand reset stored timestamp on reset events. - Add locomotion retargeter tests covering rate invariance, zero-input no drift, and reset timestamp clearing; update docs to reference
fallback_dt.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/retargeters/locomotion_retargeter.py |
Switch hip-height integration timestep to be derived from graph_time.real_time_ns; rename config to fallback_dt; clear timestamp on reset. |
src/core/retargeting_engine_tests/python/test_locomotion_retargeter.py |
Add tests validating rate-invariant integration, zero-input stability, and reset behavior. |
docs/source/references/retargeting/index.rst |
Update retargeter config documentation to mention fallback_dt and graph_time-derived steady-state dt. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Two assertions in test_locomotion_retargeter.py compared the float32 hip-height output against a Python float with exact equality / 1e-9 tolerance. CI on Ubuntu (Python 3.10–3.13) round-tripped the values slightly off (0.7200000286 ≠ 0.72), failing both tests. Switch both checks to math.isclose with float32-friendly absolute tolerances (1e-6 for the zero-input case, 1e-5 for the post-reset fallback-dt case). The rate-invariance test already passed; only the overly tight equality checks needed to relax. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/core/retargeting_engine_tests/python/test_locomotion_retargeter.py`:
- Around line 153-155: The assertion uses abs_tol=1e-9 which is too tight for
float32 outputs; update the test so the comparison between h_after_reset (from
outputs["root_command"][0], float32) and expected (computed from
LocomotionRootCmdRetargeterConfig) uses a looser absolute tolerance such as 1e-6
(matching the existing rate-invariance test) to avoid spurious failures due to
float32 rounding.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 360721fb-b6d3-41c0-9f54-a919365ced4a
📒 Files selected for processing (3)
docs/source/references/retargeting/index.rstsrc/core/retargeting_engine_tests/python/test_locomotion_retargeter.pysrc/retargeters/locomotion_retargeter.py
Summary
LocomotionRootCmdRetargeterintegrated hip height with a hardcodedconfig.dt=1/60, so deployments at 90/120 Hz integrated 1.5x/2x too slowly relative to the operator's intent.dtfromComputeContext.graph_time.real_time_nseach step. First frame after init/reset uses the configured nominalfallback_dt(1/60 by default), since no prior timestamp exists.dt→fallback_dtto make the role explicit. No callers in this repo passeddt=as a kwarg, but downstream consumers should be aware.test_locomotion_retargeter.pywith a rate-invariance test (60/90/120 Hz produce the same hip-height delta over the same wall-clock duration), a stick-zero no-drift test, and a reset-clears-prev-timestamp test.docs/source/references/retargeting/index.rstto mentionfallback_dt.Why this matters
This is a correctness bug visible in any non-60 Hz deployment. CloudXR commonly runs at 90 Hz; locomotion stick → hip-height behavior was wrong in those sessions.
Test plan
ctest -R retargeting_test_locomotion_retargeterretargeting_test_retargeter_resetcontinues to pass🤖 Generated with Claude Code
Summary by CodeRabbit
Improvements
Documentation