Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
100 changes: 50 additions & 50 deletions dimos/robot/all_blueprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,57 +90,57 @@

all_modules = {
"agent": "dimos.agents.agent",
"arm_teleop_module": "dimos.teleop.quest.quest_extensions",
"camera_module": "dimos.hardware.sensors.camera.module",
"cartesian_motion_controller": "dimos.manipulation.control.servo_control.cartesian_motion_controller",
"control_coordinator": "dimos.control.coordinator",
"cost_mapper": "dimos.mapping.costmapper",
"demo_calculator_skill": "dimos.agents.skills.demo_calculator_skill",
"demo_robot": "dimos.agents.skills.demo_robot",
"detection3d_module": "dimos.perception.detection.module3D",
"detection_db_module": "dimos.perception.detection.moduleDB",
"fastlio2_module": "dimos.hardware.sensors.lidar.fastlio2.module",
"foxglove_bridge": "dimos.robot.foxglove_bridge",
"g1_connection": "dimos.robot.unitree.g1.connection",
"g1_sim_connection": "dimos.robot.unitree.g1.sim",
"g1_skills": "dimos.robot.unitree.g1.skill_container",
"go2_connection": "dimos.robot.unitree.go2.connection",
"google_maps_skill": "dimos.agents.skills.google_maps_skill_container",
"gps_nav_skill": "dimos.agents.skills.gps_nav_skill",
"grasping_module": "dimos.manipulation.grasping.grasping",
"joint_trajectory_controller": "dimos.manipulation.control.trajectory_controller.joint_trajectory_controller",
"keyboard_teleop": "dimos.robot.unitree.keyboard_teleop",
"keyboard_teleop_module": "dimos.teleop.keyboard.keyboard_teleop_module",
"manipulation_module": "dimos.manipulation.manipulation_module",
"arm-teleop-module": "dimos.teleop.quest.quest_extensions",
"camera-module": "dimos.hardware.sensors.camera.module",
"cartesian-motion-controller": "dimos.manipulation.control.servo_control.cartesian_motion_controller",
"control-coordinator": "dimos.control.coordinator",
"cost-mapper": "dimos.mapping.costmapper",
"demo-calculator-skill": "dimos.agents.skills.demo_calculator_skill",
"demo-robot": "dimos.agents.skills.demo_robot",
"detection-db-module": "dimos.perception.detection.moduleDB",
"detection3d-module": "dimos.perception.detection.module3D",
"fastlio2-module": "dimos.hardware.sensors.lidar.fastlio2.module",
"foxglove-bridge": "dimos.robot.foxglove_bridge",
"g1-connection": "dimos.robot.unitree.g1.connection",
"g1-sim-connection": "dimos.robot.unitree.g1.sim",
"g1-skills": "dimos.robot.unitree.g1.skill_container",
"go2-connection": "dimos.robot.unitree.go2.connection",
"google-maps-skill": "dimos.agents.skills.google_maps_skill_container",
"gps-nav-skill": "dimos.agents.skills.gps_nav_skill",
"grasping-module": "dimos.manipulation.grasping.grasping",
"joint-trajectory-controller": "dimos.manipulation.control.trajectory_controller.joint_trajectory_controller",
"keyboard-teleop": "dimos.robot.unitree.keyboard_teleop",
"keyboard-teleop-module": "dimos.teleop.keyboard.keyboard_teleop_module",
"manipulation-module": "dimos.manipulation.manipulation_module",
"mapper": "dimos.robot.unitree.type.map",
"mcp_client": "dimos.agents.mcp.mcp_client",
"mid360_module": "dimos.hardware.sensors.lidar.livox.module",
"navigation_skill": "dimos.agents.skills.navigation",
"object_scene_registration_module": "dimos.perception.object_scene_registration",
"object_tracking": "dimos.perception.object_tracker",
"osm_skill": "dimos.agents.skills.osm",
"person_follow_skill": "dimos.agents.skills.person_follow",
"person_tracker_module": "dimos.perception.detection.person_tracker",
"phone_teleop_module": "dimos.teleop.phone.phone_teleop_module",
"quest_teleop_module": "dimos.teleop.quest.quest_teleop_module",
"realsense_camera": "dimos.hardware.sensors.camera.realsense.camera",
"replanning_a_star_planner": "dimos.navigation.replanning_a_star.module",
"rerun_bridge": "dimos.visualization.rerun.bridge",
"ros_nav": "dimos.navigation.rosnav",
"simple_phone_teleop_module": "dimos.teleop.phone.phone_extensions",
"mcp-client": "dimos.agents.mcp.mcp_client",
"mid360-module": "dimos.hardware.sensors.lidar.livox.module",
"navigation-skill": "dimos.agents.skills.navigation",
"object-scene-registration-module": "dimos.perception.object_scene_registration",
"object-tracking": "dimos.perception.object_tracker",
"osm-skill": "dimos.agents.skills.osm",
"person-follow-skill": "dimos.agents.skills.person_follow",
"person-tracker-module": "dimos.perception.detection.person_tracker",
"phone-teleop-module": "dimos.teleop.phone.phone_teleop_module",
"quest-teleop-module": "dimos.teleop.quest.quest_teleop_module",
"realsense-camera": "dimos.hardware.sensors.camera.realsense.camera",
"replanning-a-star-planner": "dimos.navigation.replanning_a_star.module",
"rerun-bridge": "dimos.visualization.rerun.bridge",
"ros-nav": "dimos.navigation.rosnav",
"simple-phone-teleop-module": "dimos.teleop.phone.phone_extensions",
"simulation": "dimos.simulation.manipulators.sim_module",
"spatial_memory": "dimos.perception.spatial_perception",
"speak_skill": "dimos.agents.skills.speak_skill",
"temporal_memory": "dimos.perception.experimental.temporal_memory.temporal_memory",
"twist_teleop_module": "dimos.teleop.quest.quest_extensions",
"unitree_skills": "dimos.robot.unitree.unitree_skill_container",
"spatial-memory": "dimos.perception.spatial_perception",
"speak-skill": "dimos.agents.skills.speak_skill",
"temporal-memory": "dimos.perception.experimental.temporal_memory.temporal_memory",
"twist-teleop-module": "dimos.teleop.quest.quest_extensions",
"unitree-skills": "dimos.robot.unitree.unitree_skill_container",
"utilization": "dimos.utils.monitoring",
"visualizing_teleop_module": "dimos.teleop.quest.quest_extensions",
"vlm_agent": "dimos.agents.vlm_agent",
"vlm_stream_tester": "dimos.agents.vlm_stream_tester",
"voxel_mapper": "dimos.mapping.voxels",
"wavefront_frontier_explorer": "dimos.navigation.frontier_exploration.wavefront_frontier_goal_selector",
"web_input": "dimos.agents.web_human_input",
"websocket_vis": "dimos.web.websocket_vis.websocket_vis_module",
"zed_camera": "dimos.hardware.sensors.camera.zed.camera",
"visualizing-teleop-module": "dimos.teleop.quest.quest_extensions",
"vlm-agent": "dimos.agents.vlm_agent",
"vlm-stream-tester": "dimos.agents.vlm_stream_tester",
"voxel-mapper": "dimos.mapping.voxels",
"wavefront-frontier-explorer": "dimos.navigation.frontier_exploration.wavefront_frontier_goal_selector",
"web-input": "dimos.agents.web_human_input",
"websocket-vis": "dimos.web.websocket_vis.websocket_vis_module",
"zed-camera": "dimos.hardware.sensors.camera.zed.camera",
}
21 changes: 5 additions & 16 deletions dimos/robot/cli/dimos.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from enum import Enum
import inspect
import sys
from typing import Any, get_args, get_origin
Expand All @@ -21,9 +20,6 @@
import typer

from dimos.core.global_config import GlobalConfig, global_config
from dimos.robot.all_blueprints import all_blueprints

RobotType = Enum("RobotType", {key.replace("-", "_").upper(): key for key in all_blueprints.keys()}) # type: ignore[misc]

main = typer.Typer(
help="Dimensional CLI",
Expand Down Expand Up @@ -102,28 +98,21 @@ def callback(**kwargs) -> None: # type: ignore[no-untyped-def]
@main.command()
def run(
ctx: typer.Context,
robot_type: RobotType = typer.Argument(..., help="Type of robot to run"),
extra_modules: list[str] = typer.Option( # type: ignore[valid-type]
[], "--extra-module", help="Extra modules to add to the blueprint"
),
robot_types: list[str] = typer.Argument(..., help="Blueprints or modules to run"),
) -> None:
"""Start a robot blueprint"""
from dimos.core.blueprints import autoconnect
from dimos.protocol import pubsub
from dimos.robot.get_all_blueprints import get_blueprint_by_name, get_module_by_name
from dimos.robot.get_all_blueprints import get_by_name
from dimos.utils.logging_config import setup_exception_handler

setup_exception_handler()

cli_config_overrides: dict[str, Any] = ctx.obj
global_config.update(**cli_config_overrides)
pubsub.lcm.autoconf() # type: ignore[attr-defined]
blueprint = get_blueprint_by_name(robot_type.value)

if extra_modules:
loaded_modules = [get_module_by_name(mod_name) for mod_name in extra_modules] # type: ignore[attr-defined]
blueprint = autoconnect(blueprint, *loaded_modules)

blueprint = autoconnect(*map(get_by_name, robot_types))
dimos = blueprint.build(cli_config_overrides=cli_config_overrides)
dimos.loop()

Expand All @@ -139,8 +128,8 @@ def show_config(ctx: typer.Context) -> None:
typer.echo(f"{field_name}: {value}")


@main.command()
def list() -> None:
@main.command(name="list")
def list_blueprints() -> None:
"""List all available blueprints."""
from dimos.robot.all_blueprints import all_blueprints

Expand Down
36 changes: 32 additions & 4 deletions dimos/robot/get_all_blueprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,48 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import difflib
import sys
from typing import NoReturn

import typer

from dimos.core.blueprints import Blueprint
from dimos.robot.all_blueprints import all_blueprints, all_modules

all_names = sorted(set(all_blueprints.keys()) | set(all_modules.keys()))


def _fail_unknown(name: str, candidates: list[str]) -> NoReturn:
typer.echo(typer.style(f"Unknown blueprint or module: {name}", fg=typer.colors.RED), err=True)
suggestions = difflib.get_close_matches(name, candidates, n=5, cutoff=0.4)
if suggestions:
typer.echo("Did you mean one of these?", err=True)
for s in suggestions:
typer.echo(f" {s}", err=True)
sys.exit(1)


def get_blueprint_by_name(name: str) -> Blueprint:
if name not in all_blueprints:
raise ValueError(f"Unknown blueprint set name: {name}")
_fail_unknown(name, list(all_blueprints.keys()))
module_path, attr = all_blueprints[name].split(":")
module = __import__(module_path, fromlist=[attr])
return getattr(module, attr) # type: ignore[no-any-return]


def get_module_by_name(name: str) -> Blueprint:
if name not in all_modules:
raise ValueError(f"Unknown module name: {name}")
python_module = __import__(all_modules[name], fromlist=[name])
return getattr(python_module, name)() # type: ignore[no-any-return]
_fail_unknown(name, list(all_modules.keys()))
attr_name = name.replace("-", "_")
python_module = __import__(all_modules[name], fromlist=[attr_name])
return getattr(python_module, attr_name)() # type: ignore[no-any-return]


def get_by_name(name: str) -> Blueprint:
if name in all_blueprints:
return get_blueprint_by_name(name)
elif name in all_modules:
return get_module_by_name(name)
else:
_fail_unknown(name, all_names)
11 changes: 9 additions & 2 deletions dimos/robot/test_all_blueprints_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@
def test_all_blueprints_is_current() -> None:
root = DIMOS_PROJECT_ROOT / "dimos"
all_blueprints, all_modules = _scan_for_blueprints(root)

common = set(all_blueprints.keys()) & set(all_modules.keys())
assert not common, (
f"Names must be unique across blueprints and modules, "
f"but these appear in both: {sorted(common)}"
)

generated_content = _generate_all_blueprints_content(all_blueprints, all_modules)

file_path = root / "robot" / "all_blueprints.py"
Expand Down Expand Up @@ -83,8 +90,8 @@ def _scan_for_blueprints(root: Path) -> tuple[dict[str, str], dict[str, str]]:
all_blueprints[cli_name] = full_path

for var_name in module_vars:
full_path = f"{module_name}:{var_name}"
all_modules[var_name] = module_name
cli_name = var_name.replace("_", "-")
all_modules[cli_name] = module_name

return all_blueprints, all_modules

Expand Down
2 changes: 1 addition & 1 deletion docs/capabilities/manipulation/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ KeyboardTeleopModule ──→ ControlCoordinator ──→ ManipulationModule

## Adding a Custom Arm

[guide is here](adding_a_custom_arm.md)
[guide is here](/docs/capabilities/manipulation/adding_a_custom_arm.md)

## Key Files

Expand Down
2 changes: 1 addition & 1 deletion docs/development/dimos_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dimos run unitree-go2-agentic
You can dynamically connect additional modules. For example:

```bash
dimos run unitree-go2 --extra-module agent --extra-module navigation_skill
dimos run unitree-go2 keyboard-teleop
```

## Adding your own
Expand Down
18 changes: 9 additions & 9 deletions docs/platforms/humanoid/g1/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ The Unitree G1 is a humanoid robot platform with full-body locomotion, arm gestu
## Install

First, install system dependencies for your platform:
- [Ubuntu](../../../installation/ubuntu.md)
- [macOS](../../../installation/osx.md)
- [Nix](../../../installation/nix.md)
- [Ubuntu](/docs/installation/ubuntu.md)
- [macOS](/docs/installation/osx.md)
- [Nix](/docs/installation/nix.md)

Then install DimOS:

Expand Down Expand Up @@ -159,9 +159,9 @@ primitive (sensors + vis)

## Deep Dive

- [Navigation Stack](../../../capabilities/navigation/readme.md) — path planning and autonomous exploration
- [Visualization](../../../usage/visualization.md) — Rerun, Foxglove, performance tuning
- [Data Streams](../../../usage/data_streams/) — RxPY streams, backpressure, quality filtering
- [Transports](../../../usage/transports/index.md) — LCM, SHM, DDS
- [Blueprints](../../../usage/blueprints.md) — composing modules
- [Agents](../../../capabilities/agents/readme.md) — LLM agent framework
- [Navigation Stack](/docs/capabilities/navigation/readme.md) — path planning and autonomous exploration
- [Visualization](/docs/usage/visualization.md) — Rerun, Foxglove, performance tuning
- [Data Streams](/docs/usage/data_streams) — RxPY streams, backpressure, quality filtering
- [Transports](/docs/usage/transports/index.md) — LCM, SHM, DDS
- [Blueprints](/docs/usage/blueprints.md) — composing modules
- [Agents](/docs/capabilities/agents/readme.md) — LLM agent framework
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,12 @@ module = [
"pinocchio",
"piper_sdk.*",
"plotext",
"pydrake",
"pydrake.*",
"plum.*",
"portal",
"pycuda",
"pycuda.*",
"pydrake",
"pydrake.*",
"pyzed",
"pyzed.*",
"rclpy.*",
Expand Down