protomotions.robot_configs module#
Robot configuration classes defining morphology and control parameters.
For model selection, asset requirements and motion preparation, see Robots.
Base Configuration#
- class protomotions.robot_configs.base.RobotConfig(
- asset,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=1,
- semantic_forward_axis_xy=None,
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset='all',
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name=None,
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=None,
- simulation_params=None,
Bases:
objectConfiguration for robot morphology and control parameters.
Defines all robot-specific parameters including asset files, body names, control settings, and physical properties. Each robot (SMPL, G1, etc.) should subclass this and provide robot-specific values.
Key configuration areas:
Asset: Robot mesh/URDF files and physical properties
Body Names: Named body parts for tracking and observations
Control: PD gains, action scales, and control modes
Kinematic Info: Joint structure extracted from MJCF/URDF
Simulator Params: Simulator-specific overrides
Example:
config = RobotConfig( semantic_forward_axis_xy=(1.0, 0.0), asset=RobotAssetConfig(asset_file_name="robot.xml"), control=ControlConfig(control_type=ControlType.BUILT_IN_PD) )
- asset: RobotAssetConfig#
- semantic_forward_axis_xy: Tuple[float, float] | None = None#
Robot-local xy axis that points in the anatomical facing direction.
This is intentionally 2D, not 3D. ProtoMotions assumes Z-up humanoid assets, so heading should only choose the horizontal anatomical forward direction. Keeping the field in xy avoids using a forward vector with a vertical component that would require re-orienting the robot to stand upright before heading logic can be applied.
Every robot config declares this explicitly:
__post_init__refusesNone, and a saved robot subtree without the field fails to load, sincefrom_treerebuilds every dataclass through its constructor. To identify the axis for a new robot, runpython scripts/identify_robot_facing_axis.py --robots <robot-name> --view.
- imu_mount_quat: Tuple[float, float, float, float] = (0.0, 0.0, 0.0, 1.0)#
Unit xyzw rotation from sensor axes to the carrying body’s axes.
- control: ControlConfig#
- kinematic_info: KinematicInfo#
- property anchor_body_index: int#
Body index observations/rewards anchor on (0 = root), derived from the name.
There is one anchor slot, anchor_body_name. Assigning it re-derives the index on the next read, so the two cannot drift apart; there is no stored index to set (update_fields and the override funnel refuse it). The cache is rebuilt when it is absent too, so a config unpickled from a pre-property bundle (which has no cache) re-derives from the name rather than raising AttributeError on the first read.
- property resolved_anchor_body_name: str#
The anchored body’s name, resolved through anchor_body_index.
- body_indices(*names)[source]#
Indices for body names, ‘root’, ‘all’ or semantic groups, in declaration order.
Each name is ‘root’, ‘all’, a key of common_naming_to_robot_body_names, or a body name; the expansion is abstract_names_to_body_names’, with an unknown name and a body selected twice refused (both of which that function silently allows).
- bodies_matching(pattern)[source]#
Indices of bodies whose name fully matches
pattern(regex), in body order.
- update_fields(**kwargs)[source]#
Update robot config fields and reprocess derived fields.
This is useful when you need to modify fields after initialization without manually calling __post_init__.
- Parameters:
**kwargs – Fields to update on the robot config
- __init__(
- asset,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=1,
- semantic_forward_axis_xy=None,
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset='all',
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name=None,
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=None,
- simulation_params=None,
SMPL Humanoid#
- class protomotions.robot_configs.smpl.SmplRobotConfig(asset: protomotions.robot_configs.base.RobotAssetConfig = <factory>, common_naming_to_robot_body_names: Dict[str, str] = <factory>, default_root_height: float = 0.95, semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0), default_dof_pos: Union[List[float], MockTensor, Dict[str, float], NoneType] = None, contact_bodies: Union[List[str], str, NoneType] = None, contact_partners: Union[List[str], str] = <factory>, trackable_bodies_subset: List[str] = <factory>, non_termination_contact_bodies: List[str] = <factory>, init_state: Optional[protomotions.robot_configs.base.InitState] = None, reset_noise: Optional[protomotions.simulator.base_simulator.config.RobotNoiseConfig] = None, mimic_small_marker_bodies: Optional[List[str]] = None, anchor_body_name: Optional[str] = None, imu_body_name: Optional[str] = None, imu_mount_quat: Tuple[float, float, float, float] = (0.0, 0.0, 0.0, 1.0), contact_pairs_multiplier: int = 16, control: protomotions.robot_configs.base.ControlConfig = <factory>, control_hz: int = 30, simulation_params: protomotions.robot_configs.base.SimulatorParams = <factory>)[source]#
Bases:
RobotConfig- semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0)#
Robot-local xy axis that points in the anatomical facing direction.
This is intentionally 2D, not 3D. ProtoMotions assumes Z-up humanoid assets, so heading should only choose the horizontal anatomical forward direction. Keeping the field in xy avoids using a forward vector with a vertical component that would require re-orienting the robot to stand upright before heading logic can be applied.
Every robot config declares this explicitly:
__post_init__refusesNone, and a saved robot subtree without the field fails to load, sincefrom_treerebuilds every dataclass through its constructor. To identify the axis for a new robot, runpython scripts/identify_robot_facing_axis.py --robots <robot-name> --view.
- __init__(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=0.95,
- semantic_forward_axis_xy=(1.0,
- 0.0),
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset=<factory>,
- non_termination_contact_bodies=<factory>,
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name=None,
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=30,
- simulation_params=<factory>,
SMPL-X Humanoid#
- class protomotions.robot_configs.smplx.SMPLXRobotConfig(asset: protomotions.robot_configs.base.RobotAssetConfig = <factory>, common_naming_to_robot_body_names: Dict[str, List[str]] = <factory>, default_root_height: float = 0.95, semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0), default_dof_pos: Union[List[float], MockTensor, Dict[str, float], NoneType] = None, contact_bodies: List[str] = <factory>, contact_partners: Union[List[str], str] = <factory>, trackable_bodies_subset: Union[List[str], str] = 'all', non_termination_contact_bodies: List[str] = <factory>, init_state: Optional[protomotions.robot_configs.base.InitState] = None, reset_noise: Optional[protomotions.simulator.base_simulator.config.RobotNoiseConfig] = None, mimic_small_marker_bodies: List[str] = <factory>, anchor_body_name: Optional[str] = None, imu_body_name: Optional[str] = None, imu_mount_quat: Tuple[float, float, float, float] = (0.0, 0.0, 0.0, 1.0), contact_pairs_multiplier: int = 20, control: protomotions.robot_configs.base.ControlConfig = <factory>, control_hz: int = 30, simulation_params: protomotions.robot_configs.base.SimulatorParams = <factory>)[source]#
Bases:
RobotConfig- semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0)#
Robot-local xy axis that points in the anatomical facing direction.
This is intentionally 2D, not 3D. ProtoMotions assumes Z-up humanoid assets, so heading should only choose the horizontal anatomical forward direction. Keeping the field in xy avoids using a forward vector with a vertical component that would require re-orienting the robot to stand upright before heading logic can be applied.
Every robot config declares this explicitly:
__post_init__refusesNone, and a saved robot subtree without the field fails to load, sincefrom_treerebuilds every dataclass through its constructor. To identify the axis for a new robot, runpython scripts/identify_robot_facing_axis.py --robots <robot-name> --view.
- __init__(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=0.95,
- semantic_forward_axis_xy=(1.0,
- 0.0),
- default_dof_pos=None,
- contact_bodies=<factory>,
- contact_partners=<factory>,
- trackable_bodies_subset='all',
- non_termination_contact_bodies=<factory>,
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=<factory>,
- anchor_body_name=None,
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=20,
- control=<factory>,
- control_hz=30,
- simulation_params=<factory>,
Unitree H1 (Version 2)#
- class protomotions.robot_configs.h1_2.H1_2RobotConfig(asset: protomotions.robot_configs.base.RobotAssetConfig = <factory>, common_naming_to_robot_body_names: Dict[str, List[str]] = <factory>, default_root_height: float = 1.03, semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0), default_dof_pos: Union[List[float], MockTensor, Dict[str, float], NoneType] = None, contact_bodies: Union[List[str], str, NoneType] = None, contact_partners: Union[List[str], str] = <factory>, trackable_bodies_subset: List[str] = <factory>, non_termination_contact_bodies: Union[List[str], str] = 'all', init_state: Optional[protomotions.robot_configs.base.InitState] = None, reset_noise: Optional[protomotions.simulator.base_simulator.config.RobotNoiseConfig] = None, mimic_small_marker_bodies: Optional[List[str]] = None, anchor_body_name: Optional[str] = None, imu_body_name: str = 'torso_link', imu_mount_quat: Tuple[float, float, float, float] = (0.0, 0.0, 0.0, 1.0), contact_pairs_multiplier: int = 16, control: protomotions.robot_configs.base.ControlConfig = <factory>, control_hz: int = 50, simulation_params: Optional[protomotions.robot_configs.base.SimulatorParams] = None)[source]#
Bases:
RobotConfig- semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0)#
Robot-local xy axis that points in the anatomical facing direction.
This is intentionally 2D, not 3D. ProtoMotions assumes Z-up humanoid assets, so heading should only choose the horizontal anatomical forward direction. Keeping the field in xy avoids using a forward vector with a vertical component that would require re-orienting the robot to stand upright before heading logic can be applied.
Every robot config declares this explicitly:
__post_init__refusesNone, and a saved robot subtree without the field fails to load, sincefrom_treerebuilds every dataclass through its constructor. To identify the axis for a new robot, runpython scripts/identify_robot_facing_axis.py --robots <robot-name> --view.
- __init__(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=1.03,
- semantic_forward_axis_xy=(1.0,
- 0.0),
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset=<factory>,
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name=None,
- imu_body_name='torso_link',
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=50,
- simulation_params=None,
Unitree G1#
- class protomotions.robot_configs.g1.G1RobotConfig(asset: protomotions.robot_configs.base.RobotAssetConfig = <factory>, common_naming_to_robot_body_names: Dict[str, List[str]] = <factory>, default_root_height: float = 0.8, semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0), default_dof_pos: Dict[str, float] = <factory>, contact_bodies: Union[List[str], str, NoneType] = None, contact_partners: Union[List[str], str] = <factory>, trackable_bodies_subset: List[str] = <factory>, non_termination_contact_bodies: Union[List[str], str] = 'all', init_state: Optional[protomotions.robot_configs.base.InitState] = None, reset_noise: Optional[protomotions.simulator.base_simulator.config.RobotNoiseConfig] = None, mimic_small_marker_bodies: Optional[List[str]] = None, anchor_body_name: Optional[str] = 'torso_link', imu_body_name: str = 'pelvis', imu_mount_quat: Tuple[float, float, float, float] = (0.0, 0.0, 0.0, 1.0), contact_pairs_multiplier: int = 16, control: protomotions.robot_configs.base.ControlConfig = <factory>, control_hz: int = 50, simulation_params: Optional[protomotions.robot_configs.base.SimulatorParams] = None)[source]#
Bases:
RobotConfig- semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0)#
Robot-local xy axis that points in the anatomical facing direction.
This is intentionally 2D, not 3D. ProtoMotions assumes Z-up humanoid assets, so heading should only choose the horizontal anatomical forward direction. Keeping the field in xy avoids using a forward vector with a vertical component that would require re-orienting the robot to stand upright before heading logic can be applied.
Every robot config declares this explicitly:
__post_init__refusesNone, and a saved robot subtree without the field fails to load, sincefrom_treerebuilds every dataclass through its constructor. To identify the axis for a new robot, runpython scripts/identify_robot_facing_axis.py --robots <robot-name> --view.
- __init__(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=0.8,
- semantic_forward_axis_xy=(1.0,
- 0.0),
- default_dof_pos=<factory>,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset=<factory>,
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name='torso_link',
- imu_body_name='pelvis',
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=50,
- simulation_params=None,
AMP Humanoid#
- class protomotions.robot_configs.amp.AMPRobotConfig(asset: protomotions.robot_configs.base.RobotAssetConfig = <factory>, common_naming_to_robot_body_names: Dict[str, List[str]] = <factory>, default_root_height: float = 0.8, semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0), default_dof_pos: Union[List[float], MockTensor, Dict[str, float], NoneType] = None, contact_bodies: Union[List[str], str, NoneType] = None, contact_partners: Union[List[str], str] = <factory>, trackable_bodies_subset: List[str] = <factory>, non_termination_contact_bodies: Union[List[str], str] = 'all', init_state: Optional[protomotions.robot_configs.base.InitState] = None, reset_noise: Optional[protomotions.simulator.base_simulator.config.RobotNoiseConfig] = None, mimic_small_marker_bodies: Optional[List[str]] = None, anchor_body_name: Optional[str] = None, imu_body_name: Optional[str] = None, imu_mount_quat: Tuple[float, float, float, float] = (0.0, 0.0, 0.0, 1.0), contact_pairs_multiplier: int = 16, control: protomotions.robot_configs.base.ControlConfig = <factory>, control_hz: int = 30, simulation_params: protomotions.robot_configs.base.SimulatorParams = <factory>)[source]#
Bases:
RobotConfig- semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0)#
Robot-local xy axis that points in the anatomical facing direction.
This is intentionally 2D, not 3D. ProtoMotions assumes Z-up humanoid assets, so heading should only choose the horizontal anatomical forward direction. Keeping the field in xy avoids using a forward vector with a vertical component that would require re-orienting the robot to stand upright before heading logic can be applied.
Every robot config declares this explicitly:
__post_init__refusesNone, and a saved robot subtree without the field fails to load, sincefrom_treerebuilds every dataclass through its constructor. To identify the axis for a new robot, runpython scripts/identify_robot_facing_axis.py --robots <robot-name> --view.
- __init__(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=0.8,
- semantic_forward_axis_xy=(1.0,
- 0.0),
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset=<factory>,
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name=None,
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=30,
- simulation_params=<factory>,
SOMA23#
- class protomotions.robot_configs.soma23.Soma23RobotConfig(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=0.95,
- semantic_forward_axis_xy=(0.0,
- -1.0),
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset=<factory>,
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name=None,
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=30,
- simulation_params=<factory>,
Bases:
RobotConfig23-body humanoid derived from SOMASkeleton30.
Drops seven unactuated leaf end-effectors:
Jaw, LeftEye, RightEye, LeftHandThumbEnd, LeftHandMiddleEnd, RightHandThumbEnd, RightHandMiddleEnd
Remaining 23 bodies (22 joints × 3-DOF hinge = 66 DOFs):
Hips (root), Spine1, Spine2, Chest, Neck1, Neck2, Head, RightShoulder, RightArm, RightForeArm, RightHand, LeftShoulder, LeftArm, LeftForeArm, LeftHand, RightLeg, RightShin, RightFoot, RightToeBase, LeftLeg, LeftShin, LeftFoot, LeftToeBase
See mjcf/soma23_humanoid.xml for definition.
- semantic_forward_axis_xy: Tuple[float, float] = (0.0, -1.0)#
Robot-local xy axis that points in the anatomical facing direction.
This is intentionally 2D, not 3D. ProtoMotions assumes Z-up humanoid assets, so heading should only choose the horizontal anatomical forward direction. Keeping the field in xy avoids using a forward vector with a vertical component that would require re-orienting the robot to stand upright before heading logic can be applied.
Every robot config declares this explicitly:
__post_init__refusesNone, and a saved robot subtree without the field fails to load, sincefrom_treerebuilds every dataclass through its constructor. To identify the axis for a new robot, runpython scripts/identify_robot_facing_axis.py --robots <robot-name> --view.
- __init__(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=0.95,
- semantic_forward_axis_xy=(0.0,
- -1.0),
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset=<factory>,
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name=None,
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=30,
- simulation_params=<factory>,
Anatomical SOMA#
- class protomotions.robot_configs.anatomic_soma.AnatomicSomaRobotConfig(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=0.95,
- semantic_forward_axis_xy=(1.0,
- 0.0),
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset=<factory>,
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name='Chest',
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=30,
- simulation_params=<factory>,
Bases:
RobotConfig52 serial hinges, 23 semantic parts and 39 primitive colliders.
The SOMA23 skeleton with its joints expanded into serial hinges on their own carrier links: 15 of the 22 joints get three hinges (pitch, roll and twist), the knees, elbows and toes one hinge each, and Neck2 a single yaw (15 * 3 + 7 = 52). That gives 53 bodies, of which the 30 intermediate links are non-colliding hinge carriers sitting on their semantic body. Joint ranges are engineering limits, not a medically validated human range-of-motion model. Motion files must be retargeted to this skeleton; SOMA23 packs (66 DOFs, 23 bodies) do not load.
See mjcf/anatomic_soma.xml for the definition.
- semantic_forward_axis_xy: Tuple[float, float] = (1.0, 0.0)#
Robot-local xy axis that points in the anatomical facing direction.
This is intentionally 2D, not 3D. ProtoMotions assumes Z-up humanoid assets, so heading should only choose the horizontal anatomical forward direction. Keeping the field in xy avoids using a forward vector with a vertical component that would require re-orienting the robot to stand upright before heading logic can be applied.
Every robot config declares this explicitly:
__post_init__refusesNone, and a saved robot subtree without the field fails to load, sincefrom_treerebuilds every dataclass through its constructor. To identify the axis for a new robot, runpython scripts/identify_robot_facing_axis.py --robots <robot-name> --view.
- __init__(
- asset=<factory>,
- common_naming_to_robot_body_names=<factory>,
- default_root_height=0.95,
- semantic_forward_axis_xy=(1.0,
- 0.0),
- default_dof_pos=None,
- contact_bodies=None,
- contact_partners=<factory>,
- trackable_bodies_subset=<factory>,
- non_termination_contact_bodies='all',
- init_state=None,
- reset_noise=None,
- mimic_small_marker_bodies=None,
- anchor_body_name='Chest',
- imu_body_name=None,
- imu_mount_quat=(0.0,
- 0.0,
- 0.0,
- 1.0),
- contact_pairs_multiplier=16,
- control=<factory>,
- control_hz=30,
- simulation_params=<factory>,