Watch it run

Autonomous vision pick-and-place on Bob (2026-06-04): the arm finds a red brick by camera, plans the grasp, lifts it, and places it in the bowl — no teleoperation and no hand-coded coordinates.

Hardware

Compute
Raspberry Pi 5 (8 GB)
Vision
OAK-D (Luxonis)
Arm
SO-ARM101 (5-DOF, FeeTech servo bus)
Registry ID
RRN-000000000002

Problem

On 2026-05-09 the RobotRegistryFoundation registry was reset, invalidating every evidence record, transparency-log entry, and run-bundle previously issued. Re-establishing public, verifiable evidence required rebuilding from zero against real (non-stub) hardware before any claim could carry weight.

Approach

Three sequential phases:

  1. Phase 1 — real actuator. Ship so-arm101-actuator v0.1.1 to PyPI (RPN-000000000002), wire it through robot-md-gateway via entry-point dispatch on Bob (Raspberry Pi 5 + SO-ARM101 over /dev/ttyACM0).
  2. Phase 2 — re-issue the evidence. Re-run the prior cert-intake suite (GW-001, GATED-MOTION-100, REPLAY-10) post-reset, and add MOTION-FIDELITY-100 against real hardware on the gravity-neutral shoulder_pan joint. 4 evidence records logged at indices 1–4.
  3. Phase 3 — range-of-motion breadth. Calibrate Bob's actual reachable joint ranges (three previously-unknown mechanical stops discovered: elbow_flex floor ~−0.241 rad, wrist_flex ceiling ~+0.462 rad, wrist_roll ceiling ~+1.537 rad). Ship so-arm101-actuator v0.2.1 with Bob-calibrated SAFE_RANGE_RAD + SO_ARM101_MOVE_TOLERANCE_RAD env override. Run FULL-SWEEP-100 at tolerance 0.07 rad. 5th evidence record logged at index 5.

Evidence

All five evidence records and both run-bundles are countersigned by rrf-root in RRF's public transparency log. Each evidence record is one test result (property, iterations, pass/fail) signed by the rig key and the witness key and then logged by RRF. RRF's intake endpoint is called cert-intake and its IDs start with cert_, but these are self-run test results, not certifications: the witness is Craig, who also runs RRF. Each row below includes a copy-pasteable verification command.

Property Iterations Outcome Evidence ID Log idx
GW-001 (/dev/ttyACM0 bypass denied) 10 10/10 EACCES cert_86cf536308b20cd925684084af2d663c 1
bob.local/GATED-MOTION-100 (dispatch path) 100 100/100 within 5 s; p50=21 ms p95=25 ms cert_0e0ca979ca6925cc8ec4131a15c20b0e 2
bob.local/REPLAY-10 (in-process replay defense) 10 10/10 deny:replay cert_44fad966dc2b8987cf2cfa60e77931bc 3
bob.local/MOTION-FIDELITY-100 (shoulder_pan only) 100 100/100 reached; p50=341 ms p95=369 ms cert_c4ec0bda561e21e621d4acfb0c760128 4
bob.local/FULL-SWEEP-100 (all 6 joints, tolerance 0.07 rad) 100 100/100 reached; p50=509 ms p95=759 ms max=825 ms cert_c19b998f6a67d97699b8fd66bd2bae1d 5

Verify yourself

curl -sS -A "case-study-verify/1.0" https://robotregistryfoundation.org/v2/cert-intake/cert_86cf536308b20cd925684084af2d663c/proof
curl -sS -A "case-study-verify/1.0" https://robotregistryfoundation.org/v2/cert-intake/cert_0e0ca979ca6925cc8ec4131a15c20b0e/proof
curl -sS -A "case-study-verify/1.0" https://robotregistryfoundation.org/v2/cert-intake/cert_44fad966dc2b8987cf2cfa60e77931bc/proof
curl -sS -A "case-study-verify/1.0" https://robotregistryfoundation.org/v2/cert-intake/cert_c4ec0bda561e21e621d4acfb0c760128/proof
curl -sS -A "case-study-verify/1.0" https://robotregistryfoundation.org/v2/cert-intake/cert_c19b998f6a67d97699b8fd66bd2bae1d/proof
curl -sS -A "case-study-verify/1.0" https://robotregistryfoundation.org/v2/run-bundles/runbundle_0d215563624c
curl -sS -A "case-study-verify/1.0" https://robotregistryfoundation.org/v2/run-bundles/runbundle_8ec34ed19180

Each call returns JSON with transparency_log_index and rrf_log_signature. The -A User-Agent matters — Cloudflare blocks the default curl/<version>.

Result

Signed off: bypass denial, gated dispatch latency, replay defense, single-joint motion fidelity, and 6-joint range-of-motion fidelity — all on real hardware, all post-reset.

Not signed off:
  • SF-001 (ESTOP latency ≤ 100 ms physical) — gated on physical ESTOP hardware the operator does not currently have.
  • SF-002 (network-loss safe-stop ≤ 3.5 s) — N/A on this rig (WiFi-only; no wired interface to drop).

Path to NORMATIVE: add SF-001 evidence against physical ESTOP, then re-issue this declaration as NORMATIVE citing all six evidence IDs.

What broke and what we learned

  • Wrist flex stalled at high angle. The SO-ARM101 wrist motor brown-outs near maximum flex. Cap the IK solver at 0.85× joint limit to avoid stall-and-fault cycles.
  • OAK-D factory extrinsic didn't fit the mount. The shipped extrinsic calibration doesn't account for non-standard mounting orientations. Recalibrate per camera mount; don't reuse the factory file for wall or off-axis installations.
  • feetech-servo-sdk 1.0.0 PacketHandler() factory is broken. Bypass it. All servo call sites use scservo_sdk.sms_sts(ph) directly instead of going through the feetech-servo-sdk factory.

Reproducibility

To replicate this evidence on a comparable rig:

  1. pip install so-arm101-actuator==0.2.1 on a host wired to an SO-ARM101 over /dev/ttyACM0.
  2. Calibrate your rig's SAFE_RANGE_RAD via a sweep test (the v0.2.1 defaults reflect Bob's mechanical stops; your rig may differ). Set per-joint overrides via SO_ARM101_SAFE_RANGE_RAD env var if needed.
  3. Pick a SO_ARM101_MOVE_TOLERANCE_RAD that matches your rig's steady-state precision (the v0.2.1 default is 0.02; Bob runs at 0.07 to accommodate gravity-load undershoot on shoulder_lift).
  4. Install + run robot-md-gateway 0.5.0a2 via systemd; register your robot under your own RRN.
  5. Pre-sign INVOKE envelopes with your operator key (see spec for envelope canonicalization rules).
  6. Dispatch envelopes through the gateway; collect outcome telemetry; build evidence + run-bundle bodies; POST to /v2/cert-intake and /v2/run-bundles.
  7. Verify each ID round-trips via /proof.

The pose list for FULL-SWEEP-100 is deterministic given seed: so_arm101_actuator.sweep.generate_sweep_poses(iterations=100, seed=42) — same seed, same poses.

Where safety is meant to be enforced.
Physical limits are meant to be enforced at Layer 3 (robot-md-gateway and the actuator driver it calls), and only for commands that pass through it. OpenCastor (Layer 4) does not embed the gateway yet, so actuators it drives directly are not covered. Declaration alone (Layer 1) does not enforce safety. Agent host alone (Layer 2) is not the safety boundary. If a deployment lacks Layer 3, no safety claim attaches to it. Layer 3 is not a certified safety function, and hostile-input testing in simulation (October 2026) found motions it does not yet bound.