Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@

[Recorded demo](https://huggingface.co/spaces/Dvidia/dvidia-training) · [Synthetic datasets](https://huggingface.co/datasets/Dvidia/dvidia-training-examples) · [Pilot models](https://huggingface.co/Dvidia/dvidia-training-pilot)

**[Arm interfaces and installation v0.1](docs/arm-interfaces-v01.md).**
The **0.1.3.dev3 preview** adds `dvidia-arm`: three explicit native simulation
adapters, exact PiPER policy compatibility checks, separate install/run commands,
and a data-only lift-planning gate. A fixed tracking study retains **54/54
numerically valid attempts**, including **21/1,260 offline compute-budget
exceedances**. These are mechanics checks, not task success or cross-arm transfer.
[Benchmark](benchmarks/arm-interfaces-v01/README.md) ·
[Install the preview](https://github.com/Dvidia-Inference/dvidia-training/releases/tag/arm-interfaces-v0.1-preview) ·
[Hugging Face evidence](https://huggingface.co/datasets/Dvidia/arm-interfaces-v01).

**[Build a reusable task environment](docs/task-environments-v02.md).**
The **0.1.3.dev2 native preview** adds a local metric editor and
`dvidia-environment`: multiple rigid objects, an open bin, explicit OpenUSD and
Expand Down
42 changes: 42 additions & 0 deletions benchmarks/arm-interfaces-v01/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# DVIDIA arm interface tracking evidence v0.1

Three explicit native simulation interfaces: **PiPER**, **SO101**, and **UR5e + Robotiq 2F-85**.

This is a local CPU mechanics and interface benchmark. It contains no trained policy, object manipulation task, physical robot connection or hardware-latency qualification.

## What was run

- 54 fixed attempts: three profiles × hold / bounded arm perturbation / gripper cycle × 10 / 20 / 40 ms updates × two repeats.
- Every attempt simulates 0.4 seconds at a native 1 ms timestep, without hidden settling or automatic retries.
- 54/54 attempts were numerically valid, with zero native warnings; this is not a task-success count.
- 21,654 recorded state rows and 1,260 issued command events are retained.
- **21 of 1,260 offline control blocks exceeded their nominal compute budget**: PiPER 13, SO101 1, UR5e/Robotiq 7. These are unpaced computation diagnostics, not measured physical deadlines.
- The independent read-only audit recomputed 648 RMS/max values with zero trace/source digest or command-alignment mismatches.

All cases and repeats are retained. Repeats use identical deterministic initial states and trajectories for timing variability; they do not establish generalization, confidence intervals or statistically independent task trials. No profile or update period was selected automatically.

## Accuracy and speed mean specific things

Arm tracking is measured in radians. PiPER gripper tracking uses its single-finger slide command in metres, SO101 uses a moving-jaw hinge target in radians, and Robotiq uses its native 0–255 servo coordinate. These are reported separately.

Robotiq feedback is derived from the pinned affine servo model as `-(bias0 + bias1 * actuator_length) / gain`. It is not an aperture, force or tactile measurement. Raw state and the mapping parameters are retained.

Tracking errors compare observed state with both the held issued target and the continuous reference at the observation time. Terminal-link position/orientation errors use native forward kinematics at the desired arm configuration; the link origin is not a calibrated fingertip tool centre point.

`compile_and_initialize_wall_s` includes pinned asset verification, model compilation and initialization. `control_loop_compute_s` includes the complete control block. **`native_step_compute_s` measures the full observed-step wrapper: native stepping, forward update, state checks/snapshot and reference FK. It is not pure physics-engine execution time.** Trace serialization is outside the loop; total attempt timing stops before writing the final result receipt.

The run used Python 3.12.9, MuJoCo 3.15.0 and NumPy 2.5.3 on Darwin arm64. The machine was an interactive shared host, not an isolated real-time test rig. Upstream gravity compensation and mechanics differ by profile. Do not interpret this table as a hardware quality ranking, minimum-system specification or sensor-to-actuator latency measurement.

## Read the evidence

[Interface and installation guide](../../docs/arm-interfaces-v01.md)

- [Bounded summary](summary.json): all 27 condition summaries, settings, source hashes and timing scope.
- [Independent audit](audit.json) and [original audit source](audit.py).
- [Prepared artifact identities](publication-artifacts.json): archive and full inventory hashes.

The companion evidence ZIP retains every raw trace; large traces are excluded from Git. The portable verifier is inside the ZIP. This directory records prepared artifacts and does not itself claim a completed publication.

Archive: `arm-interfaces-v01-release-20261031.zip` · 11,159,124 bytes · SHA-256 `48200eb5c647badff7db5ee14272571b93d9c31003d9f5f92dd6e28d062b272b`.

Original DVIDIA source and synthetic records: MIT. PiPER simulation assets: MIT; SO101: Apache-2.0; UR5e: BSD-3-Clause; Robotiq 2F-85: BSD-2-Clause. Full upstream notices are preserved in the companion archive.
12 changes: 12 additions & 0 deletions benchmarks/arm-interfaces-v01/audit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"schema": "dvidia.arm-interface-audit/v1",
"report_sha256": "5dd90299bd17515aee578631b46e3146c07ad18909eea838153d37bc4e9b1c5d",
"attempts": 54,
"state_rows": 21654,
"issued_command_events": 1260,
"independent_metric_comparisons": 648,
"source_and_trace_digest_mismatches": 0,
"command_time_alignment_mismatches": 0,
"offline_control_budget_exceedances": 21,
"scope": "Read-only numerical/digest audit; not a repeat run or physical validation."
}
71 changes: 71 additions & 0 deletions benchmarks/arm-interfaces-v01/audit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""Read-only independent audit of the fixed arm-interface tracking run."""
from hashlib import sha256
import json
import math
from pathlib import Path

root=Path('runs/arm-interfaces-v01-20261031')
report=json.loads((root/'report.json').read_text())
protocol_bytes=(root/'protocol.json').read_bytes()
assert sha256(protocol_bytes).hexdigest()==report['protocol']['sha256']
protocol=json.loads(protocol_bytes)
assert len(protocol['schedule'])==54==len(report['attempts'])
assert all(sha256((root/'source'/f['name']).read_bytes()).hexdigest()==f['sha256'] for f in protocol['source_inventory'])
assert len({a['id'] for a in report['attempts']})==54
rows_total=commands_total=metric_comparisons=0
for scheduled,result in zip(protocol['schedule'],report['attempts']):
assert all(result[k]==v for k,v in scheduled.items())
folder=root/result['id']
assert json.loads((folder/'result.json').read_text())==result
assert json.loads((folder/'started.json').read_text())['attempt']==scheduled
raw=(folder/'trace.json').read_bytes()
assert sha256(raw).hexdigest()==result['trace']['sha256'] and len(raw)==result['trace']['bytes']
trace=json.loads(raw)
rows,commands=trace['rows'],trace['commands']
assert result['valid'] and not result['error'] and not result['warnings'] and not result['warning_counters']
assert len(rows)==401 and len(commands)==round(.4/result['control_period_s'])
assert rows[-1]['elapsed_s']==.4 and result['simulated_seconds']==.4
substeps=round(result['control_period_s']/.001)
arm_indices=result['contract']['arm_action_indices']
gripper=result['gripper_coordinate']
series={key:[] for key in result['metrics'] if key!='state_rows'}
for index,row in enumerate(rows):
assert math.isclose(row['elapsed_s'],index*.001,abs_tol=1e-12)
assert math.isclose(row['native_time_s'],row['elapsed_s'],abs_tol=1e-10)
if index==0: continue
held=commands[(index-1)//substeps]['values_native']
assert held==row['applied_command_native']
reference=row['continuous_reference_command_native']
# Compiled interfaces have direct scalar arm joints at these qpos addresses.
actual=[row['qpos_native'][i] for i in arm_indices]
series['arm_held_target'].extend(value-held[i] for value,i in zip(actual,arm_indices))
series['arm_continuous_reference'].extend(value-reference[i] for value,i in zip(actual,arm_indices))
jaw=-(gripper['bias0']+gripper['bias1']*row['gripper_actuator_length_native'])/gripper['gain']
series['gripper_held_target'].append(jaw-held[gripper['action_index']])
series['gripper_continuous_reference'].append(jaw-reference[gripper['action_index']])
xyz,goal=row['terminal_link_position_m'],row['reference_terminal_link_position_m']
series['terminal_position_continuous_reference'].append(math.sqrt(sum((a-b)**2 for a,b in zip(xyz,goal))))
quat,goalquat=row['terminal_link_quaternion_wxyz'],row['reference_terminal_link_quaternion_wxyz']
dot=min(1.,max(0.,abs(sum(a*b for a,b in zip(quat,goalquat)))))
series['terminal_orientation_continuous_reference'].append(2*math.acos(dot))
for key,values in series.items():
measured=result['metrics'][key]
assert measured['count']==len(values)
rms=math.sqrt(sum(v*v for v in values)/len(values))
assert math.isclose(measured['rms'],rms,abs_tol=1e-10,rel_tol=1e-10),(result['id'],key,measured['rms'],rms)
assert math.isclose(measured['max_abs'],max(map(abs,values)),abs_tol=1e-10,rel_tol=1e-10)
metric_comparisons+=2
assert result['metrics']['arm_continuous_reference']['unit']=='rad'
assert result['metrics']['gripper_continuous_reference']['unit']==gripper['unit']
timing=result['timing']
assert len(timing['native_steps_s'])==400 and len(timing['control_intervals_s'])==len(commands)
assert timing['offline_control_budget_exceedances']==sum(v>result['control_period_s'] for v in timing['control_intervals_s'])
rows_total+=len(rows);commands_total+=len(commands)
identity=sha256((root/'report.json').read_bytes()).hexdigest()
output={'schema':'dvidia.arm-interface-audit/v1','report_sha256':identity,'attempts':54,
'state_rows':rows_total,'issued_command_events':commands_total,'independent_metric_comparisons':metric_comparisons,
'source_and_trace_digest_mismatches':0,'command_time_alignment_mismatches':0,
'offline_control_budget_exceedances':sum(a['timing']['offline_control_budget_exceedances'] for a in report['attempts']),
'scope':'Read-only numerical/digest audit; not a repeat run or physical validation.'}
Path('runs/arm-interfaces-v01-audit-20261031.json').write_text(json.dumps(output,indent=2)+'\n')
print(json.dumps(output,indent=2))
Loading
Loading