# ManiGuard datagen-v1 robot config -- single-arm Franka (7 arm joints + 1 gripper), 2 cameras. # # Maps the datagen LeRobot v2.1 features to LingBot's unified feature space. The datagen # datasets ship FLAT keys (state / actions / image_left / wrist_image) instead of the # observation.* names used by the RoboTwin sample. That is fine: `origin_keys` is a # free-form lookup into the LeRobot item (see lingbotvla/data/vla_data/utils.py -- # `out_item[target_key] = item[convert_info['origin_keys']]`), and check_robot_config only # validates the TARGET side (the unified names must be declared in the training config's # data.joints / data.cameras). So no dataset conversion is required: the six datagen # datasets stay read-only and byte-identical to the ones the pi0.5 / pi0 / GR00T / SmolVLA # tracks train on -- the whole point of the ManiGuard benchmark's same-data guarantee. # # 8-D layout of both `state` and `actions`: [arm_q(7), gripper(1)] # arm.position <- [0:7) # effector.position <- [7:8) # The unified vector is 55-D; the dims we do not fill are padded/masked by the loader # (data.joints keeps the pretraining-aligned sizes, incl. an unused end.position entry). # # subtract_state: False on BOTH features -- the model learns ABSOLUTE joint targets. # This follows LingBot's own simulation recipe (configs/robot_configs/robotwin.yaml, where # both features use False; state-relative arm actions are the recommendation for REAL-robot # data) and matches our datasets, whose `actions` are absolute joint positions. # => At eval the server's output is fed straight to the JointController with NO # delta/un-relative step (same contract as SmolVLA; pi0.5/pi0/GR00T do add state back). # # Cameras: the policy consumes 2 views -- the `left` overview + wrist -- identical to the # other four base models (benchmark parity). The datagen datasets also ship three more # overviews (image_opposite / image_right / image_left_shoulder); they are simply not mapped. # # norm_stats below is a DEFAULT: every family has its own statistics, so run_sft.sh passes # `--data.norm_stats_file assets/norm_stats/maniguard_.json` per run, which takes # precedence (FeatureTransform: an explicit norm_stats_path overrides the robot config's). states: - observation.state.arm.position: origin_keys: - state: start: 0 end: 7 - observation.state.effector.position: origin_keys: - state: start: 7 end: 8 actions: - action.arm.position: origin_keys: - actions: start: 0 end: 7 subtract_state: False - action.effector.position: origin_keys: - actions: start: 7 end: 8 subtract_state: False images: - observation.images.camera_top: origin_keys: image_left - observation.images.camera_wrist_left: origin_keys: wrist_image # norm_stats points at THIS checkpoint's own statistics (the file shipped beside this # one). It must stay present even when a loader passes an explicit path: LingBot's # FeatureTransform does `robot_config.pop('norm_stats')` with no default on both # branches, so a missing key raises KeyError. The path is relative to this checkpoint's # root -- resolve it yourself, or pass an absolute `norm_stats_path` # (maniguard/serve/lingbot_native.py does the latter). norm_stats: maniguard/norm_stats.json