Skip to content

refactored manipulation blueprints for better organization#2553

Open
mustafab0 wants to merge 4 commits into
mainfrom
refactor/manipulation-blueprints
Open

refactored manipulation blueprints for better organization#2553
mustafab0 wants to merge 4 commits into
mainfrom
refactor/manipulation-blueprints

Conversation

@mustafab0

Copy link
Copy Markdown
Contributor

Problem

Manipulation blueprints have been all over the place as the project has evolved
Closes DIM-1033

Solution

refactored blueprint to match existing robot blueprint format

Contributor License Agreement

  • [ x] I have read and approved the CLA.

@codecov

codecov Bot commented Jun 21, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
2274 1 2273 74
View the full list of 1 ❄️ flaky test(s)
dimos.e2e_tests.test_dimsim_walk_forward::test_walk_forward

Flake rate in main: 29.63% (Passed 19 times, Failed 8 times)

Stack Traces | 208s run time
lcm_spy = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x748d3da77e00>
start_blueprint = <function start_blueprint.<locals>.set_name_and_start at 0x748d3bb80040>
human_input = <function human_input.<locals>.send_human_input at 0x748d3bb80400>
dim_sim = <dimos.e2e_tests.dim_sim_client.DimSimClient object at 0x748d3d4f2d50>

    @pytest.mark.self_hosted_large
    def test_walk_forward(lcm_spy, start_blueprint, human_input, dim_sim) -> None:
        start_blueprint(
            "run",
            "--disable",
            "spatial-memory",
            "--disable",
            "security-module",
            "unitree-go2-agentic",
            simulator="dimsim",
        )
        lcm_spy.save_topic(".../McpClient/on_system_modules/res")
        lcm_spy.wait_for_saved_topic(".../McpClient/on_system_modules/res", timeout=1200.0)
    
        origin_x, origin_y = 1, 2
        dim_sim.set_agent_position(origin_x, origin_y)
    
        human_input("move forward 3 meter")
    
>       lcm_spy.wait_until_odom_position(origin_x + 3, origin_y, threshold=0.4, timeout=120)

dim_sim    = <dimos.e2e_tests.dim_sim_client.DimSimClient object at 0x748d3d4f2d50>
human_input = <function human_input.<locals>.send_human_input at 0x748d3bb80400>
lcm_spy    = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x748d3da77e00>
origin_x   = 1
origin_y   = 2
start_blueprint = <function start_blueprint.<locals>.set_name_and_start at 0x748d3bb80040>

dimos/e2e_tests/test_dimsim_walk_forward.py:37: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/e2e_tests/lcm_spy.py:182: in wait_until_odom_position
    self.wait_for_message_result(
        predicate  = <function LcmSpy.wait_until_odom_position.<locals>.predicate at 0x748d3bb9ede0>
        self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x748d3da77e00>
        threshold  = 0.4
        timeout    = 120
        x          = 4
        y          = 2
dimos/e2e_tests/lcm_spy.py:168: in wait_for_message_result
    self.wait_until(
        event      = <threading.Event at 0x748d3d4f2f60: unset>
        fail_message = 'Failed to get to position x=4, y=2'
        listener   = <function LcmSpy.wait_for_message_result.<locals>.listener at 0x748d3bb80360>
        predicate  = <function LcmSpy.wait_until_odom_position.<locals>.predicate at 0x748d3bb9ede0>
        self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x748d3da77e00>
        timeout    = 120
        topic      = '/odom#geometry_msgs.PoseStamped'
        type       = <class 'dimos.msgs.geometry_msgs.PoseStamped.PoseStamped'>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x748d3da77e00>

    def wait_until(
        self,
        *,
        condition: Callable[[], bool],
        timeout: float,
        error_message: str,
        poll_interval: float = 0.1,
    ) -> None:
        start_time = time.time()
        while time.time() - start_time < timeout:
            if condition():
                return
            time.sleep(poll_interval)
>       raise TimeoutError(error_message)
E       TimeoutError: Failed to get to position x=4, y=2

condition  = <bound method Event.is_set of <threading.Event at 0x748d3d4f2f60: unset>>
error_message = 'Failed to get to position x=4, y=2'
poll_interval = 0.1
self       = <dimos.e2e_tests.lcm_spy.LcmSpy object at 0x748d3da77e00>
start_time = 1782014154.8610508
timeout    = 120

dimos/e2e_tests/lcm_spy.py:105: TimeoutError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@mustafab0 mustafab0 marked this pull request as ready for review June 21, 2026 02:51
@mustafab0 mustafab0 enabled auto-merge (squash) June 21, 2026 02:51
@greptile-apps

greptile-apps Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR reorganizes manipulation blueprints from scattered files (dimos/control/blueprints/, dimos/manipulation/blueprints.py, and flat per-robot blueprints.py files) into per-manipulator packages with dedicated sub-modules (basic, teleop, agentic, etc.), following the pattern already established for other robot types.

  • Hardware factory functions, FK model paths, and planning model configs are extracted into per-robot config.py files; shared helpers (trajectory_task, coordinator, planner, mujoco_if_sim) move to dimos.robot.manipulators.common.*; all_blueprints.py entry-points are updated to the new paths.
  • dimos/manipulation/blueprints.py and dimos/control/blueprints/teleop.py and _hardware.py are removed and replaced by the new structure; dimos/control/blueprints/dual.py is renamed and trimmed to common/mixed.py.
  • The old xarm coordinator task-name mismatch and the simulation bypass in the dual-arm blueprint have been addressed by consistently using the xarm7_hardware()/xarm6_hardware() helpers and the trajectory_task() factory.

Confidence Score: 5/5

This is a well-structured refactoring with no functional regressions; all entry-point names are preserved, and simulation/CAN-port handling is correctly delegated to hardware helpers throughout.

The refactoring consistently applies the new trajectory_task() / coordinator() / planner() helpers across xArm, OpenArm, A-750, and most of piper. The one inconsistency (piper basic coordinator hardcodes traj_piper rather than deriving via the helper) is a cosmetic/future-proofing concern that does not affect any currently registered blueprint. The previously flagged xArm task-name mismatch and the dual-arm simulation bypass have been addressed.

dimos/robot/manipulators/piper/blueprints/basic.py — trajectory task name is inconsistent with the xArm pattern and would silently fail if a ManipulationModule planner is ever paired with this coordinator.

Important Files Changed

Filename Overview
dimos/robot/manipulators/xarm/config.py Extracts xArm hardware factory functions and model config helpers from the old _hardware.py and manipulation/blueprints.py; simulation branching correctly delegated to xarm7_hardware()/xarm6_hardware().
dimos/robot/manipulators/xarm/blueprints/basic.py Single and dual xArm coordinator and planner blueprints now use trajectory_task() helper consistently; coordinator_xarm6 task-name mismatch from previous threads is resolved.
dimos/robot/manipulators/piper/blueprints/basic.py Piper basic coordinator correctly wires piper_hardware() + mujoco_if_sim, but hardcodes 'traj_piper' as the task name instead of using the trajectory_task() helper, creating an inconsistency with xArm peers and the expected 'traj_arm' from make_piper_model_config(name='arm').
dimos/robot/manipulators/common/blueprints.py Clean shared factory helpers (trajectory_task, cartesian_ik_task, teleop_ik_task, coordinator, planner) that eliminate repetition across manipulator stacks.
dimos/robot/manipulators/common/mixed.py Renamed from control/blueprints/dual.py; retains coordinator_piper_xarm and adds coordinator_teleop_dual with correct CAN fallback (can_port or 'can0').
dimos/robot/manipulators/common/sim.py New mujoco_if_sim helper uses a lazy import of MujocoSimModule, avoiding heavy simulation dependencies on non-simulation runs.
dimos/robot/all_blueprints.py All entry-point paths updated to new module locations; no regressions in registered blueprint names found.
dimos/manipulation/blueprints.py Reduced to a thin compatibility re-export layer pointing to the new per-robot modules; existing import names preserved.
dimos/robot/manipulators/xarm/blueprints/teleop.py Teleop, servo, velocity, and combined xArm blueprints cleanly ported; correctly uses xarm7_hardware()/xarm6_hardware() for simulation-aware adapters.
dimos/robot/manipulators/piper/config.py Piper hardware factory and model config helpers correctly extracted; piper_hardware() handles simulation and CAN fallback (can_port or 'can0').

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph common["dimos.robot.manipulators.common"]
        BP["blueprints.py\ntrajector_task / cartesian_ik_task\nteleop_ik_task / coordinator / planner"]
        SIM["sim.py\nmujoco_if_sim()"]
        MIXED["mixed.py\ncoordinator_piper_xarm\ncoordinator_teleop_dual"]
        MOCK["mock.py\ncoordinator_mock\ncoordinator_dual_mock"]
    end
    subgraph xarm["dimos.robot.manipulators.xarm"]
        XCFG["config.py\nxarm7_hardware / xarm6_hardware\nmake_xarm_model_config"]
        XBASIC["blueprints/basic.py\ncoordinator_xarm7/6\nxarm7_planner_coordinator"]
        XTELEOP["blueprints/teleop.py\ncoordinator_teleop_xarm7/6"]
        XAGENT["blueprints/agentic.py\nxarm_perception_agent"]
    end
    subgraph piper["dimos.robot.manipulators.piper"]
        PCFG["config.py\npiper_hardware\nmake_piper_model_config"]
        PBASIC["blueprints/basic.py\ncoordinator_piper"]
        PTELEOP["blueprints/teleop.py\ncoordinator_teleop_piper"]
    end
    ALL["robot/all_blueprints.py\nentry-point registry"]
    BP --> XBASIC & XTELEOP & PBASIC & PTELEOP
    SIM --> XBASIC & XTELEOP & PBASIC & PTELEOP
    XCFG --> XBASIC & XTELEOP & MIXED
    PCFG --> PBASIC & PTELEOP & MIXED
    XBASIC --> XAGENT
    XBASIC & XTELEOP & PBASIC & PTELEOP & MIXED & MOCK --> ALL
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    subgraph common["dimos.robot.manipulators.common"]
        BP["blueprints.py\ntrajector_task / cartesian_ik_task\nteleop_ik_task / coordinator / planner"]
        SIM["sim.py\nmujoco_if_sim()"]
        MIXED["mixed.py\ncoordinator_piper_xarm\ncoordinator_teleop_dual"]
        MOCK["mock.py\ncoordinator_mock\ncoordinator_dual_mock"]
    end
    subgraph xarm["dimos.robot.manipulators.xarm"]
        XCFG["config.py\nxarm7_hardware / xarm6_hardware\nmake_xarm_model_config"]
        XBASIC["blueprints/basic.py\ncoordinator_xarm7/6\nxarm7_planner_coordinator"]
        XTELEOP["blueprints/teleop.py\ncoordinator_teleop_xarm7/6"]
        XAGENT["blueprints/agentic.py\nxarm_perception_agent"]
    end
    subgraph piper["dimos.robot.manipulators.piper"]
        PCFG["config.py\npiper_hardware\nmake_piper_model_config"]
        PBASIC["blueprints/basic.py\ncoordinator_piper"]
        PTELEOP["blueprints/teleop.py\ncoordinator_teleop_piper"]
    end
    ALL["robot/all_blueprints.py\nentry-point registry"]
    BP --> XBASIC & XTELEOP & PBASIC & PTELEOP
    SIM --> XBASIC & XTELEOP & PBASIC & PTELEOP
    XCFG --> XBASIC & XTELEOP & MIXED
    PCFG --> PBASIC & PTELEOP & MIXED
    XBASIC --> XAGENT
    XBASIC & XTELEOP & PBASIC & PTELEOP & MIXED & MOCK --> ALL
Loading

Reviews (2): Last reviewed commit: "fixed greptile comments" | Re-trigger Greptile

Comment thread dimos/robot/manipulators/common/mixed.py
Comment thread dimos/robot/manipulators/xarm/blueprints/basic.py
Comment thread dimos/robot/manipulators/xarm/blueprints/basic.py Outdated
Comment thread dimos/robot/manipulators/common/mock.py Outdated
@github-actions github-actions Bot added the ready-to-merge Required CI checks have passed on this PR label Jun 21, 2026
@github-actions github-actions Bot added ready-to-merge Required CI checks have passed on this PR and removed ready-to-merge Required CI checks have passed on this PR labels Jun 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Required CI checks have passed on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant