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 cert ID, 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:
-
Phase 1 — real actuator. Ship
so-arm101-actuatorv0.1.1 to PyPI (RPN-000000000002), wire it throughrobot-md-gatewayvia entry-point dispatch on Bob (Raspberry Pi 5 + SO-ARM101 over/dev/ttyACM0). -
Phase 2 — re-issue cert envelope. Re-run the prior cert-intake suite
(
GW-001,GATED-MOTION-100,REPLAY-10) post-reset, and addMOTION-FIDELITY-100against real hardware on the gravity-neutralshoulder_panjoint. 4 cert IDs minted at log indices 1–4. -
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-actuatorv0.2.1 with Bob-calibratedSAFE_RANGE_RAD+SO_ARM101_MOVE_TOLERANCE_RADenv override. RunFULL-SWEEP-100at tolerance 0.07 rad. 5th cert minted at log index 5.
Evidence
All five cert IDs and both run-bundles are countersigned by rrf-root in the
public transparency log. Each row below includes a copy-pasteable verification command.
| Property | Iterations | Outcome | Cert 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.
-
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 cert 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 usescservo_sdk.sms_sts(ph)directly instead of going through thefeetech-servo-sdkfactory.
Reproducibility
To replicate this evidence on a comparable rig:
-
pip install so-arm101-actuator==0.2.1on a host wired to an SO-ARM101 over/dev/ttyACM0. -
Calibrate your rig's
SAFE_RANGE_RADvia a sweep test (the v0.2.1 defaults reflect Bob's mechanical stops; your rig may differ). Set per-joint overrides viaSO_ARM101_SAFE_RANGE_RADenv var if needed. -
Pick a
SO_ARM101_MOVE_TOLERANCE_RADthat 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). -
Install + run
robot-md-gateway0.5.0a2 via systemd; register your robot under your own RRN. - Pre-sign INVOKE envelopes with your operator key (see spec for envelope canonicalization rules).
-
Dispatch envelopes through the gateway; collect outcome telemetry; build cert +
run-bundle bodies; POST to
/v2/cert-intakeand/v2/run-bundles. - 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.