CoolFace
Datasetpublic

Harrysunshine/so101-sim-pickplace

SO-101 Sim Pick-and-Place Simulated pick-and-place demonstrations for the SO-101 arm, generated in ManiSkill3 / SAPIEN with a robot model, object geometry and camera calibration matched to a real desktop rig. Config Task prompt Object Episodes Frames Trajectories from cube40 Pick up a cube and place in the bin 40 mm cube 465 172,869 scripted servo cube20 Pick up a small cube and place in the bin 20 mm cube 477 186,438 scripted servo cylinder40 Pick up a can and… See the full description on the dataset page: https://huggingface.co/datasets/Harrysunshine/so101-sim-pickplace.

sourceHugging Faceapache-2.0updated 23d agoView on Hugging Face
0likes276downloads
Dataset Card

SO-101 Sim Pick-and-Place

Simulated pick-and-place demonstrations for the SO-101 arm, generated in ManiSkill3 / SAPIEN with a robot model, object geometry and camera calibration matched to a real desktop rig.

ConfigTask promptObjectEpisodesFramesTrajectories from
cube40Pick up a cube and place in the bin40 mm cube465172,869scripted servo
cube20Pick up a small cube and place in the bin20 mm cube477186,438scripted servo
cylinder40Pick up a can and place in the bin40 mm cylinder, upright468175,585scripted servo
cube40_rlPick up a cube and place in the bin40 mm cube23997,682RL grasps, script transports
total1,649632,574

The prompts are byte-identical to the corresponding tasks in our real-robot recordings — same object, same physical kit, same wording. A VLA keys on the prompt text, so a single differing word would make it learn one task as two and quietly forfeit the cross-domain transfer. cube20 has no real-robot counterpart; it is worded to sit alongside the others.

★ Units: the same mixed convention a real SO-101 records

action and observation.state are six-dimensional and not normalised. The convention is mixed, because that is what the real robot produces — lerobot-record drives an SO-101 through so_follower, whose per-joint normalisation modes differ:

ChannelUnitRange in this dataset
shoulder_pan … wrist_roll (5 arm joints)degrees−110 … 116
gripper0–100 % of travel5.6 … 74.5

The gripper is a percentage, not an angle: so_follower hard-codes it to MotorNormMode.RANGE_0_100 regardless of use_degrees. Matching a simulator to a real arm is therefore a per-channel conversion, not one unit change. The percentage is computed from the gripper joint's own URDF limits (−10° … 100°, so 110° of travel):

percent = (degrees − (−10)) / 110 × 100

Cross-check against hardware: the simulated fully-open pose is 44.95° → 49.96 %, and the real arm measures 50.6 % at the same pose.

⚠️ Community SO-101 datasets do not all use this convention — HuggingFace's own lerobot/svla_so101_pickplace is normalised to ±100 (its action touches exactly ±100.00, the signature of a clamp). Check before mixing datasets: the gripper channel is the one that bites, because degrees and percent happen to span the same numeric range here, so a wrong assumption looks plausible and only shows up as "grasping never learns".

action is an absolute joint-position target (not a delta), recorded at control mode pd_joint_pos. Observations are 480×640 RGB from two cameras (top, wrist) at 30 fps, robot_type = so_follower.

Every episode's frame 0 is the real arm's power-on pose [-5.76, -102.68, 92.97, 63.38, -0.53, 1.90] (degrees), identical across all 1,649 episodes.

Verification

Driving the simulator with real-robot actions reproduces the real observations before contact: per-channel correlation 0.991–1.000, residual ≤1.22° (arm) / 0.48 % (gripper), zero out-of-limit actions. Replaying this dataset's actions back into the simulator from each episode's recorded initial scene completes the task and reproduces the recorded observations to within the simulator's own run-to-run non-determinism.

The one systematic difference that remains is a ~2° zero-point offset on elbow_flex between the real arm's calibration midpoint and the URDF zero. That is per-robot calibration, not a convention mismatch, and it is deliberately not compensated in simulation.

Only completed episodes are included

Each episode is judged by the environment's own evaluate() (object inside the bin opening ∧ arm not touching the object ∧ arm static ∧ arm not touching the bin): 1,833 → 1,649, dropping 184 (10.0 %). Of those kept, over 99.8 % have the object in the bin, with a median final offset of 0.04–0.21 of the bin opening's half-width.