Twins

XLeRobot dual-arm mobile robot (0.3, omni-wheel base)

Vector Wang and the XLeRobot contributors. A certified SimCloud mobile-manipulator twin: the report below is the evidence, check by check, from its latest validation.

certifiedv1.0.0SimCloud twin badge for XLeRobot dual-arm mobile robot (0.3, omni-wheel base)

twin
xlerobot
version
1.0.0
firmware
17 x feetech-sts3215 12V 1:345; lerobot xlerobot driver: arms and head P16 I0 D43 (the SO-101 driver: D32), zero at mid-range; wheels in velocity mode under 3000 counts/s
certified
04 Oct 2026
kind
mobile-manipulator
toolchain
simtwin 0.1.1
re-checked
14 Nov 2026, error

checks passed

20 / 26

6 with a warning

engines passed

2 / 2

mujoco, pybullet

worst tracking error

2.5°

left_gripper, 0.044 rad RMSE

control latency

136 ms

fitted from xlerobot-team/xlerobot-pick-cup-lr-merge-20260904@c3f58d5aa35e

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 xlerobot@1.0.0, 14 joints
files-presentpass5 named and 137 referenced files present inside the twin
mjcf-loadspasscompiles in MuJoCo 3.14.0: 22 bodies, 20 joints, 17 actuators, 47 meshes
urdf-loadspass27 links, 26 joints, root 'chassis'
joint-names-agreepass17 moving joints, same names, types and tree order: wheel_left, wheel_back, wheel_right, left_shoulder_pan, left_shoulder_lift, left_elbow_flex, left_wrist_flex, left_wrist_roll, left_gripper, right_shoulder_pan, right_shoulder_lift, right_elbow_flex, right_wrist_flex, right_wrist_roll, right_gripper, head_pan, head_tilt; the MJCF adds the base's planar joints base_x, base_y, base_yaw
joint-axes-agreepass17 joints: axes within 0.001 deg and anchors within 0.002 mm over 13 configurations
joint-limits-agreepass14 joints agree within 0 (tolerance 0.001 rad)
twin-limits-agreepasstwin.json limits match URDF and MJCF within 3e-06
units-consistentpasshwUnits, policyIO and 3 cameras are consistent
no-massless-bodiespassevery moving body has mass (45 links and rigid groups checked)
inertia-validpass49 inertias positive definite and within the triangle inequality
mass-agreepass18 rigid groups agree; total 12.0005 kg (URDF) vs 12.0000 kg (MJCF)
actuator-rangespass14 actuators command exactly their joint's range
actuator-params-agreepassactuator parameters of 14 joints agree between twin.json and the models
self-collision-homewarnhome is collision-free; collision geometry interpenetrates at rest: left_lower_arm and left_shoulder by 4.8 mm, left_shoulder and left_wrist by 4.0 mm, right_lower_arm and right_shoulder by 4.8 mm, right_shoulder and right_wrist by 4.0 mm (a pose the real arm reaches without contact: the collision shapes are larger than the parts there)
mesh-validpass30 meshes, 402720 triangles, all readable with plausible size and outward faces; 8 notes: assets/raskogbody.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; assets/raskogwheel1.stl: not closed (0 boundary and 16 non-manifold edges): engines use its convex hull for contact, which is fine, but inertia from this geometry would be wrong; assets/topbase1.stl: not closed (0 boundary and 10 non-manifold edges): engines use its convex hull for contact, which is fine, but inertia from this geometry would be wrong; assets/topbase2.stl: not closed (0 boundary and 32 non-manifold edges): engines use its convex hull for contact, which is fine, but inertia from this geometry would be wrong
chainspass2 arms: left (5 joints + gripper left_gripper, tool point left_gripperframe); right (5 joints + gripper right_gripper, tool point right_gripperframe); other actuated joints head_pan, head_tilt; holonomic base: base_x, base_y, base_yaw driven by velocity actuators base_x_vel, base_y_vel, base_yaw_vel, 3 wheels (wheel_left, wheel_back, wheel_right)
componentspassleft: so-101@1.0.0 at components/so-101 (content digest is the certified bundle's), certified 2026-10-04 by simtwin 0.1.1 (sysid pass, fidelity pass); axes within 0.000 deg and joint and tool points within 0.000 mm of the component's at 13 configurations in both models, 8 bodies' mass, centre of mass, inertia and collision geometry; right: so-101@1.0.0 at components/so-101 (content digest is the certified bundle's), certified 2026-10-04 by simtwin 0.1.1 (sysid pass, fidelity pass); axes within 0.000 deg and joint and tool points within 0.000 mm of the component's at 13 configurations in both models, 8 bodies' mass, centre of mass, inertia and collision geometry. Reused from the components, not refitted here: kp, kv, armature, frictionloss, damping, backlashRad, effortLimit, velocityLimit, timeconst, effortRating of every arm joint. Also reused by declaration, from a joint in another role (the same servo under a different load, so an assumption the fidelity check cannot test unless a recording moves them): head_pan <- shoulder_pan, head_tilt <- shoulder_lift
base-kinematicswarn3 wheels read from the models, holonomic: omni wheels realise every body velocity (rank 3, condition 5.5); the driver (lerobot xlerobot (software/src/robots/xlerobot/xlerobot.py at 749abc8): wheel radius 0.05 m, base radius 0.125 m) on this geometry achieves vx at 101.8 %, vy at 101.8 %, wz at 99.0 % of a commanded twist - within 5 %, a calibration difference between the driver's constants and the CAD; at the wheels' 4.6019 rad/s: vx up to 0.27 m/s, vy up to 0.23 m/s, wz up to 1.82 rad/s
base-stabilitypassstatically stable everywhere it was sampled: 12.00 kg; centre of mass at home (-0.001, 0.000) m, 0.423 m high, 154 mm inside the support polygon (base.support, 4 corners); 400 sampled configurations of every joint: closest 141 mm inside; at home it tips forward (braking) past 4.2 m/s^2, backward (accelerating) past 4.1 m/s^2, to the left (turning right) past 3.6 m/s^2, to the right (turning left) past 3.6 m/s^2 (the base's real acceleration is not identified: base-dynamics)
base-dynamicswarnno recording drives this base, so its dynamics are not identified: how fast it accelerates, how its wheels slip on a floor, how its servos follow a speed command. The twin moves the base kinematically - velocity actuators on its planar joints reach a commanded twist in about 20 ms, without slip - and its mass properties are estimates (twin.json provenance). Trust it for where the base goes, not for how it gets there.
crosscheckpassmujoco: replayed; pybullet: within 0.276 deg and 0.38 mm of MuJoCo over 4 s.
sysidwarn14 joints reuse so-101@1.0.0's fitted values (verified value for value by the components check; that twin's own sysid fitted them). Nothing reused was refitted on this twin's recordings: the fidelity check measures it there. head_pan, head_tilt take values from a joint in another role (head_pan <- shoulder_pan, head_tilt <- shoulder_lift): an assumption, flagged here
fidelitywarnleft arm on xlerobot-team/xlerobot-pick-cup-lr-merge-20260904@c3f58d5aa35e episodes 91-201 (open loop): RMS left_shoulder_pan 0.87, left_shoulder_lift 1.92, left_elbow_flex 1.58, left_wrist_flex 1.33, left_wrist_roll 0.27, left_gripper 2.53 deg; latency 136 ms twin vs 115 ms arm; right arm on xlerobot-team/xlerobot-pick-cup-lr-merge-20260904@c3f58d5aa35e episodes 0-90 (open loop): RMS right_shoulder_pan 0.52, right_shoulder_lift 2.34, right_elbow_flex 1.88, right_wrist_flex 1.71, right_wrist_roll 0.29, right_gripper 2.25 deg; latency 137 ms twin vs 107 ms arm (right_shoulder_lift tracks 2.34 deg RMS (pass at 2)); not measured, no recording moves them: head_pan, head_tilt
dataset-unitswarnxlerobot-team/xlerobot-pick-cup-lr-merge-20260904@c3f58d5aa35e: units deg, range_0_100 confirmed by the values | xlerobot-team/xlerobot-pick-cup-lr-merge-20260904@c3f58d5aa35e: units deg, range_0_100 confirmed by the values; right_arm_shoulder_pan.pos: the values do not decide the unit (lattice spacing 0.087912 = 360/4095 deg: LeRobot degrees mode, or range_m100_100 with a span of exactly 2275 counts (no value past 100 and no clamp to tell them apart)); using the declared deg; right_arm_shoulder_lift.pos: the values do not decide the unit (lattice spacing 0.087912 = 360/4095 deg: LeRobot degrees mode, or range_m100_100 with a span of exactly 2275 counts (no value past 100 and no clamp to tell them apart)); using the declared deg; right_arm_elbow_flex.pos: the values do not decide the unit (lattice spacing 0.087912 = 360/4095 deg: LeRobot degrees mode, or range_m100_100 with a span of exactly 2275 counts (no value past 100 and no clamp to tell them apart)); using the declared deg; right_arm_wrist_flex.pos: the values do not decide the unit (lattice spacing 0.087912 = 360/4095 deg: LeRobot degrees mode, or range_m100_100 with a span of exactly 2275 counts (no value past 100 and no clamp to tell them apart)); using the declared deg; right_arm_wrist_roll.pos: the values do not decide the unit (lattice spacing 0.087912 = 360/4095 deg: LeRobot degrees mode, or range_m100_100 with a span of exactly 2275 counts (no value past 100 and no clamp to tell them apart)); using the declared deg; right_gripper goes 2.5 deg past the twin's limit in 0.3 % of frames
cataloguepassxlerobot-twin@1.0.0: 8 operators (backlash, coarse, compliance, drift, lag, mass, sluggish, weak-grip) over 12 arm joints, sized from this robot's recordings, 13 hazards; valid under mutational's rules

Fidelity per joint

Commanded against measured joint positions over 202 episodes of xlerobot-team/xlerobot-pick-cup-lr-merge-20260904@c3f58d5aa35e: tracking error as RMSE, and overshoot of each step. Control latency 136 ms.

JointTracking RMSE (rad)(degrees)Overshoot
left_shoulder_pan0.0150.870.5%
left_shoulder_lift0.0331.920.0%
left_elbow_flex0.0281.580.0%
left_wrist_flex0.0231.330.5%
left_wrist_roll0.0050.270.0%
left_gripper0.0442.530.0%
right_shoulder_pan0.0090.520.6%
right_shoulder_lift0.0412.340.0%
right_elbow_flex0.0331.880.0%
right_wrist_flex0.0301.710.2%
right_wrist_roll0.0050.290.0%
right_gripper0.0392.250.1%

Engines

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

EngineVersionStatusMeasured
mujoco3.14.0passmaxTrackingRad 0.892
pybullet202010061passmaxJointDivergenceRad 0.00481, rmsJointDivergenceRad 0.000748, maxTipDivergenceM 0.000385

Policy compatibility

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

No policy was checked against this twin.

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.0certified17 x feetech-sts3215 12V 1:345; lerobot xlerobot driver: arms and head P16 I0 D43 (the SO-101 driver: D32), zero at mid-range; wheels in velocity mode under 3000 counts/s04 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: XLeRobot dual-arm mobile robot (0.3, omni-wheel base)

Markdown

[![SimCloud twin: XLeRobot dual-arm mobile robot (0.3, omni-wheel base)](https://sim.mutational.in/v1/twins/badge/xlerobot.svg)](https://sim.mutational.in/twins/xlerobot)

HTML

<a href="https://sim.mutational.in/twins/xlerobot"><img src="https://sim.mutational.in/v1/twins/badge/xlerobot.svg" alt="SimCloud twin: XLeRobot dual-arm mobile robot (0.3, omni-wheel base)"></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": "xlerobot@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).