Twins

SO-101 follower arm

The Robot Studio / Hugging Face. A certified SimCloud arm twin: the report below is the evidence, check by check, from its latest validation.

certifiedv1.0.0SimCloud twin badge for SO-101 follower arm

twin
so-101
version
1.0.0
firmware
feetech-sts3215 12V 1:345, lerobot P16 I0 D32, zero at mid-range
certified
04 Oct 2026
kind
arm
toolchain
simtwin 0.1.1
re-checked
14 Nov 2026, error

checks passed

21 / 22

1 with a warning

engines passed

2 / 2

mujoco, pybullet

worst tracking error

1.1°

gripper, 0.020 rad RMSE

control latency

134 ms

fitted from lerobot/svla_so101_pickplace@f641879e2217

Checks

Each check the validation ran, in the order it ran them, with what it found. Run by simtwin 0.1.1 on 2026-10-04.

CheckStatusWhat it found
twin-schemapassvalid simtwin.twin/1 for so-101@1.0.0, 6 joints
files-presentpass5 named and 52 referenced files present inside the twin
mjcf-loadspasscompiles in MuJoCo 3.14.0: 8 bodies, 6 joints, 6 actuators, 17 meshes
urdf-loadspass10 links, 9 joints, root 'base_link'
joint-names-agreepass6 moving joints, same names, types and tree order: shoulder_pan, shoulder_lift, elbow_flex, wrist_flex, wrist_roll, gripper
joint-axes-agreepass6 joints: axes within 0.001 deg and anchors within 0.002 mm over 13 configurations
joint-limits-agreepass6 joints agree within 3.7e-06 (tolerance 0.001 rad)
twin-limits-agreepasstwin.json limits match URDF and MJCF within 3.7e-06
units-consistentpasshwUnits, policyIO and 1 cameras are consistent
no-massless-bodiespassevery moving body has mass (16 links and rigid groups checked)
inertia-validpass18 inertias positive definite and within the triangle inequality
mass-agreepass7 rigid groups agree; total 0.6456 kg (URDF) vs 0.6454 kg (MJCF)
actuator-rangespass6 actuators command exactly their joint's range
actuator-params-agreepassactuator parameters of 6 joints agree between twin.json and the models
self-collision-homewarnhome is collision-free; collision geometry interpenetrates at rest: lower_arm and shoulder by 4.8 mm, shoulder and wrist by 4.0 mm (a pose the real arm reaches without contact: the collision shapes are larger than the parts there)
mesh-validpass17 meshes, 334358 triangles, all readable with plausible size and outward faces; 1 notes: assets/motor_holder_so101_base_v1.stl: not closed (0 boundary and 1 non-manifold edges): engines use its convex hull for contact, which is fine, but inertia from this geometry would be wrong
crosscheckpassmujoco: replayed; pybullet: within 0.276 deg and 0.38 mm of MuJoCo over 4 s.
dataset-unitspasslerobot/svla_so101_pickplace@f641879e2217: units range_0_100, range_m100_100 confirmed by the values; wrist_roll.pos: the recording arm's calibrated span is 359.9 deg, the twin's range 320.0 deg
sysidpassdeclared parameters are at the fit on lerobot/svla_so101_pickplace@f641879e2217 episodes 0-4 (within 2 % of its error); parameters the data does not decide (kept as declared): effort, timeconst; search: 3480 evaluations, 100 % of its budget, 6 of 6 joints verified rather than searched (their declared values were already a local optimum)
fidelitypasslerobot/svla_so101_pickplace@f641879e2217 episodes 5-14 (held out), open loop: RMS shoulder_pan 0.31, shoulder_lift 0.65, elbow_flex 0.42, wrist_flex 0.29, wrist_roll 0.24, gripper 1.14 deg; latency 134 ms twin vs 125 ms arm
fidelity:armnet/armnetbench_v01_lerobot_so101passarmnet/armnetbench_v01_lerobot_so101@1db69c82b589 episodes 0-14: RMS shoulder_pan 0.25, shoulder_lift 1.20, elbow_flex 1.24, wrist_flex 0.37, wrist_roll 0.18, gripper 2.19 deg
cataloguepassso-101-twin@1.0.0: 8 operators (backlash, coarse, compliance, drift, lag, mass, sluggish, weak-grip) with magnitudes from this twin's fit, 13 hazards; valid under mutational's rules

Fidelity per joint

Commanded against measured joint positions over 10 episodes of lerobot/svla_so101_pickplace@f641879e2217: tracking error as RMSE, and overshoot of each step. Control latency 134 ms.

JointTracking RMSE (rad)(degrees)Overshoot
shoulder_pan0.0050.310.0%
shoulder_lift0.0110.650.0%
elbow_flex0.0070.420.0%
wrist_flex0.0050.290.0%
wrist_roll0.0040.240.0%
gripper0.0201.140.3%

Engines

The same trajectories run in each engine the twin exports to, and compared.

EngineVersionStatusMeasured
mujoco3.14.0passmaxTrackingRad 0.803
pybullet202010061passmaxJointDivergenceRad 0.00481, rmsJointDivergenceRad 0.000901, maxTipDivergenceM 0.000385

Policy compatibility

Whether a policy's inputs and outputs - names, order, units - are the twin's.

PolicyStatusDetail
lerobot/smolvla_basefailsmolvla: camera keys ['observation.images.camera1', 'observation.images.camera2', 'observation.images.camera3'] are not twin cameras (twin maps ['observation.images.wrist']): the scene must supply them, or rename them to a twin camera; the checkpoint does not say which dataset it learnt from: joint names unverified; so100: training values lie outside the twin's joint range (shoulder_lift 15..225 deg vs [-105, 105]; elbow_flex 10..209 deg vs [-97, 97]; wrist_flex -17..131 deg vs [-104, 104]): another calibration convention (an SO-100 'old calibration', zero with the arm stretched out, reads ~120 deg on shoulder_lift and elbow_flex); so100-blue: training values lie outside the twin's joint range (shoulder_lift 47..205 deg vs [-105, 105]; elbow_flex 89..162 deg vs [-97, 97]; wrist_flex 17..111 deg vs [-104, 104]; wrist_roll -183..-30 deg vs [-157, 163]): another calibration convention (an SO-100 'old calibration', zero with the arm stretched out, reads ~120 deg on shoulder_lift and elbow_flex); so100-red: training values lie outside the twin's joint range (shoulder_lift 39..210 deg vs [-105, 105]; elbow_flex 86..161 deg vs [-97, 97]; wrist_flex 24..110 deg vs [-104, 104]; wrist_roll -171..-37 deg vs [-157, 163]): another calibration convention (an SO-100 'old calibration', zero with the arm stretched out, reads ~120 deg on shoulder_lift and elbow_flex)
samarth-shukla6/act-svla-so101-pickplacewarnact: camera keys ['observation.images.up', 'observation.images.side'] are not twin cameras (twin maps ['observation.images.wrist']): the scene must supply them, or rename them to a twin camera; statistics: trained on range_m100_100 values, the twin's policyIO speaks deg: configure the follower with use_degrees=false

Downloads

Version 1.0.0, as it was certified. The bundle holds twin.json and every file it names.

Versions

Every published version. A newer certified version supersedes the one before it; the older reports stay readable.

VersionStatusFirmwareCertifiedFiles
1.0.0certifiedfeetech-sts3215 12V 1:345, lerobot P16 I0 D32, zero at mid-range04 Oct 2026reportbundle

Badge

For a README or a datasheet: it shows the twin's status and the engines it passed in, and links to the twin's page in the catalogue, where its report is.

SimCloud twin: SO-101 follower arm

Markdown

[![SimCloud twin: SO-101 follower arm](https://sim.mutational.in/v1/twins/badge/so-101.svg)](https://sim.mutational.in/twins/so-101)

HTML

<a href="https://sim.mutational.in/twins/so-101"><img src="https://sim.mutational.in/v1/twins/badge/so-101.svg" alt="SimCloud twin: SO-101 follower arm"></a>

Use it in an evaluation

A task names the twin by id and version; SimCloud fetches this bundle for it. Run a policy for N episodes, under perturbations, and read the success rate with its interval.

eval@1 task spec

{
  "runtime": "eval@1",
  "robot": {
    "twin": "so-101@1.0.0"
  },
  "scene": {
    "builtin": "tabletop"
  },
  "policy": {
    "kind": "scripted",
    "name": "reach-grasp"
  },
  "episodes": 20
}

Or pick it in New campaign, Evaluation. Every task on a managed pool is priced before it runs (pricing).