-
Notifications
You must be signed in to change notification settings - Fork 0
Control Orchestrator - Unified Controller for multi-arm and full body controller #970
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
Overview
This PR introduces a unified Control Orchestrator for multi-arm and full-body robot control. The architecture replaces per-driver control loops with a single centralized 100Hz tick loop featuring per-joint priority arbitration. The design separates hardware backends from control logic through the ManipulatorBackend protocol, enabling easy integration of new robots.
Key Changes
New Control Architecture:
- Single deterministic tick loop (read → compute → arbitrate → route → write) at 100Hz
- Per-joint priority-based arbitration allowing multiple controllers to share joints
- Centralized time management (tasks use orchestrator time, not
time.time()) - Support for partial joint commands with hold-last-value behavior
Hardware Abstraction:
ManipulatorBackendprotocol for vendor-agnostic hardware interfaces- Implementations for XArm, Piper, and Mock backends
BackendHardwareInterfacewrapper providing namespaced joint names and partial command support
Task System:
ControlTaskprotocol for passive controllers called by orchestratorJointTrajectoryTaskfor trajectory execution- Preemption notifications when higher-priority tasks take control
New Files:
- Control orchestrator core (orchestrator.py, tick_loop.py, task.py, hardware_interface.py)
- Backend implementations (xarm/backend.py, piper/backend.py, mock/backend.py)
- Pre-configured blueprints for common setups
- Interactive RPC client for trajectory control
- Comprehensive unit and E2E tests
Deprecated:
- Old manipulators architecture moved to
manipulators_old/
Critical Issues Found
Logic Errors (Must Fix)
-
Mode mixing bug in
tick_loop.py: When routing commands to hardware, if multiple joints on the same hardware interface require different control modes (e.g., one joint needs POSITION, another needs VELOCITY), only the last mode is used for all joints. This will cause incorrect robot behavior. -
Race condition in
orchestrator.py: Theexecute_trajectory()RPC method readstime.perf_counter()outside the task lock, but the tick loop thread may be concurrently accessing task state. This creates a race condition on the trajectory start time. -
Incomplete preemption handling: When mode conflicts occur at the same priority level, commands are dropped but tasks aren't notified via
on_preempted(), leaving them unaware their commands are being ignored. -
Piper enable retry bug: The enable loop can succeed on the 100th attempt but still return False due to an off-by-one error in the success check.
Style/Best Practice Issues
-
Lost preemption source: Preemption notifications use hardcoded string instead of tracking which specific task caused the preemption, making debugging harder.
-
Trajectory completion: Final waypoint may not be precisely reached if the tick occurs slightly after trajectory end.
-
TORQUE mode silently dropped: While acceptable (most hardware doesn't support it), this should be better documented.
-
Hardware setup error handling: Partial initialization can occur if enable fails after connection succeeds.
-
Unused variables: Dead code in orchestrator_client.py.
Architecture Assessment
Strengths:
- Clean separation of concerns with Protocol-based design
- Well-thought-out arbitration system for multi-controller scenarios
- Centralized timing prevents common distributed control issues
- Good test coverage (unit + E2E)
- Clear documentation and examples
Concerns:
- The mode mixing bug in routing is critical and will cause runtime failures
- Thread safety needs more attention, especially around task state transitions
- Missing validation that all joints on a hardware interface use the same control mode
Testing
The PR includes solid test coverage:
- Unit tests for core components (arbitration, tasks, hardware interface)
- E2E tests for single and dual-arm scenarios
- Tests for trajectory execution, cancellation, and status querying
However, tests don't cover:
- Mode conflict scenarios
- Concurrent execution edge cases
- The specific race conditions identified
Confidence Score: 2/5
- This PR has critical logic errors in the core control loop that will cause incorrect robot behavior with multiple control modes
- Score of 2 reflects serious issues that must be fixed before merge: (1) Mode mixing bug in tick_loop routing will cause wrong control modes to be applied to joints, (2) Race condition in trajectory execution timing, (3) Incomplete preemption notifications leaving tasks in inconsistent states, (4) Off-by-one error in Piper enable logic. While the architecture is well-designed and most code is solid, these bugs affect core functionality and could cause dangerous robot behavior in production.
- Pay close attention to dimos/control/tick_loop.py (mode routing bug), dimos/control/orchestrator.py (race condition), and dimos/hardware/manipulators/piper/backend.py (enable retry logic)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| dimos/control/tick_loop.py | 2/5 | Core control loop with critical mode mixing bug in routing, incomplete preemption handling for mode conflicts, and loss of preemption source information |
| dimos/control/orchestrator.py | 3/5 | Main orchestrator module with race condition in execute_trajectory time synchronization and error handling issue in hardware setup |
| dimos/control/hardware_interface.py | 3/5 | Hardware abstraction with TORQUE mode silently dropped and minor initialization race condition |
| dimos/control/tasks/trajectory_task.py | 4/5 | Trajectory task implementation with minor edge case where final position may not be held at completion |
| dimos/hardware/manipulators/piper/backend.py | 3/5 | Piper hardware backend with potential infinite loop bug in enable retry logic |
| dimos/manipulation/control/orchestrator_client.py | 4/5 | Interactive RPC client with two unused variable issues (syntax errors) |
Sequence Diagram
sequenceDiagram
participant User
participant Orchestrator
participant TickLoop
participant Task1
participant Task2
participant HWInterface
participant Backend
User->>Orchestrator: execute_trajectory(task_name, traj)
Orchestrator->>Task1: execute(trajectory, t_now)
Task1-->>Orchestrator: True (accepted)
loop Every 10ms (100Hz)
TickLoop->>HWInterface: read_state()
HWInterface->>Backend: read_joint_positions()
Backend-->>HWInterface: positions
HWInterface-->>TickLoop: joint states
TickLoop->>Task1: is_active()
Task1-->>TickLoop: True
TickLoop->>Task1: claim()
Task1-->>TickLoop: ResourceClaim(joints, priority=10)
TickLoop->>Task2: is_active()
Task2-->>TickLoop: True
TickLoop->>Task2: claim()
Task2-->>TickLoop: ResourceClaim(joints, priority=100)
TickLoop->>Task1: compute(state)
Task1-->>TickLoop: JointCommandOutput
TickLoop->>Task2: compute(state)
Task2-->>TickLoop: JointCommandOutput
Note over TickLoop: Arbitrate per-joint<br/>(higher priority wins)
alt Task2 preempted Task1
TickLoop->>Task1: on_preempted(by_task, joints)
end
Note over TickLoop: Route commands<br/>to hardware
TickLoop->>HWInterface: write_command(commands, mode)
HWInterface->>Backend: write_joint_positions(ordered)
Backend-->>HWInterface: success
HWInterface-->>TickLoop: success
TickLoop->>Orchestrator: publish joint_state
end
User->>Orchestrator: get_trajectory_status(task_name)
Orchestrator->>Task1: get_state()
Task1-->>Orchestrator: EXECUTING
Orchestrator-->>User: status dict
e9c529b to
caeb3c1
Compare
… threads also invokes rpc calls to arm specific SDK backends
…ms and joint control - added dataclasses for orchestrator and protocol for ControlTask
…orchestrator. Also solves namespace for multiple arm and hardware
…tes next commands, and arbitrates priority of different tasks and controllers
explicit false added to the Torque Mode command sent, to avoid silent failing scenario
Mode conflict detection in routing: Added check in _route_to_hardware
Preemption tracking: Changed structure to {preempted_task: {joint: winning_task}}
Mode conflict preemption: Tasks dropped due to mode conflict at same priority
Trajectory completion edge case: Returns final position instead of None on completion
Dead code removal: and Piper backend cleanup
… backend cleanup task.py: Use match statement in get_values() tick_loop.py: Add JointWinner NamedTuple for cleaner arbitration logic xarm/backend.py: Extract unit conversions into static helper methods
…sting winner hardware_interface.py: Call set_control_mode() before mode-specific writes, Convert if/elif to match statement for control mode dispatch
…sting winner hardware_interface.py: Call set_control_mode() before mode-specific writes, convert if/elif to match statement trajectory_task.py: Defer start time to first compute() for consistent timing orchestrator.py: Extract _setup_hardware() helper for cleaner config setup piper and xarm/backend.py: Fail fast on read_joint_positions(), map SERVO_POSITION to mode 1 hardware_interface.py: Retry initialization with proper error propagation, spec.py: Add SERVO_POSITION control mode for confusion between position planning and position servo task.py: added SERVO_POSITION to JointCommandOutput helper
|
@greptile final final review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
66 files reviewed, 6 comments
…ly inherit from ControlTask protocol
| def _create_backend_from_config(self, cfg: HardwareConfig) -> ManipulatorBackend: | ||
| """Create a manipulator backend from config.""" | ||
| match cfg.type.lower(): | ||
| case "mock": | ||
| from dimos.hardware.manipulators.mock import MockBackend | ||
|
|
||
| return MockBackend(dof=cfg.dof) | ||
| case "xarm": | ||
| if cfg.ip is None: | ||
| raise ValueError("ip is required for xarm backend") | ||
| from dimos.hardware.manipulators.xarm import XArmBackend | ||
|
|
||
| return XArmBackend(ip=cfg.ip, dof=cfg.dof) | ||
| case "piper": | ||
| from dimos.hardware.manipulators.piper import PiperBackend | ||
|
|
||
| return PiperBackend(can_port=cfg.can_port or "can0", dof=cfg.dof) | ||
| case _: | ||
| raise ValueError(f"Unknown backend type: {cfg.type}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Horrible fix ASAP after this PR. No modularity to other robots
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @staticmethod | ||
| def _m_to_mm(m: float) -> float: | ||
| return m * 1000.0 | ||
|
|
||
| @staticmethod | ||
| def _mm_to_m(mm: float) -> float: | ||
| return mm / 1000.0 | ||
|
|
||
| @staticmethod | ||
| def _rad_to_deg(rad: float) -> float: | ||
| return math.degrees(rad) | ||
|
|
||
| @staticmethod | ||
| def _deg_to_rad(deg: float) -> float: | ||
| return math.radians(deg) | ||
|
|
||
| @staticmethod | ||
| def _velocity_to_speed_mm(velocity: float) -> float: | ||
| """Convert 0-1 velocity fraction to mm/s (max ~500 mm/s).""" | ||
| return velocity * 500 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very bad ASAP move out of this folder why would we have general manipulator utils in xarm backend
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will address in the second pass
| print("-" * 70) | ||
|
|
||
|
|
||
| def preview_trajectory(trajectory: JointTrajectory, joint_names: list[str]) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to be moved to some orchestrator visualizer class
| @@ -0,0 +1,696 @@ | |||
| #!/usr/bin/env python3 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally bad file. Shell class should use our CLI standard among other things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
… controller (#970) * archive old driver to manipulators_old for redesign * spec.py defining minimal protocol for an arm driver * xarm driver driver added - driver owns control thread and robot state threads also invokes rpc calls to arm specific SDK backends * xarm SDK specific wrapper to interface with dimos RPC calls from the driver * removed type checking for old armdriver spec from the cartesian controller * replicated piper driver to meet the new architecture * added mock backend * updated all blueprints to add new arm module * Added readme explaining new driver architecture overview * config now parsed in backend init instead of connect method * addded dual arm control blueprint using trajectory controller * adding a control orchestrator for single control loop for multiple arms and joint control - added dataclasses for orchestrator and protocol for ControlTask * hardware interface protocol that wraps specific arm SDK to work with orchestrator. Also solves namespace for multiple arm and hardware * main orchestrator module and control loop that claims resources computes next commands, and arbitrates priority of different tasks and controllers * added a trajectory task implementation that performs trajecotry control * added blueprints to launch orchestratory module with differnt arms for testing * updated blueprints to add piper + xarm blueprint * orchestrator client that can send tasks to the control orchestrator module * added a readme * added pytest and e2e test * Update dimos/control/hardware_interface.py explicit false added to the Torque Mode command sent, to avoid silent failing scenario * CI code cleanup * Fixed issues flagged by greptile Mode conflict detection in routing: Added check in _route_to_hardware Preemption tracking: Changed structure to {preempted_task: {joint: winning_task}} Mode conflict preemption: Tasks dropped due to mode conflict at same priority Trajectory completion edge case: Returns final position instead of None on completion Dead code removal: and Piper backend cleanup * Renamed deprecated old manipuialtion test file and Mypy type fixes * fix mypy test * mypy test fix added explicit type * Remove deprecated manipulators_old folder * fixed redef error in dual trajectory setter * Fixed bugs identified by greptile overview: 1. tick_loop.py - Race condition in _route_to_hardware 2. orchestrator.py - Added hardware_added tracking list and rollback in outer except block 3. hardware_interface.py - Added disconnect() to both HardwareInterface protocol and BackendHardwareInterface 4. Added disconnect() to both HardwareInterface protocol and BackendHardwareInterface 5. orchestrator.py - Start order fix Moved super().start() to end, after tick loop starts successfully 6. trajectory_task.py - Added Empty joint_names validation * addressed greptile suggestion: hardware_interface.py - Torque mode logging fix orchestrator.py - Fail hardware removal if joints in use tick_loop.py - Rate control drift fix * undo change to pyproject.toml * Replaced _running bool with threading.Event (_stop_event) for thread safety Removed duplicate _auto_start() call from __init__ - connection now only happens in start() orchestrator_client.py IPython conversion * added type ignore for ipythin * removed check for has attribute in hardware interface Moved super.start() at the beginning replaced running bool with stop_event in tick_loop to improve thread safety removed default ip from init removed simple dataclasses test * orchestrator.py: Use match statement for backend factory, restructure backend cleanup task.py: Use match statement in get_values() tick_loop.py: Add JointWinner NamedTuple for cleaner arbitration logic xarm/backend.py: Extract unit conversions into static helper methods * tick_loop.py: Notify preemption when lower-priority task loses to existing winner hardware_interface.py: Call set_control_mode() before mode-specific writes, Convert if/elif to match statement for control mode dispatch * tick_loop.py: Notify preemption when lower-priority task loses to existing winner hardware_interface.py: Call set_control_mode() before mode-specific writes, convert if/elif to match statement trajectory_task.py: Defer start time to first compute() for consistent timing orchestrator.py: Extract _setup_hardware() helper for cleaner config setup piper and xarm/backend.py: Fail fast on read_joint_positions(), map SERVO_POSITION to mode 1 hardware_interface.py: Retry initialization with proper error propagation, spec.py: Add SERVO_POSITION control mode for confusion between position planning and position servo task.py: added SERVO_POSITION to JointCommandOutput helper * cleaned up legacy blueprints for manipulator drivers * enforce ManipulatorBackend Protocol on the backend.py * feat: add runtime protocol checks for manipulator backends * added runtime checking for controlTask protocol * Add TaskStatus dataclass, refactor get_trajectory_status and Explicitly inherit from ControlTask protocol --------- Co-authored-by: stash <pomichterstash@gmail.com>
… controller (#970) * archive old driver to manipulators_old for redesign * spec.py defining minimal protocol for an arm driver * xarm driver driver added - driver owns control thread and robot state threads also invokes rpc calls to arm specific SDK backends * xarm SDK specific wrapper to interface with dimos RPC calls from the driver * removed type checking for old armdriver spec from the cartesian controller * replicated piper driver to meet the new architecture * added mock backend * updated all blueprints to add new arm module * Added readme explaining new driver architecture overview * config now parsed in backend init instead of connect method * addded dual arm control blueprint using trajectory controller * adding a control orchestrator for single control loop for multiple arms and joint control - added dataclasses for orchestrator and protocol for ControlTask * hardware interface protocol that wraps specific arm SDK to work with orchestrator. Also solves namespace for multiple arm and hardware * main orchestrator module and control loop that claims resources computes next commands, and arbitrates priority of different tasks and controllers * added a trajectory task implementation that performs trajecotry control * added blueprints to launch orchestratory module with differnt arms for testing * updated blueprints to add piper + xarm blueprint * orchestrator client that can send tasks to the control orchestrator module * added a readme * added pytest and e2e test * Update dimos/control/hardware_interface.py explicit false added to the Torque Mode command sent, to avoid silent failing scenario * CI code cleanup * Fixed issues flagged by greptile Mode conflict detection in routing: Added check in _route_to_hardware Preemption tracking: Changed structure to {preempted_task: {joint: winning_task}} Mode conflict preemption: Tasks dropped due to mode conflict at same priority Trajectory completion edge case: Returns final position instead of None on completion Dead code removal: and Piper backend cleanup * Renamed deprecated old manipuialtion test file and Mypy type fixes * fix mypy test * mypy test fix added explicit type * Remove deprecated manipulators_old folder * fixed redef error in dual trajectory setter * Fixed bugs identified by greptile overview: 1. tick_loop.py - Race condition in _route_to_hardware 2. orchestrator.py - Added hardware_added tracking list and rollback in outer except block 3. hardware_interface.py - Added disconnect() to both HardwareInterface protocol and BackendHardwareInterface 4. Added disconnect() to both HardwareInterface protocol and BackendHardwareInterface 5. orchestrator.py - Start order fix Moved super().start() to end, after tick loop starts successfully 6. trajectory_task.py - Added Empty joint_names validation * addressed greptile suggestion: hardware_interface.py - Torque mode logging fix orchestrator.py - Fail hardware removal if joints in use tick_loop.py - Rate control drift fix * undo change to pyproject.toml * Replaced _running bool with threading.Event (_stop_event) for thread safety Removed duplicate _auto_start() call from __init__ - connection now only happens in start() orchestrator_client.py IPython conversion * added type ignore for ipythin * removed check for has attribute in hardware interface Moved super.start() at the beginning replaced running bool with stop_event in tick_loop to improve thread safety removed default ip from init removed simple dataclasses test * orchestrator.py: Use match statement for backend factory, restructure backend cleanup task.py: Use match statement in get_values() tick_loop.py: Add JointWinner NamedTuple for cleaner arbitration logic xarm/backend.py: Extract unit conversions into static helper methods * tick_loop.py: Notify preemption when lower-priority task loses to existing winner hardware_interface.py: Call set_control_mode() before mode-specific writes, Convert if/elif to match statement for control mode dispatch * tick_loop.py: Notify preemption when lower-priority task loses to existing winner hardware_interface.py: Call set_control_mode() before mode-specific writes, convert if/elif to match statement trajectory_task.py: Defer start time to first compute() for consistent timing orchestrator.py: Extract _setup_hardware() helper for cleaner config setup piper and xarm/backend.py: Fail fast on read_joint_positions(), map SERVO_POSITION to mode 1 hardware_interface.py: Retry initialization with proper error propagation, spec.py: Add SERVO_POSITION control mode for confusion between position planning and position servo task.py: added SERVO_POSITION to JointCommandOutput helper * cleaned up legacy blueprints for manipulator drivers * enforce ManipulatorBackend Protocol on the backend.py * feat: add runtime protocol checks for manipulator backends * added runtime checking for controlTask protocol * Add TaskStatus dataclass, refactor get_trajectory_status and Explicitly inherit from ControlTask protocol --------- Co-authored-by: stash <pomichterstash@gmail.com>
* feat(sim): add MJLab G1 velocity policy profile
Introduce a 'mujoco_profile' concept allowing self-contained MuJoCo
simulation bundles (MJCF + ONNX policy + assets) to be loaded by name.
Key changes:
- GlobalConfig: new 'mujoco_profile' field (--mujoco-profile CLI flag)
- model.py: profile-scoped asset loading and bundle.json support
- mujoco_process.py: read camera names from bundle.json per profile
- policy.py: MjlabVelocityOnnxController reads joint_names,
default_joint_pos, action_scale from ONNX metadata for exact
MJLab action contract (per-joint scaling & named ordering)
- mujoco_connection.py: skip menagerie download when profile is set
- blueprints.py / rerun_init.py: gate Rerun init on rerun_enabled
Bundle added to data/.lfs/mujoco_sim.tar.gz (LFS-tracked):
data/mujoco_sim/unitree_g1_mjlab/
├── model.xml (MJLab-compiled G1 MJCF with correct actuators)
├── policy.onnx (trained velocity policy with metadata)
├── bundle.json (camera name mappings)
└── assets/ (STL meshes from MJLab asset_zoo)
Usage:
dimos --simulation \
--mujoco-profile unitree_g1_mjlab \
run unitree-g1-basic-sim
* CI code cleanup
* fix(sim): resolve meshdir/profile asset conflicts for GO2 and G1
- mujoco_process.py: only use mujoco_profile when explicitly set
(fixes GO2 accidentally being treated as a profile bundle)
- model.py: rewrite scene XML to remove meshdir/texturedir attrs
and prefix mesh/texture filenames explicitly, preventing scene
compiler settings from hijacking robot mesh resolution
* configure unitree go2 mapper to use 10 cm voxels (#1032)
* feat(sim): add MuJoCo subprocess profiler for performance debugging
Adds a built-in timing breakdown for the MuJoCo simulation subprocess.
When enabled, logs rolling averages of time spent in each component:
- physics_ms: mj_step loop
- viewer_sync_ms: MuJoCo viewer synchronization
- rgb_render_ms, depth_render_ms: camera rendering
- pcd_ms: depth-to-pointcloud + voxel downsample
- *_shm_ms: shared memory writes
- ctrl_calls, ctrl_obs_ms, ctrl_onnx_ms: policy cost breakdown
This helps diagnose performance issues (e.g. 'molasses' effect) by
showing exactly where frame time is being spent.
Usage:
# Standard G1 sim with profiler:
dimos --simulation --mujoco-profiler --mujoco-profiler-interval-s 2 run unitree-g1-basic-sim
# MJLab bundle with profiler:
dimos --simulation --mujoco-profile unitree_g1_mjlab --mujoco-profiler --mujoco-profiler-interval-s 2 run unitree-g1-basic-sim
New GlobalConfig flags:
- mujoco_profiler: bool (default False)
- mujoco_profiler_interval_s: float (default 2.0)
* pre commit
* small docs clarification (#1043)
* Fix split view on wide monitors (#1048)
* fix print to be correct URL based on rerun web or not
* make width of rerun/command center adjustable
* swap sides
* Docs: Install & Develop (#1022)
* minimal edit
* rice the readme
* grammar
* formatting
* fix examples
* change links to reduce change count
* improve wording
* wording
* remove acknowledgements
* improve the humancli example
* formatting
* Update README.md
* switch to dev branch for development
* changes for paul
* Update README.md
* fix broken link
* update broken link
* Add uv to nix and fix resulting problems (#1021)
* add uv to nix and fix resulting problems
* fix for linux
* v0.0.8 version update (#1050)
* Style changes in docs (#1051)
* capitalization
* punctuation
* more small fixes
* Revert "Add uv to nix and fix resulting problems (#1021)" (#1053)
This reverts commit 8af8f8f.
* Transport benchmarks & Raw ROS transport (#1038)
* raw rospubsub and benchmarks
* typefixes, shm added to the benchmark
* SHM is not so important to tell us every time when it starts
* greptile comments
* Add co-authorship line to commit message filter patterns
* Remove unused contextmanager import
* lcmservice correct kernel settings reintroduced
* mixin mixin resolved
* lcmservice tests fix
* macos lcm rmem fix
* feat: default to rerun-web and auto-open browser on startup (#1019)
- Changed GlobalConfig.viewer_backend default from rerun-native to rerun-web
- WebsocketVisModule now opens dashboard in browser automatically on start
- Requested by Jeff
Co-authored-by: s <pomichterstash@gmail.com>
* chore: fix indentation in blueprints ambiguity check
* CI code cleanup
* use p controller to stop oscillations on unitree go2 (#1014)
* Dynamic session providers for onnxruntime (#983)
* refactor(policy): update inference session initialization
* refactor(policy): simplify inference session provider initialization
* Log the policy directory and provider
* Perception Full Refactor and Cleanup, deprecated Manipulation AIO Pipeline and replaced with Object Scene Registration (#936)
* added rate limiting and backpressure to pointcloud publishing
CI code cleanup
updated ZED module to the same standard as realsense
CI code cleanup
fixed stash's comments
CI code cleanup
mypy fixes + comments
removed property of camera_info
should pass CI now
added detection3d pointcloud types from depth image
added yoloe support and 3D object segmentation
CI code cleanup
use yoloe-s instead for nuc
CI code cleanup
removed deprecated perception code
some pointcloud color changes
major refactor and added object class for object scene registration
CI code cleanup
refactored, added objectDB for persistent object memory
CI code cleanup
made objectDB a normal class instead of a module
CI code cleanup
revert to dev
reverted more files
CI code cleanup
completely refactored object scene registration to work natively in dimos instead of using ROS as transport. Made everything super clean and working
CI code cleanup
bug fixed + use yoloe-l by default
added yolo object exlusion list
CI code cleanup
added zed camera to the object registration demo
CI code cleanup
added image and pointclou2 fixes and as_numpy function
working promptable object scene registration
CI code cleanup
bug fixes
bug fix + remove ros imports
should not fail CI now
CI code cleanup
more CI fixes, somehow local CI did not catch
changed prompt fixed bug
CI code cleanup
reverted some changes
Cleanup very dead code and fixed mypy errors
CI code cleanup
fixed more mypy
CI code cleanup
* one last mypy fix
* added default to imagedetection2d to not set off mypy
* fixed bug and default to open vocab for detection
* mypy fixes
* fixed one last mypy error
* fixed all of Stash's comments
* should pass mypy now
* added uv lock
* sync uv.lock with dev
* fixed the last mypy error
* fixed mypy errors from source
* reverted mypy import error fixes
* fixed Ivan's comment
* fixed last of ivan's comment
* remove all to_ros_msgs stuff in this commit
* passed Ivan's detector tests
* added README for depth camera integration
* fixed last of Stash's comments
* feat(cli): type-free topic echo via /topic#pkg.Msg inference, this mi… (#988)
* feat(cli): type-free topic echo via /topic#pkg.Msg inference, this mirrors ros topic echo functionality.
- Make type_name optional in 'dimos topic echo'
- Infer message type from LCM channel suffix (e.g. /odom#nav_msgs.Odometry)
- Dynamically import dimos.msgs.<pkg> and call cls.lcm_decode(data)
- Keep existing explicit-type mode working
- Update transports.md docs
* fix(cli): use LCMPubSubBase instead of raw lcm.LCM for topic echo, my bad
* verify blueprints (#1018)
* verify blueprints
* Fix geometry msgs check failure in CI
---------
Co-authored-by: stash <pomichterstash@gmail.com>
* Experimental Streamed Temporal Memory with SpatioTemporal & Entity based RAG (#973)
* temporal memory + vlm agent + blueprints
* fixing module issue and style
* fix skill registration
* removing state functions unpickable
* inheritancefixes and memory management
* docstring for query
* microcommit: fixing memory buffer
* sharpness filter and simplified frame filtering
* CI code cleanup
* initial graph database implementation
* db implementation, working and stylized, best reply is unitree_go2_office_walk2
* type checking issues
* final edits, move into experimental, revert non-memory code edits, typechecking
* persistent db flag enabled in config
* Fix test to not run in CI due to LFS pull
* Fix CLIP filter to use dimensional clip
* Add path to temporal memory
* revert video operators
* Revert moondream
* added temporal memory docs
* Refactor move to /experimental/temporal_memory
---------
Co-authored-by: Paul Nechifor <paul@nechifor.net>
Co-authored-by: Stash Pomichter <pomichterstash@gmail.com>
Co-authored-by: shreyasrajesh0308 <shreyasrajesh0308@users.noreply.github.com>
Co-authored-by: spomichter <12108168+spomichter@users.noreply.github.com>
* Control Orchestrator - Unified Controller for multi-arm and full body controller (#970)
* archive old driver to manipulators_old for redesign
* spec.py defining minimal protocol for an arm driver
* xarm driver driver added - driver owns control thread and robot state threads also invokes rpc calls to arm specific SDK backends
* xarm SDK specific wrapper to interface with dimos RPC calls from the driver
* removed type checking for old armdriver spec from the cartesian controller
* replicated piper driver to meet the new architecture
* added mock backend
* updated all blueprints to add new arm module
* Added readme explaining new driver architecture overview
* config now parsed in backend init instead of connect method
* addded dual arm control blueprint using trajectory controller
* adding a control orchestrator for single control loop for multiple arms and joint control - added dataclasses for orchestrator and protocol for ControlTask
* hardware interface protocol that wraps specific arm SDK to work with orchestrator. Also solves namespace for multiple arm and hardware
* main orchestrator module and control loop that claims resources computes next commands, and arbitrates priority of different tasks and controllers
* added a trajectory task implementation that performs trajecotry control
* added blueprints to launch orchestratory module with differnt arms for testing
* updated blueprints to add piper + xarm blueprint
* orchestrator client that can send tasks to the control orchestrator module
* added a readme
* added pytest and e2e test
* Update dimos/control/hardware_interface.py
explicit false added to the Torque Mode command sent, to avoid silent failing scenario
* CI code cleanup
* Fixed issues flagged by greptile
Mode conflict detection in routing: Added check in _route_to_hardware
Preemption tracking: Changed structure to {preempted_task: {joint: winning_task}}
Mode conflict preemption: Tasks dropped due to mode conflict at same priority
Trajectory completion edge case: Returns final position instead of None on completion
Dead code removal: and Piper backend cleanup
* Renamed deprecated old manipuialtion test file and Mypy type fixes
* fix mypy test
* mypy test fix added explicit type
* Remove deprecated manipulators_old folder
* fixed redef error in dual trajectory setter
* Fixed bugs identified by greptile overview:
1. tick_loop.py - Race condition in _route_to_hardware
2. orchestrator.py - Added hardware_added tracking list and rollback in outer except block
3. hardware_interface.py - Added disconnect() to both HardwareInterface protocol and BackendHardwareInterface
4. Added disconnect() to both HardwareInterface protocol and BackendHardwareInterface
5. orchestrator.py - Start order fix Moved super().start() to end, after tick loop starts successfully
6. trajectory_task.py - Added Empty joint_names validation
* addressed greptile suggestion:
hardware_interface.py - Torque mode logging fix
orchestrator.py - Fail hardware removal if joints in use
tick_loop.py - Rate control drift fix
* undo change to pyproject.toml
* Replaced _running bool with threading.Event (_stop_event) for thread safety
Removed duplicate _auto_start() call from __init__ - connection now only happens in start()
orchestrator_client.py IPython conversion
* added type ignore for ipythin
* removed check for has attribute in hardware interface
Moved super.start() at the beginning
replaced running bool with stop_event in tick_loop to improve thread safety
removed default ip from init
removed simple dataclasses test
* orchestrator.py: Use match statement for backend factory, restructure backend cleanup
task.py: Use match statement in get_values()
tick_loop.py: Add JointWinner NamedTuple for cleaner arbitration logic
xarm/backend.py: Extract unit conversions into static helper methods
* tick_loop.py: Notify preemption when lower-priority task loses to existing winner
hardware_interface.py: Call set_control_mode() before mode-specific writes, Convert if/elif to match statement for control mode dispatch
* tick_loop.py: Notify preemption when lower-priority task loses to existing winner
hardware_interface.py: Call set_control_mode() before mode-specific writes, convert if/elif to match statement
trajectory_task.py: Defer start time to first compute() for consistent timing
orchestrator.py: Extract _setup_hardware() helper for cleaner config setup
piper and xarm/backend.py: Fail fast on read_joint_positions(), map SERVO_POSITION to mode 1
hardware_interface.py: Retry initialization with proper error propagation,
spec.py: Add SERVO_POSITION control mode for confusion between position planning and position servo
task.py: added SERVO_POSITION to JointCommandOutput helper
* cleaned up legacy blueprints for manipulator drivers
* enforce ManipulatorBackend Protocol on the backend.py
* feat: add runtime protocol checks for manipulator backends
* added runtime checking for controlTask protocol
* Add TaskStatus dataclass, refactor get_trajectory_status and Explicitly inherit from ControlTask protocol
---------
Co-authored-by: stash <pomichterstash@gmail.com>
* configure unitree go2 mapper to use 10 cm voxels (#1032)
* Create DDSPubSubBase, DDSTopic
* Create PickleDDS
* Fix hash/equality inconsistency in DDSTopic
* Add DDSMsg
* Create DDSTransport
* Add broadcast and subscribe methods to DDSTransport
* Create DDSService
* Add CycloneDDS package
* Remove unnecessary attributes
* Add threading and serialization methods to DDSService
* Ensure broadcast and subscribe methods initialize DDS if not started
* Add Transport benchmarking capabilities to CycloneDDS (#1055)
* raw rospubsub and benchmarks
* typefixes, shm added to the benchmark
* SHM is not so important to tell us every time when it starts
* greptile comments
* Add co-authorship line to commit message filter patterns
* Remove unused contextmanager import
---------
Co-authored-by: Ivan Nikolic <lesh@sysphere.org>
* Fix DDS segmentation fault using bytearray for binary data storage
Replace base64 string encoding with native IDL bytearray type to eliminate
buffer overflow issues. The original base64 encoding exceeded CycloneDDS's
default string size limit (~256 bytes) and caused crashes on messages >= 1KB.
Key changes:
- Use make_idl_struct with bytearray field instead of string
- Convert bytes to bytearray when publishing to DDS
- Convert bytearray back to bytes when receiving from DDS
- Add _DDSMessageListener for async message dispatch
- Implement thread-safe DataWriter/DataReader management
- Add pickle support via __getstate__/__setstate__
Result: All 12 DDS benchmark tests pass (64B to 10MB messages).
* Refactor DDS PubSub implementation to use CycloneDDS Topic
* Remove DDS pickling
* CI code cleanup
* bugfix
* CI code cleanup
---------
Co-authored-by: leshy <lesh@sysphere.org>
Co-authored-by: Jeff Hykin <jeff.hykin@gmail.com>
Co-authored-by: Paul Nechifor <paul@nechifor.net>
Co-authored-by: s <pomichterstash@gmail.com>
Co-authored-by: Miguel Villa Floran <miguel.villafloran@gmail.com>
Co-authored-by: alexlin2 <44330195+alexlin2@users.noreply.github.com>
Co-authored-by: claire wang <clara32356@gmail.com>
Co-authored-by: shreyasrajesh0308 <shreyasrajesh0308@users.noreply.github.com>
Co-authored-by: spomichter <12108168+spomichter@users.noreply.github.com>
Co-authored-by: Mustafa Bhadsorawala <39084056+mustafab0@users.noreply.github.com>
Added:
Old drivers moved to manipulators_old/
Below is the comparison between the old and the new driver architecture.