Benchmarks¶
This page lists the measured tracking performance of both control backends on
real hardware, explains exactly how the numbers were produced, and shows you
how to reproduce them on your own arm with piper-track-test.
Measured results¶
All numbers below were measured on one Piper-X arm running firmware S-V1.8-9,
using the shipped default gains, with the benchmark trajectory built into
piper-track-test (a 3 cm circle at 5 s per lap).
| Metric | Position mode (piper) |
Impedance mode (piper_mit, shipped soft gains) |
|---|---|---|
| Static hold error | ≈ 0 mm | 11 mm |
| Dynamic RMS (3 cm circle, 5 s/lap) | 1.34 mm | 14.1 mm |
| Estimated latency | ~10 ms | ~90 ms |
Two related measurements for context:
- Quest pose link: the wired controller-pose stream runs at a measured 90–92 Hz. Video panels do not affect it — they use a separate TCP port and drop frames rather than queue.
- Contact force in impedance mode: bounded at roughly the cartesian
stiffness times the 0.12 m target tether (
max_cmd_deviation), which works out to about 20 N with the shipped gains.
Impedance numbers scale with kp
The impedance-mode figures are a property of the shipped soft gains, not
of the controller itself. Raising kp tightens tracking (and raises the
contact-force bound); lowering it makes the arm softer and the error
larger. Position mode has no such trade-off because the firmware runs a
stiff position servo. See Control modes for the gain
model and tuning advice.
Method: what piper-track-test does¶
piper-track-test commands a small, slow circle around the arm's current pose
and compares the commanded end-effector position against the measured one. The
run has two phases:
- Static hold (3 s). The tool repeatedly commands the starting pose and records the measured position. The static hold error is the distance between the two — effectively how far the arm sags or offsets when asked to stand still.
- Moving phase (12 s by default). The tool traces a circle in the x–z plane around the starting pose. The circle radius is 3 cm by default (capped at 5 cm), one lap takes 5 s by default, and the amplitude ramps in over the first 2 s. Every commanded position is clamped to the teleop workspace box, and the z coordinate never goes below the starting height.
Commands and measurements are sampled at 100 Hz by default. The report skips the first 2.5 s of the moving phase (the amplitude ramp) so the steady-state numbers are not diluted by the gentle start. It then prints:
- static hold error (mean and max, mm),
- dynamic error (RMS and max, mm),
- per-axis RMS error (x, y, z, mm),
- estimated command-to-measurement latency, plus the residual RMS error after removing that pure delay.
How latency is estimated: the tool cross-correlates the commanded x position against the measured x position over the steady-state window, testing time shifts from 0 up to 0.4 s, and reports the shift with the highest correlation. At the default 100 Hz sample rate this gives the estimate a resolution of 10 ms. It also reports the dynamic RMS after shifting the measurement back by that delay — useful for separating "the arm is late" from "the arm takes a different path".
Reproduce the numbers¶
Power on the arm, bring up the CAN link, and home the arm first (make home
after every power-on). Then:
Uses the piper_mit MIT-impedance backend with your configured gains.
The tool waits 2.5 s after connecting for the impedance entry and gain
ramp to settle before it starts measuring.
You can vary the trajectory and sampling:
| Flag | Default | Meaning |
|---|---|---|
--amp |
0.03 |
Circle radius in meters (clamped to 0.05 max) |
--period |
5.0 |
Seconds per revolution |
--duration |
12.0 |
Length of the moving phase in seconds |
--rate |
100.0 |
Command/sample rate in Hz |
--config |
– | Apply a config overlay (see Configuration) |
--impedance |
– | Force the piper_mit backend (the default backend) |
--position |
– | Force the piper backend (move_p) |
--sim |
– | Force the fake simulation backend |
The full flag reference lives in the CLI reference.
Compare apples to apples
If you tune impedance.kp/kd for your task, re-run piper-track-test
with the same config overlay you teleoperate with. The benchmark uses the
same --config mechanism as the other tools, so the numbers you measure
describe exactly the controller your dataset will record.
What the numbers mean for data collection¶
- Position mode (1.34 mm dynamic RMS, ~10 ms) is the right choice for high-precision free-space tasks where the arm should go exactly where you point and nothing will be touched along the way.
- Impedance mode (14.1 mm dynamic RMS, ~90 ms at soft gains) is the
default for a reason: for contact-rich tasks the compliance and the bounded
contact force matter far more than millimeter-level tracking, and the error
shrinks if you raise
kp.
The tracking error is between commanded and measured pose. Your datasets
record both (action.arm_eef and observation.arm_eef), so a policy trained
on this data sees the same controller behavior the benchmark measures — which
is also why the control backend and gains are written into each dataset's
provenance metadata. See Control modes for choosing a
backend and Dataset format for what gets recorded.
Honest notes
- All headline numbers come from one Piper-X unit on firmware S-V1.8-9 with the shipped default gains. Your arm, firmware, gains, and payload will shift the results — treat the table as a reference point, not a spec sheet.
- Latency is estimated by cross-correlating commanded vs. measured x position, with 10 ms resolution at the default 100 Hz rate. It is a whole-loop figure (command path + controller + mechanics), not a bus or network measurement.
- The benchmark circles around whatever pose the arm holds when the tool starts, so a different starting pose can give different numbers — especially for the impedance-mode static hold error.