holosoma-inference 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. holosoma_inference-0.1.0/PKG-INFO +39 -0
  2. holosoma_inference-0.1.0/README.md +227 -0
  3. holosoma_inference-0.1.0/holosoma_inference/__init__.py +0 -0
  4. holosoma_inference-0.1.0/holosoma_inference/compat.py +10 -0
  5. holosoma_inference-0.1.0/holosoma_inference/config/__init__.py +11 -0
  6. holosoma_inference-0.1.0/holosoma_inference/config/config_types/__init__.py +13 -0
  7. holosoma_inference-0.1.0/holosoma_inference/config/config_types/inference.py +33 -0
  8. holosoma_inference-0.1.0/holosoma_inference/config/config_types/observation.py +53 -0
  9. holosoma_inference-0.1.0/holosoma_inference/config/config_types/robot.py +236 -0
  10. holosoma_inference-0.1.0/holosoma_inference/config/config_types/task.py +212 -0
  11. holosoma_inference-0.1.0/holosoma_inference/config/config_values/__init__.py +10 -0
  12. holosoma_inference-0.1.0/holosoma_inference/config/config_values/inference.py +120 -0
  13. holosoma_inference-0.1.0/holosoma_inference/config/config_values/observation.py +161 -0
  14. holosoma_inference-0.1.0/holosoma_inference/config/config_values/robot.py +264 -0
  15. holosoma_inference-0.1.0/holosoma_inference/config/config_values/task.py +67 -0
  16. holosoma_inference-0.1.0/holosoma_inference/config/tests/__init__.py +0 -0
  17. holosoma_inference-0.1.0/holosoma_inference/config/tests/test_task_config.py +123 -0
  18. holosoma_inference-0.1.0/holosoma_inference/config/utils.py +3 -0
  19. holosoma_inference-0.1.0/holosoma_inference/inputs/__init__.py +52 -0
  20. holosoma_inference-0.1.0/holosoma_inference/inputs/api/__init__.py +0 -0
  21. holosoma_inference-0.1.0/holosoma_inference/inputs/api/base.py +51 -0
  22. holosoma_inference-0.1.0/holosoma_inference/inputs/api/commands.py +61 -0
  23. holosoma_inference-0.1.0/holosoma_inference/inputs/impl/__init__.py +0 -0
  24. holosoma_inference-0.1.0/holosoma_inference/inputs/impl/interface.py +90 -0
  25. holosoma_inference-0.1.0/holosoma_inference/inputs/impl/joystick.py +27 -0
  26. holosoma_inference-0.1.0/holosoma_inference/inputs/impl/keyboard.py +176 -0
  27. holosoma_inference-0.1.0/holosoma_inference/inputs/impl/ros2.py +122 -0
  28. holosoma_inference-0.1.0/holosoma_inference/inputs/impl/usb_joystick.py +273 -0
  29. holosoma_inference-0.1.0/holosoma_inference/inputs/tests/__init__.py +0 -0
  30. holosoma_inference-0.1.0/holosoma_inference/inputs/tests/conftest.py +86 -0
  31. holosoma_inference-0.1.0/holosoma_inference/inputs/tests/test_dual_mode.py +81 -0
  32. holosoma_inference-0.1.0/holosoma_inference/inputs/tests/test_factory.py +155 -0
  33. holosoma_inference-0.1.0/holosoma_inference/inputs/tests/test_joystick.py +141 -0
  34. holosoma_inference-0.1.0/holosoma_inference/inputs/tests/test_keyboard.py +119 -0
  35. holosoma_inference-0.1.0/holosoma_inference/inputs/tests/test_providers.py +1155 -0
  36. holosoma_inference-0.1.0/holosoma_inference/inputs/tests/test_ros2.py +120 -0
  37. holosoma_inference-0.1.0/holosoma_inference/policies/__init__.py +6 -0
  38. holosoma_inference-0.1.0/holosoma_inference/policies/base.py +863 -0
  39. holosoma_inference-0.1.0/holosoma_inference/policies/dual_mode.py +195 -0
  40. holosoma_inference-0.1.0/holosoma_inference/policies/locomotion.py +122 -0
  41. holosoma_inference-0.1.0/holosoma_inference/policies/tests/__init__.py +1 -0
  42. holosoma_inference-0.1.0/holosoma_inference/policies/tests/test_select_policy_class.py +111 -0
  43. holosoma_inference-0.1.0/holosoma_inference/policies/tests/test_wbt_utils.py +250 -0
  44. holosoma_inference-0.1.0/holosoma_inference/policies/wbt.py +474 -0
  45. holosoma_inference-0.1.0/holosoma_inference/policies/wbt_utils.py +161 -0
  46. holosoma_inference-0.1.0/holosoma_inference/py.typed +0 -0
  47. holosoma_inference-0.1.0/holosoma_inference/run_policy.py +228 -0
  48. holosoma_inference-0.1.0/holosoma_inference/sdk/__init__.py +33 -0
  49. holosoma_inference-0.1.0/holosoma_inference/sdk/base/__init__.py +0 -0
  50. holosoma_inference-0.1.0/holosoma_inference/sdk/base/base_interface.py +186 -0
  51. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/__init__.py +0 -0
  52. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/booster_interface.py +102 -0
  53. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/command_sender/__init__.py +34 -0
  54. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/command_sender/base/__init__.py +9 -0
  55. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/command_sender/base/basic_command_sender.py +121 -0
  56. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/command_sender/booster/__init__.py +7 -0
  57. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/command_sender/booster/booster_command_sender.py +106 -0
  58. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/command_sender/booster/joystick_message.py +25 -0
  59. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/command_sender/booster/remote_control_service.py +311 -0
  60. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/state_processor/__init__.py +36 -0
  61. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/state_processor/base/__init__.py +9 -0
  62. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/state_processor/base/basic_state_processor.py +57 -0
  63. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/state_processor/booster/__init__.py +7 -0
  64. holosoma_inference-0.1.0/holosoma_inference/sdk/booster/state_processor/booster/booster_state_processor.py +64 -0
  65. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree/__init__.py +0 -0
  66. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree/unitree_interface.py +135 -0
  67. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree/unitree_interface_mp.py +212 -0
  68. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree_high_level/__init__.py +37 -0
  69. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree_high_level/arm_client/__init__.py +3 -0
  70. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree_high_level/arm_client/arm_client.py +351 -0
  71. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree_high_level/arm_client/const.py +236 -0
  72. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree_high_level/loco_client/__init__.py +3 -0
  73. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree_high_level/loco_client/loco_client.py +104 -0
  74. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree_high_level/multiprocess_proxy/__init__.py +3 -0
  75. holosoma_inference-0.1.0/holosoma_inference/sdk/unitree_high_level/multiprocess_proxy/multiprocess_proxy.py +116 -0
  76. holosoma_inference-0.1.0/holosoma_inference/sensors/__init__.py +0 -0
  77. holosoma_inference-0.1.0/holosoma_inference/sensors/base.py +33 -0
  78. holosoma_inference-0.1.0/holosoma_inference/utils/__init__.py +0 -0
  79. holosoma_inference-0.1.0/holosoma_inference/utils/clock.py +141 -0
  80. holosoma_inference-0.1.0/holosoma_inference/utils/latency.py +118 -0
  81. holosoma_inference-0.1.0/holosoma_inference/utils/math/__init__.py +29 -0
  82. holosoma_inference-0.1.0/holosoma_inference/utils/math/misc.py +6 -0
  83. holosoma_inference-0.1.0/holosoma_inference/utils/math/quat.py +133 -0
  84. holosoma_inference-0.1.0/holosoma_inference/utils/misc.py +33 -0
  85. holosoma_inference-0.1.0/holosoma_inference/utils/network.py +22 -0
  86. holosoma_inference-0.1.0/holosoma_inference/utils/rate.py +130 -0
  87. holosoma_inference-0.1.0/holosoma_inference/utils/wandb.py +120 -0
  88. holosoma_inference-0.1.0/holosoma_inference.egg-info/PKG-INFO +39 -0
  89. holosoma_inference-0.1.0/holosoma_inference.egg-info/SOURCES.txt +93 -0
  90. holosoma_inference-0.1.0/holosoma_inference.egg-info/dependency_links.txt +1 -0
  91. holosoma_inference-0.1.0/holosoma_inference.egg-info/entry_points.txt +13 -0
  92. holosoma_inference-0.1.0/holosoma_inference.egg-info/requires.txt +31 -0
  93. holosoma_inference-0.1.0/holosoma_inference.egg-info/top_level.txt +1 -0
  94. holosoma_inference-0.1.0/setup.cfg +4 -0
  95. holosoma_inference-0.1.0/setup.py +71 -0
@@ -0,0 +1,39 @@
1
+ Metadata-Version: 2.4
2
+ Name: holosoma-inference
3
+ Version: 0.1.0
4
+ Summary: holosoma-inference: inference components for humanoid robot policies
5
+ Author: Amazon FAR Team
6
+ Keywords: humanoid robotics inference policy onnx
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: pydantic
10
+ Requires-Dist: loguru
11
+ Requires-Dist: netifaces
12
+ Requires-Dist: onnx
13
+ Requires-Dist: onnxruntime
14
+ Requires-Dist: scipy
15
+ Requires-Dist: sshkeyboard
16
+ Requires-Dist: termcolor
17
+ Requires-Dist: pyyaml
18
+ Requires-Dist: tyro>=0.10.0a4
19
+ Requires-Dist: wandb
20
+ Requires-Dist: zmq
21
+ Requires-Dist: defusedxml
22
+ Requires-Dist: evdev
23
+ Requires-Dist: importlib_metadata>=4.6; python_version < "3.12"
24
+ Requires-Dist: eval_type_backport; python_version < "3.10"
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=6.0; extra == "dev"
27
+ Requires-Dist: black>=22.0; extra == "dev"
28
+ Requires-Dist: flake8>=4.0; extra == "dev"
29
+ Provides-Extra: unitree
30
+ Requires-Dist: far-unitree-sdk==0.1.4; extra == "unitree"
31
+ Provides-Extra: booster
32
+ Requires-Dist: far-booster-sdk==0.1.0; extra == "booster"
33
+ Dynamic: author
34
+ Dynamic: description-content-type
35
+ Dynamic: keywords
36
+ Dynamic: provides-extra
37
+ Dynamic: requires-dist
38
+ Dynamic: requires-python
39
+ Dynamic: summary
@@ -0,0 +1,227 @@
1
+ # Holosoma Inference
2
+
3
+ Policy inference for humanoid robot policies.
4
+
5
+ ## Supported Policies
6
+
7
+ | Robot | Locomotion | WBT |
8
+ |:----------:|:----------:|:---:|
9
+ | Unitree G1 | ✅ | ✅ |
10
+ | Booster T1 | ✅ | ❌ |
11
+
12
+ | Simulator | Locomotion | WBT |
13
+ |:-----------------------:|:----------:|:---:|
14
+ | IsaacGym | ✅ | ❌ |
15
+ | IsaacSim | ✅ | ✅ |
16
+ | MuJoCo (inference only) | ✅ | ✅ |
17
+
18
+ - ✅ (full support)
19
+ - 🚧 (in progress/partial support)
20
+ - ❌ (no support)
21
+
22
+ ## Quick Start
23
+
24
+ ### Setup the Environment
25
+
26
+ ```bash
27
+ cd ~/holosoma
28
+ bash scripts/setup_inference.sh # Create a virtual environment with all dependencies
29
+ source scripts/source_inference_setup.sh # Activate the virtual environment
30
+ ```
31
+
32
+ ### Choose Your Workflow
33
+
34
+ Select the appropriate workflow guide based on your setup:
35
+
36
+ #### Real Robot Deployment
37
+ - **[Real Robot Locomotion](docs/workflows/real-robot-locomotion.md)** - Run locomotion policies on physical Unitree G1 or Booster T1 robots
38
+ - **[Real Robot Whole Body Tracking](docs/workflows/real-robot-wbt.md)** - Run WBT policies on physical Unitree G1 robots
39
+
40
+ #### Simulation (MuJoCo)
41
+ - **[Sim-to-Sim Locomotion](docs/workflows/sim-to-sim-locomotion.md)** - Test locomotion policies in MuJoCo simulation
42
+ - **[Sim-to-Sim Whole Body Tracking](docs/workflows/sim-to-sim-wbt.md)** - Test WBT policies in MuJoCo simulation
43
+
44
+ Each workflow guide includes:
45
+ - Hardware/environment setup instructions
46
+ - Step-by-step commands
47
+ - Control references
48
+ - Deployment options (offboard/onboard/Docker)
49
+ - Troubleshooting tips
50
+
51
+ ---
52
+
53
+ # Policy Controls
54
+
55
+ Commands for controlling policies during execution.
56
+
57
+ **Important**: All policy controls that use keyboard should be entered in the **policy terminal** (where you ran `run_policy.py`), not in the MuJoCo window. MuJoCo has separate controls for simulation (see workflow docs).
58
+
59
+ ## General Controls
60
+
61
+ | Action | Keyboard | Joystick |
62
+ |--------|----------|----------|
63
+ | Start the policy | `]` | A button |
64
+ | Stop the policy | `o` | B button |
65
+ | Set robot to default pose | `i` | Y button |
66
+ | Kill controller program | - | L1 (LB) + R1 (RB) |
67
+
68
+ ## Locomotion (Velocity Tracking)
69
+
70
+ | Action | Keyboard | Joystick |
71
+ |--------|----------|----------|
72
+ | Switch walking/standing | `=` | Start button |
73
+ | Adjust linear velocity | `w` `a` `s` `d` | Left stick |
74
+ | Adjust angular velocity | `q` `e` | Right stick |
75
+
76
+ **Default pose**: Standing pose
77
+
78
+ ## Whole-Body Tracking
79
+
80
+ | Action | Keyboard | Joystick |
81
+ |--------|----------|----------|
82
+ | Start the policy | `]` | A button |
83
+ | Start motion clip | `m` | Select+A |
84
+
85
+ **Default pose**: Standing with raised arms
86
+
87
+ ## Joystick-Only Features
88
+
89
+ - **Select button**: Switch between policies (when multiple policies are loaded)
90
+
91
+
92
+ # Configuration Overrides
93
+
94
+ ## Loading ONNX Checkpoints from Wandb
95
+
96
+ You can load ONNX checkpoints directly from Wandb without manually downloading them first. This is useful for quickly testing models from training runs.
97
+
98
+ **Syntax:**
99
+ ```bash
100
+ --task.model-path wandb://entity/project_name/run_id/model.onnx
101
+ ```
102
+
103
+ **Example with G1 locomotion:**
104
+ ```bash
105
+ source scripts/source_inference_setup.sh
106
+ python3 src/holosoma_inference/holosoma_inference/run_policy.py inference:g1-29dof-loco \
107
+ --task.model-path wandb://my-username/my-project/run-abc123/fastsac_g1_29dof.onnx \
108
+ --task.use-joystick \
109
+ --task.interface eth0
110
+ ```
111
+
112
+ **Example with Wandb HTTPS URL:**
113
+ ```bash
114
+ python3 src/holosoma_inference/holosoma_inference/run_policy.py inference:g1-29dof-loco \
115
+ --task.model-path https://wandb.ai/username/project/runs/abc123/files/model.onnx \
116
+ --task.use-joystick \
117
+ --task.interface eth0
118
+ ```
119
+
120
+ The model will be automatically downloaded and cached locally. The entity is your Wandb username or organization name.
121
+
122
+ ## Finding Your Network Interface
123
+
124
+ The `--task.interface` parameter specifies which network interface to use for communicating with the robot. The correct interface name varies by computer and network card.
125
+
126
+ **Common interface names:**
127
+ - `eth0` - Common Ethernet interface name
128
+ - `enp0s31f6` - Modern Linux Ethernet naming
129
+ - `lo` - Loopback interface (for sim2sim)
130
+
131
+ **To find your interface name:**
132
+ ```bash
133
+ ifconfig
134
+ ```
135
+
136
+ Look for the interface connected to your robot's network. For real robot deployments, use the interface with an IP address on the same subnet as your robot. For sim2sim deployments, use `lo` (loopback).
137
+
138
+ ## Observation History Length (> 1)
139
+
140
+ If a policy was trained with stacked observations (e.g., history length 4), you must pass the same history length at inference time so the observation tensor matches the model's expected input size.
141
+
142
+ Example:
143
+
144
+ ```bash
145
+ python3 src/holosoma_inference/holosoma_inference/run_policy.py inference:g1-29dof-wbt \
146
+ --task.model-path <path-to-model>.onnx \
147
+ --task.interface eth0 \
148
+ --observation.history_length_dict.actor_obs=4
149
+ ```
150
+
151
+ The override updates the `actor_obs` buffer before the ONNX session is initialized, so any policy (locomotion or WBT) can run with longer observation histories as long as the underlying model was trained that way.
152
+
153
+
154
+ ## Input Sources
155
+
156
+ The policy supports two independent input channels that can each be set to `keyboard`, `joystick`, or `ros2`:
157
+
158
+ | Channel | What it controls | CLI flag |
159
+ |---------|-----------------|----------|
160
+ | `velocity_input` | Continuous velocity commands (linear/angular) | `--task.velocity-input` |
161
+ | `state_input` | Discrete commands: start/stop, walk/stand, kp tuning, policy switching | `--task.state-input` |
162
+
163
+ ### Shortcuts (backwards compatible)
164
+
165
+ For the common case where both channels use the same source:
166
+
167
+ ```bash
168
+ --task.use-joystick # Sets both channels to joystick
169
+ --task.use-keyboard # Sets both channels to keyboard (this is the default)
170
+ ```
171
+
172
+ ### Mixed input examples
173
+
174
+ **ROS2 `cmd_vel` with keyboard commands** — velocity from ROS2, operator uses keyboard for start/stop:
175
+
176
+ ```bash
177
+ python3 src/holosoma_inference/holosoma_inference/run_policy.py inference:g1-29dof-loco \
178
+ --task.model-path <path-to-model>.onnx \
179
+ --task.velocity-input ros2 \
180
+ --task.state-input keyboard \
181
+ --task.interface eth0
182
+ ```
183
+
184
+ **Fully autonomous** — both channels from ROS2:
185
+
186
+ ```bash
187
+ python3 src/holosoma_inference/holosoma_inference/run_policy.py inference:g1-29dof-loco \
188
+ --task.model-path <path-to-model>.onnx \
189
+ --task.velocity-input ros2 \
190
+ --task.state-input ros2 \
191
+ --task.interface eth0
192
+ ```
193
+
194
+ ### ROS2 topics
195
+
196
+ | Topic | Message type | Channel | Description |
197
+ |-------|-------------|---------|-------------|
198
+ | `cmd_vel` | `geometry_msgs/TwistStamped` | `velocity_input` | Linear (x, y) and angular (z) velocity, clamped to [-1, 1] |
199
+ | `holosoma/state_input` | `std_msgs/String` | `state_input` | Text commands: `walk`, `stand`, `start`, `stop`, `init` |
200
+
201
+ Topic names are configurable via `--task.ros-cmd-vel-topic` and `--task.ros-state-input-topic`.
202
+
203
+ **Note**: Shortcut flags (`--task.use-joystick`, `--task.use-keyboard`) cannot be combined with `--task.velocity-input` or `--task.state-input`.
204
+
205
+ ## Overriding Control Gains
206
+
207
+ By default, control gains (kp/kd) are loaded from ONNX model metadata. You can override these values in your configuration:
208
+
209
+ ### G1 29-DOF with Custom Control Gains
210
+
211
+ ```bash
212
+ python3 src/holosoma_inference/holosoma_inference/run_policy.py inference:g1-29dof-loco \
213
+ --task.model-path src/holosoma_inference/holosoma_inference/models/loco/g1_29dof/fastsac_g1_29dof.onnx \
214
+ --robot.motor-kp 40.2 99.1 40.2 99.1 28.5 28.5 40.2 99.1 40.2 99.1 28.5 28.5 40.2 28.5 28.5 14.3 14.3 14.3 14.3 14.3 16.8 16.8 14.3 14.3 14.3 14.3 14.3 16.8 16.8 \
215
+ --robot.motor-kd 2.6 6.3 2.6 6.3 1.8 1.8 2.6 6.3 2.6 6.3 1.8 1.8 2.6 1.8 1.8 0.9 0.9 0.9 0.9 0.9 1.1 1.1 0.9 0.9 0.9 0.9 0.9 1.1 1.1
216
+ ```
217
+
218
+ ### T1 29-DOF with Custom Control Gains
219
+
220
+ ```bash
221
+ python3 src/holosoma_inference/holosoma_inference/run_policy.py inference:t1-29dof-loco \
222
+ --task.model-path src/holosoma_inference/holosoma_inference/models/loco/t1_29dof/ppo_t1_29dof.onnx \
223
+ --robot.motor-kp 5.0 5.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 20.0 200.0 200.0 200.0 200.0 200.0 50.0 50.0 200.0 200.0 200.0 200.0 50.0 50.0 \
224
+ --robot.motor-kd 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 5.0 5.0 5.0 5.0 5.0 3.0 3.0 5.0 5.0 5.0 5.0 3.0 3.0
225
+ ```
226
+
227
+ **Note**: When control gains are not specified, they will be automatically loaded from the ONNX model metadata. This is the recommended approach as it ensures the gains match those used during training.
@@ -0,0 +1,10 @@
1
+ """Python version compatibility shims."""
2
+
3
+ import sys
4
+
5
+ if sys.version_info >= (3, 12):
6
+ from importlib.metadata import entry_points
7
+ else:
8
+ from importlib_metadata import entry_points
9
+
10
+ __all__ = ["entry_points"]
@@ -0,0 +1,11 @@
1
+ """Tyro-based configuration system for holosoma_inference.
2
+
3
+ This module provides a type-safe configuration system using Pydantic dataclasses and Tyro CLI.
4
+ """
5
+
6
+ from . import config_types, config_values
7
+
8
+ __all__ = [
9
+ "config_types",
10
+ "config_values",
11
+ ]
@@ -0,0 +1,13 @@
1
+ """Type definitions for holosoma_inference configuration system."""
2
+
3
+ from .inference import InferenceConfig
4
+ from .observation import ObservationConfig
5
+ from .robot import RobotConfig
6
+ from .task import TaskConfig
7
+
8
+ __all__ = [
9
+ "InferenceConfig",
10
+ "ObservationConfig",
11
+ "RobotConfig",
12
+ "TaskConfig",
13
+ ]
@@ -0,0 +1,33 @@
1
+ """Top-level inference configuration types for holosoma_inference."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pydantic.dataclasses import dataclass
6
+
7
+ from .observation import ObservationConfig
8
+ from .robot import RobotConfig
9
+ from .task import TaskConfig
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class InferenceConfig:
14
+ """Top-level configuration for policy inference.
15
+
16
+ Combines robot, observation, and task configurations
17
+ for running policies on real robots or in simulation.
18
+ """
19
+
20
+ robot: RobotConfig
21
+ """Robot hardware and control configuration."""
22
+
23
+ observation: ObservationConfig
24
+ """Observation space configuration."""
25
+
26
+ task: TaskConfig
27
+ """Task execution configuration."""
28
+
29
+ secondary: InferenceConfig | None = None
30
+ """Secondary policy config for dual-mode (X-button switch).
31
+ When set, enables runtime switching between this (primary) policy and the secondary.
32
+ Override any field: --secondary.task.model-path, --secondary.task.rl-rate, etc.
33
+ Set to None to disable dual-mode."""
@@ -0,0 +1,53 @@
1
+ """Observation configuration types for holosoma_inference."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pydantic.dataclasses import dataclass
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class ObservationConfig:
10
+ """Observation space configuration.
11
+
12
+ Defines which observations are used, their dimensions,
13
+ scaling factors, history lengths, etc. for policy inference.
14
+ """
15
+
16
+ obs_dict: dict[str, list[str]]
17
+ """Maps observation group names to lists of observation components.
18
+
19
+ Each key represents an observation group (e.g., "actor_obs", "critic_obs"),
20
+ and each value is a list of observation component names that belong to that group.
21
+
22
+ Example:
23
+ {"actor_obs": ["base_ang_vel", "projected_gravity", "dof_pos"]}
24
+ """
25
+
26
+ obs_dims: dict[str, int]
27
+ """Dimension of each observation component.
28
+
29
+ Maps each observation component name to its dimensionality.
30
+
31
+ Example:
32
+ {"base_ang_vel": 3, "dof_pos": 29, "actions": 29}
33
+ """
34
+
35
+ obs_scales: dict[str, float]
36
+ """Scaling factor applied to each observation component.
37
+
38
+ Maps each observation component name to a scaling factor that will be
39
+ multiplied with the raw observation values during preprocessing.
40
+
41
+ Example:
42
+ {"base_ang_vel": 0.25, "dof_vel": 0.05, "projected_gravity": 1.0}
43
+ """
44
+
45
+ history_length_dict: dict[str, int]
46
+ """Number of timesteps to keep in history for each observation group.
47
+
48
+ Maps each observation group name to the number of historical timesteps
49
+ to maintain. A value of 1 means only the current observation is used.
50
+
51
+ Example:
52
+ {"actor_obs": 1, "critic_obs": 3}
53
+ """
@@ -0,0 +1,236 @@
1
+ """Robot configuration types for holosoma_inference."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import typing
6
+ from typing import Any
7
+
8
+ from pydantic.dataclasses import dataclass
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class RobotConfig:
13
+ """Robot hardware and control configuration.
14
+
15
+ Defines all robot-specific parameters including kinematics,
16
+ control gains, limits, and SDK configuration.
17
+
18
+ Examples
19
+ --------
20
+ G1 29-DOF robot configuration:
21
+ >>> robot_config = RobotConfig(
22
+ ... robot_type="g1_29dof",
23
+ ... robot="g1",
24
+ ... num_motors=29,
25
+ ... num_joints=29,
26
+ ... default_dof_angles=(...), # 29 values
27
+ ... motor_kp=(...), # 29 values
28
+ ... # ... other required fields
29
+ ... )
30
+ """
31
+
32
+ # =========================================================================
33
+ # Identity (REQUIRED - no defaults)
34
+ # =========================================================================
35
+
36
+ robot_type: str
37
+ """Robot identifier (e.g., 'g1_29dof', 't1_29dof')."""
38
+
39
+ robot: str
40
+ """Robot family name (e.g., 'g1', 't1')."""
41
+
42
+ # =========================================================================
43
+ # Default Positions (REQUIRED - immutable tuples, no defaults)
44
+ # =========================================================================
45
+
46
+ default_dof_angles: tuple[float, ...]
47
+ """Default joint angles in radians (length: num_joints).
48
+
49
+ These are the target positions when the robot is in its default standing pose.
50
+ """
51
+
52
+ default_motor_angles: tuple[float, ...]
53
+ """Default motor angles in radians (length: num_motors).
54
+
55
+ Typically identical to default_dof_angles unless there's a motor-to-joint mapping.
56
+ """
57
+
58
+ # =========================================================================
59
+ # Mappings (REQUIRED - no defaults)
60
+ # =========================================================================
61
+
62
+ motor2joint: tuple[int, ...]
63
+ """Motor index to joint index mapping (length: num_motors).
64
+
65
+ Maps motor indices to their corresponding joint indices.
66
+ For most robots, this is an identity mapping [0, 1, 2, ..., n-1].
67
+ """
68
+
69
+ joint2motor: tuple[int, ...]
70
+ """Joint index to motor index mapping (length: num_joints).
71
+
72
+ Inverse of motor2joint mapping.
73
+ """
74
+
75
+ dof_names: tuple[str, ...]
76
+ """Joint names in order (length: num_joints).
77
+
78
+ Example: ('left_hip_pitch_joint', 'left_hip_roll_joint', ...)
79
+ """
80
+
81
+ # =========================================================================
82
+ # Deprecation candidates with no defaults
83
+ # =========================================================================
84
+
85
+ dof_names_upper_body: tuple[str, ...]
86
+ """Upper body joint names (length: num_upper_body_joints).
87
+
88
+ Subset of dof_names containing only upper body joints.
89
+ """
90
+
91
+ dof_names_lower_body: tuple[str, ...]
92
+ """Lower body joint names (length: num_joints - num_upper_body_joints).
93
+
94
+ Subset of dof_names containing only lower body joints (legs + waist).
95
+ """
96
+
97
+ # =========================================================================
98
+ # Control Gains (OPTIONAL - can be loaded from ONNX metadata)
99
+ # =========================================================================
100
+
101
+ motor_kp: tuple[float, ...] | None = None
102
+ """Proportional gains for PD control (length: num_motors).
103
+
104
+ These gains are applied in the motor-space PD controller:
105
+ tau = kp * (q_target - q_current) + kd * (dq_target - dq_current)
106
+
107
+ If None, values will be loaded from ONNX model metadata during inference.
108
+ If provided, these values override the ONNX metadata.
109
+ """
110
+
111
+ motor_kd: tuple[float, ...] | None = None
112
+ """Derivative gains for PD control (length: num_motors).
113
+
114
+ These gains are applied in the motor-space PD controller.
115
+
116
+ If None, values will be loaded from ONNX model metadata during inference.
117
+ If provided, these values override the ONNX metadata.
118
+ """
119
+
120
+ default_per_joint_action_scale: tuple[float, ...] | None = None
121
+ """Fallback per-joint action scales used when ONNX metadata is missing."""
122
+
123
+ # =========================================================================
124
+ # WBT Stiff Startup Configuration (OPTIONAL - for WBT policies)
125
+ # =========================================================================
126
+
127
+ stiff_startup_pos: tuple[float, ...] | None = None
128
+ """Stiff startup joint positions for WBT policy (length: num_joints).
129
+
130
+ Target positions used during stiff hold mode before policy activation.
131
+ Only used by WholeBodyTracking policy.
132
+ """
133
+
134
+ stiff_startup_kp: tuple[float, ...] | None = None
135
+ """Stiff startup position gains for WBT policy (length: num_joints).
136
+
137
+ Proportional gains used during stiff hold mode before policy activation.
138
+ Only used by WholeBodyTracking policy.
139
+ """
140
+
141
+ stiff_startup_kd: tuple[float, ...] | None = None
142
+ """Stiff startup velocity gains for WBT policy (length: num_joints).
143
+
144
+ Derivative gains used during stiff hold mode before policy activation.
145
+ Only used by WholeBodyTracking policy.
146
+ """
147
+
148
+ # =========================================================================
149
+ # SDK Configuration (OPTIONAL - with defaults)
150
+ # =========================================================================
151
+
152
+ sdk_type: str = "unitree"
153
+ """SDK type for robot communication.
154
+
155
+ Built-in types: 'unitree', 'booster'.
156
+ Extensions can register additional SDK types.
157
+ """
158
+
159
+ motor_type: typing.Literal["serial", "parallel"] = "serial"
160
+ """Motor communication type."""
161
+
162
+ message_type: typing.Literal["HG", "GO2"] = "HG"
163
+ """Message protocol type."""
164
+
165
+ # =========================================================================
166
+ # Dimensions (OPTIONAL - with defaults)
167
+ # =========================================================================
168
+
169
+ num_motors: int = 29
170
+ """Number of motors in the robot."""
171
+
172
+ num_joints: int = 29
173
+ """Number of joints in the robot."""
174
+
175
+ # =========================================================================
176
+ # Link Names (OPTIONAL - with defaults)
177
+ # =========================================================================
178
+
179
+ torso_link_name: str = "torso_link"
180
+ """Name of the torso/base link in the robot model."""
181
+
182
+ left_hand_link_name: str | None = None
183
+ """Name of the left hand/end-effector link (if applicable)."""
184
+
185
+ right_hand_link_name: str | None = None
186
+ """Name of the right hand/end-effector link (if applicable)."""
187
+
188
+ # =========================================================================
189
+ # SDK-Specific Configuration (optional)
190
+ # =========================================================================
191
+
192
+ unitree_legged_const: dict[str, Any] | None = None
193
+ """Unitree SDK-specific constants.
194
+
195
+ Contains protocol-specific values like HIGHLEVEL, LOWLEVEL, etc.
196
+ Only used when sdk_type='unitree'.
197
+ """
198
+
199
+ weak_motor_joint_index: dict[str, int] | None = None
200
+ """Mapping of joint names to their weak motor indices.
201
+
202
+ Used for robots with weak motors that need special handling.
203
+ """
204
+
205
+ motion: dict[str, list[str]] | None = None
206
+ """Motion reference configuration.
207
+
208
+ Specifies body names used for motion tracking/reference.
209
+ Example: {'body_name_ref': ['torso_link']}
210
+ """
211
+
212
+ # =========================================================================
213
+ # Deprecation candidates
214
+ # (I'm moving for parity with hydra, but I'd like to remove in the future)
215
+ # =========================================================================
216
+
217
+ dof_names_parallel_mech: tuple[str, ...] = ()
218
+ """Parallel mechanism joint names (optional, booster specific)."""
219
+
220
+ use_sensor: bool = False
221
+ """Whether to use sensor feedback instead of joint states."""
222
+
223
+ num_upper_body_joints: int = 14
224
+ """Number of upper body degrees of freedom."""
225
+
226
+ # =========================================================================
227
+ # Per-Robot Calibration
228
+ # =========================================================================
229
+
230
+ joint_offsets_deg: tuple[float, ...] | None = None
231
+ """Per-joint offsets in degrees applied to lowcmd (action-space only).
232
+
233
+ These offsets correct for per-robot motor calibration differences without
234
+ affecting the observation/state space. Converted to radians at init time.
235
+ Length must equal num_joints when provided.
236
+ """