# Data config: pusht — 100 Franka teleop demonstrations of the real-hardware # Push-T task (HF dataset SleepMastger/pusht-manipulation), 32,131 frames at # 10 Hz across 4 collection sessions. Converted to LeRobot v2.1 by # lift2lerobot/convert_lift_hdf5_to_lerobot_v21.py (--fps 10) via the # raw/pusht_layout symlink shim. # # Task string (deploy-critical, must byte-match at inference, NO trailing # period): "push the T block to the target outline" # # DEGENERATE CHANNELS — read before changing norm settings. # The teleop rig commanded translation only and the gripper stayed clamped on # the pusher pen for the whole task, so 6 of the 15 numeric channels are # constant across all 32,131 frames (measured, not assumed): # action drx, dry, drz range 0.0 # action gripper range 0.0 (raw +1 -> (1-g)/2 -> 0.0) # state gripL, gripR range 3.2e-05 # The dataset README warns this makes a min/max normalizer divide by zero. # It does NOT here: SingleFieldLinearNormalizer (normalizer.py:96-118) has # `ignore_dim = input_range < range_tol` with range_tol = 1e-4, which catches # all six (the tightest, 3.2e-05, clears it by 3x) and gives them scale 1.0 # with offset -min instead of dividing by ~0. So an ignored dim normalizes to # (x - min): exactly 0 for the four action dims whose raw range is exactly # 0.0, and [0, 3.2e-05] for the two gripper state dims. Either way the output # is finite and bounded by the raw range, i.e. below range_tol — negligible # next to the +/-1 live channels. Verified end to end by preflight.py, not # just read off the source. Keeping the full 7-dim action / 8-dim proprio # costs nothing and keeps the architecture byte-identical to the dish_utensil # and fruit runs, so results stay comparable. If you ever raise range_tol # below 3.2e-05, the gripper state dims WILL go inf — don't. # # Staged by stage_pusht_local.sh to node-local /tmp (NOT /dev/shm — 853 wipe). train: _target_: fastwam.datasets.lerobot.robot_video_dataset.RobotVideoDataset dataset_dirs: - /tmp/george_pusht/pusht_lerobot_v21 shape_meta: images: - key: image raw_shape: [3, 256, 256] shape: [3, 224, 224] - key: wrist_image raw_shape: [3, 256, 256] shape: [3, 224, 224] action: - key: default raw_shape: 7 # before transform shape: 7 # after transform state: - key: default raw_shape: 8 # before transform shape: 8 # after transform num_frames: 33 global_sample_stride: 1 action_video_freq_ratio: 4 # 32 action, 9 video frames video_size: [224, 448] # final resize video camera_key: null val_set_proportion: 0.0 is_training_set: true skip_padding_as_possible: false concat_multi_camera: "horizontal" processor: _target_: fastwam.datasets.lerobot.processors.fastwam_processor.FastWAMProcessor shape_meta: ${data.train.shape_meta} num_obs_steps: ${data.train.num_frames} num_output_cameras: 2 action_output_dim: 7 # eef_pose (6) + gripper (1) proprio_output_dim: 8 # eef_pose (6) + gripper (2) delta_action_dim_mask: # The raw HDF5 actions are ALREADY per-step deltas (dx,dy,dz in metres # per 100 ms), so this mask is not a "convert to delta" switch — the # processor only uses it to zero PADDED action steps on the dims where # 0 is the neutral value (fastwam_processor.py:300-308). default: [true, true, true, true, true, true, false] # eef poses are delta, gripper is not # action & state normalization action_state_transforms: null use_stepwise_action_norm: False norm_default_mode: min/max norm_exception_mode: null action_state_merger: _target_: fastwam.datasets.lerobot.transforms.action_state_merger.ConcatLeftAlign train_transforms: - _target_: fastwam.datasets.lerobot.transforms.image.ToTensor - _target_: torchvision.transforms.Resize size: [224, 224] val_transforms: - _target_: fastwam.datasets.lerobot.transforms.image.ToTensor - _target_: torchvision.transforms.Resize size: [224, 224] text_embedding_cache_dir: /tmp/george_pusht/pusht_text_embeds_cache context_len: 128