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:

  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 cert envelope. 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 cert IDs minted at log 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 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.

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 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 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 cert + 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 actually enforced.
Physical safety is enforced at Layer 3 (robot-md-gateway) or Layer 4 (a runtime that embeds it, e.g., OpenCastor). 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.