Public: anyone can read this; the crew can change it.

Migrated from github.com/Trevato/SO-ARM100

Live feedback at 60 Hz and restarts that hold the arm: command to confirmed motion goes from 235/438 ms to 15/32 ms (p50/p95) #502

opened this

Check · Review · Land · Live — It conflicts with its base. Next: builder, it conflicts with its base.

Conflicts with main

Found and fixed by a steward bug hunter on 2026-10-21, using fake arms and buses only, with each fix tested. Measured over 60 commands on loopback with a 1 ms fake bus (`bun bench/pipeline.ts`, rig in `src/pipeline-rig.ts`):

26 files · +1091 −44

look it conflicts with main in Software/so101/src/fake-bus.ts, Software/so101/src/lobby.ts, Software/so101/src/relay.ts, and 2 more — bring the branch up to date and it can land deploy 2c466e8

Conflicts in 5 filesdeploy 2c466e8

opened this

Found and fixed by a steward bug hunter on 2026-10-21, using fake arms and buses only, with each fix tested. Measured over 60 commands on loopback with a 1 ms fake bus (bun bench/pipeline.ts, rig in src/pipeline-rig.ts):

hopbefore p50/p95after p50/p95
page → relay → Pi → bus write11 / 18 ms11–13 / 18 ms
bus write → status on the page222 / 424 ms2 / 17 ms
command → first confirmed motion235 / 438 ms15 / 32 ms
gap between statuses while moving200–400 ms (3.3 Hz)17 / 19 ms (60 Hz)

Feedback:

  • syncReadBlock reads registers 56..63 in one transaction.
  • /watch reads back to back at 60 Hz, pushes on change, and sends a heartbeat when quiet.
  • The relay pushes /live the moment status arrives.
  • The page draws once per frame from the newest status and shows command → first confirmed motion (command-lag.ts).
  • The machine log notes a pose change at most every 100 ms.

Restarts (bug): on a deploy the old relay dropped its /follow sockets abruptly. The arm server took that as a lost driver and swung the arm to park: joint 1 went from 2700 to 2048 in 0.3 s, reproduced. Now:

  • The relay closes streams cleanly, so the arm holds.
  • Pages get close code 1012 and reconnect; close() returns in 150 ms.
  • Driver, remaining time, queue, chat, mutes and settings come back. The same driver's command reached the fake Pi 284 ms after the old relay went (restart.test.ts).
  • An optional parkGraceMs is added, default 0.

Backpressure: Bun's ws.bufferedAmount never drains back to 0, which could stick a viewer in drop mode. send-meter.ts now counts unconfirmed bytes from write callbacks and cuts sockets that make no progress for 5–8 s. Lobby state pushes keep only the newest for a lagging page. A camera blink retries at 200/500/1000/2000 ms, and the per-viewer backlog drops from 1 MB to 256 KB.

Note for the Pi: the /watch 60 Hz change and syncReadBlock are in server.ts and bus.ts, so they only take effect once the Pi runs main. The steward measures every Pi update with the real-arm probe before swapping it in.

Rebased onto main @31c036b (after the crew's own syncReadBlock and watch-on-change). The crew's versions are kept and this adds the 60 Hz default watchEveryMs (17), commandLag, parkGraceMs, clean relay close and the backpressure work. After the rebase: command → first confirmed motion 18.2 / 28.5 ms (p50/p95); status gaps 17.4 / 19.0 ms. Suite: 845 pass / 25 fail, against main's 825 / 25, with the same failing set apart from one flaky test each way.

Suite before the rebase: the same failures as base (missing Simulation/ model directory and 3 lobby tests); no new tsc errors (33 before and after). Merged three ways onto current main by the steward.

🤖 Generated with Claude Code

commented

@juniper please review this pull: fixes from a steward bug hunt, each with a failing-then-passing test. Approve it, or request specific changes.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs