Download real_robot/source/deployment/model_server/xtrainer2_command.py from mmmmmcyaaa/ReTime: direct link, hf CLI and curl.
- Browser
- Download file 3.6 kB
-
https://huggingface.co/mmmmmcyaaa/ReTime/resolve/main/real_robot/source/deployment/model_server/xtrainer2_command.py
- Command line
-
hf download hf://mmmmmcyaaa/ReTime/real_robot/source/deployment/model_server/xtrainer2_command.py
-
curl -L -o xtrainer2_command.py https://huggingface.co/mmmmmcyaaa/ReTime/resolve/main/real_robot/source/deployment/model_server/xtrainer2_command.py
3.6 kB
| """xtrainer2 command layout used between StarVLA and the real robot. | |
| The converted LeRobot dataset stores each arm as ``xyz + quaternion + gripper``. | |
| StarVLA / PyTorch3D read that quaternion as ``w, x, y, z``. The robot HDF5 | |
| streams and the robot controller use ``x, y, z, w``. | |
| The training transform already maps quaternion <-> rotation-6D. After | |
| un-normalization the server therefore has 16-D **wxyz** commands. Sending | |
| those 16 numbers to the robot without this reorder will execute the wrong | |
| orientation. | |
| Do not confuse these widths: | |
| * 14 – joint angles in the source HDF5 (not used for this VLA) | |
| * 16 – stored / robot EEF command (after this conversion, xyzw) | |
| * 20 – model tensor after rotation-6D (horizon is a separate axis) | |
| """ | |
| from __future__ import annotations | |
| import numpy as np | |
| from starVLA.dataloader.relative_pose import compose_quaternion | |
| QUATERNION_STARTS = (3, 11) | |
| POSITION_SLICES = ((0, 3), (8, 11)) | |
| ACTION_DIM = 16 | |
| ROBOT_TYPE = "xtrainer2_bimanual_eef" | |
| SOURCE_QUATERNION_FORMAT = "xyzw" | |
| MODEL_QUATERNION_FORMAT = "wxyz" | |
| #: Value of ``DataConfig.robot_command_layout`` that selects the conversions in | |
| #: this module. The policy server reads that attribute instead of matching on a | |
| #: class name. | |
| COMMAND_LAYOUT = "xtrainer2_bimanual_eef_xyzw" | |
| def _as_float_array(values: np.ndarray) -> np.ndarray: | |
| array = np.asarray(values, dtype=np.float32) | |
| if array.shape[-1] != ACTION_DIM: | |
| raise ValueError(f"expected last dimension {ACTION_DIM}, got {array.shape}") | |
| return array | |
| def wxyz_to_xyzw_block(block: np.ndarray) -> np.ndarray: | |
| """``w, x, y, z`` -> ``x, y, z, w``.""" | |
| return np.concatenate([block[..., 1:4], block[..., :1]], axis=-1) | |
| def xyzw_to_wxyz_block(block: np.ndarray) -> np.ndarray: | |
| """``x, y, z, w`` -> ``w, x, y, z``.""" | |
| return np.concatenate([block[..., 3:4], block[..., :3]], axis=-1) | |
| def model_actions_to_robot(values: np.ndarray) -> np.ndarray: | |
| """Convert un-normalized StarVLA actions (wxyz) to robot commands (xyzw).""" | |
| converted = np.array(_as_float_array(values), copy=True) | |
| for start in QUATERNION_STARTS: | |
| converted[..., start : start + 4] = wxyz_to_xyzw_block(converted[..., start : start + 4]) | |
| return converted | |
| def robot_state_to_model(values: np.ndarray) -> np.ndarray: | |
| """Convert robot observations (xyzw) to the layout StarVLA was trained on.""" | |
| converted = np.array(_as_float_array(values), copy=True) | |
| for start in QUATERNION_STARTS: | |
| converted[..., start : start + 4] = xyzw_to_wxyz_block(converted[..., start : start + 4]) | |
| return converted | |
| def compose_relative_eef_wxyz(relative_actions: np.ndarray, state_wxyz: np.ndarray) -> np.ndarray: | |
| """Turn rel-mode 16-D wxyz actions into absolute 16-D wxyz poses. | |
| Positions add the current EE; rotations left-multiply the current | |
| quaternion; grippers are already absolute and are left unchanged. | |
| """ | |
| relative = np.array(_as_float_array(relative_actions), copy=True) | |
| state = np.asarray(state_wxyz, dtype=np.float32).reshape(-1, ACTION_DIM)[0] | |
| absolute = relative | |
| for start, end in POSITION_SLICES: | |
| absolute[..., start:end] = relative[..., start:end] + state[start:end] | |
| for start in QUATERNION_STARTS: | |
| absolute[..., start : start + 4] = compose_quaternion( | |
| state[start : start + 4], | |
| relative[..., start : start + 4], | |
| ) | |
| return absolute | |
| def is_relative_action_mode(action_mode: object | None) -> bool: | |
| if action_mode is None: | |
| return False | |
| return str(action_mode).lower() in {"rel", "relative"} | |