fix jogging stepping by holding one velocity instead of re-arming
`set_cartesian_velocity` passed `duration=velocity_command_ttl_s` on every message, so each one re-armed a timed segment and the controller re-planned the same motion. On a real Lite6 that is not smooth travel: the arm moves in steps. Reducing how often the velocity is sent does not help — re-arming four times a second still steps — so it now uses `duration=0`, the SDK's "always effective, will not stop automatically", and skips a velocity that has not changed. One command stands until a different one replaces it. That removes the controller-side expiry, which `_expire_jog` was relying on: it flipped `_jogging` and reported `ready` without commanding anything, because the controller's own timer had already stopped the arm. With the velocity held indefinitely that would leave an arm travelling while the node reported idle, so `_expire_jog` now queues the stop itself. It goes through the job queue rather than the driver, since it runs on the reporter thread and the control thread owns the driver. `VELOCITY_COMMAND_TTL_S` is unchanged in value and meaning to a caller, but it is now enforced here rather than by the controller. Both halves are one commit on purpose: `duration=0` without the stop in `_expire_jog` is an arm that never stops when its sender dies. Adds tests/test_driver.py — the driver had no direct coverage, because FakeArm replaces it everywhere else, which is why this was invisible to the suite.
This commit is contained in:
@@ -60,7 +60,7 @@ Everything is configured through environment variables — see README.md for the
|
||||
## Test
|
||||
|
||||
```bash
|
||||
uv run pytest # 86 tests, no robot and no dataflow needed
|
||||
uv run pytest # 92 tests, no robot and no dataflow needed
|
||||
uv run ruff check .
|
||||
```
|
||||
|
||||
@@ -183,6 +183,15 @@ A typed optional input therefore forces the example dataflow to wire it. `reques
|
||||
## Rules
|
||||
|
||||
- Do not mention AI tools in commit messages or documentation.
|
||||
- **A velocity is set on the controller once and held.** `set_cartesian_velocity` passes no
|
||||
duration and skips an unchanged velocity, because re-arming makes the controller re-plan
|
||||
the same motion and the arm steps instead of travelling — four times a second is enough
|
||||
to feel it. Do not reintroduce a per-message `duration`, and do not "simplify" the
|
||||
unchanged-velocity check away.
|
||||
- **`_expire_jog` is the deadman, not bookkeeping.** Nothing else stops an arm whose sender
|
||||
died mid-jog: the controller holds the velocity indefinitely. It must command the stop,
|
||||
not merely report `ready` — an arm travelling while the node says idle is worse than no
|
||||
expiry at all.
|
||||
- This controls a real robot. Test changes carefully and preserve the safety checks: the
|
||||
reachability check before a move, the arrival confirmation after it, and the live error
|
||||
reads that make both of them mean anything.
|
||||
|
||||
Reference in New Issue
Block a user