← Real2Sim home

SIMULATOR · SIMULATION ONLY

superdex_gs: SuperDex physics + Gaussian-splat D415 wrist camera

A standalone simulator for the UR5 CB3 + OnRobot RG2 bottle pick with the new RealSense D415 on mount v4. SuperDex supplies the contact physics (the engine where state-only PPO learned this pick); the calibrated mjlab_gs rendering stack supplies the wrist image (Warp mesh foreground over a 155k-Gaussian room). One vectorized environment serves the privileged state teacher and the image student, with every domain-randomization family from policy_training, mjlab_gs and rl_training.

Next stage: state RL teacher trained in superdex_gs →

1,659
state env steps/s (512 envs, idle hold)
359
state env steps/s during scripted grasping (256 envs)
1,055
visual 320×180 env steps/s, nominal (512 envs)
688
visual 320×180 env steps/s, full DR (512 envs)
3.4e-07 m
FK parity vs calibrated MuJoCo scene
0.27 mm
max bottle resting penetration, 12 tabletop locations

Hardware: one RTX A6000 (rendering) and a 28-core / 56-thread Xeon W-3175X (physics). Throughput is total environment steps per second across all parallel environments at 20 Hz control with 2 ms physics. Evidence below is from the scripts named in each section; the scripted expert is privileged and is not a learned policy.

What was built

Scenemjlab_gs calibrated room, table, pedestal, UR5 CB3 and legacy RG2 with the D455 replaced by the D415 on mount v4. D415 colour factory intrinsics 1280×720 (fx 913.94, fy 912.14); optical centre matches the CAD metadata to 2.5e-15 m; vertical FOV 43.08°.
PhysicsMJCF robot converted to a SuperDex articulation (22 links incl. welded convex-hull collision links); RG2 parallelograms closed with cycle joints and two symmetric torque-limited drives; bottle scan surface as SDF; 4 cm table slab, cabinet, pedestal and floor. 2 ms implicit steps, 25 per 20 Hz tick.
Control7-D base-frame Cartesian actions (5 mm, 1° per tick), damped-least-squares IK and analytic gravity compensation at 125 Hz, gripper linkage target; contract superdex-gs-cartesian-v1.
ParallelismEach worker process owns a block of SuperDex scenes and runs whole ticks (IK + physics) with shared-memory state; the main process batches DR, observations, rewards, success and GPU rendering. A thread backend is kept for comparison.
RenderingRender-only mujoco_warp model fed with SuperDex poses, mjlab_gs's calibrated Warp foreground with shadows and textures, gsplat room with the pedestal field moved per world, CUDA-graph capture (57 ms → 0.40 ms per image), per-world camera, light, material, texture, background and image randomization.
TasksState teacher: 43-D privileged observation. Visual student: 16-D proprioception + 3-D goal + 180×320 RGB; 61-D critic. Strict success: ≥10 cm clearance, bilateral pad contact, stable, held 2 s. Details: TASK.md, README.md.

Issues found and fixed while validating

SymptomCauseFix (before the final measurements)
RG2 linkage jammed at 0.05 radSuperDex revolute limits are z components; MJCF hinge axes were yJoint frames rotated so every hinge axis is +z; FK parity re-checked
Arm sagged 2 mrad with exact gravity feed-forwardTracking force is 2·stiffness·errorStiffness = kp/2; effective kp measured
Throughput flat beyond ~12 cores (620 steps/s at 64 envs)Python GIL re-acquired after every Scene.stepWorker processes with shared-memory state, one message per 20 Hz tick
Wrist render cost 57 ms per call regardless of world countThe calibrated Warp renderer rebuilds its kernel in Python per callCUDA-graph capture of the whole Warp sequence (bit-identical, 0.40 ms/image)
Bottles sank, tipped or fell through the table away from its centreContact sampled on a 12-triangle tabletopTabletop tessellated to ≤3 cm triangles; checked at 12 locations
Bottles tipped at reset under combined layout + physics randomizationChanging the bottle's local COM after posing moves its shapeMass properties set before the pose
Randomized starts inside the table or bottleUnfiltered joint offsets (also in mjlab_gs)Reset guard halves offsets until the TCP clears table and bottle

Physics validation

Grasp-and-lift through the action interface

A privileged scripted expert issues the same 7-D actions a policy would (approach, descend, close, lift). Each environment's first episode counts; strict success as above.

DR presetStartScaleSuccessesRateFailure outcomes
nominaljoint0.016 / 16100%–
teachercartesian (49 Cartesian)0.356 / 56100%–
teachercartesian (21 Cartesian)1.051 / 5691%lifted, hold < 2 s 3, never bilaterally grasped 2
teacherjoint0.356 / 56100%–
teacherjoint0.655 / 5698%lifted, hold < 2 s 1
teacherjoint1.051 / 5691%lifted, hold < 2 s 3, never bilaterally grasped 2
visualjoint0.356 / 56100%–
visualjoint0.653 / 5695%lifted, hold < 2 s 3
visualjoint1.033 / 5659%grasped, not lifted 10 cm 3, lifted, hold < 2 s 7, never bilaterally grasped 13

Reachability of the randomized layouts

top-down TCP orientation (nominal, ±0.12 rad yaw), 5 mm tolerance; homotopy damped-least-squares IK from the nominal arm pose. Unreachable Cartesian starts fall back to the joint-offset start.

PresetScaleTop-down grasp reachableCartesian start reachable
teacher0.3120 / 120107 / 120
teacher0.692 / 12058 / 120
teacher1.058 / 12037 / 120
visual0.3113 / 12089 / 120
visual0.680 / 12051 / 120
visual1.054 / 12040 / 120

The expert never re-plans: it has no regrasp, no reorientation and no recovery after a bottle is knocked over. At full layout randomization many bottles sit outside the arm's top-down workspace (table ±30 cm, base ±20 cm), so failures there mostly reflect the distribution and the expert rather than simulator errors. Raw results are linked below.

Wrist camera and domain randomization

Nominal D415 wrist view (4 worlds)
Nominal D415 wrist view (4 worlds)
Full visual DR, scale 1.0 (8 worlds)
Full visual DR, scale 1.0 (8 worlds)
Visual DR, scale 0.3 (8 worlds)
Visual DR, scale 0.3 (8 worlds)
Grasp sequence, nominal (every second)
Grasp sequence, nominal (every second)
All randomized quantities (RANDOMIZATION.md)
FamilyQuantityRange at scale 1Source
layouttable XY / yaw±0.30 m / ±30° (teacher ±0.15 m / ±15°)MG (PT ±1.5 cm / ±1.4°)
layoutbottle positioninterpolates nominal → uniform over tabletop minus 5 cm margin (±0.340, ±0.182 m)MG
layoutbottle yaw±180° relative to tableMG, PT
layoutrobot base + pedestal XY / yaw (Gaussian pedestal moves with it)±0.20 m / ±30° about the pedestal origin (teacher ±0.10 / ±15°)MG (PT ±5 mm / ±1°)
robot_initarm joint offsets±[45, 20, 30, 45, 30, 90]° (teacher ±[15, 10, 10, 15, 15, 30]°); guard halves offsets until the TCP is ≥ 4 cm above the table and clear of the bottleMG; guard new
robot_initCartesian start (`start_mode="cartesian"`)TCP = grasp + 17 cm stratum {11, 14.5, 18} cm, XY ±7 / ±4.5 cm, grasp yaw ±0.12 rad; IK from nominalPT
robot_initinitial gripper opennessU(0.85, 1)MG
physicsfriction (bottle, pads, fingertips, table, floor)×0.7–1.3MG
physicsbottle mass + inertia×0.8–1.2MG
physicsbottle COM offset±3 mm per axisnew
physicsdrive damping (arm kd, RG2 joint viscous)×0.8–1.2MG
physicsarm position gains×0.9–1.1 (gravity feed-forward uses the randomized gain)new
physicsgripper force limit×0.8–1.2new
cameramount position / rotation±1 cm / ±5°MG (PT ±2 mm / ±1°)
camerafocal lengths fx, fy×(1 ± 0.02)MG, PT
cameraprincipal point±6.4 / ±3.6 px of the 1280×720 sensor (0.5%)MG, PT (rescaled to D415)
lightingkey light position / direction±0.3 m / ±0.15 per componentPT
lightingkey light intensity and tint×0.7–1.3, per-channel ×0.9–1.1MG, PT
lightingtwo fill lightseach on with p = 0.5, intensity U(0, 0.3), random position above the tablePT (multi-light)
materialsper-material RGB gain×0.8–1.2 per channel, independent per materialPT (MG shared one gain)
materialsper-material specular×0.5–1.5PT
materialstable texturep = 0.5: calibrated scan, else 2 stripe patterns (PT formula) or 3 builtin patternsPT
backgroundGaussian room brightness and tint×0.85–1.15 and ×0.95–1.05 per channelnew
imageexposure / white balance×0.85–1.15 / ×0.95–1.05 per channelMG, PT
imagesensor noiseσ ~ U(0.3, 2)/255 per episode, per pixel per framePT (MG fixed σ)
imagecontrast / gamma×0.9–1.1 eachPT augmentation
image3×3 blurp = 0.1 per episodePT augmentation
timingaction latencyone-tick delay for the episode with p = 0.2new
timingstale camera framep = 0.05 per ticknew
timingAR(1) correlated translation noiseσ mm (default 0), ρ 0.9PT (evaluation option)
observation_noiseteacher joints / velocities / relative positions±0.01 rad / ±0.05 rad/s / ±2 mmMG/RL teacher
disturbancebottle pushp = 0.2 per episode, 0.05–0.2 N horizontal, random time 4–10 s, 0.1 sMG/RL (evaluation push schedules) as a training DR
goalcommanded positionnominal TCP ± 5/5/3 cmMG

Throughput, GPU and CPU

throughput
breakdown
workers
render_cost
gpu_memory

State task, process backend (idle hold)

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
state, hold, process backend11532.615.63.30.00.00.001.4
state, hold, process backend8833416.719.44.50.00.00.005.8
state, hold, process backend161666833.421.12.80.00.00.0011.0
state, hold, process backend323292146.130.64.10.00.00.0022.8
state, hold, process backend64561,05052.554.06.90.00.00.0028.4
state, hold, process backend128561,28264.186.513.30.00.00.0029.5
state, hold, process backend256561,51375.7148.320.80.00.00.0031.2
state, hold, process backend512561,65983.0271.137.50.00.00.0027.6

Times are wall-clock ms per 20 Hz tick for all environments together.

State task, thread backend (idle hold)

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
state, hold, thread backend (8 threads)88773.8100.23.90.00.00.002.4
state, hold, thread backend (8 threads)64831115.5195.110.90.00.00.004.5
state, hold, thread backend (8 threads)256843521.7564.024.80.00.00.005.7

Times are wall-clock ms per 20 Hz tick for all environments together.

State task, scripted grasping (contact-rich)

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
state, scripted pick (contact)16161889.480.83.60.00.00.0012.9
state, scripted pick (contact)645626913.5225.310.80.00.00.0027.3
state, scripted pick (contact)2565635917.9685.924.20.00.00.0031.3

Times are wall-clock ms per 20 Hz tick for all environments together.

Visual task 320×180, nominal

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
visual 320x180, nominal161647723.823.52.47.60.01.469.3
visual 320x180, nominal645672736.459.57.421.20.01.7120.9
visual 320x180, nominal256561,00650.3150.321.582.60.02.4220.6
visual 320x180, nominal512561,05552.7273.440.4171.60.03.2918.2

Times are wall-clock ms per 20 Hz tick for all environments together.

Visual task 320×180, full domain randomization

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
visual 320x180, full DR 1.0161633816.931.52.513.40.01.968.8
visual 320x180, full DR 1.0645649925.075.58.843.90.02.0818.5
visual 320x180, full DR 1.02565664732.4197.023.4175.20.02.3717.1
visual 320x180, full DR 1.05125668834.4351.638.5353.60.03.3715.4

Times are wall-clock ms per 20 Hz tick for all environments together.

Visual scripted grasping (DR 0.3) and state hold with teacher DR 1.0

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
visual 320x180, scripted pick, DR 0.3645622711.4216.511.951.90.02.0920.0
visual 320x180, scripted pick, DR 0.32565630115.0623.324.2199.60.02.3822.0
state, hold, teacher DR 1.0256561,20860.4188.523.40.00.00.0030.6

Times are wall-clock ms per 20 Hz tick for all environments together.

Worker process sweep

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
state 256 envs, 7 workers256760730.4398.423.00.00.00.006.8
state 256 envs, 14 workers256141,01250.6229.423.40.00.00.0011.6
state 256 envs, 28 workers256281,25963.0180.522.80.00.00.0019.7
state 256 envs, 56 workers256561,49774.8149.121.90.00.00.0031.2

Times are wall-clock ms per 20 Hz tick for all environments together.

IK update rate and physics timestep

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
state 128 envs, IK every 1 substeps1285684142.1139.312.80.00.00.0031.9
state 128 envs, IK every 2 substeps128561,09754.8103.912.80.00.00.0031.3
state 128 envs, IK every 4 substeps128561,27964.087.013.10.00.00.0029.5
state 128 envs, IK every 8 substeps128561,40270.178.812.50.00.00.0028.3
state 128 envs, 1 ms physics1285674837.4156.814.40.00.00.0031.1

Times are wall-clock ms per 20 Hz tick for all environments together.

Image resolution and shadows

ConfigurationEnvsWorkersEnv steps/sSim s / wall sSimulateObserveRenderResetGPU GiBCPU cores
visual 128 envs 90x160128561,04952.490.713.018.30.01.8325.6
visual 128 envs 180x3201285688544.392.812.639.10.02.0421.4
visual 128 envs 360x6401285660830.494.213.1103.10.03.2014.9
visual 128 envs 720x12801285630715.493.012.0311.60.09.557.3
visual 128 envs 180x320 no shadows1285697748.989.912.428.70.02.0423.8

Times are wall-clock ms per 20 Hz tick for all environments together.

For reference, mjlab_gs (MuJoCo-Warp, fully on GPU) measured 10,871 state env steps/s at 1,024 worlds and 2,842 visual steps/s at 1,024 worlds with 128×128 images. superdex_gs trades that throughput for SuperDex's contact model: physics runs on CPU cores, so throughput is set by core count, and contact-rich phases cost more than idle steps.

Rendering and contact-cost studies

Randomized robot-base layouts. The pedestal Gaussians move with the base, so each world needs its own rasterization. The exact path (default, as mjlab_gs, chunks of 16) costs 0.59 ms per image at 256 worlds. An optional two-layer composite (room batched once, 19k pedestal Gaussians per world, depth-ordered alpha compositing) costs 0.43 ms, with background PSNR median 47.8 dB but 31.2 dB in the worst world (edge artifacts where the camera sees the pedestal), so it is not the default.

two-layer worst case
Worst world: exact (left), two-layer (middle), absolute difference ×4 (right).

Collision-hull resolution. 16 envs, teacher DR 0.3, scripted pick; mean worker physics ms per 20 Hz tick (one world per worker). Default keeps MuJoCo full convex hulls.

Max hull verticesPhysics ms/tick, approachPhysics ms/tick, grasp + holdScripted success
full (MuJoCo hulls, default)34.556.816/16
20033.554.816/16
6432.640.115/16

RL integration. An rsl_rl 5.5 PPO runner consumed the environment through superdex_gs.rl.RslRlEnv for 5 iterations (15,360 steps, 128 envs, 653 steps/s including updates). This checks the interface only; no teacher has been trained yet.

Unit tests: 7 passed in 2.41s

Videos

Left: third-person MuJoCo view of the same state. Right: the policy's wrist RGB (D415, Warp mesh + Gaussian room), with clearance, contact and hold overlays.

nominal: preset nominal scale 0.0, env 0 — scripted expert, success=True, max clearance 15.5 cm, best hold 8.40 s. Illustration; not a learned policy.
nominal: preset nominal scale 0.0, env 1 — scripted expert, success=True, max clearance 15.5 cm, best hold 8.40 s. Illustration; not a learned policy.
teacher_dr_0.6: preset teacher scale 0.6, env 0 — scripted expert, success=True, max clearance 16.1 cm, best hold 3.60 s. Illustration; not a learned policy.
teacher_dr_0.6: preset teacher scale 0.6, env 1 — scripted expert, success=True, max clearance 15.5 cm, best hold 8.05 s. Illustration; not a learned policy.
visual_dr_0.5: preset visual scale 0.5, env 0 — scripted expert, success=True, max clearance 15.4 cm, best hold 6.55 s. Illustration; not a learned policy.
visual_dr_0.5: preset visual scale 0.5, env 1 — scripted expert, success=True, max clearance 15.6 cm, best hold 3.50 s. Illustration; not a learned policy.
visual_dr_1.0: preset visual scale 1.0, env 0 — scripted expert, success=True, max clearance 15.5 cm, best hold 2.40 s. Illustration; not a learned policy.
visual_dr_1.0: preset visual scale 1.0, env 1 — scripted expert, success=False, max clearance 15.9 cm, best hold 0.60 s. Illustration; not a learned policy.

Limitations

Raw artifacts

benchmark/ik_period_1.json · benchmark/ik_period_2.json · benchmark/ik_period_4.json · benchmark/ik_period_8.json · benchmark/image_180x320.json · benchmark/image_180x320_noshadow.json · benchmark/image_360x640.json · benchmark/image_720x1280.json · benchmark/image_90x160.json · benchmark/physics_dt_1ms.json · benchmark/state_hold_sweep.json · benchmark/state_hold_sweep_threads.json · benchmark/state_hold_teacher_dr.json · benchmark/state_pick_sweep.json · benchmark/visual_hold_fulldr.json · benchmark/visual_hold_nominal.json · benchmark/visual_pick_dr03.json · benchmark/workers_14.json · benchmark/workers_28.json · benchmark/workers_56.json · benchmark/workers_7.json · reports/physics_checks.json · reports/fk_parity.json · reports/scene_build.json · reports/contract_visual.json · pick/nominal.json · pick/teacher_cartesian_0.3.json · pick/teacher_cartesian_1.0.json · pick/teacher_joint_0.3.json · pick/teacher_joint_0.6.json · pick/teacher_joint_1.0.json · pick/visual_joint_0.3.json · pick/visual_joint_0.6.json · pick/visual_joint_1.0.json

Built 2026-09-14T23:03:20+00:00 · Physics-only simulator experiments · RL training · mjlab_gs