Implementation:Facebookresearch Habitat lab HumanoidUtils
| Knowledge Sources | |
|---|---|
| Domains | Embodied_AI, Humanoid_Animation, Motion_Conversion |
| Last Updated | 2026-02-15 00:00 GMT |
Overview
Provides utilities for converting SMPL-X format human motion data into Habitat-compatible joint rotations, including a MotionConverterSMPLX class and a global_correction_quat helper for coordinate frame alignment.
Description
This module bridges the gap between the SMPL-X human body model format and Habitat's humanoid representation. Key components:
smplx_body_joint_names:
- A comprehensive list of 127+ joint names from the SMPL-X body model, including body joints (pelvis, spine, limbs), hand joints (finger phalanges), face landmarks (eyes, nose, mouth, contour), and eye/ear keypoints.
global_correction_quat:
- Given an "up" vector and a "forward" vector in a local coordinate frame, produces a correction quaternion to convert to the global Habitat frame (+Y up, -Z forward).
- Computes two sequential rotations: first aligning up to Y-axis, then aligning forward to -Z axis.
MotionConverterSMPLX:
- Initializes a PyBullet physics client with the target URDF model to read joint structure.
- convert_pose_to_rotation: Converts a single SMPL-X pose (root translation, root orientation in axis-angle, joint rotations in axis-angle) from the SMPL-X coordinate frame (+X forward, +Z up) to the Habitat coordinate frame (-Z forward, +Y up). Returns corrected root translation, root rotation matrix, and a list of quaternion joint rotations.
- convert_motion_file: Batch-converts an entire NPZ motion file containing SMPL-X motion sequences into a Habitat-compatible pickle file. Reads
trans,root_orient, andposesarrays along with frame rate metadata.
The module includes a __main__ block that demonstrates converting CMU motion capture files.
Usage
Use MotionConverterSMPLX as a preprocessing tool to convert SMPL-X motion capture data (NPZ format) into pickle files that can be loaded by the HumanoidRearrangeController. The global_correction_quat function is useful whenever coordinate frame alignment is needed between external motion data and Habitat's internal representation.
Code Reference
Source Location
- Repository: Facebookresearch_Habitat_lab
- File: habitat-lab/habitat/utils/humanoid_utils.py
- Lines: 1-349
Signature
def global_correction_quat(
up_v: mn.Vector3, forward_v: mn.Vector3
) -> mn.Quaternion: ...
class MotionConverterSMPLX:
def __init__(self, urdf_path: str): ...
def convert_pose_to_rotation(
self, root_translation, root_orientation, pose_joints
) -> Tuple[mn.Vector3, mn.Matrix3x3, List[float]]: ...
def convert_motion_file(
self, motion_path: str, output_path: str = "output_motion"
) -> None: ...
Import
from habitat.utils.humanoid_utils import (
MotionConverterSMPLX,
global_correction_quat,
smplx_body_joint_names,
)
I/O Contract
Inputs (MotionConverterSMPLX.__init__)
| Name | Type | Required | Description |
|---|---|---|---|
| urdf_path | str | Yes | Path to the humanoid URDF file that defines the target skeleton joint structure |
Inputs (convert_pose_to_rotation)
| Name | Type | Required | Description |
|---|---|---|---|
| root_translation | array-like (3,) | Yes | Global pelvis translation in SMPL-X coordinates |
| root_orientation | array-like (3,) | Yes | Global root orientation in axis-angle format (SMPL-X convention) |
| pose_joints | array-like (N*3,) | Yes | Joint rotations in axis-angle format, 3 values per joint (excluding root) |
Outputs (convert_pose_to_rotation)
| Name | Type | Description |
|---|---|---|
| root_translation | mn.Vector3 | Corrected root translation in Habitat coordinates (+Y up, -Z forward) |
| root_rotation | mn.Matrix3x3 | 3x3 rotation matrix for the root in Habitat coordinates |
| new_pose | List[float] | List of quaternion values [x, y, z, w] for each joint (4 values per spherical joint) |
Inputs (convert_motion_file)
| Name | Type | Required | Description |
|---|---|---|---|
| motion_path | str | Yes | Path to the NPZ file containing SMPL-X motion data (trans, root_orient, poses, and optionally mocap_frame_rate or frame_rate) |
| output_path | str | No | Output path for the converted pickle file (default "output_motion"); '.pkl' extension is appended automatically |
Outputs (convert_motion_file)
| Name | Type | Description |
|---|---|---|
| file | .pkl file | Pickle file containing a dict with "pose_motion" key holding joints_array, transform_array, displacement (None), and fps |
Usage Examples
Converting a Motion File
from habitat.utils.humanoid_utils import MotionConverterSMPLX
converter = MotionConverterSMPLX(
urdf_path="data/humanoids/humanoid_data/female_2/female_2.urdf"
)
converter.convert_motion_file(
motion_path="data/humanoids/humanoid_data/walk_motion/CMU_10_04_stageii.npz",
output_path="data/humanoids/humanoid_data/walk_motion/CMU_10_04_stageii",
)
# Produces: CMU_10_04_stageii.pkl
Using the Global Correction Quaternion
import magnum as mn
from habitat.utils.humanoid_utils import global_correction_quat
# SMPL-X uses +Z up, +X forward
correction = global_correction_quat(
up_v=mn.Vector3.z_axis(),
forward_v=mn.Vector3.x_axis(),
)
# Apply correction to transform a vector from SMPL-X to Habitat frame
smplx_forward = mn.Vector3(1.0, 0.0, 0.0)
habitat_forward = correction.transform_vector(smplx_forward)
# habitat_forward should be approximately (0, 0, -1) (Habitat's forward)
Converting a Single Pose
import numpy as np
from habitat.utils.humanoid_utils import MotionConverterSMPLX
converter = MotionConverterSMPLX(
urdf_path="data/humanoids/humanoid_data/female_2/female_2.urdf"
)
root_trans = np.array([0.0, 0.0, 1.0])
root_orient = np.array([0.0, 0.0, 0.0]) # no rotation
pose_joints = np.zeros(21 * 3) # T-pose, 21 body joints
root_translation, root_rotation, joint_quats = (
converter.convert_pose_to_rotation(root_trans, root_orient, pose_joints)
)