-
Notifications
You must be signed in to change notification settings - Fork 152
Description
Problem
Unitree WebRTC connections require tight clock synchronization between the control computer and robot (within 100ms). Clock divergence affects:
- Command timestamps
- Sensor data correlation
- Control loop timing
- Telemetry synchronization
Currently, there's no automated check or sync for clock drift before connecting to hardware.
Proposed Solution
Add ClockSyncConfigurator to the system configurator framework (same pattern as LCM's multicast/buffer checks).
Implementation
File: dimos/protocol/service/system_configurator.py
class ClockSyncConfigurator(SystemConfigurator):
"""Check and sync local clock with NTP server."""
critical = False
MAX_DIVERGENCE_SECONDS = 0.1 # 100ms for WebRTC
NTP_SERVER = "time.windows.com"
def check(self) -> bool:
# Use ntpdate -q to query clock offset
# Return False if divergence > threshold
def explanation(self) -> str | None:
# Show offset in ms and sync command
def fix(self) -> None:
# Run: sudo ntpdate <server>Reference implementation: Available in proposal docs (attached or can provide)
Integration Challenge
Problem: Modules/connections run in separate runner processes without STDIO access. Can't prompt for user input during module/connection initialization.
Current LCM pattern:
lcmservice.autoconf()runs at CLI startup (before blueprints)- Has STDIO access for user prompts
- Global/early execution
Naive approach (won't work):
class UnitreeWebRTCConnection:
def __init__(self, ip):
self.autoconf() # ❌ No STDIO in runner process
# ... connect ...Required approach:
- Collect system config requirements before spawning runner processes
- Run all configurators with user prompts at CLI level
- Then proceed with blueprint execution
Proposed Integration Strategy
Option 1: Blueprint-level system config registration
Add system_config field to blueprints:
# In unitree_go2_blueprints.py
def unitree_go2(ip=None, sim=False, ...):
system_checks = []
if not sim and ip not in ["fake", "mock", "replay", "mujoco"]:
system_checks.append(
ClockSyncConfigurator(max_divergence=0.1)
)
return Blueprint(
modules=[GO2Connection(ip=ip), ...],
system_config=system_checks # ← new field
)Then in blueprint startup (before runner spawns):
configure_system(blueprint.system_config) # has STDIO, can prompt
# ... spawn runners, execute blueprint ...Pros:
- Declarative (clear what system config a blueprint needs)
- Runs before runner processes spawn
- Has STDIO for user prompts
- Conditional per blueprint (hardware vs sim)
Cons:
- Requires Blueprint infrastructure changes
- Need to add system_config field + collection/execution logic
Option 2: Module metadata + collection phase
Add classmethod to modules that need system config:
class UnitreeWebRTCConnection:
@classmethod
def system_requirements(cls) -> list[SystemConfigurator]:
return [ClockSyncConfigurator(max_divergence=0.1)]Before executing blueprint, scan modules and collect requirements:
# In blueprint execution
requirements = []
for module in blueprint.modules:
if hasattr(module.__class__, 'system_requirements'):
requirements.extend(module.__class__.system_requirements())
configure_system(requirements) # run before spawning runnersPros:
- Less invasive (no Blueprint schema changes)
- Modules declare their own requirements
Cons:
- Harder to make conditional (hardware vs sim)
- Requires scanning all modules
Acceptance Criteria
-
ClockSyncConfiguratorimplemented insystem_configurator.py - Unit tests for clock sync check/fix
- Integration strategy chosen and implemented
- System config runs before runner processes spawn
- User prompted with STDIO access
- Works for hardware Go2/G1 (skipped for sim/replay)
- Tested on actual hardware with intentional clock skew
Related
- Existing system config framework:
dimos/protocol/service/system_configurator.py - LCM autoconf example:
dimos/protocol/service/lcmservice.py - Runner process architecture: (need docs reference)
Implementation Status
- ✅
ClockSyncConfiguratorclass designed and documented - ⏸️ Integration blocked on runner process STDIO constraint
- ⏸️ Needs blueprint-level or pre-execution collection strategy