Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fe0d810
feat(g1-wbc): groot-wbc real-hw + sim blueprints
Nabla7 May 6, 2026
35c5b28
feat(g1-wbc-sim): DIMOS_MUJOCO_VIEW=1 spawns native MuJoCo viewer in …
Nabla7 May 6, 2026
bf83913
fix(g1-wbc-sim): inject menagerie mesh assets in MuJoCo viewer subpro…
Nabla7 May 6, 2026
b7bb6c9
fix(g1-wbc-sim): tick_rate=50 + decimation=1 + ramp=0 to match GR00T …
Nabla7 May 6, 2026
c3c0f82
fix(g1-wbc-sim): strip lidar/scene-mesh/multi-camera from mujoco_sim_…
Nabla7 May 6, 2026
a3ccd2c
chore(g1-wbc): drop unused drive_trains/go2 + revert pyproject/uv.loc…
Nabla7 May 6, 2026
d039820
fix: restore dev's unitree_go2 drive_train (accidentally deleted in c…
Nabla7 May 6, 2026
0ed6efb
chore(g1-wbc): drop perception2/viser leaks + test file (defer to fol…
Nabla7 May 6, 2026
3c1aacc
chore(g1-wbc): drop __init__.py files, match repo namespace-package c…
Nabla7 May 6, 2026
8825549
chore(g1-wbc): drop simulation/mujoco/model.py changes (unrelated to PR)
Nabla7 May 6, 2026
62a1110
chore(g1-wbc): drop unused make_quadruped_joints + GRIPPER enum (carr…
Nabla7 May 7, 2026
2d2ba1d
chore(g1-wbc): strip unrelated leftovers (lidar scene_option, get_cam…
Nabla7 May 7, 2026
fef9460
fix(g1-wbc): passive lowstate sub + restore arm/dry_run wiring
Nabla7 May 7, 2026
a400d26
chore(g1-wbc): restore unrelated files accidentally swept into PR
Nabla7 May 7, 2026
b553645
Merge remote-tracking branch 'origin/dev' into pim/feat/g1-groot-wbc
Nabla7 May 7, 2026
a7aa3bf
fix(coordinator): merge duplicate _create_whole_body_adapter
Nabla7 May 7, 2026
74b6404
refactor(g1-wbc): drop monolith adapter, use Mustafa's transport bridge
Nabla7 May 7, 2026
7f91e52
fix(g1-wbc-sim): resolve MJCF path via get_data so CWD doesn't matter
Nabla7 May 7, 2026
117df92
refactor(g1-wbc): paul-review fixes + bridge composition smoke test
Nabla7 May 7, 2026
995c735
fix(g1-wbc): safe-stop lowcmd on disconnect + skip release when idle
Nabla7 May 7, 2026
224e7e9
chore(g1-wbc): strip section-marker comments
Nabla7 May 7, 2026
bbcc777
fix(g1-wbc): mypy errors uncovered by full CI-matching env
Nabla7 May 8, 2026
38d6c91
-
jeff-hykin May 9, 2026
4aa9d08
-
jeff-hykin May 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions data/.lfs/groot.tar.gz
Git LFS file not shown
4 changes: 2 additions & 2 deletions data/.lfs/mujoco_sim.tar.gz
Git LFS file not shown
14 changes: 14 additions & 0 deletions dimos/control/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from enum import Enum
from typing import Any

from dimos.hardware.whole_body.spec import WholeBodyConfig

HardwareId = str
JointName = str
TaskName = str
Expand Down Expand Up @@ -61,6 +63,16 @@ class HardwareComponent:
address: Connection address - IP for TCP, port for CAN
auto_enable: Whether to auto-enable servos
gripper_joints: Joints that use adapter gripper methods (separate from joints).
domain_id: DDS domain ID for adapters that use DDS transport
(e.g. Unitree G1). Real robot uses 0; unitree_mujoco sim
defaults to 1. Ignored by non-DDS adapters.
adapter_kwargs: Generic untyped kwargs forwarded to the adapter
constructor — use for adapter-specific knobs that don't
belong in the spec.
wb_config: Whole-body-specific config (PD gains etc.). Populate
on hardware_type=WHOLE_BODY components. Keeps WB-only knobs
off the generic HardwareComponent shared by manipulators,
bases, and grippers.
"""

hardware_id: HardwareId
Expand All @@ -70,7 +82,9 @@ class HardwareComponent:
address: str | None = None
auto_enable: bool = True
gripper_joints: list[JointName] = field(default_factory=list)
domain_id: int = 0
adapter_kwargs: dict[str, Any] = field(default_factory=dict)
wb_config: WholeBodyConfig | None = None

@property
def all_joints(self) -> list[JointName]:
Expand Down
243 changes: 223 additions & 20 deletions dimos/control/coordinator.py

Large diffs are not rendered by default.

37 changes: 34 additions & 3 deletions dimos/control/hardware_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,34 @@ def __init__(
self._component = component
self._joint_names = component.joints

# Resolve per-joint PD gains once at wire-up time. Gains live on
# the WB-specific sub-config; fall back to _DEFAULT_KP/_DEFAULT_KD
# if the blueprint didn't supply a wb_config.
n = len(self._joint_names)
wb = component.wb_config
kp_in = wb.kp if wb is not None else None
kd_in = wb.kd if wb is not None else None
if kp_in is not None:
if len(kp_in) != n:
raise ValueError(
f"HardwareComponent '{component.hardware_id}': wb_config.kp length "
f"{len(kp_in)} does not match joints length {n}"
)
self._kp = list(kp_in)
else:
self._kp = [_DEFAULT_KP] * n
if kd_in is not None:
if len(kd_in) != n:
raise ValueError(
f"HardwareComponent '{component.hardware_id}': wb_config.kd length "
f"{len(kd_in)} does not match joints length {n}"
)
self._kd = list(kd_in)
else:
self._kd = [_DEFAULT_KD] * n
self._kp_by_name = dict(zip(self._joint_names, self._kp, strict=False))
self._kd_by_name = dict(zip(self._joint_names, self._kd, strict=False))

self._last_commanded: dict[str, float] = {}
self._initialized = False
self._warned_unknown_joints: set[str] = set()
Expand Down Expand Up @@ -361,10 +389,13 @@ def read_state(self) -> dict[JointName, JointState]:
}

def write_command(self, commands: dict[str, float], mode: ControlMode) -> bool:
"""Write position commands — converts to MotorCommand with PD gains.
"""Write position commands — converts to MotorCommand with per-joint PD gains.

Only POSITION / SERVO_POSITION are supported; other modes are warned
and dropped (matches ConnectedHardware's warn-and-skip pattern).
Per-joint kp/kd come from ``component.wb_config`` (resolved in
``__init__``); fall back to ``_DEFAULT_KP``/``_DEFAULT_KD`` when
the blueprint didn't supply gains.
"""
from dimos.hardware.whole_body.spec import MotorCommand

Expand Down Expand Up @@ -392,8 +423,8 @@ def write_command(self, commands: dict[str, float], mode: ControlMode) -> bool:
MotorCommand(
q=self._last_commanded[name],
dq=0.0,
kp=_DEFAULT_KP,
kd=_DEFAULT_KD,
kp=self._kp_by_name[name],
kd=self._kd_by_name[name],
tau=0.0,
)
for name in self._joint_names
Expand Down
Loading
Loading