File size: 3,422 Bytes
1e1de0b 9b38f2b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | # 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_<family>.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
|