Skip to content

fix: legacy robot.q/qd mutation never wrote handle's integration back - #129

Merged
petercorke merged 1 commit into
jhavl:futurefrom
petercorke:fix/sync-legacy-bidirectional
Aug 21, 2026
Merged

fix: legacy robot.q/qd mutation never wrote handle's integration back#129
petercorke merged 1 commit into
jhavl:futurefrom
petercorke:fix/sync-legacy-bidirectional

Conversation

@petercorke

Copy link
Copy Markdown
Collaborator

Summary

_sync_legacy() only pulled robot.q/robot.qd -> handle.q/handle.qd (detecting the deprecated direct-mutation style and adopting it), but never pushed Swift's own per-step integration (velocity-mode step_v()) back into robot.q/robot.qd.

A control loop that reads robot.q back mid-loop -- the normal pattern, and RTB's own documented README example -- saw a permanently stale configuration: fkine()/jacobe() never advanced, so the computed qd never changed either, and the robot just ran the same joint velocity forever without converging or stopping. Not just a deprecation-warning nuisance -- a silent functional break with no error.

Reproduced RTB's exact README p_servo example headlessly:

  • Without this fix: hits a 500-step cap, never arrives, panda.q frozen at the initial value the entire time.
  • With this fix: converges in 43 steps.

Fix

Added _push_legacy(), the mirror of _sync_legacy(): once a handle is confirmed to be in legacy mode (_warned), write handle.q/handle.qd back into robot._q/robot._qd after each step_v() integration, keeping the snapshot in sync so this doesn't retrigger the warning.

Gated on _warned (not unconditional) so a handle never driven the legacy way -- the intended case, including several handles sharing one plain robot model -- is untouched, preserving the actual design goal of the refactor.

Companion RTB PRs:

  • docs: update Swift RRMC example to the AssemblyHandle API (README + examples/RRMC_swift.py)
  • fix: Robot._to_dict() uses set_alpha(), deprecated by spatialgeometry

Test plan

  • New test test_legacy_qd_mutation_updates_robot_q_after_step: drives panda.qd directly across two env.step() calls, asserts panda.q advances correctly and only warns once
  • Full suite passes (91 default + 9 rtb-marked; one pre-existing, unrelated spatialgeometry Polyline gap from a stale local install, not this change)
  • Manual repro of RTB's exact README example, headless, before/after

_sync_legacy() only pulled robot.q/qd -> handle.q/qd (detecting the
deprecated direct-mutation style and adopting it), but never pushed
Swift's own per-step integration (velocity-mode step_v()) back into
robot.q/qd. A control loop that reads robot.q back mid-loop -- the
normal pattern, e.g. RTB's own README p_servo example -- saw a
permanently stale configuration: fkine()/jacobe() never advanced, so
the computed qd never changed either, and the robot just ran the same
joint velocity forever without ever converging or stopping.

Reproduced RTB's exact README example headlessly: without this fix it
hits a 500-step cap never arriving, with panda.q frozen at the initial
value the entire time; with the fix, converges in 43 steps.

Add _push_legacy(), the mirror of _sync_legacy(): once a handle is
confirmed to be in legacy mode (_warned), write handle.q/qd back into
robot._q/_qd after each step_v() integration, keeping the snapshot in
sync so this doesn't retrigger the warning. Gated on _warned (not
unconditional) so a handle never driven the legacy way -- the intended
case, including several handles sharing one plain robot model -- is
untouched, preserving the actual design goal of the refactor.
@petercorke
petercorke merged commit b3a02bd into jhavl:future Aug 21, 2026
1 check 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.

1 participant