diff --git a/dimos/__init__.py b/dimos/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/agents/agent.py b/dimos/agents/agent.py index ab576fb109..6e24cee870 100644 --- a/dimos/agents/agent.py +++ b/dimos/agents/agent.py @@ -30,7 +30,7 @@ from dimos.core.module import Module, ModuleConfig, SkillInfo from dimos.core.rpc_client import RpcCall, RPCClient from dimos.core.stream import In, Out -from dimos.protocol.rpc import RPCSpec +from dimos.protocol.rpc.spec import RPCSpec from dimos.spec.utils import Spec if TYPE_CHECKING: diff --git a/dimos/agents/demo_agent.py b/dimos/agents/demo_agent.py index bd69fc6cae..b839b0809c 100644 --- a/dimos/agents/demo_agent.py +++ b/dimos/agents/demo_agent.py @@ -14,9 +14,9 @@ from dimos.agents.agent import Agent from dimos.core.blueprints import autoconnect -from dimos.hardware.sensors.camera import zed from dimos.hardware.sensors.camera.module import camera_module from dimos.hardware.sensors.camera.webcam import Webcam +from dimos.hardware.sensors.camera.zed import compat as zed demo_agent = autoconnect(Agent.blueprint()) diff --git a/dimos/agents/mcp/__init__.py b/dimos/agents/mcp/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/agents/mcp/test_mcp_client.py b/dimos/agents/mcp/test_mcp_client.py index 56b98c3cd2..c903e5f11c 100644 --- a/dimos/agents/mcp/test_mcp_client.py +++ b/dimos/agents/mcp/test_mcp_client.py @@ -19,7 +19,7 @@ from dimos.agents.annotation import skill from dimos.core.module import Module -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.data import get_data diff --git a/dimos/agents/skills/demo_robot.py b/dimos/agents/skills/demo_robot.py index aa4e81e2cc..789e26d7e1 100644 --- a/dimos/agents/skills/demo_robot.py +++ b/dimos/agents/skills/demo_robot.py @@ -17,7 +17,7 @@ from dimos.core.module import Module from dimos.core.stream import Out -from dimos.mapping.types import LatLon +from dimos.mapping.models import LatLon class DemoRobot(Module): diff --git a/dimos/agents/skills/google_maps_skill_container.py b/dimos/agents/skills/google_maps_skill_container.py index c03932924f..e218601696 100644 --- a/dimos/agents/skills/google_maps_skill_container.py +++ b/dimos/agents/skills/google_maps_skill_container.py @@ -20,7 +20,7 @@ from dimos.core.module import Module from dimos.core.stream import In from dimos.mapping.google_maps.google_maps import GoogleMaps -from dimos.mapping.types import LatLon +from dimos.mapping.models import LatLon from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/agents/skills/gps_nav_skill.py b/dimos/agents/skills/gps_nav_skill.py index 63cf4a3dd3..1464665131 100644 --- a/dimos/agents/skills/gps_nav_skill.py +++ b/dimos/agents/skills/gps_nav_skill.py @@ -19,7 +19,7 @@ from dimos.core.module import Module from dimos.core.rpc_client import RpcCall from dimos.core.stream import In, Out -from dimos.mapping.types import LatLon +from dimos.mapping.models import LatLon from dimos.mapping.utils.distance import distance_in_meters from dimos.utils.logging_config import setup_logger diff --git a/dimos/agents/skills/navigation.py b/dimos/agents/skills/navigation.py index 8442846f32..47ae21c799 100644 --- a/dimos/agents/skills/navigation.py +++ b/dimos/agents/skills/navigation.py @@ -22,9 +22,10 @@ from dimos.core.module import Module from dimos.core.stream import In from dimos.models.qwen.bbox import BBox -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 -from dimos.msgs.geometry_msgs.Vector3 import make_vector3 -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3, make_vector3 +from dimos.msgs.sensor_msgs.Image import Image from dimos.navigation.base import NavigationState from dimos.navigation.visual.query import get_object_bbox_from_image from dimos.types.robot_location import RobotLocation diff --git a/dimos/agents/skills/osm.py b/dimos/agents/skills/osm.py index 613bc0806e..d0281fb808 100644 --- a/dimos/agents/skills/osm.py +++ b/dimos/agents/skills/osm.py @@ -16,8 +16,8 @@ from dimos.agents.annotation import skill from dimos.core.module import Module from dimos.core.stream import In +from dimos.mapping.models import LatLon from dimos.mapping.osm.current_location_map import CurrentLocationMap -from dimos.mapping.types import LatLon from dimos.mapping.utils.distance import distance_in_meters from dimos.models.vl.qwen import QwenVlModel from dimos.utils.logging_config import setup_logger diff --git a/dimos/agents/skills/person_follow.py b/dimos/agents/skills/person_follow.py index 7a6c6ecfe9..f1cafed6cd 100644 --- a/dimos/agents/skills/person_follow.py +++ b/dimos/agents/skills/person_follow.py @@ -29,8 +29,10 @@ from dimos.models.segmentation.edge_tam import EdgeTAMProcessor from dimos.models.vl.base import VlModel from dimos.models.vl.create import create -from dimos.msgs.geometry_msgs import Twist -from dimos.msgs.sensor_msgs import CameraInfo, Image, PointCloud2 +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.navigation.visual.query import get_object_bbox_from_image from dimos.navigation.visual_servoing.detection_navigation import DetectionNavigation from dimos.navigation.visual_servoing.visual_servoing_2d import VisualServoing2D diff --git a/dimos/agents/skills/test_google_maps_skill_container.py b/dimos/agents/skills/test_google_maps_skill_container.py index 1519f9d1df..376d6d306e 100644 --- a/dimos/agents/skills/test_google_maps_skill_container.py +++ b/dimos/agents/skills/test_google_maps_skill_container.py @@ -21,8 +21,8 @@ from dimos.agents.skills.google_maps_skill_container import GoogleMapsSkillContainer from dimos.core.module import Module from dimos.core.stream import Out -from dimos.mapping.google_maps.types import Coordinates, LocationContext, Position -from dimos.mapping.types import LatLon +from dimos.mapping.google_maps.models import Coordinates, LocationContext, Position +from dimos.mapping.models import LatLon class FakeGPS(Module): diff --git a/dimos/agents/skills/test_gps_nav_skills.py b/dimos/agents/skills/test_gps_nav_skills.py index 4060b1814e..c1e380ccd1 100644 --- a/dimos/agents/skills/test_gps_nav_skills.py +++ b/dimos/agents/skills/test_gps_nav_skills.py @@ -18,7 +18,7 @@ from dimos.agents.skills.gps_nav_skill import GpsNavSkillContainer from dimos.core.module import Module from dimos.core.stream import Out -from dimos.mapping.types import LatLon +from dimos.mapping.models import LatLon class FakeGPS(Module): diff --git a/dimos/agents/skills/test_navigation.py b/dimos/agents/skills/test_navigation.py index e31fae93b5..e4a60db081 100644 --- a/dimos/agents/skills/test_navigation.py +++ b/dimos/agents/skills/test_navigation.py @@ -18,8 +18,8 @@ from dimos.agents.skills.navigation import NavigationSkillContainer from dimos.core.module import Module from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.Image import Image class FakeCamera(Module): diff --git a/dimos/agents/test_agent.py b/dimos/agents/test_agent.py index bb6caa6337..e925e52a4a 100644 --- a/dimos/agents/test_agent.py +++ b/dimos/agents/test_agent.py @@ -19,7 +19,7 @@ from dimos.agents.annotation import skill from dimos.core.module import Module -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.data import get_data diff --git a/dimos/agents/vlm_agent.py b/dimos/agents/vlm_agent.py index c39f79830a..81bad79ae5 100644 --- a/dimos/agents/vlm_agent.py +++ b/dimos/agents/vlm_agent.py @@ -21,7 +21,7 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: diff --git a/dimos/agents/vlm_stream_tester.py b/dimos/agents/vlm_stream_tester.py index 4126c6b3a0..5f2165dc8d 100644 --- a/dimos/agents/vlm_stream_tester.py +++ b/dimos/agents/vlm_stream_tester.py @@ -20,7 +20,7 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import In, Out -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/agents_deprecated/__init__.py b/dimos/agents_deprecated/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/agents_deprecated/memory/__init__.py b/dimos/agents_deprecated/memory/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/agents_deprecated/modules/__init__.py b/dimos/agents_deprecated/modules/__init__.py deleted file mode 100644 index 99163d55d0..0000000000 --- a/dimos/agents_deprecated/modules/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Agent modules for DimOS.""" diff --git a/dimos/agents_deprecated/modules/base.py b/dimos/agents_deprecated/modules/base.py index 891edbe4bd..0927e184fc 100644 --- a/dimos/agents_deprecated/modules/base.py +++ b/dimos/agents_deprecated/modules/base.py @@ -29,9 +29,9 @@ from dimos.utils.logging_config import setup_logger try: - from .gateway import UnifiedGatewayClient + from dimos.agents_deprecated.modules.gateway.client import UnifiedGatewayClient except ImportError: - from dimos.agents_deprecated.modules.gateway import UnifiedGatewayClient + from dimos.agents_deprecated.modules.gateway.client import UnifiedGatewayClient logger = setup_logger() diff --git a/dimos/agents_deprecated/modules/gateway/__init__.py b/dimos/agents_deprecated/modules/gateway/__init__.py deleted file mode 100644 index 58ed40cd95..0000000000 --- a/dimos/agents_deprecated/modules/gateway/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Gateway module for unified LLM access.""" - -from .client import UnifiedGatewayClient -from .utils import convert_tools_to_standard_format, parse_streaming_response - -__all__ = ["UnifiedGatewayClient", "convert_tools_to_standard_format", "parse_streaming_response"] diff --git a/dimos/agents_deprecated/modules/gateway/utils.py b/dimos/agents_deprecated/modules/gateway/utils.py deleted file mode 100644 index 526d3b9724..0000000000 --- a/dimos/agents_deprecated/modules/gateway/utils.py +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Utility functions for gateway operations.""" - -import logging -from typing import Any - -logger = logging.getLogger(__name__) - - -def convert_tools_to_standard_format(tools: list[dict[str, Any]]) -> list[dict[str, Any]]: - """Convert DimOS tool format to standard format accepted by gateways. - - DimOS tools come from pydantic_function_tool and have this format: - { - "type": "function", - "function": { - "name": "tool_name", - "description": "tool description", - "parameters": { - "type": "object", - "properties": {...}, - "required": [...] - } - } - } - - We keep this format as it's already standard JSON Schema format. - """ - if not tools: - return [] - - # Tools are already in the correct format from pydantic_function_tool - return tools - - -def parse_streaming_response(chunk: dict[str, Any]) -> dict[str, Any]: - """Parse a streaming response chunk into a standard format. - - Args: - chunk: Raw chunk from the gateway - - Returns: - Parsed chunk with standard fields: - - type: "content" | "tool_call" | "error" | "done" - - content: The actual content (text for content type, tool info for tool_call) - - metadata: Additional information - """ - # Handle TensorZero streaming format - if "choices" in chunk: - # OpenAI-style format from TensorZero - choice = chunk["choices"][0] if chunk["choices"] else {} - delta = choice.get("delta", {}) - - if "content" in delta: - return { - "type": "content", - "content": delta["content"], - "metadata": {"index": choice.get("index", 0)}, - } - elif "tool_calls" in delta: - tool_calls = delta["tool_calls"] - if tool_calls: - tool_call = tool_calls[0] - return { - "type": "tool_call", - "content": { - "id": tool_call.get("id"), - "name": tool_call.get("function", {}).get("name"), - "arguments": tool_call.get("function", {}).get("arguments", ""), - }, - "metadata": {"index": tool_call.get("index", 0)}, - } - elif choice.get("finish_reason"): - return { - "type": "done", - "content": None, - "metadata": {"finish_reason": choice["finish_reason"]}, - } - - # Handle direct content chunks - if isinstance(chunk, str): - return {"type": "content", "content": chunk, "metadata": {}} - - # Handle error responses - if "error" in chunk: - return {"type": "error", "content": chunk["error"], "metadata": chunk} - - # Default fallback - return {"type": "unknown", "content": chunk, "metadata": {}} - - -def create_tool_response(tool_id: str, result: Any, is_error: bool = False) -> dict[str, Any]: - """Create a properly formatted tool response. - - Args: - tool_id: The ID of the tool call - result: The result from executing the tool - is_error: Whether this is an error response - - Returns: - Formatted tool response message - """ - content = str(result) if not isinstance(result, str) else result - - return { - "role": "tool", - "tool_call_id": tool_id, - "content": content, - "name": None, # Will be filled by the calling code - } - - -def extract_image_from_message(message: dict[str, Any]) -> dict[str, Any] | None: - """Extract image data from a message if present. - - Args: - message: Message dict that may contain image data - - Returns: - Dict with image data and metadata, or None if no image - """ - content = message.get("content", []) - - # Handle list content (multimodal) - if isinstance(content, list): - for item in content: - if isinstance(item, dict): - # OpenAI format - if item.get("type") == "image_url": - return { - "format": "openai", - "data": item["image_url"]["url"], - "detail": item["image_url"].get("detail", "auto"), - } - # Anthropic format - elif item.get("type") == "image": - return { - "format": "anthropic", - "data": item["source"]["data"], - "media_type": item["source"].get("media_type", "image/jpeg"), - } - - return None diff --git a/dimos/agents_deprecated/prompt_builder/__init__.py b/dimos/agents_deprecated/prompt_builder/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/agents_deprecated/tokenizer/__init__.py b/dimos/agents_deprecated/tokenizer/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/control/__init__.py b/dimos/control/__init__.py deleted file mode 100644 index 639f0ba38a..0000000000 --- a/dimos/control/__init__.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""ControlCoordinator - Centralized control for multi-arm coordination. - -This module provides a centralized control coordinator that replaces -per-driver/per-controller loops with a single deterministic tick-based system. - -Features: -- Single tick loop (read -> compute -> arbitrate -> route -> write) -- Per-joint arbitration (highest priority wins) -- Mode conflict detection -- Partial command support (hold last value) -- Aggregated preemption notifications - -Example: - >>> from dimos.control import ControlCoordinator - >>> from dimos.control.tasks import JointTrajectoryTask, JointTrajectoryTaskConfig - >>> from dimos.hardware.manipulators.xarm import XArmAdapter - >>> - >>> # Create coordinator - >>> coord = ControlCoordinator(tick_rate=100.0) - >>> - >>> # Add hardware - >>> adapter = XArmAdapter(ip="192.168.1.185", dof=7) - >>> adapter.connect() - >>> coord.add_hardware("left_arm", adapter) - >>> - >>> # Add task - >>> joints = [f"left_arm_joint{i+1}" for i in range(7)] - >>> task = JointTrajectoryTask( - ... "traj_left", - ... JointTrajectoryTaskConfig(joint_names=joints, priority=10), - ... ) - >>> coord.add_task(task) - >>> - >>> # Start - >>> coord.start() -""" - -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "components": [ - "HardwareComponent", - "HardwareId", - "HardwareType", - "JointName", - "JointState", - "make_gripper_joints", - "make_joints", - ], - "coordinator": [ - "ControlCoordinator", - "ControlCoordinatorConfig", - "TaskConfig", - "control_coordinator", - ], - "hardware_interface": ["ConnectedHardware"], - "task": [ - "ControlMode", - "ControlTask", - "CoordinatorState", - "JointCommandOutput", - "JointStateSnapshot", - "ResourceClaim", - ], - "tick_loop": ["TickLoop"], - }, -) diff --git a/dimos/control/blueprints.py b/dimos/control/blueprints.py index 7c6036b20c..fff2083322 100644 --- a/dimos/control/blueprints.py +++ b/dimos/control/blueprints.py @@ -39,8 +39,9 @@ ) from dimos.control.coordinator import TaskConfig, control_coordinator from dimos.core.transport import LCMTransport -from dimos.msgs.geometry_msgs import PoseStamped, Twist -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.teleop.quest.quest_types import Buttons from dimos.utils.data import LfsPath diff --git a/dimos/control/coordinator.py b/dimos/control/coordinator.py index 16f4e53f46..0757f27705 100644 --- a/dimos/control/coordinator.py +++ b/dimos/control/coordinator.py @@ -49,13 +49,9 @@ TwistBaseAdapter, ) from dimos.hardware.manipulators.spec import ManipulatorAdapter -from dimos.msgs.geometry_msgs import ( - PoseStamped, - Twist, -) -from dimos.msgs.sensor_msgs import ( - JointState, -) +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.teleop.quest.quest_types import ( Buttons, ) @@ -258,7 +254,10 @@ def _create_task_from_config(self, cfg: TaskConfig) -> ControlTask: task_type = cfg.type.lower() if task_type == "trajectory": - from dimos.control.tasks import JointTrajectoryTask, JointTrajectoryTaskConfig + from dimos.control.tasks.trajectory_task import ( + JointTrajectoryTask, + JointTrajectoryTaskConfig, + ) return JointTrajectoryTask( cfg.name, @@ -269,7 +268,7 @@ def _create_task_from_config(self, cfg: TaskConfig) -> ControlTask: ) elif task_type == "servo": - from dimos.control.tasks import JointServoTask, JointServoTaskConfig + from dimos.control.tasks.servo_task import JointServoTask, JointServoTaskConfig return JointServoTask( cfg.name, @@ -280,7 +279,7 @@ def _create_task_from_config(self, cfg: TaskConfig) -> ControlTask: ) elif task_type == "velocity": - from dimos.control.tasks import JointVelocityTask, JointVelocityTaskConfig + from dimos.control.tasks.velocity_task import JointVelocityTask, JointVelocityTaskConfig return JointVelocityTask( cfg.name, @@ -291,7 +290,7 @@ def _create_task_from_config(self, cfg: TaskConfig) -> ControlTask: ) elif task_type == "cartesian_ik": - from dimos.control.tasks import CartesianIKTask, CartesianIKTaskConfig + from dimos.control.tasks.cartesian_ik_task import CartesianIKTask, CartesianIKTaskConfig if cfg.model_path is None: raise ValueError(f"CartesianIKTask '{cfg.name}' requires model_path in TaskConfig") diff --git a/dimos/control/examples/cartesian_ik_jogger.py b/dimos/control/examples/cartesian_ik_jogger.py index d2a2f4d119..bf3b36a972 100644 --- a/dimos/control/examples/cartesian_ik_jogger.py +++ b/dimos/control/examples/cartesian_ik_jogger.py @@ -116,7 +116,7 @@ def to_pose_stamped(self, task_name: str) -> Any: Args: task_name: Task name to use as frame_id for routing """ - from dimos.msgs.geometry_msgs import PoseStamped + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped from dimos.msgs.geometry_msgs.Quaternion import Quaternion from dimos.msgs.geometry_msgs.Vector3 import Vector3 @@ -168,7 +168,7 @@ def run_jogger_ui(model_path: str | None = None, ee_joint_id: int = 6) -> None: ee_joint_id: End-effector joint ID in the model """ from dimos.core.transport import LCMTransport - from dimos.msgs.geometry_msgs import PoseStamped + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped # Use Piper model if not specified if model_path is None: diff --git a/dimos/control/task.py b/dimos/control/task.py index c9ef03fbf0..afad70bb05 100644 --- a/dimos/control/task.py +++ b/dimos/control/task.py @@ -34,7 +34,8 @@ from dimos.hardware.manipulators.spec import ControlMode if TYPE_CHECKING: - from dimos.msgs.geometry_msgs import Pose, PoseStamped + from dimos.msgs.geometry_msgs.Pose import Pose + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped from dimos.teleop.quest.quest_types import Buttons diff --git a/dimos/control/tasks/__init__.py b/dimos/control/tasks/__init__.py deleted file mode 100644 index 5b869b01f9..0000000000 --- a/dimos/control/tasks/__init__.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Task implementations for the ControlCoordinator.""" - -from dimos.control.tasks.cartesian_ik_task import ( - CartesianIKTask, - CartesianIKTaskConfig, -) -from dimos.control.tasks.servo_task import ( - JointServoTask, - JointServoTaskConfig, -) -from dimos.control.tasks.teleop_task import ( - TeleopIKTask, - TeleopIKTaskConfig, -) -from dimos.control.tasks.trajectory_task import ( - JointTrajectoryTask, - JointTrajectoryTaskConfig, -) -from dimos.control.tasks.velocity_task import ( - JointVelocityTask, - JointVelocityTaskConfig, -) - -__all__ = [ - "CartesianIKTask", - "CartesianIKTaskConfig", - "JointServoTask", - "JointServoTaskConfig", - "JointTrajectoryTask", - "JointTrajectoryTaskConfig", - "JointVelocityTask", - "JointVelocityTaskConfig", - "TeleopIKTask", - "TeleopIKTaskConfig", -] diff --git a/dimos/control/tasks/cartesian_ik_task.py b/dimos/control/tasks/cartesian_ik_task.py index 67d4e4ed52..2525db69e6 100644 --- a/dimos/control/tasks/cartesian_ik_task.py +++ b/dimos/control/tasks/cartesian_ik_task.py @@ -50,7 +50,8 @@ from numpy.typing import NDArray import pinocchio # type: ignore[import-untyped] - from dimos.msgs.geometry_msgs import Pose, PoseStamped + from dimos.msgs.geometry_msgs.Pose import Pose + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped logger = setup_logger() diff --git a/dimos/control/tasks/teleop_task.py b/dimos/control/tasks/teleop_task.py index 115b455fe6..3f20502759 100644 --- a/dimos/control/tasks/teleop_task.py +++ b/dimos/control/tasks/teleop_task.py @@ -51,7 +51,8 @@ from numpy.typing import NDArray - from dimos.msgs.geometry_msgs import Pose, PoseStamped + from dimos.msgs.geometry_msgs.Pose import Pose + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped from dimos.teleop.quest.quest_types import Buttons logger = setup_logger() diff --git a/dimos/control/tasks/trajectory_task.py b/dimos/control/tasks/trajectory_task.py index 16a271018a..fd0a9fda6e 100644 --- a/dimos/control/tasks/trajectory_task.py +++ b/dimos/control/tasks/trajectory_task.py @@ -32,7 +32,8 @@ JointCommandOutput, ResourceClaim, ) -from dimos.msgs.trajectory_msgs import JointTrajectory, TrajectoryState +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory +from dimos.msgs.trajectory_msgs.TrajectoryStatus import TrajectoryState from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/control/test_control.py b/dimos/control/test_control.py index a4b7e0a5bc..3de7865ae3 100644 --- a/dimos/control/test_control.py +++ b/dimos/control/test_control.py @@ -38,7 +38,8 @@ ) from dimos.control.tick_loop import TickLoop from dimos.hardware.manipulators.spec import ManipulatorAdapter -from dimos.msgs.trajectory_msgs import JointTrajectory, TrajectoryPoint +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory +from dimos.msgs.trajectory_msgs.TrajectoryPoint import TrajectoryPoint @pytest.fixture diff --git a/dimos/control/tick_loop.py b/dimos/control/tick_loop.py index e45a17030b..dc1ed32dbb 100644 --- a/dimos/control/tick_loop.py +++ b/dimos/control/tick_loop.py @@ -38,7 +38,7 @@ JointStateSnapshot, ResourceClaim, ) -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: diff --git a/dimos/core/__init__.py b/dimos/core/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/core/blueprints.py b/dimos/core/blueprints.py index abfeb29b2f..cac8507881 100644 --- a/dimos/core/blueprints.py +++ b/dimos/core/blueprints.py @@ -209,7 +209,8 @@ def _is_name_unique(self, name: str) -> bool: return sum(1 for n, _ in self._all_name_types if n == name) == 1 def _run_configurators(self) -> None: - from dimos.protocol.service.system_configurator import configure_system, lcm_configurators + from dimos.protocol.service.system_configurator.base import configure_system + from dimos.protocol.service.system_configurator.lcm_config import lcm_configurators configurators = [*lcm_configurators(), *self.configurator_checks] diff --git a/dimos/core/docker_runner.py b/dimos/core/docker_runner.py index 99833a9b97..dcb75fbdee 100644 --- a/dimos/core/docker_runner.py +++ b/dimos/core/docker_runner.py @@ -28,7 +28,7 @@ from dimos.core.docker_build import build_image, image_exists from dimos.core.module import Module, ModuleConfig from dimos.core.rpc_client import RpcCall -from dimos.protocol.rpc import LCMRPC +from dimos.protocol.rpc.pubsubrpc import LCMRPC from dimos.utils.logging_config import setup_logger from dimos.visualization.rerun.bridge import RERUN_GRPC_PORT, RERUN_WEB_PORT diff --git a/dimos/core/introspection/__init__.py b/dimos/core/introspection/__init__.py deleted file mode 100644 index c40c3d49e6..0000000000 --- a/dimos/core/introspection/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Module and blueprint introspection utilities.""" - -from dimos.core.introspection.module import INTERNAL_RPCS, render_module_io -from dimos.core.introspection.svg import to_svg - -__all__ = ["INTERNAL_RPCS", "render_module_io", "to_svg"] diff --git a/dimos/core/introspection/blueprint/__init__.py b/dimos/core/introspection/blueprint/__init__.py deleted file mode 100644 index 6545b39dfa..0000000000 --- a/dimos/core/introspection/blueprint/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Blueprint introspection and rendering. - -Renderers: - - dot: Graphviz DOT format (hub-style with type nodes as intermediate hubs) -""" - -from dimos.core.introspection.blueprint import dot -from dimos.core.introspection.blueprint.dot import LayoutAlgo, render_svg - -__all__ = ["LayoutAlgo", "dot", "render_svg"] diff --git a/dimos/core/introspection/module/__init__.py b/dimos/core/introspection/module/__init__.py deleted file mode 100644 index 444d0e24f3..0000000000 --- a/dimos/core/introspection/module/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Module introspection and rendering. - -Renderers: - - ansi: ANSI terminal output (default) - - dot: Graphviz DOT format -""" - -from dimos.core.introspection.module import ansi, dot -from dimos.core.introspection.module.info import ( - INTERNAL_RPCS, - ModuleInfo, - ParamInfo, - RpcInfo, - SkillInfo, - StreamInfo, - extract_module_info, -) -from dimos.core.introspection.module.render import render_module_io - -__all__ = [ - "INTERNAL_RPCS", - "ModuleInfo", - "ParamInfo", - "RpcInfo", - "SkillInfo", - "StreamInfo", - "ansi", - "dot", - "extract_module_info", - "render_module_io", -] diff --git a/dimos/core/module.py b/dimos/core/module.py index ab21ce17a9..1c5b311883 100644 --- a/dimos/core/module.py +++ b/dimos/core/module.py @@ -34,19 +34,21 @@ from dimos.core.core import T, rpc from dimos.core.global_config import GlobalConfig, global_config -from dimos.core.introspection.module import extract_module_info, render_module_io +from dimos.core.introspection.module.info import extract_module_info +from dimos.core.introspection.module.render import render_module_io from dimos.core.resource import Resource from dimos.core.rpc_client import RpcCall from dimos.core.stream import In, Out, RemoteOut, Transport -from dimos.protocol.rpc import LCMRPC, RPCSpec -from dimos.protocol.service import BaseConfig, Configurable -from dimos.protocol.tf import LCMTF, TFSpec +from dimos.protocol.rpc.pubsubrpc import LCMRPC +from dimos.protocol.rpc.spec import RPCSpec +from dimos.protocol.service.spec import BaseConfig, Configurable +from dimos.protocol.tf.tf import LCMTF, TFSpec from dimos.utils import colors from dimos.utils.generic import classproperty if TYPE_CHECKING: from dimos.core.blueprints import Blueprint - from dimos.core.introspection.module import ModuleInfo + from dimos.core.introspection.module.info import ModuleInfo from dimos.core.rpc_client import RPCClient if sys.version_info >= (3, 13): diff --git a/dimos/core/resource_monitor/__init__.py b/dimos/core/resource_monitor/__init__.py deleted file mode 100644 index 217941a2ec..0000000000 --- a/dimos/core/resource_monitor/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from dimos.core.resource_monitor.logger import ( - LCMResourceLogger, - ResourceLogger, - StructlogResourceLogger, -) -from dimos.core.resource_monitor.monitor import StatsMonitor -from dimos.core.resource_monitor.stats import ProcessStats, WorkerStats, collect_process_stats - -__all__ = [ - "LCMResourceLogger", - "ProcessStats", - "ResourceLogger", - "StatsMonitor", - "StructlogResourceLogger", - "WorkerStats", - "collect_process_stats", -] diff --git a/dimos/core/resource_monitor/stats.py b/dimos/core/resource_monitor/stats.py index 485132db46..6264d5c7f9 100644 --- a/dimos/core/resource_monitor/stats.py +++ b/dimos/core/resource_monitor/stats.py @@ -19,7 +19,7 @@ import psutil -from dimos.utils.decorators import ttl_cache +from dimos.utils.decorators.decorators import ttl_cache # Cache Process objects so cpu_percent(interval=None) has a previous sample. _proc_cache: dict[int, psutil.Process] = {} diff --git a/dimos/core/rpc_client.py b/dimos/core/rpc_client.py index e46124469c..84de18d671 100644 --- a/dimos/core/rpc_client.py +++ b/dimos/core/rpc_client.py @@ -17,7 +17,8 @@ from dimos.core.stream import RemoteStream from dimos.core.worker import MethodCallProxy -from dimos.protocol.rpc import LCMRPC, RPCSpec +from dimos.protocol.rpc.pubsubrpc import LCMRPC +from dimos.protocol.rpc.spec import RPCSpec from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/core/test_blueprints.py b/dimos/core/test_blueprints.py index 19dbf62c74..5f7bf33b8b 100644 --- a/dimos/core/test_blueprints.py +++ b/dimos/core/test_blueprints.py @@ -33,7 +33,7 @@ from dimos.core.rpc_client import RpcCall from dimos.core.stream import In, Out from dimos.core.transport import LCMTransport -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.spec.utils import Spec # Disable Rerun for tests (prevents viewer spawn and gRPC flush errors) diff --git a/dimos/core/test_core.py b/dimos/core/test_core.py index 3bd1383761..f9a89829d5 100644 --- a/dimos/core/test_core.py +++ b/dimos/core/test_core.py @@ -22,8 +22,8 @@ from dimos.core.stream import In, Out from dimos.core.testing import MockRobotClient from dimos.core.transport import LCMTransport, pLCMTransport -from dimos.msgs.geometry_msgs import Vector3 -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.odometry import Odometry diff --git a/dimos/core/test_stream.py b/dimos/core/test_stream.py index 16cb44b907..fdea17d2a3 100644 --- a/dimos/core/test_stream.py +++ b/dimos/core/test_stream.py @@ -24,7 +24,7 @@ from dimos.core.stream import In from dimos.core.testing import MockRobotClient from dimos.core.transport import LCMTransport, pLCMTransport -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.odometry import Odometry diff --git a/dimos/core/test_worker.py b/dimos/core/test_worker.py index 306b3fdb3d..021b2e21c4 100644 --- a/dimos/core/test_worker.py +++ b/dimos/core/test_worker.py @@ -21,7 +21,7 @@ from dimos.core.module import Module from dimos.core.stream import In, Out from dimos.core.worker_manager import WorkerManager -from dimos.msgs.geometry_msgs import Vector3 +from dimos.msgs.geometry_msgs.Vector3 import Vector3 if TYPE_CHECKING: from dimos.core.resource_monitor.stats import WorkerStats diff --git a/dimos/core/testing.py b/dimos/core/testing.py index 3bb5865192..a128fc4767 100644 --- a/dimos/core/testing.py +++ b/dimos/core/testing.py @@ -19,11 +19,11 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import Vector3 -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.lidar import pointcloud2_from_webrtc_lidar from dimos.robot.unitree.type.odometry import Odometry -from dimos.utils.testing import SensorReplay +from dimos.utils.testing.replay import SensorReplay class MockRobotClient(Module): diff --git a/dimos/e2e_tests/conftest.py b/dimos/e2e_tests/conftest.py index 51ab7c2c18..12f4a674a6 100644 --- a/dimos/e2e_tests/conftest.py +++ b/dimos/e2e_tests/conftest.py @@ -22,7 +22,8 @@ from dimos.e2e_tests.conf_types import StartPersonTrack from dimos.e2e_tests.dimos_cli_call import DimosCliCall from dimos.e2e_tests.lcm_spy import LcmSpy -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion from dimos.msgs.geometry_msgs.Vector3 import make_vector3 from dimos.msgs.std_msgs.Bool import Bool from dimos.simulation.mujoco.person_on_track import PersonTrackPublisher diff --git a/dimos/e2e_tests/lcm_spy.py b/dimos/e2e_tests/lcm_spy.py index 9efed09d5e..030591f52e 100644 --- a/dimos/e2e_tests/lcm_spy.py +++ b/dimos/e2e_tests/lcm_spy.py @@ -22,8 +22,8 @@ import lcm -from dimos.msgs import DimosMsg -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.protocol import DimosMsg from dimos.protocol.service.lcmservice import LCMService diff --git a/dimos/e2e_tests/test_control_coordinator.py b/dimos/e2e_tests/test_control_coordinator.py index 5bb7a096f7..80b63c529f 100644 --- a/dimos/e2e_tests/test_control_coordinator.py +++ b/dimos/e2e_tests/test_control_coordinator.py @@ -24,8 +24,10 @@ from dimos.control.coordinator import ControlCoordinator from dimos.core.rpc_client import RPCClient -from dimos.msgs.sensor_msgs import JointState -from dimos.msgs.trajectory_msgs import JointTrajectory, TrajectoryPoint, TrajectoryState +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory +from dimos.msgs.trajectory_msgs.TrajectoryPoint import TrajectoryPoint +from dimos.msgs.trajectory_msgs.TrajectoryStatus import TrajectoryState @pytest.mark.skipif_in_ci diff --git a/dimos/e2e_tests/test_simulation_module.py b/dimos/e2e_tests/test_simulation_module.py index b5902ad7e2..e08183fc24 100644 --- a/dimos/e2e_tests/test_simulation_module.py +++ b/dimos/e2e_tests/test_simulation_module.py @@ -16,7 +16,9 @@ import pytest -from dimos.msgs.sensor_msgs import JointCommand, JointState, RobotState +from dimos.msgs.sensor_msgs.JointCommand import JointCommand +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.sensor_msgs.RobotState import RobotState def _positions_within_tolerance( diff --git a/dimos/exceptions/__init__.py b/dimos/exceptions/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/hardware/__init__.py b/dimos/hardware/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/hardware/drive_trains/__init__.py b/dimos/hardware/drive_trains/__init__.py deleted file mode 100644 index c6e843feea..0000000000 --- a/dimos/hardware/drive_trains/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Drive train hardware adapters for velocity-commanded platforms.""" diff --git a/dimos/hardware/drive_trains/flowbase/__init__.py b/dimos/hardware/drive_trains/flowbase/__init__.py deleted file mode 100644 index 25f95e399c..0000000000 --- a/dimos/hardware/drive_trains/flowbase/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""FlowBase twist base adapter for holonomic base control via Portal RPC.""" diff --git a/dimos/hardware/drive_trains/mock/__init__.py b/dimos/hardware/drive_trains/mock/__init__.py deleted file mode 100644 index 9b6f630040..0000000000 --- a/dimos/hardware/drive_trains/mock/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Mock twist base adapter for testing without hardware. - -Usage: - >>> from dimos.hardware.drive_trains.mock import MockTwistBaseAdapter - >>> adapter = MockTwistBaseAdapter(dof=3) - >>> adapter.connect() - True - >>> adapter.write_velocities([0.5, 0.0, 0.1]) - True - >>> adapter.read_velocities() - [0.5, 0.0, 0.1] -""" - -from dimos.hardware.drive_trains.mock.adapter import MockTwistBaseAdapter - -__all__ = ["MockTwistBaseAdapter"] diff --git a/dimos/hardware/end_effectors/__init__.py b/dimos/hardware/end_effectors/__init__.py deleted file mode 100644 index 9a7aa9759a..0000000000 --- a/dimos/hardware/end_effectors/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .end_effector import EndEffector - -__all__ = ["EndEffector"] diff --git a/dimos/hardware/manipulators/__init__.py b/dimos/hardware/manipulators/__init__.py deleted file mode 100644 index 58986c9211..0000000000 --- a/dimos/hardware/manipulators/__init__.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Manipulator drivers for robotic arms. - -Architecture: Protocol-based adapters for different manipulator hardware. -- spec.py: ManipulatorAdapter Protocol and shared types -- xarm/: XArm adapter -- piper/: Piper adapter -- mock/: Mock adapter for testing - -Usage: - >>> from dimos.hardware.manipulators.xarm import XArm - >>> arm = XArm(ip="192.168.1.185") - >>> arm.start() - >>> arm.enable_servos() - >>> arm.move_joint([0, 0, 0, 0, 0, 0]) - -Testing: - >>> from dimos.hardware.manipulators.xarm import XArm - >>> from dimos.hardware.manipulators.mock import MockAdapter - >>> arm = XArm(adapter=MockAdapter()) - >>> arm.start() # No hardware needed! -""" - -from dimos.hardware.manipulators.spec import ( - ControlMode, - DriverStatus, - JointLimits, - ManipulatorAdapter, - ManipulatorInfo, -) - -__all__ = [ - "ControlMode", - "DriverStatus", - "JointLimits", - "ManipulatorAdapter", - "ManipulatorInfo", -] diff --git a/dimos/hardware/manipulators/mock/__init__.py b/dimos/hardware/manipulators/mock/__init__.py deleted file mode 100644 index 63be6f7e98..0000000000 --- a/dimos/hardware/manipulators/mock/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Mock adapter for testing manipulator drivers without hardware. - -Usage: - >>> from dimos.hardware.manipulators.xarm import XArm - >>> from dimos.hardware.manipulators.mock import MockAdapter - >>> arm = XArm(adapter=MockAdapter()) - >>> arm.start() # No hardware needed! - >>> arm.move_joint([0.1, 0.2, 0.3, 0.4, 0.5, 0.6]) - >>> assert arm.adapter.read_joint_positions() == [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] -""" - -from dimos.hardware.manipulators.mock.adapter import MockAdapter - -__all__ = ["MockAdapter"] diff --git a/dimos/hardware/manipulators/piper/__init__.py b/dimos/hardware/manipulators/piper/__init__.py deleted file mode 100644 index bfeb89b1c0..0000000000 --- a/dimos/hardware/manipulators/piper/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Piper manipulator hardware adapter. - -Usage: - >>> from dimos.hardware.manipulators.piper import PiperAdapter - >>> adapter = PiperAdapter(can_port="can0") - >>> adapter.connect() - >>> positions = adapter.read_joint_positions() -""" - -from dimos.hardware.manipulators.piper.adapter import PiperAdapter - -__all__ = ["PiperAdapter"] diff --git a/dimos/hardware/manipulators/registry.py b/dimos/hardware/manipulators/registry.py index 65dbe74b50..9e63fa349b 100644 --- a/dimos/hardware/manipulators/registry.py +++ b/dimos/hardware/manipulators/registry.py @@ -33,7 +33,6 @@ import importlib import logging -import pkgutil from typing import TYPE_CHECKING, Any if TYPE_CHECKING: @@ -78,19 +77,25 @@ def available(self) -> list[str]: def discover(self) -> None: """Discover and register adapters from subpackages. + Scans for subdirectories containing an adapter.py module. Can be called multiple times to pick up newly added adapters. """ - import dimos.hardware.manipulators as pkg + from pathlib import Path - for _, name, ispkg in pkgutil.iter_modules(pkg.__path__): - if not ispkg: + pkg_dir = Path(__file__).parent + for child in sorted(pkg_dir.iterdir()): + if not child.is_dir() or child.name.startswith(("_", ".")): + continue + if not (child / "adapter.py").exists(): continue try: - module = importlib.import_module(f"dimos.hardware.manipulators.{name}.adapter") + module = importlib.import_module( + f"dimos.hardware.manipulators.{child.name}.adapter" + ) if hasattr(module, "register"): module.register(self) except ImportError as e: - logger.debug(f"Skipping adapter {name}: {e}") + logger.debug(f"Skipping adapter {child.name}: {e}") adapter_registry = AdapterRegistry() diff --git a/dimos/hardware/manipulators/spec.py b/dimos/hardware/manipulators/spec.py index ed63a21e82..868b714bfa 100644 --- a/dimos/hardware/manipulators/spec.py +++ b/dimos/hardware/manipulators/spec.py @@ -26,7 +26,9 @@ from enum import Enum from typing import Protocol, runtime_checkable -from dimos.msgs.geometry_msgs import Quaternion, Transform, Vector3 +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 class DriverStatus(Enum): diff --git a/dimos/hardware/manipulators/xarm/__init__.py b/dimos/hardware/manipulators/xarm/__init__.py deleted file mode 100644 index 8bcab667c1..0000000000 --- a/dimos/hardware/manipulators/xarm/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""XArm manipulator hardware adapter. - -Usage: - >>> from dimos.hardware.manipulators.xarm import XArmAdapter - >>> adapter = XArmAdapter(ip="192.168.1.185", dof=6) - >>> adapter.connect() - >>> positions = adapter.read_joint_positions() -""" - -from dimos.hardware.manipulators.xarm.adapter import XArmAdapter - -__all__ = ["XArmAdapter"] diff --git a/dimos/hardware/sensors/camera/gstreamer/gstreamer_camera.py b/dimos/hardware/sensors/camera/gstreamer/gstreamer_camera.py index ec19d6844e..c723cab130 100644 --- a/dimos/hardware/sensors/camera/gstreamer/gstreamer_camera.py +++ b/dimos/hardware/sensors/camera/gstreamer/gstreamer_camera.py @@ -25,7 +25,7 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import Out -from dimos.msgs.sensor_msgs import Image, ImageFormat +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat from dimos.utils.logging_config import setup_logger # Add system path for gi module if needed diff --git a/dimos/hardware/sensors/camera/gstreamer/gstreamer_camera_test_script.py b/dimos/hardware/sensors/camera/gstreamer/gstreamer_camera_test_script.py index 8785a9260b..a18d52fbb0 100755 --- a/dimos/hardware/sensors/camera/gstreamer/gstreamer_camera_test_script.py +++ b/dimos/hardware/sensors/camera/gstreamer/gstreamer_camera_test_script.py @@ -21,8 +21,8 @@ from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.transport import LCMTransport from dimos.hardware.sensors.camera.gstreamer.gstreamer_camera import GstreamerCameraModule -from dimos.msgs.sensor_msgs import Image -from dimos.protocol import pubsub +from dimos.msgs.sensor_msgs.Image import Image +from dimos.protocol.pubsub.impl import lcmpubsub as _lcm logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @@ -59,7 +59,7 @@ def main() -> None: logging.getLogger().setLevel(logging.DEBUG) # Initialize LCM - pubsub.lcm.autoconf() # type: ignore[attr-defined] + _lcm.autoconf() # type: ignore[attr-defined] # Start dimos dimos = ModuleCoordinator() diff --git a/dimos/hardware/sensors/camera/module.py b/dimos/hardware/sensors/camera/module.py index 0f055f0352..e0d0b3407e 100644 --- a/dimos/hardware/sensors/camera/module.py +++ b/dimos/hardware/sensors/camera/module.py @@ -26,7 +26,9 @@ from dimos.core.stream import Out from dimos.hardware.sensors.camera.spec import CameraHardware from dimos.hardware.sensors.camera.webcam import Webcam -from dimos.msgs.geometry_msgs import Quaternion, Transform, Vector3 +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo from dimos.msgs.sensor_msgs.Image import Image, sharpness_barrier from dimos.spec import perception diff --git a/dimos/hardware/sensors/camera/realsense/__init__.py b/dimos/hardware/sensors/camera/realsense/__init__.py deleted file mode 100644 index 58f519a12e..0000000000 --- a/dimos/hardware/sensors/camera/realsense/__init__.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import annotations - -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from dimos.hardware.sensors.camera.realsense.camera import ( - RealSenseCamera, - RealSenseCameraConfig, - realsense_camera, - ) - -__all__ = ["RealSenseCamera", "RealSenseCameraConfig", "realsense_camera"] - - -def __getattr__(name: str) -> object: - if name in __all__: - from dimos.hardware.sensors.camera.realsense.camera import ( - RealSenseCamera, - RealSenseCameraConfig, - realsense_camera, - ) - - globals().update( - RealSenseCamera=RealSenseCamera, - RealSenseCameraConfig=RealSenseCameraConfig, - realsense_camera=realsense_camera, - ) - return globals()[name] - raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/dimos/hardware/sensors/camera/realsense/camera.py b/dimos/hardware/sensors/camera/realsense/camera.py index 5908525826..23bc19cdad 100644 --- a/dimos/hardware/sensors/camera/realsense/camera.py +++ b/dimos/hardware/sensors/camera/realsense/camera.py @@ -35,8 +35,10 @@ DepthCameraConfig, DepthCameraHardware, ) -from dimos.msgs.geometry_msgs import Quaternion, Transform, Vector3 -from dimos.msgs.sensor_msgs import CameraInfo +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo from dimos.msgs.sensor_msgs.Image import Image, ImageFormat from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.foxglove_bridge import FoxgloveBridge diff --git a/dimos/hardware/sensors/camera/spec.py b/dimos/hardware/sensors/camera/spec.py index be37ec734a..dcb0196ff2 100644 --- a/dimos/hardware/sensors/camera/spec.py +++ b/dimos/hardware/sensors/camera/spec.py @@ -17,8 +17,9 @@ from reactivex.observable import Observable -from dimos.msgs.geometry_msgs import Quaternion, Transform -from dimos.msgs.sensor_msgs import CameraInfo +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo from dimos.msgs.sensor_msgs.Image import Image from dimos.protocol.service.spec import BaseConfig, Configurable diff --git a/dimos/hardware/sensors/camera/webcam.py b/dimos/hardware/sensors/camera/webcam.py index 51199624fe..cfd1a080a0 100644 --- a/dimos/hardware/sensors/camera/webcam.py +++ b/dimos/hardware/sensors/camera/webcam.py @@ -23,8 +23,8 @@ from reactivex.observable import Observable from dimos.hardware.sensors.camera.spec import CameraConfig, CameraHardware -from dimos.msgs.sensor_msgs import CameraInfo, Image -from dimos.msgs.sensor_msgs.Image import ImageFormat +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat from dimos.utils.reactive import backpressure diff --git a/dimos/hardware/sensors/camera/zed/camera.py b/dimos/hardware/sensors/camera/zed/camera.py index 2df9afd70c..214b1f73e3 100644 --- a/dimos/hardware/sensors/camera/zed/camera.py +++ b/dimos/hardware/sensors/camera/zed/camera.py @@ -33,8 +33,10 @@ DepthCameraConfig, DepthCameraHardware, ) -from dimos.msgs.geometry_msgs import Quaternion, Transform, Vector3 -from dimos.msgs.sensor_msgs import CameraInfo +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo from dimos.msgs.sensor_msgs.Image import Image, ImageFormat from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.foxglove_bridge import FoxgloveBridge diff --git a/dimos/hardware/sensors/camera/zed/__init__.py b/dimos/hardware/sensors/camera/zed/compat.py similarity index 97% rename from dimos/hardware/sensors/camera/zed/__init__.py rename to dimos/hardware/sensors/camera/zed/compat.py index 6e3b905e90..3cec8d9566 100644 --- a/dimos/hardware/sensors/camera/zed/__init__.py +++ b/dimos/hardware/sensors/camera/zed/compat.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""ZED camera hardware interfaces.""" +"""ZED camera compatibility layer and SDK detection.""" from pathlib import Path diff --git a/dimos/hardware/sensors/camera/zed/test_zed.py b/dimos/hardware/sensors/camera/zed/test_zed.py index 2716e809a5..a98055a355 100644 --- a/dimos/hardware/sensors/camera/zed/test_zed.py +++ b/dimos/hardware/sensors/camera/zed/test_zed.py @@ -15,7 +15,7 @@ import pytest -from dimos.hardware.sensors.camera import zed +from dimos.hardware.sensors.camera.zed import compat as zed from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo diff --git a/dimos/hardware/sensors/fake_zed_module.py b/dimos/hardware/sensors/fake_zed_module.py index ca5014337b..16e85aa93c 100644 --- a/dimos/hardware/sensors/fake_zed_module.py +++ b/dimos/hardware/sensors/fake_zed_module.py @@ -27,12 +27,12 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import Image, ImageFormat -from dimos.msgs.std_msgs import Header -from dimos.protocol.tf import TF +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.msgs.std_msgs.Header import Header +from dimos.protocol.tf.tf import TF from dimos.utils.logging_config import setup_logger -from dimos.utils.testing import TimedSensorReplay +from dimos.utils.testing.replay import TimedSensorReplay logger = setup_logger(level=logging.INFO) @@ -278,7 +278,9 @@ def _publish_pose(self, msg) -> None: # type: ignore[no-untyped-def] # Publish TF transform from world to camera import time - from dimos.msgs.geometry_msgs import Quaternion, Transform, Vector3 + from dimos.msgs.geometry_msgs.Quaternion import Quaternion + from dimos.msgs.geometry_msgs.Transform import Transform + from dimos.msgs.geometry_msgs.Vector3 import Vector3 transform = Transform( translation=Vector3(*msg.position), diff --git a/dimos/hardware/sensors/lidar/__init__.py b/dimos/hardware/sensors/lidar/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/hardware/sensors/lidar/fastlio2/__init__.py b/dimos/hardware/sensors/lidar/fastlio2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/hardware/sensors/lidar/livox/__init__.py b/dimos/hardware/sensors/lidar/livox/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/manipulation/__init__.py b/dimos/manipulation/__init__.py deleted file mode 100644 index d2a511d146..0000000000 --- a/dimos/manipulation/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Manipulation module for robot arm motion planning and control.""" - -from dimos.manipulation.manipulation_module import ( - ManipulationModule, - ManipulationModuleConfig, - ManipulationState, - manipulation_module, -) -from dimos.manipulation.pick_and_place_module import ( - PickAndPlaceModule, - PickAndPlaceModuleConfig, - pick_and_place_module, -) - -__all__ = [ - "ManipulationModule", - "ManipulationModuleConfig", - "ManipulationState", - "PickAndPlaceModule", - "PickAndPlaceModuleConfig", - "manipulation_module", - "pick_and_place_module", -] diff --git a/dimos/manipulation/blueprints.py b/dimos/manipulation/blueprints.py index 7a0eefb37a..8ef2c03279 100644 --- a/dimos/manipulation/blueprints.py +++ b/dimos/manipulation/blueprints.py @@ -35,12 +35,15 @@ from dimos.control.coordinator import TaskConfig, control_coordinator from dimos.core.blueprints import autoconnect from dimos.core.transport import LCMTransport -from dimos.hardware.sensors.camera.realsense import realsense_camera +from dimos.hardware.sensors.camera.realsense.camera import realsense_camera from dimos.manipulation.manipulation_module import manipulation_module from dimos.manipulation.pick_and_place_module import pick_and_place_module -from dimos.manipulation.planning.spec import RobotModelConfig -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Transform, Vector3 -from dimos.msgs.sensor_msgs import JointState +from dimos.manipulation.planning.spec.config import RobotModelConfig +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.perception.object_scene_registration import object_scene_registration_module from dimos.robot.foxglove_bridge import foxglove_bridge # TODO: migrate to rerun from dimos.utils.data import get_data diff --git a/dimos/manipulation/control/__init__.py b/dimos/manipulation/control/__init__.py deleted file mode 100644 index ec85660eb3..0000000000 --- a/dimos/manipulation/control/__init__.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Manipulation Control Modules - -Hardware-agnostic controllers for robotic manipulation tasks. - -Submodules: -- servo_control: Real-time servo-level controllers (Cartesian motion control) -- trajectory_controller: Trajectory planning and execution -""" - -# Re-export from servo_control for backwards compatibility -from dimos.manipulation.control.servo_control import ( - CartesianMotionController, - CartesianMotionControllerConfig, - cartesian_motion_controller, -) - -# Re-export from trajectory_controller -from dimos.manipulation.control.trajectory_controller import ( - JointTrajectoryController, - JointTrajectoryControllerConfig, - joint_trajectory_controller, -) - -__all__ = [ - # Servo control - "CartesianMotionController", - "CartesianMotionControllerConfig", - # Trajectory control - "JointTrajectoryController", - "JointTrajectoryControllerConfig", - "cartesian_motion_controller", - "joint_trajectory_controller", -] diff --git a/dimos/manipulation/control/coordinator_client.py b/dimos/manipulation/control/coordinator_client.py index cbaad28df2..dfa99371a6 100644 --- a/dimos/manipulation/control/coordinator_client.py +++ b/dimos/manipulation/control/coordinator_client.py @@ -54,7 +54,7 @@ ) if TYPE_CHECKING: - from dimos.msgs.trajectory_msgs import JointTrajectory + from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory class CoordinatorClient: diff --git a/dimos/manipulation/control/dual_trajectory_setter.py b/dimos/manipulation/control/dual_trajectory_setter.py index 05793eeb76..3fdccea400 100644 --- a/dimos/manipulation/control/dual_trajectory_setter.py +++ b/dimos/manipulation/control/dual_trajectory_setter.py @@ -37,8 +37,8 @@ from dimos.manipulation.planning.trajectory_generator.joint_trajectory_generator import ( JointTrajectoryGenerator, ) -from dimos.msgs.sensor_msgs import JointState -from dimos.msgs.trajectory_msgs import JointTrajectory +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory @dataclass diff --git a/dimos/manipulation/control/servo_control/__init__.py b/dimos/manipulation/control/servo_control/__init__.py deleted file mode 100644 index 5418a7e24b..0000000000 --- a/dimos/manipulation/control/servo_control/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Servo Control Modules - -Real-time servo-level controllers for robotic manipulation. -Includes Cartesian motion control with PID-based tracking. -""" - -from dimos.manipulation.control.servo_control.cartesian_motion_controller import ( - CartesianMotionController, - CartesianMotionControllerConfig, - cartesian_motion_controller, -) - -__all__ = [ - "CartesianMotionController", - "CartesianMotionControllerConfig", - "cartesian_motion_controller", -] diff --git a/dimos/manipulation/control/servo_control/cartesian_motion_controller.py b/dimos/manipulation/control/servo_control/cartesian_motion_controller.py index a12fb44a96..0cbd41e218 100644 --- a/dimos/manipulation/control/servo_control/cartesian_motion_controller.py +++ b/dimos/manipulation/control/servo_control/cartesian_motion_controller.py @@ -34,8 +34,14 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import Pose, PoseStamped, Quaternion, Twist, Vector3 -from dimos.msgs.sensor_msgs import JointCommand, JointState, RobotState +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.JointCommand import JointCommand +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.sensor_msgs.RobotState import RobotState from dimos.utils.logging_config import setup_logger from dimos.utils.simple_controller import PIDController diff --git a/dimos/manipulation/control/target_setter.py b/dimos/manipulation/control/target_setter.py index f54a6af2f0..a0228c6a24 100644 --- a/dimos/manipulation/control/target_setter.py +++ b/dimos/manipulation/control/target_setter.py @@ -25,7 +25,9 @@ import time from dimos.core.transport import LCMTransport -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 class TargetSetter: diff --git a/dimos/manipulation/control/trajectory_controller/__init__.py b/dimos/manipulation/control/trajectory_controller/__init__.py deleted file mode 100644 index fb4360d4cc..0000000000 --- a/dimos/manipulation/control/trajectory_controller/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Trajectory Controller Module - -Joint-space trajectory execution for robotic manipulators. -""" - -from dimos.manipulation.control.trajectory_controller.joint_trajectory_controller import ( - JointTrajectoryController, - JointTrajectoryControllerConfig, - joint_trajectory_controller, -) - -__all__ = [ - "JointTrajectoryController", - "JointTrajectoryControllerConfig", - "joint_trajectory_controller", -] diff --git a/dimos/manipulation/control/trajectory_controller/joint_trajectory_controller.py b/dimos/manipulation/control/trajectory_controller/joint_trajectory_controller.py index ed62a7345e..465df7afea 100644 --- a/dimos/manipulation/control/trajectory_controller/joint_trajectory_controller.py +++ b/dimos/manipulation/control/trajectory_controller/joint_trajectory_controller.py @@ -36,8 +36,11 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.sensor_msgs import JointCommand, JointState, RobotState -from dimos.msgs.trajectory_msgs import JointTrajectory, TrajectoryState, TrajectoryStatus +from dimos.msgs.sensor_msgs.JointCommand import JointCommand +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.sensor_msgs.RobotState import RobotState +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory +from dimos.msgs.trajectory_msgs.TrajectoryStatus import TrajectoryState, TrajectoryStatus from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/manipulation/control/trajectory_controller/spec.py b/dimos/manipulation/control/trajectory_controller/spec.py index e11da91847..b696f2dc6a 100644 --- a/dimos/manipulation/control/trajectory_controller/spec.py +++ b/dimos/manipulation/control/trajectory_controller/spec.py @@ -30,8 +30,11 @@ if TYPE_CHECKING: from dimos.core.stream import In, Out - from dimos.msgs.sensor_msgs import JointCommand, JointState, RobotState - from dimos.msgs.trajectory_msgs import JointTrajectory as JointTrajectoryMsg, TrajectoryState + from dimos.msgs.sensor_msgs.JointCommand import JointCommand + from dimos.msgs.sensor_msgs.JointState import JointState + from dimos.msgs.sensor_msgs.RobotState import RobotState + from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory as JointTrajectoryMsg + from dimos.msgs.trajectory_msgs.TrajectoryStatus import TrajectoryState # Input topics joint_state: In[JointState] | None = None # Feedback from arm driver diff --git a/dimos/manipulation/control/trajectory_setter.py b/dimos/manipulation/control/trajectory_setter.py index a5baa512b5..25f9db2a3f 100644 --- a/dimos/manipulation/control/trajectory_setter.py +++ b/dimos/manipulation/control/trajectory_setter.py @@ -36,8 +36,8 @@ from dimos.manipulation.planning.trajectory_generator.joint_trajectory_generator import ( JointTrajectoryGenerator, ) -from dimos.msgs.sensor_msgs import JointState -from dimos.msgs.trajectory_msgs import JointTrajectory +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory class TrajectorySetter: diff --git a/dimos/manipulation/grasping/__init__.py b/dimos/manipulation/grasping/__init__.py deleted file mode 100644 index 41779f55e7..0000000000 --- a/dimos/manipulation/grasping/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from dimos.manipulation.grasping.graspgen_module import ( - GraspGenConfig, - GraspGenModule, - graspgen, -) -from dimos.manipulation.grasping.grasping import ( - GraspingModule, - grasping_module, -) - -__all__ = [ - "GraspGenConfig", - "GraspGenModule", - "GraspingModule", - "graspgen", - "grasping_module", -] diff --git a/dimos/manipulation/grasping/demo_grasping.py b/dimos/manipulation/grasping/demo_grasping.py index 01e34f905f..43a6c9a20a 100644 --- a/dimos/manipulation/grasping/demo_grasping.py +++ b/dimos/manipulation/grasping/demo_grasping.py @@ -16,8 +16,8 @@ from dimos.agents.agent import agent from dimos.core.blueprints import autoconnect -from dimos.hardware.sensors.camera.realsense import realsense_camera -from dimos.manipulation.grasping import graspgen +from dimos.hardware.sensors.camera.realsense.camera import realsense_camera +from dimos.manipulation.grasping.graspgen_module import graspgen from dimos.manipulation.grasping.grasping import grasping_module from dimos.perception.detection.detectors.yoloe import YoloePromptMode from dimos.perception.object_scene_registration import object_scene_registration_module diff --git a/dimos/manipulation/grasping/graspgen_module.py b/dimos/manipulation/grasping/graspgen_module.py index 7ec8cfeeaa..c883126840 100644 --- a/dimos/manipulation/grasping/graspgen_module.py +++ b/dimos/manipulation/grasping/graspgen_module.py @@ -25,13 +25,13 @@ from dimos.core.docker_runner import DockerModuleConfig from dimos.core.module import Module from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import PoseArray -from dimos.msgs.std_msgs import Header +from dimos.msgs.geometry_msgs.PoseArray import PoseArray +from dimos.msgs.std_msgs.Header import Header from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import matrix_to_pose if TYPE_CHECKING: - from dimos.msgs.sensor_msgs import PointCloud2 + from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 logger = setup_logger() diff --git a/dimos/manipulation/grasping/grasping.py b/dimos/manipulation/grasping/grasping.py index 433a07d846..ef05dc29e2 100644 --- a/dimos/manipulation/grasping/grasping.py +++ b/dimos/manipulation/grasping/grasping.py @@ -25,12 +25,12 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import PoseArray +from dimos.msgs.geometry_msgs.PoseArray import PoseArray from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import quaternion_to_euler if TYPE_CHECKING: - from dimos.msgs.sensor_msgs import PointCloud2 + from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 logger = setup_logger() diff --git a/dimos/manipulation/manipulation_module.py b/dimos/manipulation/manipulation_module.py index f064130965..fe5561c705 100644 --- a/dimos/manipulation/manipulation_module.py +++ b/dimos/manipulation/manipulation_module.py @@ -34,23 +34,20 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In -from dimos.manipulation.planning import ( - JointPath, +from dimos.manipulation.planning.factory import create_kinematics, create_planner +from dimos.manipulation.planning.monitor.world_monitor import WorldMonitor +from dimos.manipulation.planning.spec.config import RobotModelConfig +from dimos.manipulation.planning.spec.enums import ObstacleType +from dimos.manipulation.planning.spec.models import JointPath, Obstacle, RobotName, WorldRobotID +from dimos.manipulation.planning.spec.protocols import KinematicsSpec, PlannerSpec +from dimos.manipulation.planning.trajectory_generator.joint_trajectory_generator import ( JointTrajectoryGenerator, - KinematicsSpec, - Obstacle, - ObstacleType, - PlannerSpec, - RobotModelConfig, - RobotName, - WorldRobotID, - create_kinematics, - create_planner, ) -from dimos.manipulation.planning.monitor import WorldMonitor -from dimos.msgs.geometry_msgs import Pose, Quaternion, Vector3 -from dimos.msgs.sensor_msgs import JointState -from dimos.msgs.trajectory_msgs import JointTrajectory +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: @@ -247,7 +244,7 @@ def _on_joint_state(self, msg: JointState) -> None: def _tf_publish_loop(self) -> None: """Publish TF transforms at 10Hz for EE and extra links.""" - from dimos.msgs.geometry_msgs import Transform + from dimos.msgs.geometry_msgs.Transform import Transform period = 0.1 # 10Hz while not self._tf_stop_event.is_set(): @@ -406,7 +403,7 @@ def plan_to_pose(self, pose: Pose, robot_name: RobotName | None = None) -> bool: return self._fail("No joint state") # Convert Pose to PoseStamped for the IK solver - from dimos.msgs.geometry_msgs import PoseStamped + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped target_pose = PoseStamped( frame_id="world", @@ -750,7 +747,7 @@ def add_obstacle( return "" # Import PoseStamped here to avoid circular imports - from dimos.msgs.geometry_msgs import PoseStamped + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped obstacle = Obstacle( name=name, diff --git a/dimos/manipulation/pick_and_place_module.py b/dimos/manipulation/pick_and_place_module.py index 6d6ad1042e..b433df6801 100644 --- a/dimos/manipulation/pick_and_place_module.py +++ b/dimos/manipulation/pick_and_place_module.py @@ -37,7 +37,9 @@ ManipulationModule, ManipulationModuleConfig, ) -from dimos.msgs.geometry_msgs import Pose, Quaternion, Vector3 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.perception.detection.type.detection3d.object import ( Object as DetObject, ) @@ -45,8 +47,8 @@ from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: - from dimos.msgs.geometry_msgs import PoseArray - from dimos.msgs.sensor_msgs import PointCloud2 + from dimos.msgs.geometry_msgs.PoseArray import PoseArray + from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 logger = setup_logger() diff --git a/dimos/manipulation/planning/__init__.py b/dimos/manipulation/planning/__init__.py deleted file mode 100644 index 8aaf0caa25..0000000000 --- a/dimos/manipulation/planning/__init__.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Manipulation Planning Module - -Motion planning stack for robotic manipulators using Protocol-based architecture. - -## Architecture - -- WorldSpec: Core backend owning physics/collision (DrakeWorld, future: MuJoCoWorld) -- KinematicsSpec: IK solvers - - JacobianIK: Backend-agnostic iterative/differential IK - - DrakeOptimizationIK: Drake-specific nonlinear optimization IK -- PlannerSpec: Backend-agnostic joint-space path planning - - RRTConnectPlanner: Bi-directional RRT-Connect - - RRTStarPlanner: RRT* (asymptotically optimal) - -## Factory Functions - -Use factory functions to create components: - -```python -from dimos.manipulation.planning.factory import ( - create_world, - create_kinematics, - create_planner, -) - -world = create_world(backend="drake", enable_viz=True) -kinematics = create_kinematics(name="jacobian") # or "drake_optimization" -planner = create_planner(name="rrt_connect") # backend-agnostic -``` - -## Monitors - -Use WorldMonitor for reactive state synchronization: - -```python -from dimos.manipulation.planning.monitor import WorldMonitor - -monitor = WorldMonitor(enable_viz=True) -robot_id = monitor.add_robot(config) -monitor.finalize() -monitor.start_state_monitor(robot_id) -``` -""" - -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "factory": ["create_kinematics", "create_planner", "create_planning_stack", "create_world"], - "spec": [ - "CollisionObjectMessage", - "IKResult", - "IKStatus", - "JointPath", - "KinematicsSpec", - "Obstacle", - "ObstacleType", - "PlannerSpec", - "PlanningResult", - "PlanningStatus", - "RobotModelConfig", - "RobotName", - "WorldRobotID", - "WorldSpec", - ], - "trajectory_generator.joint_trajectory_generator": ["JointTrajectoryGenerator"], - }, -) diff --git a/dimos/manipulation/planning/examples/__init__.py b/dimos/manipulation/planning/examples/__init__.py deleted file mode 100644 index 7971835dab..0000000000 --- a/dimos/manipulation/planning/examples/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Manipulation planning examples. -""" diff --git a/dimos/manipulation/planning/examples/manipulation_client.py b/dimos/manipulation/planning/examples/manipulation_client.py index ac098ac52a..4dcd2fe9e8 100644 --- a/dimos/manipulation/planning/examples/manipulation_client.py +++ b/dimos/manipulation/planning/examples/manipulation_client.py @@ -49,7 +49,9 @@ from dimos.core.rpc_client import RPCClient from dimos.manipulation.manipulation_module import ManipulationModule -from dimos.msgs.geometry_msgs import Pose, Quaternion, Vector3 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 _client = RPCClient(None, ManipulationModule) @@ -71,7 +73,7 @@ def state() -> str: def plan(target_joints: list[float], robot_name: str | None = None) -> bool: """Plan to joint configuration. e.g. plan([0.1]*7)""" - from dimos.msgs.sensor_msgs import JointState + from dimos.msgs.sensor_msgs.JointState import JointState js = JointState(position=target_joints) return _client.plan_to_joints(js, robot_name) @@ -106,7 +108,7 @@ def execute(robot_name: str | None = None) -> bool: def home(robot_name: str | None = None) -> bool: """Plan and execute move to home position.""" - from dimos.msgs.sensor_msgs import JointState + from dimos.msgs.sensor_msgs.JointState import JointState home_joints = _client.get_robot_info(robot_name).get("home_joints", [0.0] * 7) success = _client.plan_to_joints(JointState(position=home_joints), robot_name) diff --git a/dimos/manipulation/planning/factory.py b/dimos/manipulation/planning/factory.py index d392bac563..65173dfd18 100644 --- a/dimos/manipulation/planning/factory.py +++ b/dimos/manipulation/planning/factory.py @@ -19,11 +19,7 @@ from typing import TYPE_CHECKING, Any if TYPE_CHECKING: - from dimos.manipulation.planning.spec import ( - KinematicsSpec, - PlannerSpec, - WorldSpec, - ) + from dimos.manipulation.planning.spec.protocols import KinematicsSpec, PlannerSpec, WorldSpec def create_world( diff --git a/dimos/manipulation/planning/kinematics/__init__.py b/dimos/manipulation/planning/kinematics/__init__.py deleted file mode 100644 index dacd2007cb..0000000000 --- a/dimos/manipulation/planning/kinematics/__init__.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Kinematics Module - -Contains IK solver implementations that use WorldSpec. - -## Implementations - -- JacobianIK: Backend-agnostic iterative/differential IK (works with any WorldSpec) -- DrakeOptimizationIK: Drake-specific nonlinear optimization IK (requires DrakeWorld) - -## Usage - -Use factory functions to create IK solvers: - -```python -from dimos.manipulation.planning.factory import create_kinematics - -# Backend-agnostic (works with any WorldSpec) -kinematics = create_kinematics(name="jacobian") - -# Drake-specific (requires DrakeWorld, more accurate) -kinematics = create_kinematics(name="drake_optimization") - -result = kinematics.solve(world, robot_id, target_pose) -``` -""" - -from dimos.manipulation.planning.kinematics.drake_optimization_ik import ( - DrakeOptimizationIK, -) -from dimos.manipulation.planning.kinematics.jacobian_ik import JacobianIK -from dimos.manipulation.planning.kinematics.pinocchio_ik import ( - PinocchioIK, - PinocchioIKConfig, -) - -__all__ = ["DrakeOptimizationIK", "JacobianIK", "PinocchioIK", "PinocchioIKConfig"] diff --git a/dimos/manipulation/planning/kinematics/drake_optimization_ik.py b/dimos/manipulation/planning/kinematics/drake_optimization_ik.py index 1e6b1962a5..b13aa8947a 100644 --- a/dimos/manipulation/planning/kinematics/drake_optimization_ik.py +++ b/dimos/manipulation/planning/kinematics/drake_optimization_ik.py @@ -20,10 +20,13 @@ import numpy as np -from dimos.manipulation.planning.spec import IKResult, IKStatus, WorldRobotID, WorldSpec +from dimos.manipulation.planning.spec.enums import IKStatus +from dimos.manipulation.planning.spec.models import IKResult, WorldRobotID +from dimos.manipulation.planning.spec.protocols import WorldSpec from dimos.manipulation.planning.utils.kinematics_utils import compute_pose_error -from dimos.msgs.geometry_msgs import PoseStamped, Transform -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import pose_to_matrix diff --git a/dimos/manipulation/planning/kinematics/jacobian_ik.py b/dimos/manipulation/planning/kinematics/jacobian_ik.py index c756045d36..fb493e2d5f 100644 --- a/dimos/manipulation/planning/kinematics/jacobian_ik.py +++ b/dimos/manipulation/planning/kinematics/jacobian_ik.py @@ -28,7 +28,9 @@ import numpy as np -from dimos.manipulation.planning.spec import IKResult, IKStatus, WorldRobotID, WorldSpec +from dimos.manipulation.planning.spec.enums import IKStatus +from dimos.manipulation.planning.spec.models import IKResult, WorldRobotID +from dimos.manipulation.planning.spec.protocols import WorldSpec from dimos.manipulation.planning.utils.kinematics_utils import ( check_singularity, compute_error_twist, @@ -41,8 +43,11 @@ if TYPE_CHECKING: from numpy.typing import NDArray -from dimos.msgs.geometry_msgs import PoseStamped, Transform, Twist, Vector3 -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.JointState import JointState logger = setup_logger() diff --git a/dimos/manipulation/planning/kinematics/pinocchio_ik.py b/dimos/manipulation/planning/kinematics/pinocchio_ik.py index ff1c2dcc2a..cb6ee91608 100644 --- a/dimos/manipulation/planning/kinematics/pinocchio_ik.py +++ b/dimos/manipulation/planning/kinematics/pinocchio_ik.py @@ -44,7 +44,8 @@ if TYPE_CHECKING: from numpy.typing import NDArray - from dimos.msgs.geometry_msgs import Pose, PoseStamped + from dimos.msgs.geometry_msgs.Pose import Pose + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped logger = setup_logger() diff --git a/dimos/manipulation/planning/monitor/__init__.py b/dimos/manipulation/planning/monitor/__init__.py deleted file mode 100644 index c280bd4d56..0000000000 --- a/dimos/manipulation/planning/monitor/__init__.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -World Monitor Module - -Provides reactive monitoring for keeping WorldSpec synchronized with the real world. - -## Components - -- WorldMonitor: Top-level monitor using WorldSpec Protocol -- WorldStateMonitor: Syncs joint state to WorldSpec -- WorldObstacleMonitor: Syncs obstacles to WorldSpec - -All monitors use the factory pattern and Protocol types. - -## Example - -```python -from dimos.manipulation.planning.monitor import WorldMonitor - -monitor = WorldMonitor(enable_viz=True) -robot_id = monitor.add_robot(config) -monitor.finalize() - -# Start monitoring -monitor.start_state_monitor(robot_id) -monitor.start_obstacle_monitor() - -# Handle joint state messages -monitor.on_joint_state(msg, robot_id) - -# Thread-safe collision checking -is_valid = monitor.is_state_valid(robot_id, q_test) -``` -""" - -from dimos.manipulation.planning.monitor.world_monitor import WorldMonitor -from dimos.manipulation.planning.monitor.world_obstacle_monitor import ( - WorldObstacleMonitor, -) -from dimos.manipulation.planning.monitor.world_state_monitor import WorldStateMonitor - -# Re-export message types from spec for convenience -from dimos.manipulation.planning.spec import CollisionObjectMessage - -__all__ = [ - "CollisionObjectMessage", - "WorldMonitor", - "WorldObstacleMonitor", - "WorldStateMonitor", -] diff --git a/dimos/manipulation/planning/monitor/world_monitor.py b/dimos/manipulation/planning/monitor/world_monitor.py index cca2dda013..32f519dfd4 100644 --- a/dimos/manipulation/planning/monitor/world_monitor.py +++ b/dimos/manipulation/planning/monitor/world_monitor.py @@ -23,8 +23,8 @@ from dimos.manipulation.planning.factory import create_world from dimos.manipulation.planning.monitor.world_obstacle_monitor import WorldObstacleMonitor from dimos.manipulation.planning.monitor.world_state_monitor import WorldStateMonitor -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: @@ -33,15 +33,15 @@ import numpy as np from numpy.typing import NDArray - from dimos.manipulation.planning.spec import ( + from dimos.manipulation.planning.spec.config import RobotModelConfig + from dimos.manipulation.planning.spec.models import ( CollisionObjectMessage, JointPath, Obstacle, - RobotModelConfig, WorldRobotID, - WorldSpec, ) - from dimos.msgs.vision_msgs import Detection3D + from dimos.manipulation.planning.spec.protocols import WorldSpec + from dimos.msgs.vision_msgs.Detection3D import Detection3D from dimos.perception.detection.type.detection3d.object import Object logger = setup_logger() @@ -366,7 +366,7 @@ def get_link_pose( link_name: Name of the link in the URDF joint_state: Joint state to use (uses current if None) """ - from dimos.msgs.geometry_msgs import Quaternion + from dimos.msgs.geometry_msgs.Quaternion import Quaternion with self._world.scratch_context() as ctx: if joint_state is None: diff --git a/dimos/manipulation/planning/monitor/world_obstacle_monitor.py b/dimos/manipulation/planning/monitor/world_obstacle_monitor.py index 4f69afad68..a21ee68726 100644 --- a/dimos/manipulation/planning/monitor/world_obstacle_monitor.py +++ b/dimos/manipulation/planning/monitor/world_obstacle_monitor.py @@ -29,20 +29,17 @@ import time from typing import TYPE_CHECKING, Any -from dimos.manipulation.planning.spec import ( - CollisionObjectMessage, - Obstacle, - ObstacleType, -) -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.manipulation.planning.spec.enums import ObstacleType +from dimos.manipulation.planning.spec.models import CollisionObjectMessage, Obstacle +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: from collections.abc import Callable import threading - from dimos.manipulation.planning.spec import WorldSpec - from dimos.msgs.vision_msgs import Detection3D + from dimos.manipulation.planning.spec.protocols import WorldSpec + from dimos.msgs.vision_msgs.Detection3D import Detection3D from dimos.perception.detection.type.detection3d.object import Object logger = setup_logger() diff --git a/dimos/manipulation/planning/monitor/world_state_monitor.py b/dimos/manipulation/planning/monitor/world_state_monitor.py index 87d61bb66f..8548251c73 100644 --- a/dimos/manipulation/planning/monitor/world_state_monitor.py +++ b/dimos/manipulation/planning/monitor/world_state_monitor.py @@ -31,7 +31,7 @@ import numpy as np -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: @@ -40,7 +40,7 @@ from numpy.typing import NDArray - from dimos.manipulation.planning.spec import WorldSpec + from dimos.manipulation.planning.spec.protocols import WorldSpec logger = setup_logger() diff --git a/dimos/manipulation/planning/planners/__init__.py b/dimos/manipulation/planning/planners/__init__.py deleted file mode 100644 index 8fb8ae042b..0000000000 --- a/dimos/manipulation/planning/planners/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Motion Planners Module - -Contains motion planning implementations that use WorldSpec. - -All planners are backend-agnostic - they only use WorldSpec methods and -work with any physics backend (Drake, MuJoCo, PyBullet, etc.). - -## Implementations - -- RRTConnectPlanner: Bi-directional RRT-Connect planner (fast, reliable) - -## Usage - -Use factory functions to create planners: - -```python -from dimos.manipulation.planning.factory import create_planner - -planner = create_planner(name="rrt_connect") # Returns PlannerSpec -result = planner.plan_joint_path(world, robot_id, q_start, q_goal) -``` -""" - -from dimos.manipulation.planning.planners.rrt_planner import RRTConnectPlanner - -__all__ = ["RRTConnectPlanner"] diff --git a/dimos/manipulation/planning/planners/rrt_planner.py b/dimos/manipulation/planning/planners/rrt_planner.py index 71204488c4..7f308dce0c 100644 --- a/dimos/manipulation/planning/planners/rrt_planner.py +++ b/dimos/manipulation/planning/planners/rrt_planner.py @@ -26,15 +26,11 @@ import numpy as np -from dimos.manipulation.planning.spec import ( - JointPath, - PlanningResult, - PlanningStatus, - WorldRobotID, - WorldSpec, -) +from dimos.manipulation.planning.spec.enums import PlanningStatus +from dimos.manipulation.planning.spec.models import JointPath, PlanningResult, WorldRobotID +from dimos.manipulation.planning.spec.protocols import WorldSpec from dimos.manipulation.planning.utils.path_utils import compute_path_length -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: diff --git a/dimos/manipulation/planning/spec/__init__.py b/dimos/manipulation/planning/spec/__init__.py deleted file mode 100644 index a78fb6e5fd..0000000000 --- a/dimos/manipulation/planning/spec/__init__.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Manipulation Planning Specifications.""" - -from dimos.manipulation.planning.spec.config import RobotModelConfig -from dimos.manipulation.planning.spec.enums import IKStatus, ObstacleType, PlanningStatus -from dimos.manipulation.planning.spec.protocols import ( - KinematicsSpec, - PlannerSpec, - WorldSpec, -) -from dimos.manipulation.planning.spec.types import ( - CollisionObjectMessage, - IKResult, - Jacobian, - JointPath, - Obstacle, - PlanningResult, - RobotName, - WorldRobotID, -) - -__all__ = [ - "CollisionObjectMessage", - "IKResult", - "IKStatus", - "Jacobian", - "JointPath", - "KinematicsSpec", - "Obstacle", - "ObstacleType", - "PlannerSpec", - "PlanningResult", - "PlanningStatus", - "RobotModelConfig", - "RobotName", - "WorldRobotID", - "WorldSpec", -] diff --git a/dimos/manipulation/planning/spec/config.py b/dimos/manipulation/planning/spec/config.py index e379fc1eb5..80cf248f08 100644 --- a/dimos/manipulation/planning/spec/config.py +++ b/dimos/manipulation/planning/spec/config.py @@ -22,7 +22,7 @@ from pydantic import Field from dimos.core.module import ModuleConfig -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped class RobotModelConfig(ModuleConfig): diff --git a/dimos/manipulation/planning/spec/types.py b/dimos/manipulation/planning/spec/models.py similarity index 97% rename from dimos/manipulation/planning/spec/types.py rename to dimos/manipulation/planning/spec/models.py index 2683db7814..37daa331e4 100644 --- a/dimos/manipulation/planning/spec/types.py +++ b/dimos/manipulation/planning/spec/models.py @@ -29,8 +29,8 @@ import numpy as np from numpy.typing import NDArray - from dimos.msgs.geometry_msgs import PoseStamped - from dimos.msgs.sensor_msgs import JointState + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped + from dimos.msgs.sensor_msgs.JointState import JointState RobotName: TypeAlias = str diff --git a/dimos/manipulation/planning/spec/protocols.py b/dimos/manipulation/planning/spec/protocols.py index dea4718abb..76ecd1780b 100644 --- a/dimos/manipulation/planning/spec/protocols.py +++ b/dimos/manipulation/planning/spec/protocols.py @@ -29,15 +29,15 @@ from numpy.typing import NDArray from dimos.manipulation.planning.spec.config import RobotModelConfig - from dimos.manipulation.planning.spec.types import ( + from dimos.manipulation.planning.spec.models import ( IKResult, JointPath, Obstacle, PlanningResult, WorldRobotID, ) - from dimos.msgs.geometry_msgs import PoseStamped - from dimos.msgs.sensor_msgs import JointState + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped + from dimos.msgs.sensor_msgs.JointState import JointState @runtime_checkable diff --git a/dimos/manipulation/planning/trajectory_generator/__init__.py b/dimos/manipulation/planning/trajectory_generator/__init__.py deleted file mode 100644 index a7449cf45f..0000000000 --- a/dimos/manipulation/planning/trajectory_generator/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Trajectory Generator Module - -Generates time-parameterized trajectories from waypoints. -""" - -from dimos.manipulation.planning.trajectory_generator.joint_trajectory_generator import ( - JointTrajectoryGenerator, -) - -__all__ = ["JointTrajectoryGenerator"] diff --git a/dimos/manipulation/planning/trajectory_generator/joint_trajectory_generator.py b/dimos/manipulation/planning/trajectory_generator/joint_trajectory_generator.py index 6b732d133c..1ac6b74351 100644 --- a/dimos/manipulation/planning/trajectory_generator/joint_trajectory_generator.py +++ b/dimos/manipulation/planning/trajectory_generator/joint_trajectory_generator.py @@ -32,7 +32,8 @@ import math -from dimos.msgs.trajectory_msgs import JointTrajectory, TrajectoryPoint +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory +from dimos.msgs.trajectory_msgs.TrajectoryPoint import TrajectoryPoint class JointTrajectoryGenerator: diff --git a/dimos/manipulation/planning/trajectory_generator/spec.py b/dimos/manipulation/planning/trajectory_generator/spec.py index 5357679f28..0814f5dc0b 100644 --- a/dimos/manipulation/planning/trajectory_generator/spec.py +++ b/dimos/manipulation/planning/trajectory_generator/spec.py @@ -35,7 +35,7 @@ from typing import Protocol -from dimos.msgs.trajectory_msgs import JointTrajectory +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory class JointTrajectoryGeneratorSpec(Protocol): diff --git a/dimos/manipulation/planning/utils/__init__.py b/dimos/manipulation/planning/utils/__init__.py deleted file mode 100644 index 04ec1806b5..0000000000 --- a/dimos/manipulation/planning/utils/__init__.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Manipulation Planning Utilities - -Standalone utility functions for kinematics and path operations. -These are extracted from the old ABC base classes to enable composition over inheritance. - -## Modules - -- kinematics_utils: Jacobian operations, singularity detection, pose error computation -- path_utils: Path interpolation, simplification, length computation -""" - -from dimos.manipulation.planning.utils.kinematics_utils import ( - check_singularity, - compute_error_twist, - compute_pose_error, - damped_pseudoinverse, - get_manipulability, -) -from dimos.manipulation.planning.utils.path_utils import ( - compute_path_length, - interpolate_path, - interpolate_segment, -) - -__all__ = [ - # Kinematics utilities - "check_singularity", - "compute_error_twist", - # Path utilities - "compute_path_length", - "compute_pose_error", - "damped_pseudoinverse", - "get_manipulability", - "interpolate_path", - "interpolate_segment", -] diff --git a/dimos/manipulation/planning/utils/kinematics_utils.py b/dimos/manipulation/planning/utils/kinematics_utils.py index c9f3f95a3d..02e885f1ae 100644 --- a/dimos/manipulation/planning/utils/kinematics_utils.py +++ b/dimos/manipulation/planning/utils/kinematics_utils.py @@ -36,7 +36,7 @@ if TYPE_CHECKING: from numpy.typing import NDArray - from dimos.manipulation.planning.spec import Jacobian + from dimos.manipulation.planning.spec.models import Jacobian def damped_pseudoinverse( diff --git a/dimos/manipulation/planning/utils/path_utils.py b/dimos/manipulation/planning/utils/path_utils.py index fbf8af4032..dd5de1a0a4 100644 --- a/dimos/manipulation/planning/utils/path_utils.py +++ b/dimos/manipulation/planning/utils/path_utils.py @@ -32,12 +32,13 @@ import numpy as np -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.sensor_msgs.JointState import JointState if TYPE_CHECKING: from numpy.typing import NDArray - from dimos.manipulation.planning.spec import JointPath, WorldRobotID, WorldSpec + from dimos.manipulation.planning.spec.models import JointPath, WorldRobotID + from dimos.manipulation.planning.spec.protocols import WorldSpec def interpolate_path( diff --git a/dimos/manipulation/planning/world/__init__.py b/dimos/manipulation/planning/world/__init__.py deleted file mode 100644 index 8ddef7fdff..0000000000 --- a/dimos/manipulation/planning/world/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -World Module - -Contains world implementations that own the physics/collision backend. - -## Implementations - -- DrakeWorld: Uses Drake MultibodyPlant + SceneGraph -""" - -from dimos.manipulation.planning.world.drake_world import DrakeWorld - -__all__ = ["DrakeWorld"] diff --git a/dimos/manipulation/planning/world/drake_world.py b/dimos/manipulation/planning/world/drake_world.py index 147e1e3ad3..ce155253ca 100644 --- a/dimos/manipulation/planning/world/drake_world.py +++ b/dimos/manipulation/planning/world/drake_world.py @@ -25,14 +25,10 @@ import numpy as np -from dimos.manipulation.planning.spec import ( - JointPath, - Obstacle, - ObstacleType, - RobotModelConfig, - WorldRobotID, - WorldSpec, -) +from dimos.manipulation.planning.spec.config import RobotModelConfig +from dimos.manipulation.planning.spec.enums import ObstacleType +from dimos.manipulation.planning.spec.models import JointPath, Obstacle, WorldRobotID +from dimos.manipulation.planning.spec.protocols import WorldSpec from dimos.manipulation.planning.utils.mesh_utils import prepare_urdf_for_drake from dimos.utils.logging_config import setup_logger @@ -41,8 +37,9 @@ from numpy.typing import NDArray -from dimos.msgs.geometry_msgs import PoseStamped, Transform -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.sensor_msgs.JointState import JointState try: from pydrake.geometry import ( # type: ignore[import-not-found] diff --git a/dimos/manipulation/test_manipulation_module.py b/dimos/manipulation/test_manipulation_module.py index c30ba9b55c..46a196e28c 100644 --- a/dimos/manipulation/test_manipulation_module.py +++ b/dimos/manipulation/test_manipulation_module.py @@ -30,9 +30,12 @@ ManipulationModule, ManipulationState, ) -from dimos.manipulation.planning.spec import RobotModelConfig -from dimos.msgs.geometry_msgs import Pose, PoseStamped, Quaternion, Vector3 -from dimos.msgs.sensor_msgs import JointState +from dimos.manipulation.planning.spec.config import RobotModelConfig +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.utils.data import get_data diff --git a/dimos/manipulation/test_manipulation_unit.py b/dimos/manipulation/test_manipulation_unit.py index cfd6e35fda..67ca8332b4 100644 --- a/dimos/manipulation/test_manipulation_unit.py +++ b/dimos/manipulation/test_manipulation_unit.py @@ -26,9 +26,12 @@ ManipulationModule, ManipulationState, ) -from dimos.manipulation.planning.spec import RobotModelConfig -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 -from dimos.msgs.trajectory_msgs import JointTrajectory, TrajectoryPoint +from dimos.manipulation.planning.spec.config import RobotModelConfig +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory +from dimos.msgs.trajectory_msgs.TrajectoryPoint import TrajectoryPoint @pytest.fixture diff --git a/dimos/mapping/__init__.py b/dimos/mapping/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/mapping/costmapper.py b/dimos/mapping/costmapper.py index 75b674b2a0..06bf493564 100644 --- a/dimos/mapping/costmapper.py +++ b/dimos/mapping/costmapper.py @@ -26,8 +26,8 @@ HeightCostConfig, OccupancyConfig, ) -from dimos.msgs.nav_msgs import OccupancyGrid -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/mapping/google_maps/google_maps.py b/dimos/mapping/google_maps/google_maps.py index 7f5ce32e99..18a1e25e2b 100644 --- a/dimos/mapping/google_maps/google_maps.py +++ b/dimos/mapping/google_maps/google_maps.py @@ -16,14 +16,14 @@ import googlemaps # type: ignore[import-untyped] -from dimos.mapping.google_maps.types import ( +from dimos.mapping.google_maps.models import ( Coordinates, LocationContext, NearbyPlace, PlacePosition, Position, ) -from dimos.mapping.types import LatLon +from dimos.mapping.models import LatLon from dimos.mapping.utils.distance import distance_in_meters from dimos.utils.logging_config import setup_logger diff --git a/dimos/mapping/google_maps/types.py b/dimos/mapping/google_maps/models.py similarity index 100% rename from dimos/mapping/google_maps/types.py rename to dimos/mapping/google_maps/models.py diff --git a/dimos/mapping/google_maps/test_google_maps.py b/dimos/mapping/google_maps/test_google_maps.py index 13f7fa8eaa..2805f5589c 100644 --- a/dimos/mapping/google_maps/test_google_maps.py +++ b/dimos/mapping/google_maps/test_google_maps.py @@ -13,7 +13,7 @@ # limitations under the License. -from dimos.mapping.types import LatLon +from dimos.mapping.models import LatLon def test_get_position(maps_client, maps_fixture) -> None: diff --git a/dimos/mapping/types.py b/dimos/mapping/models.py similarity index 100% rename from dimos/mapping/types.py rename to dimos/mapping/models.py diff --git a/dimos/mapping/occupancy/path_mask.py b/dimos/mapping/occupancy/path_mask.py index 5ad3010111..7744ab95ba 100644 --- a/dimos/mapping/occupancy/path_mask.py +++ b/dimos/mapping/occupancy/path_mask.py @@ -16,8 +16,8 @@ import numpy as np from numpy.typing import NDArray -from dimos.msgs.nav_msgs import Path from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid +from dimos.msgs.nav_msgs.Path import Path def make_path_mask( diff --git a/dimos/mapping/occupancy/path_resampling.py b/dimos/mapping/occupancy/path_resampling.py index 2090bf8f04..4d957a1aad 100644 --- a/dimos/mapping/occupancy/path_resampling.py +++ b/dimos/mapping/occupancy/path_resampling.py @@ -18,8 +18,11 @@ import numpy as np from scipy.ndimage import uniform_filter1d # type: ignore[import-untyped] -from dimos.msgs.geometry_msgs import Pose, PoseStamped, Quaternion, Vector3 -from dimos.msgs.nav_msgs import Path +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.nav_msgs.Path import Path from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import euler_to_quaternion diff --git a/dimos/mapping/occupancy/test_path_mask.py b/dimos/mapping/occupancy/test_path_mask.py index dede997946..f566af2a23 100644 --- a/dimos/mapping/occupancy/test_path_mask.py +++ b/dimos/mapping/occupancy/test_path_mask.py @@ -19,9 +19,9 @@ from dimos.mapping.occupancy.path_mask import make_path_mask from dimos.mapping.occupancy.path_resampling import smooth_resample_path from dimos.mapping.occupancy.visualizations import visualize_occupancy_grid -from dimos.msgs.geometry_msgs import Pose +from dimos.msgs.geometry_msgs.Pose import Pose from dimos.msgs.geometry_msgs.Vector3 import Vector3 -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.navigation.replanning_a_star.min_cost_astar import min_cost_astar from dimos.utils.data import get_data diff --git a/dimos/mapping/occupancy/test_path_resampling.py b/dimos/mapping/occupancy/test_path_resampling.py index c23f71cf89..aeda7d11ad 100644 --- a/dimos/mapping/occupancy/test_path_resampling.py +++ b/dimos/mapping/occupancy/test_path_resampling.py @@ -18,7 +18,7 @@ from dimos.mapping.occupancy.gradient import gradient from dimos.mapping.occupancy.path_resampling import simple_resample_path, smooth_resample_path from dimos.mapping.occupancy.visualize_path import visualize_path -from dimos.msgs.geometry_msgs import Pose +from dimos.msgs.geometry_msgs.Pose import Pose from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid from dimos.msgs.sensor_msgs.Image import Image diff --git a/dimos/mapping/occupancy/visualizations.py b/dimos/mapping/occupancy/visualizations.py index 2ed0364257..36321896be 100644 --- a/dimos/mapping/occupancy/visualizations.py +++ b/dimos/mapping/occupancy/visualizations.py @@ -19,8 +19,8 @@ import numpy as np from numpy.typing import NDArray -from dimos.msgs.nav_msgs import Path from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.nav_msgs.Path import Path from dimos.msgs.sensor_msgs.Image import Image, ImageFormat Palette: TypeAlias = Literal["rainbow", "turbo"] diff --git a/dimos/mapping/occupancy/visualize_path.py b/dimos/mapping/occupancy/visualize_path.py index 0662582f72..89dcf83067 100644 --- a/dimos/mapping/occupancy/visualize_path.py +++ b/dimos/mapping/occupancy/visualize_path.py @@ -16,8 +16,8 @@ import numpy as np from dimos.mapping.occupancy.visualizations import visualize_occupancy_grid -from dimos.msgs.nav_msgs import Path from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.nav_msgs.Path import Path from dimos.msgs.sensor_msgs.Image import Image, ImageFormat diff --git a/dimos/mapping/osm/__init__.py b/dimos/mapping/osm/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/mapping/osm/current_location_map.py b/dimos/mapping/osm/current_location_map.py index 832116e25c..4cfeddc9b8 100644 --- a/dimos/mapping/osm/current_location_map.py +++ b/dimos/mapping/osm/current_location_map.py @@ -16,9 +16,9 @@ from PIL import Image as PILImage, ImageDraw +from dimos.mapping.models import LatLon from dimos.mapping.osm.osm import MapImage, get_osm_map from dimos.mapping.osm.query import query_for_one_position, query_for_one_position_and_context -from dimos.mapping.types import LatLon from dimos.models.vl.base import VlModel from dimos.utils.logging_config import setup_logger diff --git a/dimos/mapping/osm/osm.py b/dimos/mapping/osm/osm.py index 31fb044087..f9b7eaafda 100644 --- a/dimos/mapping/osm/osm.py +++ b/dimos/mapping/osm/osm.py @@ -21,8 +21,8 @@ from PIL import Image as PILImage import requests # type: ignore[import-untyped] -from dimos.mapping.types import ImageCoord, LatLon -from dimos.msgs.sensor_msgs import Image, ImageFormat +from dimos.mapping.models import ImageCoord, LatLon +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat @dataclass(frozen=True) diff --git a/dimos/mapping/osm/query.py b/dimos/mapping/osm/query.py index 17fbfe3d4b..7a3c3b0154 100644 --- a/dimos/mapping/osm/query.py +++ b/dimos/mapping/osm/query.py @@ -15,8 +15,8 @@ import re from typing import Any +from dimos.mapping.models import LatLon from dimos.mapping.osm.osm import MapImage -from dimos.mapping.types import LatLon from dimos.models.vl.base import VlModel from dimos.utils.generic import extract_json_from_llm_response from dimos.utils.logging_config import setup_logger diff --git a/dimos/mapping/osm/test_osm.py b/dimos/mapping/osm/test_osm.py index 475e2b40fc..64fbb72b02 100644 --- a/dimos/mapping/osm/test_osm.py +++ b/dimos/mapping/osm/test_osm.py @@ -21,8 +21,8 @@ from requests import Request import requests_mock +from dimos.mapping.models import LatLon from dimos.mapping.osm.osm import get_osm_map -from dimos.mapping.types import LatLon from dimos.utils.data import get_data _fixture_dir = get_data("osm_map_test") diff --git a/dimos/mapping/pointclouds/demo.py b/dimos/mapping/pointclouds/demo.py index 5251fc3406..2812aaae42 100644 --- a/dimos/mapping/pointclouds/demo.py +++ b/dimos/mapping/pointclouds/demo.py @@ -25,8 +25,8 @@ read_pointcloud, visualize, ) -from dimos.msgs.nav_msgs import OccupancyGrid -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.utils.data import get_data app = typer.Typer() diff --git a/dimos/mapping/pointclouds/occupancy.py b/dimos/mapping/pointclouds/occupancy.py index 0f6ad8c0de..c9cd7e7af3 100644 --- a/dimos/mapping/pointclouds/occupancy.py +++ b/dimos/mapping/pointclouds/occupancy.py @@ -21,7 +21,7 @@ import numpy as np from scipy import ndimage # type: ignore[import-untyped] -from dimos.msgs.geometry_msgs import Pose +from dimos.msgs.geometry_msgs.Pose import Pose from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid if TYPE_CHECKING: @@ -99,7 +99,7 @@ def _simple_occupancy_kernel( if TYPE_CHECKING: from collections.abc import Callable - from dimos.msgs.sensor_msgs import PointCloud2 + from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 @dataclass(frozen=True) diff --git a/dimos/mapping/pointclouds/test_occupancy.py b/dimos/mapping/pointclouds/test_occupancy.py index d265800f24..93b5793dc8 100644 --- a/dimos/mapping/pointclouds/test_occupancy.py +++ b/dimos/mapping/pointclouds/test_occupancy.py @@ -26,8 +26,8 @@ ) from dimos.mapping.pointclouds.util import read_pointcloud from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid -from dimos.msgs.sensor_msgs import PointCloud2 from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.utils.data import get_data from dimos.utils.testing.moment import OutputMoment from dimos.utils.testing.test_moment import Go2Moment diff --git a/dimos/mapping/pointclouds/test_occupancy_speed.py b/dimos/mapping/pointclouds/test_occupancy_speed.py index 2def839dd5..ac4085e971 100644 --- a/dimos/mapping/pointclouds/test_occupancy_speed.py +++ b/dimos/mapping/pointclouds/test_occupancy_speed.py @@ -21,7 +21,7 @@ from dimos.mapping.voxels import VoxelGridMapper from dimos.utils.cli.plot import bar from dimos.utils.data import get_data, get_data_dir -from dimos.utils.testing import TimedSensorReplay +from dimos.utils.testing.replay import TimedSensorReplay @pytest.mark.tool diff --git a/dimos/mapping/test_voxels.py b/dimos/mapping/test_voxels.py index 95e70e1d6d..bb5f4ed764 100644 --- a/dimos/mapping/test_voxels.py +++ b/dimos/mapping/test_voxels.py @@ -20,7 +20,7 @@ from dimos.core.transport import LCMTransport from dimos.mapping.voxels import VoxelGridMapper -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.utils.data import get_data from dimos.utils.testing.moment import OutputMoment from dimos.utils.testing.replay import TimedSensorReplay diff --git a/dimos/mapping/utils/distance.py b/dimos/mapping/utils/distance.py index 6e8c48c205..42b8a9be04 100644 --- a/dimos/mapping/utils/distance.py +++ b/dimos/mapping/utils/distance.py @@ -14,7 +14,7 @@ import math -from dimos.mapping.types import LatLon +from dimos.mapping.models import LatLon def distance_in_meters(location1: LatLon, location2: LatLon) -> float: diff --git a/dimos/mapping/voxels.py b/dimos/mapping/voxels.py index c2078dc309..e4e03dfc01 100644 --- a/dimos/mapping/voxels.py +++ b/dimos/mapping/voxels.py @@ -25,8 +25,8 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.sensor_msgs import PointCloud2 -from dimos.utils.decorators import simple_mcache +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.utils.decorators.decorators import simple_mcache from dimos.utils.logging_config import setup_logger from dimos.utils.reactive import backpressure diff --git a/dimos/memory/embedding.py b/dimos/memory/embedding.py index e09e069f05..be73d01ac1 100644 --- a/dimos/memory/embedding.py +++ b/dimos/memory/embedding.py @@ -26,9 +26,8 @@ from dimos.core.stream import In from dimos.models.embedding.base import Embedding, EmbeddingModel from dimos.models.embedding.clip import CLIPModel -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.nav_msgs import OccupancyGrid -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid from dimos.msgs.sensor_msgs.Image import Image, sharpness_barrier from dimos.utils.reactive import getter_hot diff --git a/dimos/memory/test_embedding.py b/dimos/memory/test_embedding.py index b7e7fbb294..9a59ed51e1 100644 --- a/dimos/memory/test_embedding.py +++ b/dimos/memory/test_embedding.py @@ -15,9 +15,9 @@ import pytest from dimos.memory.embedding import EmbeddingMemory, SpatialEntry -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped from dimos.utils.data import get_data -from dimos.utils.testing import TimedSensorReplay +from dimos.utils.testing.replay import TimedSensorReplay dir_name = "unitree_go2_bigoffice" diff --git a/dimos/memory/timeseries/__init__.py b/dimos/memory/timeseries/__init__.py deleted file mode 100644 index debc14ab3a..0000000000 --- a/dimos/memory/timeseries/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Time series storage and replay.""" - -from dimos.memory.timeseries.base import TimeSeriesStore -from dimos.memory.timeseries.inmemory import InMemoryStore -from dimos.memory.timeseries.pickledir import PickleDirStore -from dimos.memory.timeseries.sqlite import SqliteStore - - -def __getattr__(name: str): # type: ignore[no-untyped-def] - if name == "PostgresStore": - from dimos.memory.timeseries.postgres import PostgresStore - - return PostgresStore - if name == "reset_db": - from dimos.memory.timeseries.postgres import reset_db - - return reset_db - raise AttributeError(f"module {__name__!r} has no attribute {name!r}") - - -__all__ = [ - "InMemoryStore", - "PickleDirStore", - "PostgresStore", - "SqliteStore", - "TimeSeriesStore", - "reset_db", -] diff --git a/dimos/models/__init__.py b/dimos/models/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/models/base.py b/dimos/models/base.py index d03ce5c539..fd18d8ba93 100644 --- a/dimos/models/base.py +++ b/dimos/models/base.py @@ -22,7 +22,7 @@ import torch from dimos.core.resource import Resource -from dimos.protocol.service import BaseConfig, Configurable +from dimos.protocol.service.spec import BaseConfig, Configurable # Device string type - 'cuda', 'cpu', 'cuda:0', 'cuda:1', etc. DeviceType = Annotated[str, "Device identifier (e.g., 'cuda', 'cpu', 'cuda:0')"] diff --git a/dimos/models/embedding/__init__.py b/dimos/models/embedding/__init__.py deleted file mode 100644 index 050d35467e..0000000000 --- a/dimos/models/embedding/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -from dimos.models.embedding.base import Embedding, EmbeddingModel - -__all__ = [ - "Embedding", - "EmbeddingModel", -] - -# Optional: CLIP support -try: - from dimos.models.embedding.clip import CLIPModel - - __all__.append("CLIPModel") -except ImportError: - pass - -# Optional: MobileCLIP support -try: - from dimos.models.embedding.mobileclip import MobileCLIPModel - - __all__.append("MobileCLIPModel") -except ImportError: - pass - -# Optional: TorchReID support -try: - from dimos.models.embedding.treid import TorchReIDModel - - __all__.append("TorchReIDModel") -except ImportError: - pass diff --git a/dimos/models/embedding/base.py b/dimos/models/embedding/base.py index 520818aabf..0c80cafc0a 100644 --- a/dimos/models/embedding/base.py +++ b/dimos/models/embedding/base.py @@ -25,7 +25,7 @@ from dimos.types.timestamped import Timestamped if TYPE_CHECKING: - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image class EmbeddingModelConfig(LocalModelConfig): diff --git a/dimos/models/embedding/clip.py b/dimos/models/embedding/clip.py index e3a61e9570..6fb42b7ccf 100644 --- a/dimos/models/embedding/clip.py +++ b/dimos/models/embedding/clip.py @@ -21,7 +21,7 @@ from dimos.models.base import HuggingFaceModel from dimos.models.embedding.base import Embedding, EmbeddingModel, HuggingFaceEmbeddingModelConfig -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image class CLIPModelConfig(HuggingFaceEmbeddingModelConfig): diff --git a/dimos/models/embedding/mobileclip.py b/dimos/models/embedding/mobileclip.py index 8ad37936be..84bba74829 100644 --- a/dimos/models/embedding/mobileclip.py +++ b/dimos/models/embedding/mobileclip.py @@ -22,7 +22,7 @@ from dimos.models.base import LocalModel from dimos.models.embedding.base import Embedding, EmbeddingModel, EmbeddingModelConfig -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.data import get_data diff --git a/dimos/models/embedding/test_embedding.py b/dimos/models/embedding/test_embedding.py index 466c974b32..20aac83dbb 100644 --- a/dimos/models/embedding/test_embedding.py +++ b/dimos/models/embedding/test_embedding.py @@ -7,7 +7,7 @@ from dimos.models.embedding.clip import CLIPModel from dimos.models.embedding.mobileclip import MobileCLIPModel from dimos.models.embedding.treid import TorchReIDModel -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.data import get_data diff --git a/dimos/models/embedding/treid.py b/dimos/models/embedding/treid.py index 69cc1aae13..21a4527781 100644 --- a/dimos/models/embedding/treid.py +++ b/dimos/models/embedding/treid.py @@ -24,7 +24,7 @@ from dimos.models.base import LocalModel from dimos.models.embedding.base import Embedding, EmbeddingModel, EmbeddingModelConfig -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.data import get_data diff --git a/dimos/models/segmentation/edge_tam.py b/dimos/models/segmentation/edge_tam.py index 54158b2b92..e9744f6d81 100644 --- a/dimos/models/segmentation/edge_tam.py +++ b/dimos/models/segmentation/edge_tam.py @@ -28,9 +28,9 @@ from PIL import Image as PILImage import torch -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.detectors.types import Detector -from dimos.perception.detection.type import ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.detectors.base import Detector +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D from dimos.perception.detection.type.detection2d.seg import Detection2DSeg from dimos.utils.data import get_data from dimos.utils.logging_config import setup_logger diff --git a/dimos/models/vl/__init__.py b/dimos/models/vl/__init__.py deleted file mode 100644 index 482a907cbd..0000000000 --- a/dimos/models/vl/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "base": ["Captioner", "VlModel"], - "florence": ["Florence2Model"], - "moondream": ["MoondreamVlModel"], - "moondream_hosted": ["MoondreamHostedVlModel"], - "openai": ["OpenAIVlModel"], - "qwen": ["QwenVlModel"], - }, -) diff --git a/dimos/models/vl/base.py b/dimos/models/vl/base.py index 1cdeb3f92f..08b83fc503 100644 --- a/dimos/models/vl/base.py +++ b/dimos/models/vl/base.py @@ -8,11 +8,13 @@ import warnings from dimos.core.resource import Resource -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.type import Detection2DBBox, Detection2DPoint, ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D +from dimos.perception.detection.type.detection2d.point import Detection2DPoint from dimos.protocol.service.spec import BaseConfig, Configurable from dimos.utils.data import get_data -from dimos.utils.decorators import retry +from dimos.utils.decorators.decorators import retry from dimos.utils.llm_utils import extract_json if sys.version_info < (3, 13): @@ -73,7 +75,7 @@ def vlm_detection_to_detection2d( Detection2DBBox instance or None if invalid """ # Here to prevent unwanted imports in the file. - from dimos.perception.detection.type import Detection2DBBox + from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox # Validate list/tuple structure if not isinstance(vlm_detection, (list, tuple)): @@ -130,7 +132,7 @@ def vlm_point_to_detection2d_point( Returns: Detection2DPoint instance or None if invalid """ - from dimos.perception.detection.type import Detection2DPoint + from dimos.perception.detection.type.detection2d.point import Detection2DPoint # Validate list/tuple structure if not isinstance(vlm_point, (list, tuple)): @@ -260,7 +262,7 @@ def query_detections( self, image: Image, query: str, **kwargs: Any ) -> ImageDetections2D[Detection2DBBox]: # Here to prevent unwanted imports in the file. - from dimos.perception.detection.type import ImageDetections2D + from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D full_query = f"""show me bounding boxes in pixels for this query: `{query}` @@ -321,7 +323,7 @@ def query_points( ImageDetections2D containing Detection2DPoint instances """ # Here to prevent unwanted imports in the file. - from dimos.perception.detection.type import ImageDetections2D + from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D full_query = f"""Show me point coordinates in pixels for this query: `{query}` diff --git a/dimos/models/vl/florence.py b/dimos/models/vl/florence.py index 2e6cf822a8..b68441328a 100644 --- a/dimos/models/vl/florence.py +++ b/dimos/models/vl/florence.py @@ -20,7 +20,7 @@ from dimos.models.base import HuggingFaceModel from dimos.models.vl.base import Captioner -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image class Florence2Model(HuggingFaceModel, Captioner): diff --git a/dimos/models/vl/moondream.py b/dimos/models/vl/moondream.py index c444d8b9ed..0f5e501ef6 100644 --- a/dimos/models/vl/moondream.py +++ b/dimos/models/vl/moondream.py @@ -9,8 +9,10 @@ from dimos.models.base import HuggingFaceModel, HuggingFaceModelConfig from dimos.models.vl.base import VlModel, VlModelConfig -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.type import Detection2DBBox, Detection2DPoint, ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D +from dimos.perception.detection.type.detection2d.point import Detection2DPoint # Moondream works well with 512x512 max MOONDREAM_DEFAULT_AUTO_RESIZE = (512, 512) diff --git a/dimos/models/vl/moondream_hosted.py b/dimos/models/vl/moondream_hosted.py index 57df91b47e..aad9fe514c 100644 --- a/dimos/models/vl/moondream_hosted.py +++ b/dimos/models/vl/moondream_hosted.py @@ -7,8 +7,10 @@ from PIL import Image as PILImage from dimos.models.vl.base import VlModel, VlModelConfig -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.type import Detection2DBBox, Detection2DPoint, ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D +from dimos.perception.detection.type.detection2d.point import Detection2DPoint class Config(VlModelConfig): diff --git a/dimos/models/vl/openai.py b/dimos/models/vl/openai.py index ec774189e4..0486bbdb30 100644 --- a/dimos/models/vl/openai.py +++ b/dimos/models/vl/openai.py @@ -6,7 +6,7 @@ from openai import OpenAI from dimos.models.vl.base import VlModel, VlModelConfig -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/models/vl/qwen.py b/dimos/models/vl/qwen.py index 014c6f73a5..202ce6759e 100644 --- a/dimos/models/vl/qwen.py +++ b/dimos/models/vl/qwen.py @@ -6,7 +6,7 @@ from openai import OpenAI from dimos.models.vl.base import VlModel, VlModelConfig -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image class QwenVlModelConfig(VlModelConfig): diff --git a/dimos/models/vl/test_base.py b/dimos/models/vl/test_base.py index 0cc5c90d0e..b0b03e70fa 100644 --- a/dimos/models/vl/test_base.py +++ b/dimos/models/vl/test_base.py @@ -6,8 +6,8 @@ from dimos.core.transport import LCMTransport from dimos.models.vl.moondream import MoondreamVlModel from dimos.models.vl.qwen import QwenVlModel -from dimos.msgs.sensor_msgs import Image, ImageFormat -from dimos.perception.detection.type import ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D from dimos.utils.data import get_data # Captured actual response from Qwen API for cafe.jpg with query "humans" diff --git a/dimos/models/vl/test_captioner.py b/dimos/models/vl/test_captioner.py index c7ebb8fc63..734c83290e 100644 --- a/dimos/models/vl/test_captioner.py +++ b/dimos/models/vl/test_captioner.py @@ -6,7 +6,7 @@ from dimos.models.vl.florence import Florence2Model from dimos.models.vl.moondream import MoondreamVlModel -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.data import get_data diff --git a/dimos/models/vl/test_vlm.py b/dimos/models/vl/test_vlm.py index 43dad0ef94..f0fd3b8d5a 100644 --- a/dimos/models/vl/test_vlm.py +++ b/dimos/models/vl/test_vlm.py @@ -11,8 +11,8 @@ from dimos.models.vl.moondream import MoondreamVlModel from dimos.models.vl.moondream_hosted import MoondreamHostedVlModel from dimos.models.vl.qwen import QwenVlModel -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.type import ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D from dimos.utils.cli.plot import bar from dimos.utils.data import get_data @@ -228,7 +228,7 @@ def test_vlm_query_multi(model_class: "type[VlModel]", model_name: str) -> None: @pytest.mark.slow def test_vlm_query_batch(model_class: "type[VlModel]", model_name: str) -> None: """Test query_batch optimization - multiple images, same query.""" - from dimos.utils.testing import TimedSensorReplay + from dimos.utils.testing.replay import TimedSensorReplay # Load 5 frames at 1-second intervals using TimedSensorReplay replay = TimedSensorReplay[Image]("unitree_go2_office_walk2/video") @@ -285,7 +285,7 @@ def test_vlm_resize( sizes: list[tuple[int, int] | None], ) -> None: """Test VLM auto_resize effect on performance.""" - from dimos.utils.testing import TimedSensorReplay + from dimos.utils.testing.replay import TimedSensorReplay replay = TimedSensorReplay[Image]("unitree_go2_office_walk2/video") image = replay.find_closest_seek(0).to_rgb() diff --git a/dimos/msgs/__init__.py b/dimos/msgs/__init__.py deleted file mode 100644 index 4395dbcc51..0000000000 --- a/dimos/msgs/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from dimos.msgs.helpers import resolve_msg_type -from dimos.msgs.protocol import DimosMsg - -__all__ = ["DimosMsg", "resolve_msg_type"] diff --git a/dimos/msgs/foxglove_msgs/__init__.py b/dimos/msgs/foxglove_msgs/__init__.py deleted file mode 100644 index 945ebf94c9..0000000000 --- a/dimos/msgs/foxglove_msgs/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from dimos.msgs.foxglove_msgs.ImageAnnotations import ImageAnnotations - -__all__ = ["ImageAnnotations"] diff --git a/dimos/msgs/geometry_msgs/Transform.py b/dimos/msgs/geometry_msgs/Transform.py index 5f50f9b9d1..9b08c8dadd 100644 --- a/dimos/msgs/geometry_msgs/Transform.py +++ b/dimos/msgs/geometry_msgs/Transform.py @@ -29,7 +29,7 @@ from dimos.msgs.geometry_msgs.Quaternion import Quaternion from dimos.msgs.geometry_msgs.Vector3 import Vector3 -from dimos.msgs.std_msgs import Header +from dimos.msgs.std_msgs.Header import Header from dimos.types.timestamped import Timestamped diff --git a/dimos/msgs/geometry_msgs/__init__.py b/dimos/msgs/geometry_msgs/__init__.py deleted file mode 100644 index 01069d765c..0000000000 --- a/dimos/msgs/geometry_msgs/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -from dimos.msgs.geometry_msgs.Point import Point -from dimos.msgs.geometry_msgs.PointStamped import PointStamped -from dimos.msgs.geometry_msgs.Pose import Pose, PoseLike, to_pose -from dimos.msgs.geometry_msgs.PoseArray import PoseArray -from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped -from dimos.msgs.geometry_msgs.PoseWithCovariance import PoseWithCovariance -from dimos.msgs.geometry_msgs.PoseWithCovarianceStamped import PoseWithCovarianceStamped -from dimos.msgs.geometry_msgs.Quaternion import Quaternion -from dimos.msgs.geometry_msgs.Transform import Transform -from dimos.msgs.geometry_msgs.Twist import Twist -from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped -from dimos.msgs.geometry_msgs.TwistWithCovariance import TwistWithCovariance -from dimos.msgs.geometry_msgs.TwistWithCovarianceStamped import TwistWithCovarianceStamped -from dimos.msgs.geometry_msgs.Vector3 import Vector3, VectorLike -from dimos.msgs.geometry_msgs.Wrench import Wrench -from dimos.msgs.geometry_msgs.WrenchStamped import WrenchStamped - -__all__ = [ - "Point", - "PointStamped", - "Pose", - "PoseArray", - "PoseLike", - "PoseStamped", - "PoseWithCovariance", - "PoseWithCovarianceStamped", - "Quaternion", - "Transform", - "Twist", - "TwistStamped", - "TwistWithCovariance", - "TwistWithCovarianceStamped", - "Vector3", - "VectorLike", - "Wrench", - "WrenchStamped", - "to_pose", -] diff --git a/dimos/msgs/geometry_msgs/test_PoseStamped.py b/dimos/msgs/geometry_msgs/test_PoseStamped.py index 82250a9113..a486f33303 100644 --- a/dimos/msgs/geometry_msgs/test_PoseStamped.py +++ b/dimos/msgs/geometry_msgs/test_PoseStamped.py @@ -15,7 +15,7 @@ import pickle import time -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped def test_lcm_encode_decode() -> None: diff --git a/dimos/msgs/geometry_msgs/test_Transform.py b/dimos/msgs/geometry_msgs/test_Transform.py index 0c15610b05..056238719a 100644 --- a/dimos/msgs/geometry_msgs/test_Transform.py +++ b/dimos/msgs/geometry_msgs/test_Transform.py @@ -18,7 +18,11 @@ import numpy as np import pytest -from dimos.msgs.geometry_msgs import Pose, PoseStamped, Quaternion, Transform, Vector3 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 def test_transform_initialization() -> None: diff --git a/dimos/msgs/geometry_msgs/test_Twist.py b/dimos/msgs/geometry_msgs/test_Twist.py index df4bd8b6a2..a4dc93f3cc 100644 --- a/dimos/msgs/geometry_msgs/test_Twist.py +++ b/dimos/msgs/geometry_msgs/test_Twist.py @@ -15,7 +15,9 @@ from dimos_lcm.geometry_msgs import Twist as LCMTwist import numpy as np -from dimos.msgs.geometry_msgs import Quaternion, Twist, Vector3 +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 def test_twist_initialization() -> None: diff --git a/dimos/msgs/geometry_msgs/test_publish.py b/dimos/msgs/geometry_msgs/test_publish.py index b3d2324af0..01c5cf7842 100644 --- a/dimos/msgs/geometry_msgs/test_publish.py +++ b/dimos/msgs/geometry_msgs/test_publish.py @@ -17,7 +17,7 @@ import lcm import pytest -from dimos.msgs.geometry_msgs import Vector3 +from dimos.msgs.geometry_msgs.Vector3 import Vector3 @pytest.mark.tool diff --git a/dimos/msgs/helpers.py b/dimos/msgs/helpers.py index 8464ec4ab1..91466f7fdd 100644 --- a/dimos/msgs/helpers.py +++ b/dimos/msgs/helpers.py @@ -19,7 +19,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from dimos.msgs import DimosMsg + from dimos.msgs.protocol import DimosMsg @lru_cache(maxsize=256) @@ -38,7 +38,10 @@ def resolve_msg_type(type_name: str) -> type[DimosMsg] | None: return None # Try different import paths + # First try the direct submodule path (e.g., dimos.msgs.geometry_msgs.Quaternion) + # then fall back to parent package (for dimos_lcm or other packages) import_paths = [ + f"dimos.msgs.{module_name}.{class_name}", f"dimos.msgs.{module_name}", f"dimos_lcm.{module_name}", ] diff --git a/dimos/msgs/nav_msgs/OccupancyGrid.py b/dimos/msgs/nav_msgs/OccupancyGrid.py index d45e1b6232..4760884620 100644 --- a/dimos/msgs/nav_msgs/OccupancyGrid.py +++ b/dimos/msgs/nav_msgs/OccupancyGrid.py @@ -28,7 +28,8 @@ import numpy as np from PIL import Image -from dimos.msgs.geometry_msgs import Pose, Vector3, VectorLike +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Vector3 import Vector3, VectorLike from dimos.types.timestamped import Timestamped diff --git a/dimos/msgs/nav_msgs/__init__.py b/dimos/msgs/nav_msgs/__init__.py deleted file mode 100644 index 9d099068ad..0000000000 --- a/dimos/msgs/nav_msgs/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from dimos.msgs.nav_msgs.OccupancyGrid import ( # type: ignore[attr-defined] - CostValues, - MapMetaData, - OccupancyGrid, -) -from dimos.msgs.nav_msgs.Odometry import Odometry -from dimos.msgs.nav_msgs.Path import Path - -__all__ = ["CostValues", "MapMetaData", "OccupancyGrid", "Odometry", "Path"] diff --git a/dimos/msgs/nav_msgs/test_OccupancyGrid.py b/dimos/msgs/nav_msgs/test_OccupancyGrid.py index d1ec8938b4..7aae8abfac 100644 --- a/dimos/msgs/nav_msgs/test_OccupancyGrid.py +++ b/dimos/msgs/nav_msgs/test_OccupancyGrid.py @@ -23,9 +23,9 @@ from dimos.mapping.occupancy.gradient import gradient from dimos.mapping.occupancy.inflation import simple_inflate from dimos.mapping.pointclouds.occupancy import general_occupancy -from dimos.msgs.geometry_msgs import Pose -from dimos.msgs.nav_msgs import OccupancyGrid -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.utils.data import get_data diff --git a/dimos/msgs/sensor_msgs/Imu.py b/dimos/msgs/sensor_msgs/Imu.py index 7fe03ce03f..f3461975ff 100644 --- a/dimos/msgs/sensor_msgs/Imu.py +++ b/dimos/msgs/sensor_msgs/Imu.py @@ -18,7 +18,8 @@ from dimos_lcm.sensor_msgs.Imu import Imu as LCMImu -from dimos.msgs.geometry_msgs import Quaternion, Vector3 +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.types.timestamped import Timestamped diff --git a/dimos/msgs/sensor_msgs/PointCloud2.py b/dimos/msgs/sensor_msgs/PointCloud2.py index 22fe731a70..67af1c5ac3 100644 --- a/dimos/msgs/sensor_msgs/PointCloud2.py +++ b/dimos/msgs/sensor_msgs/PointCloud2.py @@ -28,7 +28,8 @@ import open3d as o3d # type: ignore[import-untyped] import open3d.core as o3c # type: ignore[import-untyped] -from dimos.msgs.geometry_msgs import Transform, Vector3 +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.types.timestamped import Timestamped if TYPE_CHECKING: diff --git a/dimos/msgs/sensor_msgs/__init__.py b/dimos/msgs/sensor_msgs/__init__.py deleted file mode 100644 index 7fec2d2793..0000000000 --- a/dimos/msgs/sensor_msgs/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo -from dimos.msgs.sensor_msgs.Image import Image, ImageFormat -from dimos.msgs.sensor_msgs.Imu import Imu -from dimos.msgs.sensor_msgs.JointCommand import JointCommand -from dimos.msgs.sensor_msgs.JointState import JointState -from dimos.msgs.sensor_msgs.Joy import Joy -from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 -from dimos.msgs.sensor_msgs.RobotState import RobotState - -__all__ = [ - "CameraInfo", - "Image", - "ImageFormat", - "Imu", - "JointCommand", - "JointState", - "Joy", - "PointCloud2", - "RobotState", -] diff --git a/dimos/msgs/sensor_msgs/test_PointCloud2.py b/dimos/msgs/sensor_msgs/test_PointCloud2.py index f48802ab7a..70e6e35aec 100644 --- a/dimos/msgs/sensor_msgs/test_PointCloud2.py +++ b/dimos/msgs/sensor_msgs/test_PointCloud2.py @@ -16,9 +16,9 @@ import numpy as np -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.lidar import pointcloud2_from_webrtc_lidar -from dimos.utils.testing import SensorReplay +from dimos.utils.testing.replay import SensorReplay def test_lcm_encode_decode() -> None: diff --git a/dimos/msgs/sensor_msgs/test_image.py b/dimos/msgs/sensor_msgs/test_image.py index 24375139b3..cc2fc9f096 100644 --- a/dimos/msgs/sensor_msgs/test_image.py +++ b/dimos/msgs/sensor_msgs/test_image.py @@ -18,7 +18,7 @@ from dimos.msgs.sensor_msgs.Image import Image, ImageFormat, sharpness_barrier from dimos.utils.data import get_data -from dimos.utils.testing import TimedSensorReplay +from dimos.utils.testing.replay import TimedSensorReplay @pytest.fixture diff --git a/dimos/msgs/std_msgs/__init__.py b/dimos/msgs/std_msgs/__init__.py deleted file mode 100644 index ae8e3dd8f6..0000000000 --- a/dimos/msgs/std_msgs/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .Bool import Bool -from .Header import Header -from .Int8 import Int8 -from .Int32 import Int32 -from .UInt32 import UInt32 - -__all__ = ["Bool", "Header", "Int8", "Int32", "UInt32"] diff --git a/dimos/msgs/std_msgs/test_header.py b/dimos/msgs/std_msgs/test_header.py index 93f20da283..29f4ee2c0e 100644 --- a/dimos/msgs/std_msgs/test_header.py +++ b/dimos/msgs/std_msgs/test_header.py @@ -15,7 +15,7 @@ from datetime import datetime import time -from dimos.msgs.std_msgs import Header +from dimos.msgs.std_msgs.Header import Header def test_header_initialization_methods() -> None: diff --git a/dimos/msgs/tf2_msgs/__init__.py b/dimos/msgs/tf2_msgs/__init__.py deleted file mode 100644 index 69d4e0137e..0000000000 --- a/dimos/msgs/tf2_msgs/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from dimos.msgs.tf2_msgs.TFMessage import TFMessage - -__all__ = ["TFMessage"] diff --git a/dimos/msgs/tf2_msgs/test_TFMessage.py b/dimos/msgs/tf2_msgs/test_TFMessage.py index 8567de9988..c379481f1d 100644 --- a/dimos/msgs/tf2_msgs/test_TFMessage.py +++ b/dimos/msgs/tf2_msgs/test_TFMessage.py @@ -14,8 +14,10 @@ from dimos_lcm.tf2_msgs import TFMessage as LCMTFMessage -from dimos.msgs.geometry_msgs import Quaternion, Transform, Vector3 -from dimos.msgs.tf2_msgs import TFMessage +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.tf2_msgs.TFMessage import TFMessage def test_tfmessage_initialization() -> None: diff --git a/dimos/msgs/tf2_msgs/test_TFMessage_lcmpub.py b/dimos/msgs/tf2_msgs/test_TFMessage_lcmpub.py index 8b58a61a44..2a03b7ee71 100644 --- a/dimos/msgs/tf2_msgs/test_TFMessage_lcmpub.py +++ b/dimos/msgs/tf2_msgs/test_TFMessage_lcmpub.py @@ -16,8 +16,10 @@ import pytest -from dimos.msgs.geometry_msgs import Quaternion, Transform, Vector3 -from dimos.msgs.tf2_msgs import TFMessage +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.tf2_msgs.TFMessage import TFMessage from dimos.protocol.pubsub.impl.lcmpubsub import LCM, Topic diff --git a/dimos/msgs/trajectory_msgs/__init__.py b/dimos/msgs/trajectory_msgs/__init__.py deleted file mode 100644 index 44039e594e..0000000000 --- a/dimos/msgs/trajectory_msgs/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Trajectory message types. - -Similar to ROS trajectory_msgs package. -""" - -from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory -from dimos.msgs.trajectory_msgs.TrajectoryPoint import TrajectoryPoint -from dimos.msgs.trajectory_msgs.TrajectoryStatus import TrajectoryState, TrajectoryStatus - -__all__ = [ - "JointTrajectory", - "TrajectoryPoint", - "TrajectoryState", - "TrajectoryStatus", -] diff --git a/dimos/msgs/vision_msgs/__init__.py b/dimos/msgs/vision_msgs/__init__.py deleted file mode 100644 index 0f1c9c8dc1..0000000000 --- a/dimos/msgs/vision_msgs/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from .BoundingBox2DArray import BoundingBox2DArray -from .BoundingBox3DArray import BoundingBox3DArray -from .Detection2D import Detection2D -from .Detection2DArray import Detection2DArray -from .Detection3D import Detection3D -from .Detection3DArray import Detection3DArray - -__all__ = [ - "BoundingBox2DArray", - "BoundingBox3DArray", - "Detection2D", - "Detection2DArray", - "Detection3D", - "Detection3DArray", -] diff --git a/dimos/navigation/base.py b/dimos/navigation/base.py index 347c4ad124..1530308711 100644 --- a/dimos/navigation/base.py +++ b/dimos/navigation/base.py @@ -16,7 +16,7 @@ from abc import ABC, abstractmethod from enum import Enum -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped class NavigationState(Enum): diff --git a/dimos/navigation/bbox_navigation.py b/dimos/navigation/bbox_navigation.py index 170bff9bcd..c96ba9efad 100644 --- a/dimos/navigation/bbox_navigation.py +++ b/dimos/navigation/bbox_navigation.py @@ -20,8 +20,10 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 -from dimos.msgs.vision_msgs import Detection2DArray +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray from dimos.utils.logging_config import setup_logger logger = setup_logger(level=logging.DEBUG) diff --git a/dimos/navigation/demo_ros_navigation.py b/dimos/navigation/demo_ros_navigation.py index 4d57867d59..0efa04cd44 100644 --- a/dimos/navigation/demo_ros_navigation.py +++ b/dimos/navigation/demo_ros_navigation.py @@ -15,7 +15,9 @@ import time from dimos.core.module_coordinator import ModuleCoordinator -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.navigation import rosnav from dimos.protocol.service.lcmservice import autoconf from dimos.utils.logging_config import setup_logger diff --git a/dimos/navigation/frontier_exploration/__init__.py b/dimos/navigation/frontier_exploration/__init__.py deleted file mode 100644 index 24ce957ccf..0000000000 --- a/dimos/navigation/frontier_exploration/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .wavefront_frontier_goal_selector import WavefrontFrontierExplorer, wavefront_frontier_explorer - -__all__ = ["WavefrontFrontierExplorer", "wavefront_frontier_explorer"] diff --git a/dimos/navigation/frontier_exploration/test_wavefront_frontier_goal_selector.py b/dimos/navigation/frontier_exploration/test_wavefront_frontier_goal_selector.py index 419986780a..834897d396 100644 --- a/dimos/navigation/frontier_exploration/test_wavefront_frontier_goal_selector.py +++ b/dimos/navigation/frontier_exploration/test_wavefront_frontier_goal_selector.py @@ -17,8 +17,8 @@ import numpy as np import pytest -from dimos.msgs.geometry_msgs import Vector3 -from dimos.msgs.nav_msgs import CostValues, OccupancyGrid +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid from dimos.navigation.frontier_exploration.wavefront_frontier_goal_selector import ( WavefrontFrontierExplorer, ) @@ -56,7 +56,7 @@ def quick_costmap(): # One obstacle grid[9:10, 9:10] = CostValues.OCCUPIED - from dimos.msgs.geometry_msgs import Pose + from dimos.msgs.geometry_msgs.Pose import Pose origin = Pose() origin.position.x = -1.0 @@ -97,7 +97,7 @@ def create_test_costmap(width: int = 40, height: int = 40, resolution: float = 0 grid[13:14, 18:22] = CostValues.OCCUPIED # Top corridor obstacle # Create origin at bottom-left, adjusted for map size - from dimos.msgs.geometry_msgs import Pose + from dimos.msgs.geometry_msgs.Pose import Pose origin = Pose() # Center the map around (0, 0) in world coordinates diff --git a/dimos/navigation/frontier_exploration/utils.py b/dimos/navigation/frontier_exploration/utils.py index 28644cdd41..d5ed7df61c 100644 --- a/dimos/navigation/frontier_exploration/utils.py +++ b/dimos/navigation/frontier_exploration/utils.py @@ -19,8 +19,8 @@ import numpy as np from PIL import Image, ImageDraw -from dimos.msgs.geometry_msgs import Vector3 -from dimos.msgs.nav_msgs import CostValues, OccupancyGrid +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid def costmap_to_pil_image(costmap: OccupancyGrid, scale_factor: int = 2) -> Image.Image: diff --git a/dimos/navigation/frontier_exploration/wavefront_frontier_goal_selector.py b/dimos/navigation/frontier_exploration/wavefront_frontier_goal_selector.py index f8a5436fc1..20fab41b35 100644 --- a/dimos/navigation/frontier_exploration/wavefront_frontier_goal_selector.py +++ b/dimos/navigation/frontier_exploration/wavefront_frontier_goal_selector.py @@ -34,8 +34,9 @@ from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out from dimos.mapping.occupancy.inflation import simple_inflate -from dimos.msgs.geometry_msgs import PoseStamped, Vector3 -from dimos.msgs.nav_msgs import CostValues, OccupancyGrid +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import get_distance diff --git a/dimos/navigation/replanning_a_star/controllers.py b/dimos/navigation/replanning_a_star/controllers.py index 865aafb8be..07ba8c7119 100644 --- a/dimos/navigation/replanning_a_star/controllers.py +++ b/dimos/navigation/replanning_a_star/controllers.py @@ -19,8 +19,9 @@ from numpy.typing import NDArray from dimos.core.global_config import GlobalConfig -from dimos.msgs.geometry_msgs import Twist, Vector3 from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.utils.trigonometry import angle_diff diff --git a/dimos/navigation/replanning_a_star/global_planner.py b/dimos/navigation/replanning_a_star/global_planner.py index df2680a4a7..4c4e79cb7b 100644 --- a/dimos/navigation/replanning_a_star/global_planner.py +++ b/dimos/navigation/replanning_a_star/global_planner.py @@ -23,8 +23,8 @@ from dimos.core.global_config import GlobalConfig from dimos.core.resource import Resource from dimos.mapping.occupancy.path_resampling import smooth_resample_path -from dimos.msgs.geometry_msgs import Twist from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Twist import Twist from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid from dimos.msgs.nav_msgs.Path import Path diff --git a/dimos/navigation/replanning_a_star/goal_validator.py b/dimos/navigation/replanning_a_star/goal_validator.py index 5cd093e955..b717c76295 100644 --- a/dimos/navigation/replanning_a_star/goal_validator.py +++ b/dimos/navigation/replanning_a_star/goal_validator.py @@ -16,8 +16,8 @@ import numpy as np -from dimos.msgs.geometry_msgs import Vector3, VectorLike -from dimos.msgs.nav_msgs import CostValues, OccupancyGrid +from dimos.msgs.geometry_msgs.Vector3 import Vector3, VectorLike +from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid def find_safe_goal( diff --git a/dimos/navigation/replanning_a_star/local_planner.py b/dimos/navigation/replanning_a_star/local_planner.py index a5f8d9e457..d50d0def84 100644 --- a/dimos/navigation/replanning_a_star/local_planner.py +++ b/dimos/navigation/replanning_a_star/local_planner.py @@ -23,9 +23,10 @@ from dimos.core.global_config import GlobalConfig from dimos.core.resource import Resource -from dimos.msgs.geometry_msgs import Twist from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped -from dimos.msgs.nav_msgs import OccupancyGrid, Path +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.nav_msgs.Path import Path from dimos.navigation.base import NavigationState from dimos.navigation.replanning_a_star.controllers import Controller, PController from dimos.navigation.replanning_a_star.navigation_map import NavigationMap diff --git a/dimos/navigation/replanning_a_star/min_cost_astar.py b/dimos/navigation/replanning_a_star/min_cost_astar.py index c3430e64d9..55f502680c 100644 --- a/dimos/navigation/replanning_a_star/min_cost_astar.py +++ b/dimos/navigation/replanning_a_star/min_cost_astar.py @@ -14,8 +14,11 @@ import heapq -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, VectorLike -from dimos.msgs.nav_msgs import CostValues, OccupancyGrid, Path +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import VectorLike +from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid +from dimos.msgs.nav_msgs.Path import Path from dimos.utils.logging_config import setup_logger # Try to import C++ extension for faster pathfinding diff --git a/dimos/navigation/replanning_a_star/module.py b/dimos/navigation/replanning_a_star/module.py index 28a22a2a86..796390f06c 100644 --- a/dimos/navigation/replanning_a_star/module.py +++ b/dimos/navigation/replanning_a_star/module.py @@ -21,8 +21,11 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import PointStamped, PoseStamped, Twist -from dimos.msgs.nav_msgs import OccupancyGrid, Path +from dimos.msgs.geometry_msgs.PointStamped import PointStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.nav_msgs.Path import Path from dimos.navigation.base import NavigationInterface, NavigationState from dimos.navigation.replanning_a_star.global_planner import GlobalPlanner diff --git a/dimos/navigation/replanning_a_star/path_clearance.py b/dimos/navigation/replanning_a_star/path_clearance.py index e99fba26c3..7dc08d49e0 100644 --- a/dimos/navigation/replanning_a_star/path_clearance.py +++ b/dimos/navigation/replanning_a_star/path_clearance.py @@ -19,8 +19,8 @@ from dimos.core.global_config import GlobalConfig from dimos.mapping.occupancy.path_mask import make_path_mask -from dimos.msgs.nav_msgs import Path from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid +from dimos.msgs.nav_msgs.Path import Path class PathClearance: diff --git a/dimos/navigation/replanning_a_star/path_distancer.py b/dimos/navigation/replanning_a_star/path_distancer.py index 04d844267f..c50583ca33 100644 --- a/dimos/navigation/replanning_a_star/path_distancer.py +++ b/dimos/navigation/replanning_a_star/path_distancer.py @@ -17,7 +17,7 @@ import numpy as np from numpy.typing import NDArray -from dimos.msgs.nav_msgs import Path +from dimos.msgs.nav_msgs.Path import Path class PathDistancer: diff --git a/dimos/navigation/replanning_a_star/test_goal_validator.py b/dimos/navigation/replanning_a_star/test_goal_validator.py index 4cda9de863..69c7147696 100644 --- a/dimos/navigation/replanning_a_star/test_goal_validator.py +++ b/dimos/navigation/replanning_a_star/test_goal_validator.py @@ -15,7 +15,7 @@ import numpy as np import pytest -from dimos.msgs.geometry_msgs import Vector3 +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.msgs.nav_msgs.OccupancyGrid import CostValues, OccupancyGrid from dimos.navigation.replanning_a_star.goal_validator import find_safe_goal from dimos.utils.data import get_data diff --git a/dimos/navigation/rosnav.py b/dimos/navigation/rosnav.py index 230d94b50f..38c8e32847 100644 --- a/dimos/navigation/rosnav.py +++ b/dimos/navigation/rosnav.py @@ -27,26 +27,29 @@ from reactivex import operators as ops from reactivex.subject import Subject -from dimos import spec from dimos.agents.annotation import skill from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.stream import In, Out from dimos.core.transport import LCMTransport, ROSTransport -from dimos.msgs.geometry_msgs import ( - PoseStamped, - Quaternion, - Transform, - Twist, - TwistStamped, - Vector3, -) -from dimos.msgs.nav_msgs import Path -from dimos.msgs.sensor_msgs import Joy, PointCloud2 -from dimos.msgs.std_msgs import Bool, Int8 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.nav_msgs.Path import Path +from dimos.msgs.sensor_msgs.Joy import Joy +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.std_msgs.Bool import Bool +from dimos.msgs.std_msgs.Int8 import Int8 from dimos.msgs.tf2_msgs.TFMessage import TFMessage from dimos.navigation.base import NavigationInterface, NavigationState +from dimos.spec.control import LocalPlanner +from dimos.spec.mapping import GlobalPointcloud +from dimos.spec.nav import Nav +from dimos.spec.perception import Pointcloud from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import euler_to_quaternion @@ -64,10 +67,10 @@ class Config(ModuleConfig): class ROSNav( Module[Config], NavigationInterface, - spec.Nav, - spec.GlobalPointcloud, - spec.Pointcloud, - spec.LocalPlanner, + Nav, + GlobalPointcloud, + Pointcloud, + LocalPlanner, ): default_config = Config diff --git a/dimos/navigation/visual/query.py b/dimos/navigation/visual/query.py index 0c84e8ac34..0693ca5dd1 100644 --- a/dimos/navigation/visual/query.py +++ b/dimos/navigation/visual/query.py @@ -16,7 +16,7 @@ from dimos.models.qwen.bbox import BBox from dimos.models.vl.base import VlModel -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.generic import extract_json_from_llm_response diff --git a/dimos/navigation/visual_servoing/detection_navigation.py b/dimos/navigation/visual_servoing/detection_navigation.py index 5f89bd1faa..351883e8ac 100644 --- a/dimos/navigation/visual_servoing/detection_navigation.py +++ b/dimos/navigation/visual_servoing/detection_navigation.py @@ -15,11 +15,15 @@ from dimos_lcm.sensor_msgs import CameraInfo as DimosLcmCameraInfo import numpy as np -from dimos.msgs.geometry_msgs import Transform, Twist, Vector3 -from dimos.msgs.sensor_msgs import CameraInfo, Image, PointCloud2 +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox -from dimos.perception.detection.type.detection3d import Detection3DPC -from dimos.protocol.tf import LCMTF +from dimos.perception.detection.type.detection3d.pointcloud import Detection3DPC +from dimos.protocol.tf.tf import LCMTF from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/navigation/visual_servoing/visual_servoing_2d.py b/dimos/navigation/visual_servoing/visual_servoing_2d.py index 032b5f3370..f424b21466 100644 --- a/dimos/navigation/visual_servoing/visual_servoing_2d.py +++ b/dimos/navigation/visual_servoing/visual_servoing_2d.py @@ -14,8 +14,9 @@ import numpy as np -from dimos.msgs.geometry_msgs import Twist, Vector3 -from dimos.msgs.sensor_msgs import CameraInfo +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo class VisualServoing2D: diff --git a/dimos/perception/__init__.py b/dimos/perception/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/perception/common/__init__.py b/dimos/perception/common/__init__.py deleted file mode 100644 index 5902f54bb8..0000000000 --- a/dimos/perception/common/__init__.py +++ /dev/null @@ -1,81 +0,0 @@ -from .utils import ( - BoundingBox2D, - CameraInfo, - Detection2D, - Detection3D, - Header, - Image, - ObjectData, - Pose, - Quaternion, - Union, - Vector, - Vector3, - bbox2d_to_corners, - colorize_depth, - combine_object_data, - cp, - cv2, - detection_results_to_object_data, - draw_bounding_box, - draw_object_detection_visualization, - draw_segmentation_mask, - extract_pose_from_detection3d, - find_clicked_detection, - load_camera_info, - load_camera_info_opencv, - logger, - np, - point_in_bbox, - project_2d_points_to_3d, - project_2d_points_to_3d_cpu, - project_2d_points_to_3d_cuda, - project_3d_points_to_2d, - project_3d_points_to_2d_cpu, - project_3d_points_to_2d_cuda, - rectify_image, - setup_logger, - torch, - yaml, -) - -__all__ = [ - "BoundingBox2D", - "CameraInfo", - "Detection2D", - "Detection3D", - "Header", - "Image", - "ObjectData", - "Pose", - "Quaternion", - "Union", - "Vector", - "Vector3", - "bbox2d_to_corners", - "colorize_depth", - "combine_object_data", - "cp", - "cv2", - "detection_results_to_object_data", - "draw_bounding_box", - "draw_object_detection_visualization", - "draw_segmentation_mask", - "extract_pose_from_detection3d", - "find_clicked_detection", - "load_camera_info", - "load_camera_info_opencv", - "logger", - "np", - "point_in_bbox", - "project_2d_points_to_3d", - "project_2d_points_to_3d_cpu", - "project_2d_points_to_3d_cuda", - "project_3d_points_to_2d", - "project_3d_points_to_2d_cpu", - "project_3d_points_to_2d_cuda", - "rectify_image", - "setup_logger", - "torch", - "yaml", -] diff --git a/dimos/perception/common/utils.py b/dimos/perception/common/utils.py index c5f550ade3..1670d31998 100644 --- a/dimos/perception/common/utils.py +++ b/dimos/perception/common/utils.py @@ -25,9 +25,11 @@ import torch import yaml # type: ignore[import-untyped] -from dimos.msgs.geometry_msgs import Pose, Quaternion, Vector3 -from dimos.msgs.sensor_msgs import Image -from dimos.msgs.std_msgs import Header +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.std_msgs.Header import Header from dimos.types.manipulation import ObjectData from dimos.types.vector import Vector from dimos.utils.logging_config import setup_logger diff --git a/dimos/perception/demo_object_scene_registration.py b/dimos/perception/demo_object_scene_registration.py index ad98d0474a..cdb09d359e 100644 --- a/dimos/perception/demo_object_scene_registration.py +++ b/dimos/perception/demo_object_scene_registration.py @@ -15,8 +15,8 @@ from dimos.agents.agent import agent from dimos.core.blueprints import autoconnect -from dimos.hardware.sensors.camera.realsense import realsense_camera -from dimos.hardware.sensors.camera.zed import zed_camera +from dimos.hardware.sensors.camera.realsense.camera import realsense_camera +from dimos.hardware.sensors.camera.zed.compat import zed_camera from dimos.perception.detection.detectors.yoloe import YoloePromptMode from dimos.perception.object_scene_registration import object_scene_registration_module from dimos.robot.foxglove_bridge import foxglove_bridge diff --git a/dimos/perception/detection/__init__.py b/dimos/perception/detection/__init__.py deleted file mode 100644 index ae9f8cb14d..0000000000 --- a/dimos/perception/detection/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "detectors": ["Detector", "Yolo2DDetector"], - "module2D": ["Detection2DModule"], - "module3D": ["Detection3DModule"], - }, -) diff --git a/dimos/perception/detection/conftest.py b/dimos/perception/detection/conftest.py index 8c1a65eb8b..5f8f1bc4b9 100644 --- a/dimos/perception/detection/conftest.py +++ b/dimos/perception/detection/conftest.py @@ -23,23 +23,23 @@ import pytest from dimos.core.transport import LCMTransport -from dimos.msgs.geometry_msgs import Transform -from dimos.msgs.sensor_msgs import CameraInfo, Image, PointCloud2 -from dimos.msgs.vision_msgs import Detection2DArray +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray from dimos.perception.detection.module2D import Detection2DModule from dimos.perception.detection.module3D import Detection3DModule from dimos.perception.detection.moduleDB import ObjectDBModule -from dimos.perception.detection.type import ( - Detection2D, - Detection3DPC, - ImageDetections2D, - ImageDetections3DPC, -) -from dimos.protocol.tf import TF +from dimos.perception.detection.type.detection2d.base import Detection2D +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D +from dimos.perception.detection.type.detection3d.imageDetections3DPC import ImageDetections3DPC +from dimos.perception.detection.type.detection3d.pointcloud import Detection3DPC +from dimos.protocol.tf.tf import TF from dimos.robot.unitree.go2 import connection from dimos.robot.unitree.type.odometry import Odometry from dimos.utils.data import get_data -from dimos.utils.testing import TimedSensorReplay +from dimos.utils.testing.replay import TimedSensorReplay class Moment(TypedDict, total=False): @@ -203,7 +203,7 @@ def detection3dpc(detections3dpc) -> Detection3DPC: @pytest.fixture(scope="session") def get_moment_2d(get_moment) -> Generator[Callable[[], Moment2D], None, None]: - from dimos.perception.detection.detectors import Yolo2DDetector + from dimos.perception.detection.detectors.yolo import Yolo2DDetector c = mock.create_autospec(CameraInfo, spec_set=True, instance=True) module = Detection2DModule(detector=lambda: Yolo2DDetector(device="cpu"), camera_info=c) @@ -262,7 +262,7 @@ def moment_provider(**kwargs) -> Moment3D: @pytest.fixture(scope="session") def object_db_module(get_moment): """Create and populate an ObjectDBModule with detections from multiple frames.""" - from dimos.perception.detection.detectors import Yolo2DDetector + from dimos.perception.detection.detectors.yolo import Yolo2DDetector c = mock.create_autospec(CameraInfo, spec_set=True, instance=True) module2d = Detection2DModule(detector=lambda: Yolo2DDetector(device="cpu"), camera_info=c) diff --git a/dimos/perception/detection/detectors/__init__.py b/dimos/perception/detection/detectors/__init__.py deleted file mode 100644 index 2f151fe3ef..0000000000 --- a/dimos/perception/detection/detectors/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# from dimos.perception.detection.detectors.detic import Detic2DDetector -from dimos.perception.detection.detectors.types import Detector -from dimos.perception.detection.detectors.yolo import Yolo2DDetector - -__all__ = [ - "Detector", - "Yolo2DDetector", -] diff --git a/dimos/perception/detection/detectors/types.py b/dimos/perception/detection/detectors/base.py similarity index 84% rename from dimos/perception/detection/detectors/types.py rename to dimos/perception/detection/detectors/base.py index e85c5ae18e..40aa82e5bd 100644 --- a/dimos/perception/detection/detectors/types.py +++ b/dimos/perception/detection/detectors/base.py @@ -14,8 +14,8 @@ from abc import ABC, abstractmethod -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.type import ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D class Detector(ABC): diff --git a/dimos/perception/detection/detectors/conftest.py b/dimos/perception/detection/detectors/conftest.py index 6a2c041a8b..bb9a47e0eb 100644 --- a/dimos/perception/detection/detectors/conftest.py +++ b/dimos/perception/detection/detectors/conftest.py @@ -14,7 +14,7 @@ import pytest -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.perception.detection.detectors.person.yolo import YoloPersonDetector from dimos.perception.detection.detectors.yolo import Yolo2DDetector from dimos.perception.detection.detectors.yoloe import Yoloe2DDetector, YoloePromptMode diff --git a/dimos/perception/detection/detectors/person/test_person_detectors.py b/dimos/perception/detection/detectors/person/test_person_detectors.py index 2ed7cdc7dc..6130e5888a 100644 --- a/dimos/perception/detection/detectors/person/test_person_detectors.py +++ b/dimos/perception/detection/detectors/person/test_person_detectors.py @@ -14,7 +14,8 @@ import pytest -from dimos.perception.detection.type import Detection2DPerson, ImageDetections2D +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D +from dimos.perception.detection.type.detection2d.person import Detection2DPerson @pytest.fixture(scope="session") diff --git a/dimos/perception/detection/detectors/person/yolo.py b/dimos/perception/detection/detectors/person/yolo.py index 519f45f2f6..26d68a4510 100644 --- a/dimos/perception/detection/detectors/person/yolo.py +++ b/dimos/perception/detection/detectors/person/yolo.py @@ -14,9 +14,9 @@ from ultralytics import YOLO # type: ignore[attr-defined, import-not-found] -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.detectors.types import Detector -from dimos.perception.detection.type import ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.detectors.base import Detector +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D from dimos.utils.data import get_data from dimos.utils.gpu_utils import is_cuda_available from dimos.utils.logging_config import setup_logger diff --git a/dimos/perception/detection/detectors/test_bbox_detectors.py b/dimos/perception/detection/detectors/test_bbox_detectors.py index 2e69016eb5..c8112e9aab 100644 --- a/dimos/perception/detection/detectors/test_bbox_detectors.py +++ b/dimos/perception/detection/detectors/test_bbox_detectors.py @@ -17,8 +17,9 @@ from reactivex.disposable import CompositeDisposable from dimos.core.transport import LCMTransport -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.type import Detection2D, ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.type.detection2d.base import Detection2D +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D @pytest.fixture(params=["bbox_detector", "person_detector", "yoloe_detector"], scope="session") diff --git a/dimos/perception/detection/detectors/yolo.py b/dimos/perception/detection/detectors/yolo.py index c9a65a120e..64565cce7a 100644 --- a/dimos/perception/detection/detectors/yolo.py +++ b/dimos/perception/detection/detectors/yolo.py @@ -14,9 +14,9 @@ from ultralytics import YOLO # type: ignore[attr-defined, import-not-found] -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.detectors.types import Detector -from dimos.perception.detection.type import ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.detectors.base import Detector +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D from dimos.utils.data import get_data from dimos.utils.gpu_utils import is_cuda_available from dimos.utils.logging_config import setup_logger diff --git a/dimos/perception/detection/detectors/yoloe.py b/dimos/perception/detection/detectors/yoloe.py index 9c9881209c..536dd9f497 100644 --- a/dimos/perception/detection/detectors/yoloe.py +++ b/dimos/perception/detection/detectors/yoloe.py @@ -20,9 +20,9 @@ from numpy.typing import NDArray from ultralytics import YOLOE # type: ignore[attr-defined, import-not-found] -from dimos.msgs.sensor_msgs import Image -from dimos.perception.detection.detectors.types import Detector -from dimos.perception.detection.type import ImageDetections2D +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.detection.detectors.base import Detector +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D from dimos.utils.data import get_data from dimos.utils.gpu_utils import is_cuda_available diff --git a/dimos/perception/detection/module2D.py b/dimos/perception/detection/module2D.py index 0a07b1238d..b6d0c9358c 100644 --- a/dimos/perception/detection/module2D.py +++ b/dimos/perception/detection/module2D.py @@ -22,18 +22,20 @@ from reactivex.observable import Observable from reactivex.subject import Subject -from dimos import spec from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import Transform, Vector3 -from dimos.msgs.sensor_msgs import CameraInfo, Image -from dimos.msgs.sensor_msgs.Image import sharpness_barrier -from dimos.msgs.vision_msgs import Detection2DArray -from dimos.perception.detection.detectors import Detector # type: ignore[attr-defined] +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image, sharpness_barrier +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray +from dimos.perception.detection.detectors.base import Detector from dimos.perception.detection.detectors.yolo import Yolo2DDetector -from dimos.perception.detection.type import Filter2D, ImageDetections2D +from dimos.perception.detection.type.detection2d.base import Filter2D +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D +from dimos.spec.perception import Camera from dimos.utils.decorators.decorators import simple_mcache from dimos.utils.reactive import backpressure @@ -158,7 +160,7 @@ def stop(self) -> None: def deploy( # type: ignore[no-untyped-def] dimos: ModuleCoordinator, - camera: spec.Camera, + camera: Camera, prefix: str = "/detector2d", **kwargs, ) -> Detection2DModule: diff --git a/dimos/perception/detection/module3D.py b/dimos/perception/detection/module3D.py index 96ae4e8297..fa392dc799 100644 --- a/dimos/perception/detection/module3D.py +++ b/dimos/perception/detection/module3D.py @@ -22,19 +22,23 @@ from reactivex import operators as ops from reactivex.observable import Observable -from dimos import spec from dimos.agents.annotation import skill from dimos.core.core import rpc from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.stream import In, Out from dimos.core.transport import LCMTransport -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Transform, Vector3 -from dimos.msgs.sensor_msgs import Image, PointCloud2 -from dimos.msgs.vision_msgs import Detection2DArray +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray from dimos.perception.detection.module2D import Detection2DModule from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D -from dimos.perception.detection.type.detection3d import Detection3DPC from dimos.perception.detection.type.detection3d.imageDetections3DPC import ImageDetections3DPC +from dimos.perception.detection.type.detection3d.pointcloud import Detection3DPC +from dimos.spec.perception import Camera, Pointcloud from dimos.types.timestamped import align_timestamped from dimos.utils.reactive import backpressure @@ -177,7 +181,7 @@ def detection2d_to_3d(args): # type: ignore[no-untyped-def] transform = self.tf.get("camera_optical", pc.frame_id, detections.image.ts, 5.0) return self.process_frame(detections, pc, transform) - self.detection_stream_3d = align_timestamped( + self.detection_stream_3d = align_timestamped( # type: ignore[type-var] backpressure(self.detection_stream_2d()), self.pointcloud.observable(), # type: ignore[no-untyped-call] match_tolerance=0.25, @@ -203,8 +207,8 @@ def _publish_detections(self, detections: ImageDetections3DPC) -> None: def deploy( # type: ignore[no-untyped-def] dimos: ModuleCoordinator, - lidar: spec.Pointcloud, - camera: spec.Camera, + lidar: Pointcloud, + camera: Camera, prefix: str = "/detector3d", **kwargs, ) -> "ModuleProxy": diff --git a/dimos/perception/detection/moduleDB.py b/dimos/perception/detection/moduleDB.py index bc0a346a59..5672786b94 100644 --- a/dimos/perception/detection/moduleDB.py +++ b/dimos/perception/detection/moduleDB.py @@ -25,12 +25,16 @@ from dimos.core.core import rpc from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Transform, Vector3 -from dimos.msgs.sensor_msgs import Image, PointCloud2 -from dimos.msgs.vision_msgs import Detection2DArray +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray from dimos.perception.detection.module3D import Detection3DModule -from dimos.perception.detection.type.detection3d import Detection3DPC from dimos.perception.detection.type.detection3d.imageDetections3DPC import ImageDetections3DPC +from dimos.perception.detection.type.detection3d.pointcloud import Detection3DPC from dimos.perception.detection.type.utils import TableStr diff --git a/dimos/perception/detection/objectDB.py b/dimos/perception/detection/objectDB.py index 9af8058c55..5b73e97742 100644 --- a/dimos/perception/detection/objectDB.py +++ b/dimos/perception/detection/objectDB.py @@ -20,11 +20,11 @@ import open3d as o3d # type: ignore[import-untyped] -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: - from dimos.msgs.geometry_msgs import Vector3 + from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.perception.detection.type.detection3d.object import Object logger = setup_logger() diff --git a/dimos/perception/detection/person_tracker.py b/dimos/perception/detection/person_tracker.py index 913043f312..9dbba210a2 100644 --- a/dimos/perception/detection/person_tracker.py +++ b/dimos/perception/detection/person_tracker.py @@ -21,10 +21,13 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import PoseStamped, Transform, Vector3 -from dimos.msgs.sensor_msgs import CameraInfo, Image -from dimos.msgs.vision_msgs import Detection2DArray -from dimos.perception.detection.type import ImageDetections2D +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D from dimos.types.timestamped import align_timestamped from dimos.utils.reactive import backpressure diff --git a/dimos/perception/detection/reid/__init__.py b/dimos/perception/detection/reid/__init__.py deleted file mode 100644 index 31d50a894b..0000000000 --- a/dimos/perception/detection/reid/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -from dimos.perception.detection.reid.embedding_id_system import EmbeddingIDSystem -from dimos.perception.detection.reid.module import Config, ReidModule -from dimos.perception.detection.reid.type import IDSystem, PassthroughIDSystem - -__all__ = [ - "Config", - "EmbeddingIDSystem", - # ID Systems - "IDSystem", - "PassthroughIDSystem", - # Module - "ReidModule", -] diff --git a/dimos/perception/detection/reid/embedding_id_system.py b/dimos/perception/detection/reid/embedding_id_system.py index 15bb491f5c..faf322de07 100644 --- a/dimos/perception/detection/reid/embedding_id_system.py +++ b/dimos/perception/detection/reid/embedding_id_system.py @@ -19,7 +19,7 @@ from dimos.models.embedding.base import Embedding, EmbeddingModel from dimos.perception.detection.reid.type import IDSystem -from dimos.perception.detection.type import Detection2DBBox +from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox class EmbeddingIDSystem(IDSystem): diff --git a/dimos/perception/detection/reid/module.py b/dimos/perception/detection/reid/module.py index 0a359746d3..2bb0ecfbb2 100644 --- a/dimos/perception/detection/reid/module.py +++ b/dimos/perception/detection/reid/module.py @@ -24,8 +24,8 @@ from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out from dimos.msgs.foxglove_msgs.Color import Color -from dimos.msgs.sensor_msgs import Image -from dimos.msgs.vision_msgs import Detection2DArray +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray from dimos.perception.detection.reid.embedding_id_system import EmbeddingIDSystem from dimos.perception.detection.reid.type import IDSystem from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D @@ -48,7 +48,7 @@ def __init__(self, idsystem: IDSystem | None = None, **kwargs) -> None: # type: super().__init__(**kwargs) if idsystem is None: try: - from dimos.models.embedding import TorchReIDModel + from dimos.models.embedding.treid import TorchReIDModel idsystem = EmbeddingIDSystem(model=TorchReIDModel, padding=0) # type: ignore[arg-type] except Exception as e: diff --git a/dimos/perception/detection/reid/test_embedding_id_system.py b/dimos/perception/detection/reid/test_embedding_id_system.py index cc8632627f..2916c9040d 100644 --- a/dimos/perception/detection/reid/test_embedding_id_system.py +++ b/dimos/perception/detection/reid/test_embedding_id_system.py @@ -15,7 +15,7 @@ import numpy as np import pytest -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.perception.detection.reid.embedding_id_system import EmbeddingIDSystem from dimos.utils.data import get_data diff --git a/dimos/perception/detection/reid/test_module.py b/dimos/perception/detection/reid/test_module.py index f5672c1f67..aac6ba11d1 100644 --- a/dimos/perception/detection/reid/test_module.py +++ b/dimos/perception/detection/reid/test_module.py @@ -15,7 +15,7 @@ import pytest from dimos.core.transport import LCMTransport -from dimos.msgs.foxglove_msgs import ImageAnnotations +from dimos.msgs.foxglove_msgs.ImageAnnotations import ImageAnnotations from dimos.perception.detection.reid.embedding_id_system import EmbeddingIDSystem from dimos.perception.detection.reid.module import ReidModule @@ -23,7 +23,7 @@ @pytest.mark.tool def test_reid_ingress(imageDetections2d) -> None: try: - from dimos.models.embedding import TorchReIDModel + from dimos.models.embedding.treid import TorchReIDModel except Exception: pytest.skip("TorchReIDModel not available") diff --git a/dimos/perception/detection/type/__init__.py b/dimos/perception/detection/type/__init__.py deleted file mode 100644 index b14464d4fa..0000000000 --- a/dimos/perception/detection/type/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "detection2d.base": [ - "Detection2D", - "Filter2D", - ], - "detection2d.bbox": [ - "Detection2DBBox", - ], - "detection2d.person": [ - "Detection2DPerson", - ], - "detection2d.point": [ - "Detection2DPoint", - ], - "detection2d.imageDetections2D": [ - "ImageDetections2D", - ], - "detection3d": [ - "Detection3D", - "Detection3DBBox", - "Detection3DPC", - "ImageDetections3DPC", - "PointCloudFilter", - "height_filter", - "radius_outlier", - "raycast", - "statistical", - ], - "imageDetections": ["ImageDetections"], - "utils": ["TableStr"], - }, -) diff --git a/dimos/perception/detection/type/detection2d/__init__.py b/dimos/perception/detection/type/detection2d/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/perception/detection/type/detection2d/base.py b/dimos/perception/detection/type/detection2d/base.py index ee9374af8c..ef05813118 100644 --- a/dimos/perception/detection/type/detection2d/base.py +++ b/dimos/perception/detection/type/detection2d/base.py @@ -17,8 +17,8 @@ from dimos_lcm.vision_msgs import Detection2D as ROSDetection2D -from dimos.msgs.foxglove_msgs import ImageAnnotations -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.foxglove_msgs.ImageAnnotations import ImageAnnotations +from dimos.msgs.sensor_msgs.Image import Image from dimos.types.timestamped import Timestamped diff --git a/dimos/perception/detection/type/detection2d/bbox.py b/dimos/perception/detection/type/detection2d/bbox.py index 45dc848e9d..9ce3f11b96 100644 --- a/dimos/perception/detection/type/detection2d/bbox.py +++ b/dimos/perception/detection/type/detection2d/bbox.py @@ -22,7 +22,7 @@ from typing_extensions import Self from ultralytics.engine.results import Results # type: ignore[import-not-found] - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image from dimos_lcm.foxglove_msgs.ImageAnnotations import ( PointsAnnotation, @@ -40,9 +40,9 @@ from rich.console import Console from rich.text import Text -from dimos.msgs.foxglove_msgs import ImageAnnotations from dimos.msgs.foxglove_msgs.Color import Color -from dimos.msgs.std_msgs import Header +from dimos.msgs.foxglove_msgs.ImageAnnotations import ImageAnnotations +from dimos.msgs.std_msgs.Header import Header from dimos.perception.detection.type.detection2d.base import Detection2D from dimos.types.timestamped import to_ros_stamp, to_timestamp from dimos.utils.decorators.decorators import simple_mcache diff --git a/dimos/perception/detection/type/detection2d/imageDetections2D.py b/dimos/perception/detection/type/detection2d/imageDetections2D.py index 34033a9c50..507125c333 100644 --- a/dimos/perception/detection/type/detection2d/imageDetections2D.py +++ b/dimos/perception/detection/type/detection2d/imageDetections2D.py @@ -27,8 +27,8 @@ if TYPE_CHECKING: from ultralytics.engine.results import Results - from dimos.msgs.sensor_msgs import Image - from dimos.msgs.vision_msgs import Detection2DArray + from dimos.msgs.sensor_msgs.Image import Image + from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray T2D = TypeVar("T2D", bound=Detection2D, default=Detection2DBBox) diff --git a/dimos/perception/detection/type/detection2d/person.py b/dimos/perception/detection/type/detection2d/person.py index efb12ebdbc..e85229719a 100644 --- a/dimos/perception/detection/type/detection2d/person.py +++ b/dimos/perception/detection/type/detection2d/person.py @@ -25,7 +25,7 @@ import numpy as np from dimos.msgs.foxglove_msgs.Color import Color -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.perception.detection.type.detection2d.bbox import Bbox, Detection2DBBox from dimos.types.timestamped import to_ros_stamp from dimos.utils.decorators.decorators import simple_mcache diff --git a/dimos/perception/detection/type/detection2d/point.py b/dimos/perception/detection/type/detection2d/point.py index 216ec57b82..0155bcb9cd 100644 --- a/dimos/perception/detection/type/detection2d/point.py +++ b/dimos/perception/detection/type/detection2d/point.py @@ -31,14 +31,14 @@ Pose2D, ) -from dimos.msgs.foxglove_msgs import ImageAnnotations from dimos.msgs.foxglove_msgs.Color import Color -from dimos.msgs.std_msgs import Header +from dimos.msgs.foxglove_msgs.ImageAnnotations import ImageAnnotations +from dimos.msgs.std_msgs.Header import Header from dimos.perception.detection.type.detection2d.base import Detection2D from dimos.types.timestamped import to_ros_stamp if TYPE_CHECKING: - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image @dataclass diff --git a/dimos/perception/detection/type/detection2d/seg.py b/dimos/perception/detection/type/detection2d/seg.py index 5d4d55d0c3..aca1e34b7e 100644 --- a/dimos/perception/detection/type/detection2d/seg.py +++ b/dimos/perception/detection/type/detection2d/seg.py @@ -30,7 +30,7 @@ if TYPE_CHECKING: from ultralytics.engine.results import Results - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image @dataclass diff --git a/dimos/perception/detection/type/detection2d/test_imageDetections2D.py b/dimos/perception/detection/type/detection2d/test_imageDetections2D.py index 83487d2c25..4897d8d034 100644 --- a/dimos/perception/detection/type/detection2d/test_imageDetections2D.py +++ b/dimos/perception/detection/type/detection2d/test_imageDetections2D.py @@ -13,7 +13,7 @@ # limitations under the License. import pytest -from dimos.perception.detection.type import ImageDetections2D +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D def test_from_ros_detection2d_array(get_moment_2d) -> None: diff --git a/dimos/perception/detection/type/detection2d/test_person.py b/dimos/perception/detection/type/detection2d/test_person.py index 06c5883ae2..988222e120 100644 --- a/dimos/perception/detection/type/detection2d/test_person.py +++ b/dimos/perception/detection/type/detection2d/test_person.py @@ -17,7 +17,7 @@ def test_person_ros_confidence() -> None: """Test that Detection2DPerson preserves confidence when converting to ROS format.""" - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image from dimos.perception.detection.detectors.person.yolo import YoloPersonDetector from dimos.perception.detection.type.detection2d.person import Detection2DPerson from dimos.utils.data import get_data diff --git a/dimos/perception/detection/type/detection3d/__init__.py b/dimos/perception/detection/type/detection3d/__init__.py deleted file mode 100644 index 53ab73259e..0000000000 --- a/dimos/perception/detection/type/detection3d/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from dimos.perception.detection.type.detection3d.base import Detection3D -from dimos.perception.detection.type.detection3d.bbox import Detection3DBBox -from dimos.perception.detection.type.detection3d.imageDetections3DPC import ImageDetections3DPC -from dimos.perception.detection.type.detection3d.pointcloud import Detection3DPC -from dimos.perception.detection.type.detection3d.pointcloud_filters import ( - PointCloudFilter, - height_filter, - radius_outlier, - raycast, - statistical, -) - -__all__ = [ - "Detection3D", - "Detection3DBBox", - "Detection3DPC", - "ImageDetections3DPC", - "PointCloudFilter", - "height_filter", - "radius_outlier", - "raycast", - "statistical", -] diff --git a/dimos/perception/detection/type/detection3d/base.py b/dimos/perception/detection/type/detection3d/base.py index a5dbb742b8..afe37aac6e 100644 --- a/dimos/perception/detection/type/detection3d/base.py +++ b/dimos/perception/detection/type/detection3d/base.py @@ -18,7 +18,7 @@ from dataclasses import dataclass, field from typing import TYPE_CHECKING -from dimos.msgs.geometry_msgs import Transform +from dimos.msgs.geometry_msgs.Transform import Transform from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox if TYPE_CHECKING: diff --git a/dimos/perception/detection/type/detection3d/bbox.py b/dimos/perception/detection/type/detection3d/bbox.py index bdf2d27a7c..a3ae68a766 100644 --- a/dimos/perception/detection/type/detection3d/bbox.py +++ b/dimos/perception/detection/type/detection3d/bbox.py @@ -20,9 +20,13 @@ from dimos_lcm.vision_msgs import ObjectHypothesis, ObjectHypothesisWithPose -from dimos.msgs.geometry_msgs import Pose, PoseStamped, Quaternion, Transform, Vector3 -from dimos.msgs.std_msgs import Header -from dimos.msgs.vision_msgs import Detection3D +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.std_msgs.Header import Header +from dimos.msgs.vision_msgs.Detection3D import Detection3D from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox diff --git a/dimos/perception/detection/type/detection3d/object.py b/dimos/perception/detection/type/detection3d/object.py index ec160c4a68..639ea73ae5 100644 --- a/dimos/perception/detection/type/detection3d/object.py +++ b/dimos/perception/detection/type/detection3d/object.py @@ -24,10 +24,15 @@ import numpy as np import open3d as o3d # type: ignore[import-untyped] -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Transform, Vector3 -from dimos.msgs.sensor_msgs import Image, PointCloud2 -from dimos.msgs.std_msgs import Header -from dimos.msgs.vision_msgs import Detection3D as ROSDetection3D, Detection3DArray +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.std_msgs.Header import Header +from dimos.msgs.vision_msgs.Detection3D import Detection3D as ROSDetection3D +from dimos.msgs.vision_msgs.Detection3DArray import Detection3DArray from dimos.perception.detection.type.detection2d.seg import Detection2DSeg from dimos.perception.detection.type.detection3d.base import Detection3D diff --git a/dimos/perception/detection/type/detection3d/pointcloud.py b/dimos/perception/detection/type/detection3d/pointcloud.py index 741b9c7498..5ddec06fd5 100644 --- a/dimos/perception/detection/type/detection3d/pointcloud.py +++ b/dimos/perception/detection/type/detection3d/pointcloud.py @@ -33,8 +33,10 @@ import numpy as np from dimos.msgs.foxglove_msgs.Color import Color -from dimos.msgs.geometry_msgs import PoseStamped, Transform, Vector3 -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.perception.detection.type.detection3d.base import Detection3D from dimos.perception.detection.type.detection3d.pointcloud_filters import ( PointCloudFilter, diff --git a/dimos/perception/detection/type/detection3d/pointcloud_filters.py b/dimos/perception/detection/type/detection3d/pointcloud_filters.py index 59ad6200d9..fdb2afeebb 100644 --- a/dimos/perception/detection/type/detection3d/pointcloud_filters.py +++ b/dimos/perception/detection/type/detection3d/pointcloud_filters.py @@ -18,8 +18,8 @@ from dimos_lcm.sensor_msgs import CameraInfo -from dimos.msgs.geometry_msgs import Transform -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.perception.detection.type.detection2d.bbox import Detection2DBBox # Filters take Detection2DBBox, PointCloud2, CameraInfo, Transform and return filtered PointCloud2 or None diff --git a/dimos/perception/detection/type/imageDetections.py b/dimos/perception/detection/type/imageDetections.py index 12a1f4efb9..25cd45545a 100644 --- a/dimos/perception/detection/type/imageDetections.py +++ b/dimos/perception/detection/type/imageDetections.py @@ -20,14 +20,14 @@ from dimos_lcm.vision_msgs import Detection2DArray -from dimos.msgs.foxglove_msgs import ImageAnnotations -from dimos.msgs.std_msgs import Header +from dimos.msgs.foxglove_msgs.ImageAnnotations import ImageAnnotations +from dimos.msgs.std_msgs.Header import Header from dimos.perception.detection.type.utils import TableStr if TYPE_CHECKING: from collections.abc import Callable, Iterator - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image from dimos.perception.detection.type.detection2d.base import Detection2D T = TypeVar("T", bound=Detection2D) diff --git a/dimos/perception/detection/type/test_object3d.py b/dimos/perception/detection/type/test_object3d.py index 7057fbb9cb..ff8931e353 100644 --- a/dimos/perception/detection/type/test_object3d.py +++ b/dimos/perception/detection/type/test_object3d.py @@ -15,7 +15,7 @@ import pytest from dimos.perception.detection.moduleDB import Object3D -from dimos.perception.detection.type.detection3d import ImageDetections3DPC +from dimos.perception.detection.type.detection3d.imageDetections3DPC import ImageDetections3DPC def test_first_object(first_object) -> None: diff --git a/dimos/perception/experimental/__init__.py b/dimos/perception/experimental/__init__.py deleted file mode 100644 index 39ef33521d..0000000000 --- a/dimos/perception/experimental/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Experimental perception modules.""" diff --git a/dimos/perception/experimental/temporal_memory/clip_filter.py b/dimos/perception/experimental/temporal_memory/clip_filter.py index d747899452..9bea000712 100644 --- a/dimos/perception/experimental/temporal_memory/clip_filter.py +++ b/dimos/perception/experimental/temporal_memory/clip_filter.py @@ -18,7 +18,7 @@ import numpy as np -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/perception/experimental/temporal_memory/entity_graph_db.py b/dimos/perception/experimental/temporal_memory/entity_graph_db.py index 11c90cda87..bdc7137ce7 100644 --- a/dimos/perception/experimental/temporal_memory/entity_graph_db.py +++ b/dimos/perception/experimental/temporal_memory/entity_graph_db.py @@ -30,9 +30,12 @@ from dimos.utils.logging_config import setup_logger +from .temporal_utils.parsers import parse_batch_distance_response +from .temporal_utils.prompts import build_batch_distance_estimation_prompt + if TYPE_CHECKING: from dimos.models.vl.base import VlModel - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image logger = setup_logger() @@ -564,7 +567,6 @@ def estimate_and_save_distances( """Estimate distances between entities using VLM and save to database.""" if not frame_image: return - from . import temporal_utils as tu enriched_entities: list[dict[str, Any]] = [] for entity in parsed.get("new_entities", []): @@ -593,8 +595,8 @@ def estimate_and_save_distances( if not pairs: return try: - response = vlm.query(frame_image, tu.build_batch_distance_estimation_prompt(pairs)) - for r in tu.parse_batch_distance_response(response, pairs): + response = vlm.query(frame_image, build_batch_distance_estimation_prompt(pairs)) + for r in parse_batch_distance_response(response, pairs): if r["category"] in ("near", "medium", "far"): self.add_distance( entity_a_id=r["entity_a_id"], diff --git a/dimos/perception/experimental/temporal_memory/frame_window_accumulator.py b/dimos/perception/experimental/temporal_memory/frame_window_accumulator.py index fc2c9c8a79..4c910a1b88 100644 --- a/dimos/perception/experimental/temporal_memory/frame_window_accumulator.py +++ b/dimos/perception/experimental/temporal_memory/frame_window_accumulator.py @@ -25,7 +25,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image @dataclass diff --git a/dimos/perception/experimental/temporal_memory/temporal_memory.py b/dimos/perception/experimental/temporal_memory/temporal_memory.py index 8841d3a6b0..d4e343872b 100644 --- a/dimos/perception/experimental/temporal_memory/temporal_memory.py +++ b/dimos/perception/experimental/temporal_memory/temporal_memory.py @@ -38,16 +38,16 @@ from dimos.core.stream import In, Out from dimos.models.vl.base import VlModel from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped -from dimos.msgs.sensor_msgs import Image -from dimos.msgs.sensor_msgs.Image import sharpness_barrier +from dimos.msgs.sensor_msgs.Image import Image, sharpness_barrier from dimos.msgs.visualization_msgs.EntityMarkers import EntityMarkers, Marker from dimos.utils.logging_config import get_run_log_dir, setup_logger -from . import temporal_utils as tu from .clip_filter import CLIP_AVAILABLE, adaptive_keyframes from .entity_graph_db import EntityGraphDB from .frame_window_accumulator import Frame, FrameWindowAccumulator from .temporal_state import TemporalState +from .temporal_utils.graph_utils import build_graph_context, extract_time_window +from .temporal_utils.helpers import is_scene_stale from .window_analyzer import WindowAnalyzer try: @@ -376,7 +376,7 @@ def _analyze_window(self) -> None: w_start, w_end = window_frames[0].timestamp_s, window_frames[-1].timestamp_s # Skip stale scenes (frames too close together / camera not moving) - if tu.is_scene_stale(window_frames, self.config.stale_scene_threshold): + if is_scene_stale(window_frames, self.config.stale_scene_threshold): logger.info(f"[temporal-memory] skipping stale window [{w_start:.1f}-{w_end:.1f}s]") return @@ -553,13 +553,13 @@ def query(self, question: str) -> str: # Graph context if self._graph_db: - time_window_s = tu.extract_time_window(question) + time_window_s = extract_time_window(question) all_entity_ids = [ e["id"] for e in snap.entity_roster if isinstance(e, dict) and "id" in e ] if all_entity_ids: logger.info(f"query: building graph context for {len(all_entity_ids)} entities") - graph_context = tu.build_graph_context( + graph_context = build_graph_context( graph_db=self._graph_db, entity_ids=all_entity_ids, time_window_s=time_window_s, diff --git a/dimos/perception/experimental/temporal_memory/temporal_utils/__init__.py b/dimos/perception/experimental/temporal_memory/temporal_utils/__init__.py deleted file mode 100644 index d8119a5159..0000000000 --- a/dimos/perception/experimental/temporal_memory/temporal_utils/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Temporal memory utilities.""" - -from .graph_utils import build_graph_context, extract_time_window -from .helpers import clamp_text, format_timestamp, is_scene_stale, next_entity_id_hint -from .parsers import parse_batch_distance_response, parse_window_response -from .prompts import ( - WINDOW_RESPONSE_SCHEMA, - build_batch_distance_estimation_prompt, - build_distance_estimation_prompt, - build_query_prompt, - build_summary_prompt, - build_window_prompt, - get_structured_output_format, -) - -__all__ = [ - "WINDOW_RESPONSE_SCHEMA", - "build_batch_distance_estimation_prompt", - "build_distance_estimation_prompt", - "build_graph_context", - "build_query_prompt", - "build_summary_prompt", - "build_window_prompt", - "clamp_text", - "extract_time_window", - "format_timestamp", - "get_structured_output_format", - "is_scene_stale", - "next_entity_id_hint", - "parse_batch_distance_response", - "parse_window_response", -] diff --git a/dimos/perception/experimental/temporal_memory/test_temporal_memory_module.py b/dimos/perception/experimental/temporal_memory/test_temporal_memory_module.py index 5b37b66770..81df107ecf 100644 --- a/dimos/perception/experimental/temporal_memory/test_temporal_memory_module.py +++ b/dimos/perception/experimental/temporal_memory/test_temporal_memory_module.py @@ -34,15 +34,17 @@ from dimos.core.stream import Out from dimos.core.transport import LCMTransport from dimos.models.vl.base import VlModel -from dimos.msgs.sensor_msgs import Image -from dimos.perception.experimental.temporal_memory import ( +from dimos.msgs.sensor_msgs.Image import Image +from dimos.perception.experimental.temporal_memory.entity_graph_db import EntityGraphDB +from dimos.perception.experimental.temporal_memory.frame_window_accumulator import ( Frame, FrameWindowAccumulator, +) +from dimos.perception.experimental.temporal_memory.temporal_memory import ( TemporalMemory, TemporalMemoryConfig, - TemporalState, ) -from dimos.perception.experimental.temporal_memory.entity_graph_db import EntityGraphDB +from dimos.perception.experimental.temporal_memory.temporal_state import TemporalState from dimos.perception.experimental.temporal_memory.temporal_utils.graph_utils import ( extract_time_window, ) diff --git a/dimos/perception/experimental/temporal_memory/window_analyzer.py b/dimos/perception/experimental/temporal_memory/window_analyzer.py index cd01a3056d..3c233f8e5b 100644 --- a/dimos/perception/experimental/temporal_memory/window_analyzer.py +++ b/dimos/perception/experimental/temporal_memory/window_analyzer.py @@ -25,11 +25,17 @@ from dimos.utils.logging_config import setup_logger -from . import temporal_utils as tu +from .temporal_utils.parsers import parse_window_response +from .temporal_utils.prompts import ( + build_query_prompt, + build_summary_prompt, + build_window_prompt, + get_structured_output_format, +) if TYPE_CHECKING: from dimos.models.vl.base import VlModel - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image from .frame_window_accumulator import Frame @@ -87,14 +93,14 @@ def analyze_window( w_end: float, ) -> AnalysisResult | None: """Run VLM window analysis. Returns None on failure.""" - query = tu.build_window_prompt( + query = build_window_prompt( w_start=w_start, w_end=w_end, frame_count=len(frames), state=state_dict, ) try: - fmt = tu.get_structured_output_format() + fmt = get_structured_output_format() if len(frames) > 1: responses = self._vlm.query_batch( [f.image for f in frames], query, response_format=fmt @@ -109,7 +115,7 @@ def analyze_window( if raw is None: return None - parsed = tu.parse_window_response(raw, w_start, w_end, len(frames)) + parsed = parse_window_response(raw, w_start, w_end, len(frames)) return AnalysisResult(parsed=parsed, raw_vlm_response=raw, w_start=w_start, w_end=w_end) # It's called from the orchestrator, not here. @@ -124,7 +130,7 @@ def update_summary( if not chunk_buffer or not latest_frame: return None - prompt = tu.build_summary_prompt( + prompt = build_summary_prompt( rolling_summary=rolling_summary, chunk_windows=chunk_buffer, ) @@ -143,7 +149,7 @@ def answer_query( latest_frame: Image, ) -> QueryResult | None: """Answer a user query. Returns None on failure.""" - prompt = tu.build_query_prompt(question=question, context=context) + prompt = build_query_prompt(question=question, context=context) try: raw = self._vlm.query(latest_frame, prompt) return QueryResult(answer=raw.strip(), raw_vlm_response=raw) diff --git a/dimos/perception/object_scene_registration.py b/dimos/perception/object_scene_registration.py index ee7b87b534..5fb1748032 100644 --- a/dimos/perception/object_scene_registration.py +++ b/dimos/perception/object_scene_registration.py @@ -24,14 +24,16 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import In, Out -from dimos.msgs.foxglove_msgs import ImageAnnotations -from dimos.msgs.sensor_msgs import CameraInfo, Image, PointCloud2 -from dimos.msgs.sensor_msgs.Image import ImageFormat -from dimos.msgs.std_msgs import Header -from dimos.msgs.vision_msgs import Detection2DArray, Detection3DArray +from dimos.msgs.foxglove_msgs.ImageAnnotations import ImageAnnotations +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.std_msgs.Header import Header +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray +from dimos.msgs.vision_msgs.Detection3DArray import Detection3DArray from dimos.perception.detection.detectors.yoloe import Yoloe2DDetector, YoloePromptMode from dimos.perception.detection.objectDB import ObjectDB -from dimos.perception.detection.type import ImageDetections2D +from dimos.perception.detection.type.detection2d.imageDetections2D import ImageDetections2D from dimos.perception.detection.type.detection3d.object import ( Object, Object as DetObject, diff --git a/dimos/perception/object_tracker.py b/dimos/perception/object_tracker.py index 29a9ecc034..6afc5e0814 100644 --- a/dimos/perception/object_tracker.py +++ b/dimos/perception/object_tracker.py @@ -31,15 +31,16 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import Pose, Quaternion, Transform, Vector3 -from dimos.msgs.sensor_msgs import ( - CameraInfo, - Image, - ImageFormat, -) -from dimos.msgs.std_msgs import Header -from dimos.msgs.vision_msgs import Detection2DArray, Detection3DArray -from dimos.protocol.tf import TF +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.msgs.std_msgs.Header import Header +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray +from dimos.msgs.vision_msgs.Detection3DArray import Detection3DArray +from dimos.protocol.tf.tf import TF from dimos.types.timestamped import align_timestamped from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import ( diff --git a/dimos/perception/object_tracker_2d.py b/dimos/perception/object_tracker_2d.py index 03f3991081..a53d331aef 100644 --- a/dimos/perception/object_tracker_2d.py +++ b/dimos/perception/object_tracker_2d.py @@ -35,9 +35,9 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.sensor_msgs import Image, ImageFormat -from dimos.msgs.std_msgs import Header -from dimos.msgs.vision_msgs import Detection2DArray +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.msgs.std_msgs.Header import Header +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray from dimos.utils.logging_config import setup_logger logger = setup_logger(level=logging.INFO) diff --git a/dimos/perception/object_tracker_3d.py b/dimos/perception/object_tracker_3d.py index da35577d0d..317a58dba0 100644 --- a/dimos/perception/object_tracker_3d.py +++ b/dimos/perception/object_tracker_3d.py @@ -24,12 +24,16 @@ from dimos.core.core import rpc from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import Pose, Quaternion, Transform, Vector3 -from dimos.msgs.sensor_msgs import Image, ImageFormat -from dimos.msgs.std_msgs import Header -from dimos.msgs.vision_msgs import Detection2DArray, Detection3DArray +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.msgs.std_msgs.Header import Header +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray +from dimos.msgs.vision_msgs.Detection3DArray import Detection3DArray from dimos.perception.object_tracker_2d import ObjectTracker2D -from dimos.protocol.tf import TF +from dimos.protocol.tf.tf import TF from dimos.types.timestamped import align_timestamped from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import ( diff --git a/dimos/perception/perceive_loop_skill.py b/dimos/perception/perceive_loop_skill.py index 0d84e40897..4532e61c2e 100644 --- a/dimos/perception/perceive_loop_skill.py +++ b/dimos/perception/perceive_loop_skill.py @@ -26,8 +26,7 @@ from dimos.core.module import Module from dimos.core.stream import In from dimos.models.vl.create import create -from dimos.msgs.sensor_msgs import Image -from dimos.msgs.sensor_msgs.Image import sharpness_window +from dimos.msgs.sensor_msgs.Image import Image, sharpness_window from dimos.utils.logging_config import setup_logger from dimos.utils.reactive import backpressure diff --git a/dimos/perception/spatial_perception.py b/dimos/perception/spatial_perception.py index 0cb4ab74c1..fe6d7d50e0 100644 --- a/dimos/perception/spatial_perception.py +++ b/dimos/perception/spatial_perception.py @@ -27,7 +27,6 @@ from reactivex import Observable, interval, operators as ops from reactivex.disposable import Disposable -from dimos import spec from dimos.agents_deprecated.memory.image_embedding import ImageEmbeddingProvider from dimos.agents_deprecated.memory.spatial_vector_db import SpatialVectorDB from dimos.agents_deprecated.memory.visual_memory import VisualMemory @@ -36,12 +35,13 @@ from dimos.core.module import Module, ModuleConfig from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.stream import In -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image +from dimos.spec.perception import Camera from dimos.types.robot_location import RobotLocation from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: - from dimos.msgs.geometry_msgs import Vector3 + from dimos.msgs.geometry_msgs.Vector3 import Vector3 _OUTPUT_DIR = DIMOS_PROJECT_ROOT / "assets" / "output" _MEMORY_DIR = _OUTPUT_DIR / "memory" @@ -577,7 +577,7 @@ def query_tagged_location(self, query: str) -> RobotLocation | None: def deploy( # type: ignore[no-untyped-def] dimos: ModuleCoordinator, - camera: spec.Camera, + camera: Camera, ): spatial_memory = dimos.deploy(SpatialMemory, db_path="/tmp/spatial_memory_db") # type: ignore[attr-defined] spatial_memory.color_image.connect(camera.color_image) diff --git a/dimos/perception/test_spatial_memory.py b/dimos/perception/test_spatial_memory.py index 433896aefe..322513d459 100644 --- a/dimos/perception/test_spatial_memory.py +++ b/dimos/perception/test_spatial_memory.py @@ -22,7 +22,7 @@ from reactivex import operators as ops from reactivex.scheduler import ThreadPoolScheduler -from dimos.msgs.geometry_msgs import Pose +from dimos.msgs.geometry_msgs.Pose import Pose from dimos.perception.spatial_perception import SpatialMemory from dimos.stream.video_provider import VideoProvider diff --git a/dimos/perception/test_spatial_memory_module.py b/dimos/perception/test_spatial_memory_module.py index 22aa4d4ce8..d8567036bf 100644 --- a/dimos/perception/test_spatial_memory_module.py +++ b/dimos/perception/test_spatial_memory_module.py @@ -24,13 +24,13 @@ from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.stream import Out from dimos.core.transport import LCMTransport -from dimos.msgs.geometry_msgs import Transform -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.sensor_msgs.Image import Image from dimos.perception.spatial_perception import SpatialMemory from dimos.robot.unitree.type.odometry import Odometry from dimos.utils.data import get_data from dimos.utils.logging_config import setup_logger -from dimos.utils.testing import TimedSensorReplay +from dimos.utils.testing.replay import TimedSensorReplay logger = setup_logger() diff --git a/dimos/protocol/__init__.py b/dimos/protocol/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/protocol/encode/__init__.py b/dimos/protocol/encode/encoder.py similarity index 82% rename from dimos/protocol/encode/__init__.py rename to dimos/protocol/encode/encoder.py index 87386a09e5..b6e00e4b1c 100644 --- a/dimos/protocol/encode/__init__.py +++ b/dimos/protocol/encode/encoder.py @@ -1,3 +1,17 @@ +# Copyright 2026 Dimensional Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from abc import ABC, abstractmethod import json from typing import Generic, Protocol, TypeVar diff --git a/dimos/protocol/pubsub/__init__.py b/dimos/protocol/pubsub/__init__.py deleted file mode 100644 index 94a58b60de..0000000000 --- a/dimos/protocol/pubsub/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -import dimos.protocol.pubsub.impl.lcmpubsub as lcm -from dimos.protocol.pubsub.impl.memory import Memory -from dimos.protocol.pubsub.spec import PubSub - -__all__ = [ - "Memory", - "PubSub", - "lcm", -] diff --git a/dimos/protocol/pubsub/encoders.py b/dimos/protocol/pubsub/encoders.py index 6b2056fa8b..69aa328765 100644 --- a/dimos/protocol/pubsub/encoders.py +++ b/dimos/protocol/pubsub/encoders.py @@ -20,8 +20,8 @@ import pickle from typing import TYPE_CHECKING, Generic, Protocol, TypeVar, cast -from dimos.msgs import DimosMsg -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.protocol import DimosMsg +from dimos.msgs.sensor_msgs.Image import Image if TYPE_CHECKING: from collections.abc import Callable diff --git a/dimos/protocol/pubsub/impl/__init__.py b/dimos/protocol/pubsub/impl/__init__.py deleted file mode 100644 index 63a5bfa6d6..0000000000 --- a/dimos/protocol/pubsub/impl/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from dimos.protocol.pubsub.impl.lcmpubsub import ( - LCM as LCM, - LCMPubSubBase as LCMPubSubBase, - PickleLCM as PickleLCM, -) -from dimos.protocol.pubsub.impl.memory import Memory as Memory diff --git a/dimos/protocol/pubsub/impl/lcmpubsub.py b/dimos/protocol/pubsub/impl/lcmpubsub.py index 4e792f5965..50c7c49f2f 100644 --- a/dimos/protocol/pubsub/impl/lcmpubsub.py +++ b/dimos/protocol/pubsub/impl/lcmpubsub.py @@ -20,7 +20,7 @@ import threading from typing import Any -from dimos.msgs import DimosMsg +from dimos.msgs.protocol import DimosMsg from dimos.protocol.pubsub.encoders import ( JpegEncoderMixin, LCMEncoderMixin, @@ -63,7 +63,7 @@ def from_channel_str(channel: str, default_lcm_type: type[DimosMsg] | None = Non Channel format: /topic#module.ClassName Falls back to default_lcm_type if type cannot be parsed. """ - from dimos.msgs import resolve_msg_type + from dimos.msgs.helpers import resolve_msg_type if "#" not in channel: return Topic(topic=channel, lcm_type=default_lcm_type) diff --git a/dimos/protocol/pubsub/impl/memory.py b/dimos/protocol/pubsub/impl/memory.py index 3425a5ee3d..25e10efe32 100644 --- a/dimos/protocol/pubsub/impl/memory.py +++ b/dimos/protocol/pubsub/impl/memory.py @@ -16,7 +16,7 @@ from collections.abc import Callable from typing import Any -from dimos.protocol import encode +from dimos.protocol.encode import encoder as encode from dimos.protocol.pubsub.encoders import PubSubEncoderMixin from dimos.protocol.pubsub.spec import PubSub diff --git a/dimos/protocol/pubsub/impl/rospubsub.py b/dimos/protocol/pubsub/impl/rospubsub.py index 1a3c989a4d..1e18b3759a 100644 --- a/dimos/protocol/pubsub/impl/rospubsub.py +++ b/dimos/protocol/pubsub/impl/rospubsub.py @@ -37,7 +37,7 @@ import uuid -from dimos.msgs import DimosMsg +from dimos.msgs.protocol import DimosMsg from dimos.protocol.pubsub.impl.rospubsub_conversion import ( derive_ros_type, dimos_to_ros, diff --git a/dimos/protocol/pubsub/impl/rospubsub_conversion.py b/dimos/protocol/pubsub/impl/rospubsub_conversion.py index 275033a5ac..150c3eeb8f 100644 --- a/dimos/protocol/pubsub/impl/rospubsub_conversion.py +++ b/dimos/protocol/pubsub/impl/rospubsub_conversion.py @@ -29,7 +29,7 @@ from typing import TYPE_CHECKING, Any, cast if TYPE_CHECKING: - from dimos.msgs import DimosMsg + from dimos.msgs.protocol import DimosMsg from dimos.protocol.pubsub.impl.rospubsub import ROSMessage diff --git a/dimos/protocol/pubsub/impl/test_lcmpubsub.py b/dimos/protocol/pubsub/impl/test_lcmpubsub.py index ea80b4c445..ba29c70958 100644 --- a/dimos/protocol/pubsub/impl/test_lcmpubsub.py +++ b/dimos/protocol/pubsub/impl/test_lcmpubsub.py @@ -18,7 +18,9 @@ import pytest -from dimos.msgs.geometry_msgs import Pose, Quaternion, Vector3 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.protocol.pubsub.impl.lcmpubsub import ( LCM, LCMPubSubBase, diff --git a/dimos/protocol/pubsub/impl/test_rospubsub.py b/dimos/protocol/pubsub/impl/test_rospubsub.py index 5f574065ba..ef9df74227 100644 --- a/dimos/protocol/pubsub/impl/test_rospubsub.py +++ b/dimos/protocol/pubsub/impl/test_rospubsub.py @@ -28,7 +28,7 @@ # Add msg_name to LCM PointStamped for testing nested message conversion PointStamped.msg_name = "geometry_msgs.PointStamped" from dimos.utils.data import get_data -from dimos.utils.testing import TimedSensorReplay +from dimos.utils.testing.replay import TimedSensorReplay def ros_node(): diff --git a/dimos/protocol/pubsub/test_pattern_sub.py b/dimos/protocol/pubsub/test_pattern_sub.py index cdbce5d5a6..ac94ba1b3b 100644 --- a/dimos/protocol/pubsub/test_pattern_sub.py +++ b/dimos/protocol/pubsub/test_pattern_sub.py @@ -24,7 +24,9 @@ import pytest -from dimos.msgs.geometry_msgs import Pose, Quaternion, Vector3 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.protocol.pubsub.impl.lcmpubsub import LCM, LCMPubSubBase, Topic from dimos.protocol.pubsub.patterns import Glob from dimos.protocol.pubsub.spec import AllPubSub, PubSub diff --git a/dimos/protocol/pubsub/test_spec.py b/dimos/protocol/pubsub/test_spec.py index a240319fdf..e36741bbfd 100644 --- a/dimos/protocol/pubsub/test_spec.py +++ b/dimos/protocol/pubsub/test_spec.py @@ -23,7 +23,7 @@ import pytest -from dimos.msgs.geometry_msgs import Vector3 +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.protocol.pubsub.impl.lcmpubsub import LCM, Topic from dimos.protocol.pubsub.impl.memory import Memory diff --git a/dimos/protocol/rpc/__init__.py b/dimos/protocol/rpc/__init__.py deleted file mode 100644 index 1eb892d956..0000000000 --- a/dimos/protocol/rpc/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from dimos.protocol.rpc.pubsubrpc import LCMRPC, ShmRPC -from dimos.protocol.rpc.spec import RPCClient, RPCServer, RPCSpec - -__all__ = ["LCMRPC", "RPCClient", "RPCServer", "RPCSpec", "ShmRPC"] diff --git a/dimos/protocol/rpc/test_lcmrpc.py b/dimos/protocol/rpc/test_lcmrpc.py index f31d20cf19..5baa5ac40c 100644 --- a/dimos/protocol/rpc/test_lcmrpc.py +++ b/dimos/protocol/rpc/test_lcmrpc.py @@ -17,7 +17,7 @@ import pytest from dimos.constants import LCM_MAX_CHANNEL_NAME_LENGTH -from dimos.protocol.rpc import LCMRPC +from dimos.protocol.rpc.pubsubrpc import LCMRPC @pytest.fixture diff --git a/dimos/protocol/service/__init__.py b/dimos/protocol/service/__init__.py deleted file mode 100644 index ed6caf93c2..0000000000 --- a/dimos/protocol/service/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from dimos.protocol.service.lcmservice import LCMService -from dimos.protocol.service.spec import BaseConfig, Configurable, Service - -__all__ = ( - "BaseConfig", - "Configurable", - "LCMService", - "Service", -) diff --git a/dimos/protocol/service/lcmservice.py b/dimos/protocol/service/lcmservice.py index 9a563addb1..0211b34129 100644 --- a/dimos/protocol/service/lcmservice.py +++ b/dimos/protocol/service/lcmservice.py @@ -25,7 +25,8 @@ import lcm as lcm_mod from dimos.protocol.service.spec import BaseConfig, Service -from dimos.protocol.service.system_configurator import configure_system, lcm_configurators +from dimos.protocol.service.system_configurator.base import configure_system +from dimos.protocol.service.system_configurator.lcm_config import lcm_configurators from dimos.utils.logging_config import setup_logger if sys.version_info < (3, 13): diff --git a/dimos/protocol/service/system_configurator/__init__.py b/dimos/protocol/service/system_configurator/lcm_config.py similarity index 54% rename from dimos/protocol/service/system_configurator/__init__.py rename to dimos/protocol/service/system_configurator/lcm_config.py index 31b5af4d8c..72f1e5d774 100644 --- a/dimos/protocol/service/system_configurator/__init__.py +++ b/dimos/protocol/service/system_configurator/lcm_config.py @@ -12,18 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""System configurator package — re-exports for backward compatibility.""" +"""Platform-appropriate LCM system configurators.""" import platform -from dimos.protocol.service.system_configurator.base import ( - SystemConfigurator, - configure_system, - sudo_run, -) -from dimos.protocol.service.system_configurator.clock_sync import ClockSyncConfigurator +from dimos.protocol.service.system_configurator.base import SystemConfigurator from dimos.protocol.service.system_configurator.lcm import ( - IDEAL_RMEM_SIZE, BufferConfiguratorLinux, BufferConfiguratorMacOS, MaxFileConfiguratorMacOS, @@ -33,17 +27,6 @@ from dimos.protocol.service.system_configurator.libpython import LibPythonConfiguratorMacOS -# TODO: This is a configurator API issue and inserted here temporarily -# -# We need to use different configurators based on the underlying OS -# -# We should have separation of concerns, nothing but configurators themselves care about the OS in this context -# -# So configurators with multi-os behavior should be responsible for the right per-OS behaviour, and -# not external systems -# -# We might want to have some sort of recursive configurators -# def lcm_configurators() -> list[SystemConfigurator]: """Return the platform-appropriate LCM system configurators.""" system = platform.system() @@ -56,23 +39,7 @@ def lcm_configurators() -> list[SystemConfigurator]: return [ MulticastConfiguratorMacOS(loopback_interface="lo0"), BufferConfiguratorMacOS(), - MaxFileConfiguratorMacOS(), # TODO: this is not LCM related and shouldn't be here at all + MaxFileConfiguratorMacOS(), LibPythonConfiguratorMacOS(), ] return [] - - -__all__ = [ - "IDEAL_RMEM_SIZE", - "BufferConfiguratorLinux", - "BufferConfiguratorMacOS", - "ClockSyncConfigurator", - "LibPythonConfiguratorMacOS", - "MaxFileConfiguratorMacOS", - "MulticastConfiguratorLinux", - "MulticastConfiguratorMacOS", - "SystemConfigurator", - "configure_system", - "lcm_configurators", - "sudo_run", -] diff --git a/dimos/protocol/service/test_lcmservice.py b/dimos/protocol/service/test_lcmservice.py index 78085e2363..cbab6ff3ab 100644 --- a/dimos/protocol/service/test_lcmservice.py +++ b/dimos/protocol/service/test_lcmservice.py @@ -25,14 +25,14 @@ LCMService, autoconf, ) -from dimos.protocol.service.system_configurator import ( +from dimos.protocol.service.system_configurator.lcm import ( BufferConfiguratorLinux, BufferConfiguratorMacOS, - LibPythonConfiguratorMacOS, MaxFileConfiguratorMacOS, MulticastConfiguratorLinux, MulticastConfiguratorMacOS, ) +from dimos.protocol.service.system_configurator.libpython import LibPythonConfiguratorMacOS # autoconf tests @@ -40,7 +40,8 @@ class TestConfigureSystemForLcm: def test_creates_linux_checks_on_linux(self) -> None: with patch( - "dimos.protocol.service.system_configurator.platform.system", return_value="Linux" + "dimos.protocol.service.system_configurator.lcm_config.platform.system", + return_value="Linux", ): with patch("dimos.protocol.service.lcmservice.configure_system") as mock_configure: autoconf() @@ -53,7 +54,8 @@ def test_creates_linux_checks_on_linux(self) -> None: def test_creates_macos_checks_on_darwin(self) -> None: with patch( - "dimos.protocol.service.system_configurator.platform.system", return_value="Darwin" + "dimos.protocol.service.system_configurator.lcm_config.platform.system", + return_value="Darwin", ): with patch("dimos.protocol.service.lcmservice.configure_system") as mock_configure: autoconf() @@ -68,7 +70,8 @@ def test_creates_macos_checks_on_darwin(self) -> None: def test_passes_check_only_flag(self) -> None: with patch( - "dimos.protocol.service.system_configurator.platform.system", return_value="Linux" + "dimos.protocol.service.system_configurator.lcm_config.platform.system", + return_value="Linux", ): with patch("dimos.protocol.service.lcmservice.configure_system") as mock_configure: autoconf(check_only=True) @@ -77,7 +80,8 @@ def test_passes_check_only_flag(self) -> None: def test_logs_error_on_unsupported_system(self) -> None: with patch( - "dimos.protocol.service.system_configurator.platform.system", return_value="Windows" + "dimos.protocol.service.system_configurator.lcm_config.platform.system", + return_value="Windows", ): with patch("dimos.protocol.service.lcmservice.configure_system") as mock_configure: with patch("dimos.protocol.service.lcmservice.logger") as mock_logger: diff --git a/dimos/protocol/service/test_system_configurator.py b/dimos/protocol/service/test_system_configurator.py index 1bd44aa5e2..715d9eede7 100644 --- a/dimos/protocol/service/test_system_configurator.py +++ b/dimos/protocol/service/test_system_configurator.py @@ -19,22 +19,22 @@ import pytest -from dimos.protocol.service.system_configurator import ( +from dimos.protocol.service.system_configurator.base import ( + SystemConfigurator, + _is_root_user, + _read_sysctl_int, + _write_sysctl_int, + configure_system, + sudo_run, +) +from dimos.protocol.service.system_configurator.clock_sync import ClockSyncConfigurator +from dimos.protocol.service.system_configurator.lcm import ( IDEAL_RMEM_SIZE, BufferConfiguratorLinux, BufferConfiguratorMacOS, - ClockSyncConfigurator, MaxFileConfiguratorMacOS, MulticastConfiguratorLinux, MulticastConfiguratorMacOS, - SystemConfigurator, - configure_system, - sudo_run, -) -from dimos.protocol.service.system_configurator.base import ( - _is_root_user, - _read_sysctl_int, - _write_sysctl_int, ) # Helper function tests diff --git a/dimos/protocol/tf/__init__.py b/dimos/protocol/tf/__init__.py deleted file mode 100644 index cb00dbde3c..0000000000 --- a/dimos/protocol/tf/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from dimos.protocol.tf.tf import LCMTF, TF, MultiTBuffer, PubSubTF, TBuffer, TFConfig, TFSpec - -__all__ = ["LCMTF", "TF", "MultiTBuffer", "PubSubTF", "TBuffer", "TFConfig", "TFSpec"] diff --git a/dimos/protocol/tf/test_tf.py b/dimos/protocol/tf/test_tf.py index c1f0b13fa2..b0843bfccd 100644 --- a/dimos/protocol/tf/test_tf.py +++ b/dimos/protocol/tf/test_tf.py @@ -19,8 +19,11 @@ import pytest -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Transform, Vector3 -from dimos.protocol.tf import TF, MultiTBuffer, TBuffer +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.protocol.tf.tf import TF, MultiTBuffer, TBuffer # from https://foxglove.dev/blog/understanding-ros-transforms diff --git a/dimos/protocol/tf/tf.py b/dimos/protocol/tf/tf.py index 1b5ccadf3c..97b2132bbb 100644 --- a/dimos/protocol/tf/tf.py +++ b/dimos/protocol/tf/tf.py @@ -21,8 +21,9 @@ from typing import TypeVar from dimos.memory.timeseries.inmemory import InMemoryStore -from dimos.msgs.geometry_msgs import PoseStamped, Transform -from dimos.msgs.tf2_msgs import TFMessage +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.tf2_msgs.TFMessage import TFMessage from dimos.protocol.pubsub.impl.lcmpubsub import LCM, Topic from dimos.protocol.pubsub.spec import PubSub from dimos.protocol.service.spec import BaseConfig, Service diff --git a/dimos/protocol/tf/tflcmcpp.py b/dimos/protocol/tf/tflcmcpp.py index bf2885958d..aec1f947ce 100644 --- a/dimos/protocol/tf/tflcmcpp.py +++ b/dimos/protocol/tf/tflcmcpp.py @@ -14,7 +14,7 @@ from datetime import datetime -from dimos.msgs.geometry_msgs import Transform +from dimos.msgs.geometry_msgs.Transform import Transform from dimos.protocol.service.lcmservice import LCMConfig, LCMService from dimos.protocol.tf.tf import TFConfig, TFSpec diff --git a/dimos/robot/__init__.py b/dimos/robot/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/robot/drone/__init__.py b/dimos/robot/drone/__init__.py deleted file mode 100644 index 828059e99d..0000000000 --- a/dimos/robot/drone/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Generic drone module for MAVLink-based drones.""" - -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "camera_module": ["DroneCameraModule"], - "connection_module": ["DroneConnectionModule"], - "mavlink_connection": ["MavlinkConnection"], - }, -) diff --git a/dimos/robot/drone/blueprints/__init__.py b/dimos/robot/drone/blueprints/__init__.py deleted file mode 100644 index d011c6e4fb..0000000000 --- a/dimos/robot/drone/blueprints/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""DimOS Drone blueprints.""" - -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "basic.drone_basic": ["drone_basic"], - "agentic.drone_agentic": ["drone_agentic"], - }, -) diff --git a/dimos/robot/drone/blueprints/agentic/__init__.py b/dimos/robot/drone/blueprints/agentic/__init__.py deleted file mode 100644 index a7386b8f45..0000000000 --- a/dimos/robot/drone/blueprints/agentic/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Agentic drone blueprint.""" - -from dimos.robot.drone.blueprints.agentic.drone_agentic import drone_agentic - -__all__ = ["drone_agentic"] diff --git a/dimos/robot/drone/blueprints/basic/__init__.py b/dimos/robot/drone/blueprints/basic/__init__.py deleted file mode 100644 index 3bf4ec60ff..0000000000 --- a/dimos/robot/drone/blueprints/basic/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Basic drone blueprint.""" - -from dimos.robot.drone.blueprints.basic.drone_basic import drone_basic - -__all__ = ["drone_basic"] diff --git a/dimos/robot/drone/camera_module.py b/dimos/robot/drone/camera_module.py index 63389aa358..5343549c66 100644 --- a/dimos/robot/drone/camera_module.py +++ b/dimos/robot/drone/camera_module.py @@ -26,9 +26,9 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import Image -from dimos.msgs.std_msgs import Header +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.std_msgs.Header import Header from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/robot/drone/connection_module.py b/dimos/robot/drone/connection_module.py index c606e7467e..863f719bad 100644 --- a/dimos/robot/drone/connection_module.py +++ b/dimos/robot/drone/connection_module.py @@ -28,9 +28,13 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.mapping.types import LatLon -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Transform, Twist, Vector3 -from dimos.msgs.sensor_msgs import Image +from dimos.mapping.models import LatLon +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.Image import Image from dimos.robot.drone.dji_video_stream import DJIDroneVideoStream from dimos.robot.drone.mavlink_connection import MavlinkConnection from dimos.utils.logging_config import setup_logger diff --git a/dimos/robot/drone/dji_video_stream.py b/dimos/robot/drone/dji_video_stream.py index 1810fd4212..60618ae712 100644 --- a/dimos/robot/drone/dji_video_stream.py +++ b/dimos/robot/drone/dji_video_stream.py @@ -26,7 +26,7 @@ import numpy as np from reactivex import Observable, Subject -from dimos.msgs.sensor_msgs import Image, ImageFormat +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat from dimos.utils.logging_config import setup_logger logger = setup_logger() @@ -214,7 +214,7 @@ def get_stream(self) -> Observable[Image]: # type: ignore[override] """ from reactivex import operators as ops - from dimos.utils.testing import TimedSensorReplay + from dimos.utils.testing.replay import TimedSensorReplay def _fix_format(img: Image) -> Image: if img.format == ImageFormat.BGR: diff --git a/dimos/robot/drone/drone_tracking_module.py b/dimos/robot/drone/drone_tracking_module.py index 276b636633..5798db374b 100644 --- a/dimos/robot/drone/drone_tracking_module.py +++ b/dimos/robot/drone/drone_tracking_module.py @@ -29,8 +29,9 @@ from dimos.core.module import Module from dimos.core.stream import In, Out from dimos.models.qwen.video_query import get_bbox_from_qwen_frame -from dimos.msgs.geometry_msgs import Twist, Vector3 -from dimos.msgs.sensor_msgs import Image, ImageFormat +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat from dimos.robot.drone.drone_visual_servoing_controller import ( DroneVisualServoingController, PIDParams, diff --git a/dimos/robot/drone/mavlink_connection.py b/dimos/robot/drone/mavlink_connection.py index d8a7c97c4a..076d9cd369 100644 --- a/dimos/robot/drone/mavlink_connection.py +++ b/dimos/robot/drone/mavlink_connection.py @@ -23,7 +23,10 @@ from pymavlink import mavutil # type: ignore[import-not-found, import-untyped] from reactivex import Subject -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Twist, Vector3 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.utils.logging_config import setup_logger logger = setup_logger(level=logging.INFO) @@ -1028,7 +1031,7 @@ def __init__(self, connection_string: str) -> None: class FakeMavlink: def __init__(self) -> None: from dimos.utils.data import get_data - from dimos.utils.testing import TimedSensorReplay + from dimos.utils.testing.replay import TimedSensorReplay get_data("drone") diff --git a/dimos/robot/drone/test_drone.py b/dimos/robot/drone/test_drone.py index 88c45c9aa8..0b30c22c35 100644 --- a/dimos/robot/drone/test_drone.py +++ b/dimos/robot/drone/test_drone.py @@ -25,8 +25,10 @@ import numpy as np -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 -from dimos.msgs.sensor_msgs import Image, ImageFormat +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat from dimos.robot.drone.connection_module import DroneConnectionModule from dimos.robot.drone.dji_video_stream import FakeDJIVideoStream @@ -192,7 +194,7 @@ class TestReplayMode(unittest.TestCase): def test_fake_mavlink_connection(self) -> None: """Test FakeMavlinkConnection replays messages correctly.""" - with patch("dimos.utils.testing.TimedSensorReplay") as mock_replay: + with patch("dimos.utils.testing.replay.TimedSensorReplay") as mock_replay: # Mock the replay stream MagicMock() mock_messages = [ @@ -218,7 +220,7 @@ def test_fake_mavlink_connection(self) -> None: def test_fake_video_stream_no_throttling(self) -> None: """Test FakeDJIVideoStream returns replay stream with format fix.""" - with patch("dimos.utils.testing.TimedSensorReplay") as mock_replay: + with patch("dimos.utils.testing.replay.TimedSensorReplay") as mock_replay: mock_stream = MagicMock() mock_replay.return_value.stream.return_value = mock_stream @@ -280,7 +282,7 @@ def test_connection_module_replay_with_messages(self) -> None: os.environ["DRONE_CONNECTION"] = "replay" - with patch("dimos.utils.testing.TimedSensorReplay") as mock_replay: + with patch("dimos.utils.testing.replay.TimedSensorReplay") as mock_replay: # Set up MAVLink replay stream mavlink_messages = [ {"mavpackettype": "HEARTBEAT", "type": 2, "base_mode": 193}, @@ -433,7 +435,7 @@ def tearDown(self) -> None: self.foxglove_patch.stop() @patch("dimos.robot.drone.drone.ModuleCoordinator") - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") def test_full_system_with_replay(self, mock_replay, mock_coordinator_class) -> None: """Test full drone system initialization and operation with replay mode.""" # Set up mock replay data @@ -567,7 +569,7 @@ def deploy_side_effect(module_class, **kwargs): class TestDroneControlCommands(unittest.TestCase): """Test drone control commands with FakeMavlinkConnection.""" - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_arm_disarm_commands(self, mock_get_data, mock_replay) -> None: """Test arm and disarm commands work with fake connection.""" @@ -586,7 +588,7 @@ def test_arm_disarm_commands(self, mock_get_data, mock_replay) -> None: result = conn.disarm() self.assertIsInstance(result, bool) # Should return bool without crashing - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_takeoff_land_commands(self, mock_get_data, mock_replay) -> None: """Test takeoff and land commands with fake connection.""" @@ -605,7 +607,7 @@ def test_takeoff_land_commands(self, mock_get_data, mock_replay) -> None: result = conn.land() self.assertIsNotNone(result) - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_set_mode_command(self, mock_get_data, mock_replay) -> None: """Test flight mode setting with fake connection.""" @@ -626,7 +628,7 @@ def test_set_mode_command(self, mock_get_data, mock_replay) -> None: class TestDronePerception(unittest.TestCase): """Test drone perception capabilities.""" - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_video_stream_replay(self, mock_get_data, mock_replay) -> None: """Test video stream works with replay data.""" @@ -696,7 +698,7 @@ def piped_subscribe(callback): # type: ignore[no-untyped-def] class TestDroneMovementAndOdometry(unittest.TestCase): """Test drone movement commands and odometry.""" - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_movement_command_conversion(self, mock_get_data, mock_replay) -> None: """Test movement commands are properly converted from ROS to NED.""" @@ -716,7 +718,7 @@ def test_movement_command_conversion(self, mock_get_data, mock_replay) -> None: # Movement should be converted to NED internally # The fake connection doesn't actually send commands, but it should not crash - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_odometry_from_replay(self, mock_get_data, mock_replay) -> None: """Test odometry is properly generated from replay messages.""" @@ -763,7 +765,7 @@ def replay_stream_subscribe(callback) -> None: self.assertIsNotNone(odom.orientation) self.assertEqual(odom.frame_id, "world") - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_position_integration_indoor(self, mock_get_data, mock_replay) -> None: """Test position integration for indoor flight without GPS.""" @@ -808,7 +810,7 @@ def replay_stream_subscribe(callback) -> None: class TestDroneStatusAndTelemetry(unittest.TestCase): """Test drone status and telemetry reporting.""" - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_status_extraction(self, mock_get_data, mock_replay) -> None: """Test status is properly extracted from MAVLink messages.""" @@ -853,7 +855,7 @@ def replay_stream_subscribe(callback) -> None: self.assertIn("altitude", status) self.assertIn("heading", status) - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_telemetry_json_publishing(self, mock_get_data, mock_replay) -> None: """Test full telemetry is published as JSON.""" @@ -907,7 +909,7 @@ def replay_stream_subscribe(callback) -> None: class TestFlyToErrorHandling(unittest.TestCase): """Test fly_to() error handling paths.""" - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_concurrency_lock(self, mock_get_data, mock_replay) -> None: """flying_to_target=True rejects concurrent fly_to() calls.""" @@ -921,7 +923,7 @@ def test_concurrency_lock(self, mock_get_data, mock_replay) -> None: result = conn.fly_to(37.0, -122.0, 10.0) self.assertIn("Already flying to target", result) - @patch("dimos.utils.testing.TimedSensorReplay") + @patch("dimos.utils.testing.replay.TimedSensorReplay") @patch("dimos.utils.data.get_data") def test_error_when_not_connected(self, mock_get_data, mock_replay) -> None: """connected=False returns error immediately.""" diff --git a/dimos/robot/manipulators/__init__.py b/dimos/robot/manipulators/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/robot/manipulators/piper/__init__.py b/dimos/robot/manipulators/piper/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/robot/manipulators/piper/blueprints.py b/dimos/robot/manipulators/piper/blueprints.py index 68e02fc994..ead27fd54b 100644 --- a/dimos/robot/manipulators/piper/blueprints.py +++ b/dimos/robot/manipulators/piper/blueprints.py @@ -27,9 +27,11 @@ from dimos.core.blueprints import autoconnect from dimos.core.transport import LCMTransport from dimos.manipulation.manipulation_module import manipulation_module -from dimos.manipulation.planning.spec import RobotModelConfig -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 -from dimos.msgs.sensor_msgs import JointState +from dimos.manipulation.planning.spec.config import RobotModelConfig +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.teleop.keyboard.keyboard_teleop_module import keyboard_teleop_module from dimos.utils.data import LfsPath, get_data diff --git a/dimos/robot/manipulators/xarm/__init__.py b/dimos/robot/manipulators/xarm/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/robot/manipulators/xarm/blueprints.py b/dimos/robot/manipulators/xarm/blueprints.py index 9a1732217b..e699057b44 100644 --- a/dimos/robot/manipulators/xarm/blueprints.py +++ b/dimos/robot/manipulators/xarm/blueprints.py @@ -32,8 +32,8 @@ _make_xarm7_config, ) from dimos.manipulation.manipulation_module import manipulation_module -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.JointState import JointState from dimos.teleop.keyboard.keyboard_teleop_module import keyboard_teleop_module from dimos.utils.data import LfsPath diff --git a/dimos/robot/unitree/__init__.py b/dimos/robot/unitree/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/robot/unitree/b1/__init__.py b/dimos/robot/unitree/b1/__init__.py deleted file mode 100644 index db85984070..0000000000 --- a/dimos/robot/unitree/b1/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. - -"""Unitree B1 robot module.""" - -from .unitree_b1 import UnitreeB1 - -__all__ = ["UnitreeB1"] diff --git a/dimos/robot/unitree/b1/connection.py b/dimos/robot/unitree/b1/connection.py index 445044020d..11af31b296 100644 --- a/dimos/robot/unitree/b1/connection.py +++ b/dimos/robot/unitree/b1/connection.py @@ -28,9 +28,11 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import PoseStamped, Twist, TwistStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped from dimos.msgs.nav_msgs.Odometry import Odometry -from dimos.msgs.std_msgs import Int32 +from dimos.msgs.std_msgs.Int32 import Int32 from dimos.msgs.tf2_msgs.TFMessage import TFMessage from dimos.utils.logging_config import setup_logger diff --git a/dimos/robot/unitree/b1/joystick_module.py b/dimos/robot/unitree/b1/joystick_module.py index 9fbfd84f1e..234ff129c9 100644 --- a/dimos/robot/unitree/b1/joystick_module.py +++ b/dimos/robot/unitree/b1/joystick_module.py @@ -28,8 +28,10 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import Twist, TwistStamped, Vector3 -from dimos.msgs.std_msgs import Int32 +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.std_msgs.Int32 import Int32 class JoystickModule(Module): diff --git a/dimos/robot/unitree/b1/test_connection.py b/dimos/robot/unitree/b1/test_connection.py index e43a3124dc..f1ff5ad861 100644 --- a/dimos/robot/unitree/b1/test_connection.py +++ b/dimos/robot/unitree/b1/test_connection.py @@ -25,7 +25,8 @@ import threading import time -from dimos.msgs.geometry_msgs import TwistStamped, Vector3 +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.msgs.std_msgs.Int32 import Int32 from .connection import MockB1ConnectionModule diff --git a/dimos/robot/unitree/b1/unitree_b1.py b/dimos/robot/unitree/b1/unitree_b1.py index 6b374d1d5b..9a6d04a7ff 100644 --- a/dimos/robot/unitree/b1/unitree_b1.py +++ b/dimos/robot/unitree/b1/unitree_b1.py @@ -26,9 +26,10 @@ from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.resource import Resource from dimos.core.transport import LCMTransport, ROSTransport -from dimos.msgs.geometry_msgs import PoseStamped, TwistStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped from dimos.msgs.nav_msgs.Odometry import Odometry -from dimos.msgs.std_msgs import Int32 +from dimos.msgs.std_msgs.Int32 import Int32 from dimos.msgs.tf2_msgs.TFMessage import TFMessage from dimos.robot.robot import Robot from dimos.robot.unitree.b1.connection import ( diff --git a/dimos/robot/unitree/connection.py b/dimos/robot/unitree/connection.py index ff73d922ee..7e60080f01 100644 --- a/dimos/robot/unitree/connection.py +++ b/dimos/robot/unitree/connection.py @@ -35,9 +35,11 @@ ) from dimos.core.resource import Resource -from dimos.msgs.geometry_msgs import Pose, Transform, Twist -from dimos.msgs.sensor_msgs import Image, PointCloud2 -from dimos.msgs.sensor_msgs.Image import ImageFormat +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.lidar import RawLidarMsg, pointcloud2_from_webrtc_lidar from dimos.robot.unitree.type.lowstate import LowStateMsg from dimos.robot.unitree.type.odometry import Odometry diff --git a/dimos/robot/unitree/g1/blueprints/__init__.py b/dimos/robot/unitree/g1/blueprints/__init__.py deleted file mode 100644 index ebc18da8d3..0000000000 --- a/dimos/robot/unitree/g1/blueprints/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Cascaded G1 blueprints split into focused modules.""" - -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "agentic._agentic_skills": ["_agentic_skills"], - "agentic.unitree_g1_agentic": ["unitree_g1_agentic"], - "agentic.unitree_g1_agentic_sim": ["unitree_g1_agentic_sim"], - "agentic.unitree_g1_full": ["unitree_g1_full"], - "basic.unitree_g1_basic": ["unitree_g1_basic"], - "basic.unitree_g1_basic_sim": ["unitree_g1_basic_sim"], - "basic.unitree_g1_joystick": ["unitree_g1_joystick"], - "perceptive._perception_and_memory": ["_perception_and_memory"], - "perceptive.unitree_g1": ["unitree_g1"], - "perceptive.unitree_g1_detection": ["unitree_g1_detection"], - "perceptive.unitree_g1_shm": ["unitree_g1_shm"], - "perceptive.unitree_g1_sim": ["unitree_g1_sim"], - "primitive.uintree_g1_primitive_no_nav": ["uintree_g1_primitive_no_nav", "basic_no_nav"], - }, -) diff --git a/dimos/robot/unitree/g1/blueprints/agentic/__init__.py b/dimos/robot/unitree/g1/blueprints/agentic/__init__.py deleted file mode 100644 index 5e6db90d91..0000000000 --- a/dimos/robot/unitree/g1/blueprints/agentic/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Agentic blueprints for Unitree G1.""" diff --git a/dimos/robot/unitree/g1/blueprints/basic/__init__.py b/dimos/robot/unitree/g1/blueprints/basic/__init__.py deleted file mode 100644 index 87e6586f56..0000000000 --- a/dimos/robot/unitree/g1/blueprints/basic/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Basic blueprints for Unitree G1.""" diff --git a/dimos/robot/unitree/g1/blueprints/perceptive/__init__.py b/dimos/robot/unitree/g1/blueprints/perceptive/__init__.py deleted file mode 100644 index 9bd838e8b8..0000000000 --- a/dimos/robot/unitree/g1/blueprints/perceptive/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Perceptive blueprints for Unitree G1.""" diff --git a/dimos/robot/unitree/g1/blueprints/perceptive/unitree_g1_detection.py b/dimos/robot/unitree/g1/blueprints/perceptive/unitree_g1_detection.py index 25bff97c73..18884bd7af 100644 --- a/dimos/robot/unitree/g1/blueprints/perceptive/unitree_g1_detection.py +++ b/dimos/robot/unitree/g1/blueprints/perceptive/unitree_g1_detection.py @@ -22,10 +22,11 @@ from dimos.core.blueprints import autoconnect from dimos.core.transport import LCMTransport -from dimos.hardware.sensors.camera import zed -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import Image, PointCloud2 -from dimos.msgs.vision_msgs import Detection2DArray +from dimos.hardware.sensors.camera.zed import compat as zed +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray from dimos.perception.detection.detectors.person.yolo import YoloPersonDetector from dimos.perception.detection.module3D import Detection3DModule, detection3d_module from dimos.perception.detection.moduleDB import ObjectDBModule, detection_db_module diff --git a/dimos/robot/unitree/g1/blueprints/perceptive/unitree_g1_shm.py b/dimos/robot/unitree/g1/blueprints/perceptive/unitree_g1_shm.py index 5ee4d4c9d1..be67194b62 100644 --- a/dimos/robot/unitree/g1/blueprints/perceptive/unitree_g1_shm.py +++ b/dimos/robot/unitree/g1/blueprints/perceptive/unitree_g1_shm.py @@ -18,7 +18,7 @@ from dimos.constants import DEFAULT_CAPACITY_COLOR_IMAGE from dimos.core.blueprints import autoconnect from dimos.core.transport import pSHMTransport -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.robot.foxglove_bridge import foxglove_bridge from dimos.robot.unitree.g1.blueprints.perceptive.unitree_g1 import unitree_g1 diff --git a/dimos/robot/unitree/g1/blueprints/primitive/__init__.py b/dimos/robot/unitree/g1/blueprints/primitive/__init__.py deleted file mode 100644 index 833f767728..0000000000 --- a/dimos/robot/unitree/g1/blueprints/primitive/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Primitive blueprints for Unitree G1.""" diff --git a/dimos/robot/unitree/g1/blueprints/primitive/uintree_g1_primitive_no_nav.py b/dimos/robot/unitree/g1/blueprints/primitive/uintree_g1_primitive_no_nav.py index c47fdc377b..242fcaf38f 100644 --- a/dimos/robot/unitree/g1/blueprints/primitive/uintree_g1_primitive_no_nav.py +++ b/dimos/robot/unitree/g1/blueprints/primitive/uintree_g1_primitive_no_nav.py @@ -22,16 +22,24 @@ from dimos.core.blueprints import autoconnect from dimos.core.global_config import global_config from dimos.core.transport import LCMTransport -from dimos.hardware.sensors.camera import zed from dimos.hardware.sensors.camera.module import camera_module # type: ignore[attr-defined] from dimos.hardware.sensors.camera.webcam import Webcam +from dimos.hardware.sensors.camera.zed import compat as zed from dimos.mapping.costmapper import cost_mapper from dimos.mapping.voxels import voxel_mapper -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Transform, Twist, Vector3 -from dimos.msgs.nav_msgs import Odometry, Path -from dimos.msgs.sensor_msgs import Image, PointCloud2 -from dimos.msgs.std_msgs import Bool -from dimos.navigation.frontier_exploration import wavefront_frontier_explorer +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.nav_msgs.Odometry import Odometry +from dimos.msgs.nav_msgs.Path import Path +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.std_msgs.Bool import Bool +from dimos.navigation.frontier_exploration.wavefront_frontier_goal_selector import ( + wavefront_frontier_explorer, +) from dimos.protocol.pubsub.impl.lcmpubsub import LCM from dimos.web.websocket_vis.websocket_vis_module import websocket_vis diff --git a/dimos/robot/unitree/g1/connection.py b/dimos/robot/unitree/g1/connection.py index 94f725ac7e..1f3788de98 100644 --- a/dimos/robot/unitree/g1/connection.py +++ b/dimos/robot/unitree/g1/connection.py @@ -19,13 +19,13 @@ from pydantic import Field from reactivex.disposable import Disposable -from dimos import spec from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.stream import In -from dimos.msgs.geometry_msgs import Twist +from dimos.msgs.geometry_msgs.Twist import Twist from dimos.robot.unitree.connection import UnitreeWebRTCConnection +from dimos.spec.control import LocalPlanner from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: @@ -115,7 +115,7 @@ def publish_request(self, topic: str, data: dict[str, Any]) -> dict[Any, Any]: g1_connection = G1Connection.blueprint -def deploy(dimos: ModuleCoordinator, ip: str, local_planner: spec.LocalPlanner) -> "ModuleProxy": +def deploy(dimos: ModuleCoordinator, ip: str, local_planner: LocalPlanner) -> "ModuleProxy": connection = dimos.deploy(G1Connection, ip=ip) connection.cmd_vel.connect(local_planner.cmd_vel) connection.start() diff --git a/dimos/robot/unitree/g1/sim.py b/dimos/robot/unitree/g1/sim.py index 9226bb4e7f..206a689284 100644 --- a/dimos/robot/unitree/g1/sim.py +++ b/dimos/robot/unitree/g1/sim.py @@ -24,14 +24,14 @@ from dimos.core.core import rpc from dimos.core.module import ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import ( - PoseStamped, - Quaternion, - Transform, - Twist, - Vector3, -) -from dimos.msgs.sensor_msgs import CameraInfo, Image, PointCloud2 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.g1.connection import G1ConnectionBase from dimos.robot.unitree.mujoco_connection import MujocoConnection from dimos.robot.unitree.type.odometry import Odometry as SimOdometry diff --git a/dimos/robot/unitree/g1/skill_container.py b/dimos/robot/unitree/g1/skill_container.py index 2bd5bcdb49..b1342ca96d 100644 --- a/dimos/robot/unitree/g1/skill_container.py +++ b/dimos/robot/unitree/g1/skill_container.py @@ -22,7 +22,8 @@ from dimos.agents.annotation import skill from dimos.core.core import rpc from dimos.core.module import Module -from dimos.msgs.geometry_msgs import Twist, Vector3 +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.utils.logging_config import setup_logger logger = setup_logger() diff --git a/dimos/robot/unitree/go2/blueprints/__init__.py b/dimos/robot/unitree/go2/blueprints/__init__.py deleted file mode 100644 index cbc49694f3..0000000000 --- a/dimos/robot/unitree/go2/blueprints/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Cascaded GO2 blueprints split into focused modules.""" - -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "agentic._common_agentic": ["_common_agentic"], - "agentic.unitree_go2_agentic": ["unitree_go2_agentic"], - "agentic.unitree_go2_agentic_huggingface": ["unitree_go2_agentic_huggingface"], - "agentic.unitree_go2_agentic_mcp": ["unitree_go2_agentic_mcp"], - "agentic.unitree_go2_agentic_ollama": ["unitree_go2_agentic_ollama"], - "agentic.unitree_go2_temporal_memory": ["unitree_go2_temporal_memory"], - "basic.unitree_go2_basic": ["_linux", "_mac", "unitree_go2_basic"], - "smart._with_jpeg": ["_with_jpeglcm"], - "smart.unitree_go2": ["unitree_go2"], - "smart.unitree_go2_detection": ["unitree_go2_detection"], - "smart.unitree_go2_ros": ["unitree_go2_ros"], - "smart.unitree_go2_spatial": ["unitree_go2_spatial"], - "smart.unitree_go2_vlm_stream_test": ["unitree_go2_vlm_stream_test"], - }, -) diff --git a/dimos/robot/unitree/go2/blueprints/agentic/__init__.py b/dimos/robot/unitree/go2/blueprints/agentic/__init__.py deleted file mode 100644 index 84d1b41b23..0000000000 --- a/dimos/robot/unitree/go2/blueprints/agentic/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Agentic blueprints for Unitree GO2.""" diff --git a/dimos/robot/unitree/go2/blueprints/agentic/unitree_go2_temporal_memory.py b/dimos/robot/unitree/go2/blueprints/agentic/unitree_go2_temporal_memory.py index 13a1eec1ff..24ab47ad3b 100644 --- a/dimos/robot/unitree/go2/blueprints/agentic/unitree_go2_temporal_memory.py +++ b/dimos/robot/unitree/go2/blueprints/agentic/unitree_go2_temporal_memory.py @@ -15,7 +15,10 @@ from dimos.core.blueprints import autoconnect from dimos.core.global_config import global_config -from dimos.perception.experimental.temporal_memory import TemporalMemoryConfig, temporal_memory +from dimos.perception.experimental.temporal_memory.temporal_memory import ( + TemporalMemoryConfig, + temporal_memory, +) from dimos.robot.unitree.go2.blueprints.agentic.unitree_go2_agentic import unitree_go2_agentic # This module is imported lazily by `get_by_name()` in the CLI run command, diff --git a/dimos/robot/unitree/go2/blueprints/basic/__init__.py b/dimos/robot/unitree/go2/blueprints/basic/__init__.py deleted file mode 100644 index 79964b0297..0000000000 --- a/dimos/robot/unitree/go2/blueprints/basic/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Basic blueprints for Unitree GO2.""" diff --git a/dimos/robot/unitree/go2/blueprints/basic/unitree_go2_basic.py b/dimos/robot/unitree/go2/blueprints/basic/unitree_go2_basic.py index ce8aef2222..3325290bf7 100644 --- a/dimos/robot/unitree/go2/blueprints/basic/unitree_go2_basic.py +++ b/dimos/robot/unitree/go2/blueprints/basic/unitree_go2_basic.py @@ -21,9 +21,9 @@ from dimos.core.blueprints import autoconnect from dimos.core.global_config import global_config from dimos.core.transport import pSHMTransport -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.protocol.pubsub.impl.lcmpubsub import LCM -from dimos.protocol.service.system_configurator import ClockSyncConfigurator +from dimos.protocol.service.system_configurator.clock_sync import ClockSyncConfigurator from dimos.robot.unitree.go2.connection import go2_connection from dimos.web.websocket_vis.websocket_vis_module import websocket_vis diff --git a/dimos/robot/unitree/go2/blueprints/basic/unitree_go2_fleet.py b/dimos/robot/unitree/go2/blueprints/basic/unitree_go2_fleet.py index 015cfcdba4..908444b2fd 100644 --- a/dimos/robot/unitree/go2/blueprints/basic/unitree_go2_fleet.py +++ b/dimos/robot/unitree/go2/blueprints/basic/unitree_go2_fleet.py @@ -21,7 +21,7 @@ """ from dimos.core.blueprints import autoconnect -from dimos.protocol.service.system_configurator import ClockSyncConfigurator +from dimos.protocol.service.system_configurator.clock_sync import ClockSyncConfigurator from dimos.robot.unitree.go2.blueprints.basic.unitree_go2_basic import with_vis from dimos.robot.unitree.go2.fleet_connection import go2_fleet_connection from dimos.web.websocket_vis.websocket_vis_module import websocket_vis diff --git a/dimos/robot/unitree/go2/blueprints/smart/__init__.py b/dimos/robot/unitree/go2/blueprints/smart/__init__.py deleted file mode 100644 index 7d5bdbc3ab..0000000000 --- a/dimos/robot/unitree/go2/blueprints/smart/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Smart blueprints for Unitree GO2.""" diff --git a/dimos/robot/unitree/go2/blueprints/smart/_with_jpeg.py b/dimos/robot/unitree/go2/blueprints/smart/_with_jpeg.py index 9c77d599cf..a759b1ca50 100644 --- a/dimos/robot/unitree/go2/blueprints/smart/_with_jpeg.py +++ b/dimos/robot/unitree/go2/blueprints/smart/_with_jpeg.py @@ -14,7 +14,7 @@ # limitations under the License. from dimos.core.transport import JpegLcmTransport -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.robot.unitree.go2.blueprints.smart.unitree_go2 import unitree_go2 _with_jpeglcm = unitree_go2.transports( diff --git a/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py b/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py index 22743ac135..80e6ec701a 100644 --- a/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py +++ b/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py @@ -16,7 +16,9 @@ from dimos.core.blueprints import autoconnect from dimos.mapping.costmapper import cost_mapper from dimos.mapping.voxels import voxel_mapper -from dimos.navigation.frontier_exploration import wavefront_frontier_explorer +from dimos.navigation.frontier_exploration.wavefront_frontier_goal_selector import ( + wavefront_frontier_explorer, +) from dimos.navigation.replanning_a_star.module import replanning_a_star_planner from dimos.robot.unitree.go2.blueprints.basic.unitree_go2_basic import unitree_go2_basic diff --git a/dimos/robot/unitree/go2/blueprints/smart/unitree_go2_detection.py b/dimos/robot/unitree/go2/blueprints/smart/unitree_go2_detection.py index f2edf2cb3b..a9bb7729ae 100644 --- a/dimos/robot/unitree/go2/blueprints/smart/unitree_go2_detection.py +++ b/dimos/robot/unitree/go2/blueprints/smart/unitree_go2_detection.py @@ -20,8 +20,9 @@ from dimos.core.blueprints import autoconnect from dimos.core.transport import LCMTransport -from dimos.msgs.sensor_msgs import Image, PointCloud2 -from dimos.msgs.vision_msgs import Detection2DArray +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.vision_msgs.Detection2DArray import Detection2DArray from dimos.perception.detection.module3D import Detection3DModule, detection3d_module from dimos.robot.unitree.go2.blueprints.smart.unitree_go2 import unitree_go2 from dimos.robot.unitree.go2.connection import GO2Connection diff --git a/dimos/robot/unitree/go2/blueprints/smart/unitree_go2_ros.py b/dimos/robot/unitree/go2/blueprints/smart/unitree_go2_ros.py index a335b1e9af..b63b8f5f6c 100644 --- a/dimos/robot/unitree/go2/blueprints/smart/unitree_go2_ros.py +++ b/dimos/robot/unitree/go2/blueprints/smart/unitree_go2_ros.py @@ -14,8 +14,9 @@ # limitations under the License. from dimos.core.transport import ROSTransport -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import Image, PointCloud2 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.go2.blueprints.smart.unitree_go2 import unitree_go2 unitree_go2_ros = unitree_go2.transports( diff --git a/dimos/robot/unitree/go2/connection.py b/dimos/robot/unitree/go2/connection.py index c06028ec6f..38da7fb439 100644 --- a/dimos/robot/unitree/go2/connection.py +++ b/dimos/robot/unitree/go2/connection.py @@ -23,7 +23,6 @@ from reactivex.observable import Observable import rerun.blueprint as rrb -from dimos import spec from dimos.agents.annotation import skill from dimos.core.core import rpc from dimos.core.global_config import GlobalConfig @@ -31,18 +30,18 @@ from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.stream import In, Out from dimos.core.transport import LCMTransport, pSHMTransport +from dimos.spec.perception import Camera, Pointcloud if TYPE_CHECKING: from dimos.core.rpc_client import ModuleProxy -from dimos.msgs.geometry_msgs import ( - PoseStamped, - Quaternion, - Transform, - Twist, - Vector3, -) -from dimos.msgs.sensor_msgs import CameraInfo, Image, PointCloud2 -from dimos.msgs.sensor_msgs.Image import ImageFormat +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.connection import UnitreeWebRTCConnection from dimos.utils.data import get_data from dimos.utils.decorators.decorators import simple_mcache @@ -184,7 +183,7 @@ def publish_request(self, topic: str, data: dict): # type: ignore[no-untyped-de _Config = TypeVar("_Config", bound=ConnectionConfig, default=ConnectionConfig) -class GO2Connection(Module[_Config], spec.Camera, spec.Pointcloud): +class GO2Connection(Module[_Config], Camera, Pointcloud): default_config = ConnectionConfig # type: ignore[assignment] cmd_vel: In[Twist] diff --git a/dimos/robot/unitree/go2/fleet_connection.py b/dimos/robot/unitree/go2/fleet_connection.py index 24a95ec4d2..f0e904648a 100644 --- a/dimos/robot/unitree/go2/fleet_connection.py +++ b/dimos/robot/unitree/go2/fleet_connection.py @@ -37,7 +37,7 @@ from typing import Any as Self if TYPE_CHECKING: - from dimos.msgs.geometry_msgs import Twist + from dimos.msgs.geometry_msgs.Twist import Twist logger = setup_logger() diff --git a/dimos/robot/unitree/keyboard_teleop.py b/dimos/robot/unitree/keyboard_teleop.py index 3cd03df785..86885bc446 100644 --- a/dimos/robot/unitree/keyboard_teleop.py +++ b/dimos/robot/unitree/keyboard_teleop.py @@ -22,7 +22,8 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import Twist, Vector3 +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 # Force X11 driver to avoid OpenGL threading issues os.environ["SDL_VIDEODRIVER"] = "x11" diff --git a/dimos/robot/unitree/modular/detect.py b/dimos/robot/unitree/modular/detect.py index 99faddc946..d6ed78d101 100644 --- a/dimos/robot/unitree/modular/detect.py +++ b/dimos/robot/unitree/modular/detect.py @@ -16,8 +16,9 @@ from dimos_lcm.sensor_msgs import CameraInfo -from dimos.msgs.sensor_msgs import Image, PointCloud2 -from dimos.msgs.std_msgs import Header +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.msgs.std_msgs.Header import Header from dimos.robot.unitree.type.lidar import pointcloud2_from_webrtc_lidar from dimos.robot.unitree.type.odometry import Odometry @@ -71,8 +72,10 @@ def camera_info() -> CameraInfo: def transform_chain(odom_frame: Odometry) -> list: # type: ignore[type-arg] - from dimos.msgs.geometry_msgs import Quaternion, Transform, Vector3 - from dimos.protocol.tf import TF + from dimos.msgs.geometry_msgs.Quaternion import Quaternion + from dimos.msgs.geometry_msgs.Transform import Transform + from dimos.msgs.geometry_msgs.Vector3 import Vector3 + from dimos.protocol.tf.tf import TF camera_link = Transform( translation=Vector3(0.3, 0.0, 0.0), @@ -113,7 +116,7 @@ def broadcast( # type: ignore[no-untyped-def] ) from dimos.core.transport import LCMTransport - from dimos.msgs.geometry_msgs import PoseStamped + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped lidar_transport = LCMTransport("/lidar", PointCloud2) # type: ignore[var-annotated] odom_transport = LCMTransport("/odom", PoseStamped) # type: ignore[var-annotated] @@ -136,14 +139,14 @@ def broadcast( # type: ignore[no-untyped-def] def process_data(): # type: ignore[no-untyped-def] - from dimos.msgs.sensor_msgs import Image + from dimos.msgs.sensor_msgs.Image import Image from dimos.perception.detection.module2D import ( # type: ignore[attr-defined] Detection2DModule, build_imageannotations, ) from dimos.robot.unitree.type.odometry import Odometry from dimos.utils.data import get_data - from dimos.utils.testing import TimedSensorReplay + from dimos.utils.testing.replay import TimedSensorReplay get_data("unitree_office_walk") target = 1751591272.9654856 diff --git a/dimos/robot/unitree/mujoco_connection.py b/dimos/robot/unitree/mujoco_connection.py index 3bc4e075f7..d7c98cffd3 100644 --- a/dimos/robot/unitree/mujoco_connection.py +++ b/dimos/robot/unitree/mujoco_connection.py @@ -35,8 +35,12 @@ from reactivex.disposable import Disposable from dimos.core.global_config import GlobalConfig -from dimos.msgs.geometry_msgs import Quaternion, Twist, Vector3 -from dimos.msgs.sensor_msgs import CameraInfo, Image, ImageFormat, PointCloud2 +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image, ImageFormat +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.odometry import Odometry from dimos.simulation.mujoco.constants import ( LAUNCHER_PATH, diff --git a/dimos/robot/unitree/rosnav.py b/dimos/robot/unitree/rosnav.py index 083c7413fe..b2fe42fde5 100644 --- a/dimos/robot/unitree/rosnav.py +++ b/dimos/robot/unitree/rosnav.py @@ -19,8 +19,8 @@ from dimos.core.core import rpc from dimos.core.module import Module from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import Joy +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.Joy import Joy from dimos.msgs.std_msgs.Bool import Bool from dimos.utils.logging_config import setup_logger diff --git a/dimos/robot/unitree/testing/__init__.py b/dimos/robot/unitree/testing/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/robot/unitree/testing/mock.py b/dimos/robot/unitree/testing/mock.py index 26e6a90018..4c5e52e4b0 100644 --- a/dimos/robot/unitree/testing/mock.py +++ b/dimos/robot/unitree/testing/mock.py @@ -21,7 +21,7 @@ from reactivex import from_iterable, interval, operators as ops from reactivex.observable import Observable -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.lidar import RawLidarMsg, pointcloud2_from_webrtc_lidar diff --git a/dimos/robot/unitree/testing/test_actors.py b/dimos/robot/unitree/testing/test_actors.py index ed0b05d664..77c3d7c56f 100644 --- a/dimos/robot/unitree/testing/test_actors.py +++ b/dimos/robot/unitree/testing/test_actors.py @@ -20,7 +20,7 @@ from dimos.core.module import Module from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.transport import LCMTransport -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.map import Map as Mapper diff --git a/dimos/robot/unitree/testing/test_tooling.py b/dimos/robot/unitree/testing/test_tooling.py index d1f2eeb169..40db01feee 100644 --- a/dimos/robot/unitree/testing/test_tooling.py +++ b/dimos/robot/unitree/testing/test_tooling.py @@ -19,7 +19,7 @@ from dimos.robot.unitree.type.lidar import pointcloud2_from_webrtc_lidar from dimos.robot.unitree.type.odometry import Odometry from dimos.utils.reactive import backpressure -from dimos.utils.testing import TimedSensorReplay +from dimos.utils.testing.replay import TimedSensorReplay @pytest.mark.tool diff --git a/dimos/robot/unitree/type/__init__.py b/dimos/robot/unitree/type/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/robot/unitree/type/lidar.py b/dimos/robot/unitree/type/lidar.py index df2909dc38..f58268d442 100644 --- a/dimos/robot/unitree/type/lidar.py +++ b/dimos/robot/unitree/type/lidar.py @@ -20,7 +20,7 @@ import numpy as np import open3d as o3d # type: ignore[import-untyped] -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 # Backwards compatibility alias for pickled data LidarMessage = PointCloud2 diff --git a/dimos/robot/unitree/type/map.py b/dimos/robot/unitree/type/map.py index 274115d516..da45c003f7 100644 --- a/dimos/robot/unitree/type/map.py +++ b/dimos/robot/unitree/type/map.py @@ -28,8 +28,8 @@ from dimos.mapping.pointclouds.accumulators.general import GeneralPointCloudAccumulator from dimos.mapping.pointclouds.accumulators.protocol import PointCloudAccumulator from dimos.mapping.pointclouds.occupancy import general_occupancy -from dimos.msgs.nav_msgs import OccupancyGrid -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.go2.connection import Go2ConnectionProtocol diff --git a/dimos/robot/unitree/type/odometry.py b/dimos/robot/unitree/type/odometry.py index aa664b32ef..fabf800b6c 100644 --- a/dimos/robot/unitree/type/odometry.py +++ b/dimos/robot/unitree/type/odometry.py @@ -13,7 +13,9 @@ # limitations under the License. from typing import Literal, TypedDict -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.robot.unitree.type.timeseries import ( Timestamped, ) diff --git a/dimos/robot/unitree/type/test_lidar.py b/dimos/robot/unitree/type/test_lidar.py index 719088d77a..9a743d65b5 100644 --- a/dimos/robot/unitree/type/test_lidar.py +++ b/dimos/robot/unitree/type/test_lidar.py @@ -16,9 +16,9 @@ import itertools from typing import cast -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.lidar import RawLidarMsg, pointcloud2_from_webrtc_lidar -from dimos.utils.testing import SensorReplay +from dimos.utils.testing.replay import SensorReplay def test_init() -> None: diff --git a/dimos/robot/unitree/type/test_odometry.py b/dimos/robot/unitree/type/test_odometry.py index d0fe2b290e..8020684fb7 100644 --- a/dimos/robot/unitree/type/test_odometry.py +++ b/dimos/robot/unitree/type/test_odometry.py @@ -17,7 +17,7 @@ import pytest from dimos.robot.unitree.type.odometry import Odometry -from dimos.utils.testing import SensorReplay +from dimos.utils.testing.replay import SensorReplay _EXPECTED_TOTAL_RAD = -4.05212 diff --git a/dimos/robot/unitree/unitree_skill_container.py b/dimos/robot/unitree/unitree_skill_container.py index d2f15b9efe..a79c061567 100644 --- a/dimos/robot/unitree/unitree_skill_container.py +++ b/dimos/robot/unitree/unitree_skill_container.py @@ -24,7 +24,9 @@ from dimos.agents.annotation import skill from dimos.core.core import rpc from dimos.core.module import Module -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.navigation.base import NavigationState from dimos.utils.logging_config import setup_logger diff --git a/dimos/robot/unitree_webrtc/type/__init__.py b/dimos/robot/unitree_webrtc/type/__init__.py deleted file mode 100644 index 03ff4f4563..0000000000 --- a/dimos/robot/unitree_webrtc/type/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Compatibility re-exports for legacy dimos.robot.unitree_webrtc.type.* imports.""" - -import importlib - -__all__ = [] - - -def __getattr__(name: str): # type: ignore[no-untyped-def] - module = importlib.import_module("dimos.robot.unitree.type") - try: - return getattr(module, name) - except AttributeError as exc: - raise AttributeError(f"No {__name__} attribute {name}") from exc - - -def __dir__() -> list[str]: - module = importlib.import_module("dimos.robot.unitree.type") - return [name for name in dir(module) if not name.startswith("_")] diff --git a/dimos/rxpy_backpressure/__init__.py b/dimos/rxpy_backpressure/__init__.py deleted file mode 100644 index ff3b1f37c0..0000000000 --- a/dimos/rxpy_backpressure/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from dimos.rxpy_backpressure.backpressure import BackPressure - -__all__ = [BackPressure] diff --git a/dimos/simulation/__init__.py b/dimos/simulation/__init__.py deleted file mode 100644 index 1a68191a36..0000000000 --- a/dimos/simulation/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Try to import Isaac Sim components -try: - from .isaac import IsaacSimulator, IsaacStream -except ImportError: - IsaacSimulator = None # type: ignore[assignment, misc] - IsaacStream = None # type: ignore[assignment, misc] - -# Try to import Genesis components -try: - from .genesis import GenesisSimulator, GenesisStream -except ImportError: - GenesisSimulator = None # type: ignore[assignment, misc] - GenesisStream = None # type: ignore[assignment, misc] - -__all__ = ["GenesisSimulator", "GenesisStream", "IsaacSimulator", "IsaacStream"] diff --git a/dimos/simulation/base/__init__.py b/dimos/simulation/base/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/simulation/engines/__init__.py b/dimos/simulation/engines/__init__.py deleted file mode 100644 index d437f9a7cd..0000000000 --- a/dimos/simulation/engines/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Simulation engines for manipulator backends.""" - -from __future__ import annotations - -from typing import Literal - -from dimos.simulation.engines.base import SimulationEngine -from dimos.simulation.engines.mujoco_engine import MujocoEngine - -EngineType = Literal["mujoco"] - -_ENGINES: dict[EngineType, type[SimulationEngine]] = { - "mujoco": MujocoEngine, -} - - -def get_engine(engine_name: EngineType) -> type[SimulationEngine]: - return _ENGINES[engine_name] - - -__all__ = [ - "EngineType", - "SimulationEngine", - "get_engine", -] diff --git a/dimos/simulation/engines/base.py b/dimos/simulation/engines/base.py index d450614c62..58e76ecba6 100644 --- a/dimos/simulation/engines/base.py +++ b/dimos/simulation/engines/base.py @@ -22,7 +22,7 @@ if TYPE_CHECKING: from pathlib import Path - from dimos.msgs.sensor_msgs import JointState + from dimos.msgs.sensor_msgs.JointState import JointState class SimulationEngine(ABC): diff --git a/dimos/simulation/engines/mujoco_engine.py b/dimos/simulation/engines/mujoco_engine.py index ddaaa25ad3..2d1cdf92ac 100644 --- a/dimos/simulation/engines/mujoco_engine.py +++ b/dimos/simulation/engines/mujoco_engine.py @@ -30,7 +30,7 @@ if TYPE_CHECKING: from pathlib import Path - from dimos.msgs.sensor_msgs import JointState + from dimos.msgs.sensor_msgs.JointState import JointState logger = setup_logger() diff --git a/dimos/msgs/visualization_msgs/__init__.py b/dimos/simulation/engines/registry.py similarity index 56% rename from dimos/msgs/visualization_msgs/__init__.py rename to dimos/simulation/engines/registry.py index 0df5006c76..deadf3a404 100644 --- a/dimos/msgs/visualization_msgs/__init__.py +++ b/dimos/simulation/engines/registry.py @@ -12,8 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Visualization message types.""" +"""Simulation engine registry.""" -from dimos.msgs.visualization_msgs.EntityMarkers import EntityMarkers +from __future__ import annotations -__all__ = ["EntityMarkers"] +from typing import Literal + +from dimos.simulation.engines.base import SimulationEngine +from dimos.simulation.engines.mujoco_engine import MujocoEngine + +EngineType = Literal["mujoco"] + +_ENGINES: dict[EngineType, type[SimulationEngine]] = { + "mujoco": MujocoEngine, +} + + +def get_engine(engine_name: EngineType) -> type[SimulationEngine]: + return _ENGINES[engine_name] diff --git a/dimos/simulation/genesis/__init__.py b/dimos/simulation/genesis/__init__.py deleted file mode 100644 index 5657d9167b..0000000000 --- a/dimos/simulation/genesis/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .simulator import GenesisSimulator -from .stream import GenesisStream - -__all__ = ["GenesisSimulator", "GenesisStream"] diff --git a/dimos/simulation/isaac/__init__.py b/dimos/simulation/isaac/__init__.py deleted file mode 100644 index 2b9bdc082d..0000000000 --- a/dimos/simulation/isaac/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .simulator import IsaacSimulator -from .stream import IsaacStream - -__all__ = ["IsaacSimulator", "IsaacStream"] diff --git a/dimos/simulation/manipulators/__init__.py b/dimos/simulation/manipulators/__init__.py deleted file mode 100644 index 816de0a18d..0000000000 --- a/dimos/simulation/manipulators/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Simulation manipulator utilities.""" - -from __future__ import annotations - -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from dimos.simulation.manipulators.sim_manip_interface import SimManipInterface - from dimos.simulation.manipulators.sim_module import ( - SimulationModule, - SimulationModuleConfig, - simulation, - ) - -__all__ = [ - "SimManipInterface", - "SimulationModule", - "SimulationModuleConfig", - "simulation", -] - - -def __getattr__(name: str): # type: ignore[no-untyped-def] - if name == "SimManipInterface": - from dimos.simulation.manipulators.sim_manip_interface import SimManipInterface - - return SimManipInterface - if name in {"SimulationModule", "SimulationModuleConfig", "simulation"}: - from dimos.simulation.manipulators.sim_module import ( - SimulationModule, - SimulationModuleConfig, - simulation, - ) - - return { - "SimulationModule": SimulationModule, - "SimulationModuleConfig": SimulationModuleConfig, - "simulation": simulation, - }[name] - raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/dimos/simulation/manipulators/sim_manip_interface.py b/dimos/simulation/manipulators/sim_manip_interface.py index c829f0c864..6de570ae15 100644 --- a/dimos/simulation/manipulators/sim_manip_interface.py +++ b/dimos/simulation/manipulators/sim_manip_interface.py @@ -21,7 +21,7 @@ from typing import TYPE_CHECKING from dimos.hardware.manipulators.spec import ControlMode, JointLimits, ManipulatorInfo -from dimos.msgs.sensor_msgs import JointState +from dimos.msgs.sensor_msgs.JointState import JointState if TYPE_CHECKING: from dimos.simulation.engines.base import SimulationEngine diff --git a/dimos/simulation/manipulators/sim_module.py b/dimos/simulation/manipulators/sim_module.py index 20a55f1d02..5e873ba634 100644 --- a/dimos/simulation/manipulators/sim_module.py +++ b/dimos/simulation/manipulators/sim_module.py @@ -25,8 +25,10 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.sensor_msgs import JointCommand, JointState, RobotState -from dimos.simulation.engines import EngineType, get_engine +from dimos.msgs.sensor_msgs.JointCommand import JointCommand +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.sensor_msgs.RobotState import RobotState +from dimos.simulation.engines.registry import EngineType, get_engine from dimos.simulation.manipulators.sim_manip_interface import SimManipInterface diff --git a/dimos/simulation/manipulators/test_sim_module.py b/dimos/simulation/manipulators/test_sim_module.py index 72408fefed..951d4790e3 100644 --- a/dimos/simulation/manipulators/test_sim_module.py +++ b/dimos/simulation/manipulators/test_sim_module.py @@ -17,7 +17,7 @@ import pytest -from dimos.protocol.rpc import RPCSpec +from dimos.protocol.rpc.spec import RPCSpec from dimos.simulation.manipulators.sim_module import SimulationModule diff --git a/dimos/simulation/mujoco/mujoco_process.py b/dimos/simulation/mujoco/mujoco_process.py index 21baec473f..2644dddd36 100755 --- a/dimos/simulation/mujoco/mujoco_process.py +++ b/dimos/simulation/mujoco/mujoco_process.py @@ -29,7 +29,7 @@ import open3d as o3d # type: ignore[import-untyped] from dimos.core.global_config import GlobalConfig -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.simulation.mujoco.constants import ( DEPTH_CAMERA_FOV, LIDAR_FPS, diff --git a/dimos/simulation/mujoco/person_on_track.py b/dimos/simulation/mujoco/person_on_track.py index a816b5f3ee..f19b49e4c6 100644 --- a/dimos/simulation/mujoco/person_on_track.py +++ b/dimos/simulation/mujoco/person_on_track.py @@ -19,7 +19,7 @@ from numpy.typing import NDArray from dimos.core.transport import LCMTransport -from dimos.msgs.geometry_msgs import Pose +from dimos.msgs.geometry_msgs.Pose import Pose class PersonPositionController: diff --git a/dimos/simulation/mujoco/shared_memory.py b/dimos/simulation/mujoco/shared_memory.py index 6dad60b4b4..f677863edf 100644 --- a/dimos/simulation/mujoco/shared_memory.py +++ b/dimos/simulation/mujoco/shared_memory.py @@ -21,7 +21,7 @@ import numpy as np from numpy.typing import NDArray -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.simulation.mujoco.constants import VIDEO_HEIGHT, VIDEO_WIDTH from dimos.utils.logging_config import setup_logger diff --git a/dimos/simulation/sim_blueprints.py b/dimos/simulation/sim_blueprints.py index 8b91ff817a..494b97ccbf 100644 --- a/dimos/simulation/sim_blueprints.py +++ b/dimos/simulation/sim_blueprints.py @@ -14,12 +14,10 @@ from dimos.core.transport import LCMTransport -from dimos.msgs.sensor_msgs import ( # type: ignore[attr-defined] - JointCommand, - JointState, - RobotState, -) -from dimos.msgs.trajectory_msgs import JointTrajectory +from dimos.msgs.sensor_msgs.JointCommand import JointCommand +from dimos.msgs.sensor_msgs.JointState import JointState +from dimos.msgs.sensor_msgs.RobotState import RobotState +from dimos.msgs.trajectory_msgs.JointTrajectory import JointTrajectory from dimos.simulation.manipulators.sim_module import simulation from dimos.utils.data import LfsPath diff --git a/dimos/skills/__init__.py b/dimos/skills/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/skills/rest/__init__.py b/dimos/skills/rest/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/skills/unitree/__init__.py b/dimos/skills/unitree/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/spec/__init__.py b/dimos/spec/__init__.py deleted file mode 100644 index 1423bec9a1..0000000000 --- a/dimos/spec/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from dimos.spec.control import LocalPlanner -from dimos.spec.mapping import GlobalCostmap, GlobalPointcloud -from dimos.spec.nav import Nav -from dimos.spec.perception import Camera, Image, Pointcloud - -__all__ = [ - "Camera", - "GlobalCostmap", - "GlobalPointcloud", - "Image", - "LocalPlanner", - "Nav", - "Pointcloud", -] diff --git a/dimos/spec/control.py b/dimos/spec/control.py index 48d58a926a..b597b4faaf 100644 --- a/dimos/spec/control.py +++ b/dimos/spec/control.py @@ -15,7 +15,7 @@ from typing import Protocol from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import Twist +from dimos.msgs.geometry_msgs.Twist import Twist class LocalPlanner(Protocol): diff --git a/dimos/spec/mapping.py b/dimos/spec/mapping.py index 0ba88cfaa9..f35778f40b 100644 --- a/dimos/spec/mapping.py +++ b/dimos/spec/mapping.py @@ -15,8 +15,8 @@ from typing import Protocol from dimos.core.stream import Out -from dimos.msgs.nav_msgs import OccupancyGrid -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 class GlobalPointcloud(Protocol): diff --git a/dimos/spec/nav.py b/dimos/spec/nav.py index 08f6f42b35..ae971e7b5c 100644 --- a/dimos/spec/nav.py +++ b/dimos/spec/nav.py @@ -15,8 +15,9 @@ from typing import Protocol from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import PoseStamped, Twist -from dimos.msgs.nav_msgs import Path +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.nav_msgs.Path import Path class Nav(Protocol): diff --git a/dimos/spec/perception.py b/dimos/spec/perception.py index 1cfe352390..4fac65ad02 100644 --- a/dimos/spec/perception.py +++ b/dimos/spec/perception.py @@ -16,7 +16,10 @@ from dimos.core.stream import Out from dimos.msgs.nav_msgs.Odometry import Odometry as OdometryMsg -from dimos.msgs.sensor_msgs import CameraInfo, Image as ImageMsg, Imu, PointCloud2 +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image as ImageMsg +from dimos.msgs.sensor_msgs.Imu import Imu +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 class Image(Protocol): diff --git a/dimos/stream/__init__.py b/dimos/stream/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/stream/audio/__init__.py b/dimos/stream/audio/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/stream/video_providers/__init__.py b/dimos/stream/video_providers/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/teleop/__init__.py b/dimos/teleop/__init__.py deleted file mode 100644 index 8324113111..0000000000 --- a/dimos/teleop/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Teleoperation modules for DimOS.""" diff --git a/dimos/teleop/keyboard/__init__.py b/dimos/teleop/keyboard/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/teleop/keyboard/keyboard_teleop_module.py b/dimos/teleop/keyboard/keyboard_teleop_module.py index 854c0fbc22..a90dc3cf44 100644 --- a/dimos/teleop/keyboard/keyboard_teleop_module.py +++ b/dimos/teleop/keyboard/keyboard_teleop_module.py @@ -44,7 +44,7 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped # Force X11 driver to avoid OpenGL threading issues os.environ["SDL_VIDEODRIVER"] = "x11" diff --git a/dimos/teleop/phone/__init__.py b/dimos/teleop/phone/__init__.py deleted file mode 100644 index 552032a47b..0000000000 --- a/dimos/teleop/phone/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Phone teleoperation module for DimOS.""" - -from dimos.teleop.phone.phone_extensions import ( - SimplePhoneTeleop, - simple_phone_teleop_module, -) -from dimos.teleop.phone.phone_teleop_module import ( - PhoneTeleopConfig, - PhoneTeleopModule, - phone_teleop_module, -) - -__all__ = [ - "PhoneTeleopConfig", - "PhoneTeleopModule", - "SimplePhoneTeleop", - "phone_teleop_module", - "simple_phone_teleop_module", -] diff --git a/dimos/teleop/phone/phone_extensions.py b/dimos/teleop/phone/phone_extensions.py index 0f52fce2e0..c5cdc1fc80 100644 --- a/dimos/teleop/phone/phone_extensions.py +++ b/dimos/teleop/phone/phone_extensions.py @@ -20,7 +20,9 @@ """ from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import Twist, TwistStamped, Vector3 +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.teleop.phone.phone_teleop_module import PhoneTeleopModule diff --git a/dimos/teleop/phone/phone_teleop_module.py b/dimos/teleop/phone/phone_teleop_module.py index cc55f1f180..3f32063cce 100644 --- a/dimos/teleop/phone/phone_teleop_module.py +++ b/dimos/teleop/phone/phone_teleop_module.py @@ -36,7 +36,9 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import Twist, TwistStamped, Vector3 +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.msgs.std_msgs.Bool import Bool from dimos.utils.logging_config import setup_logger from dimos.utils.path_utils import get_project_root diff --git a/dimos/teleop/quest/__init__.py b/dimos/teleop/quest/__init__.py deleted file mode 100644 index 83daf4347b..0000000000 --- a/dimos/teleop/quest/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Quest teleoperation module.""" - -from dimos.teleop.quest.quest_extensions import ( - ArmTeleopModule, - TwistTeleopModule, - VisualizingTeleopModule, - arm_teleop_module, - twist_teleop_module, - visualizing_teleop_module, -) -from dimos.teleop.quest.quest_teleop_module import ( - Hand, - QuestTeleopConfig, - QuestTeleopModule, - QuestTeleopStatus, - quest_teleop_module, -) -from dimos.teleop.quest.quest_types import ( - Buttons, - QuestControllerState, - ThumbstickState, -) - -__all__ = [ - "ArmTeleopModule", - "Buttons", - "Hand", - "QuestControllerState", - "QuestTeleopConfig", - "QuestTeleopModule", - "QuestTeleopStatus", - "ThumbstickState", - "TwistTeleopModule", - "VisualizingTeleopModule", - # Blueprints - "arm_teleop_module", - "quest_teleop_module", - "twist_teleop_module", - "visualizing_teleop_module", -] diff --git a/dimos/teleop/quest/blueprints.py b/dimos/teleop/quest/blueprints.py index ac86a0325f..a3aa54ee08 100644 --- a/dimos/teleop/quest/blueprints.py +++ b/dimos/teleop/quest/blueprints.py @@ -22,7 +22,7 @@ ) from dimos.core.blueprints import autoconnect from dimos.core.transport import LCMTransport -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped from dimos.teleop.quest.quest_extensions import arm_teleop_module, visualizing_teleop_module from dimos.teleop.quest.quest_types import Buttons diff --git a/dimos/teleop/quest/quest_extensions.py b/dimos/teleop/quest/quest_extensions.py index c92ac55a43..46e868837d 100644 --- a/dimos/teleop/quest/quest_extensions.py +++ b/dimos/teleop/quest/quest_extensions.py @@ -25,7 +25,8 @@ from pydantic import Field from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import PoseStamped, TwistStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped from dimos.teleop.quest.quest_teleop_module import Hand, QuestTeleopConfig, QuestTeleopModule from dimos.teleop.quest.quest_types import Buttons, QuestControllerState from dimos.teleop.utils.teleop_visualization import ( diff --git a/dimos/teleop/quest/quest_teleop_module.py b/dimos/teleop/quest/quest_teleop_module.py index 3c8e6e9812..5868aab620 100644 --- a/dimos/teleop/quest/quest_teleop_module.py +++ b/dimos/teleop/quest/quest_teleop_module.py @@ -37,8 +37,8 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import Out -from dimos.msgs.geometry_msgs import PoseStamped -from dimos.msgs.sensor_msgs import Joy +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.sensor_msgs.Joy import Joy from dimos.teleop.quest.quest_types import Buttons, QuestControllerState from dimos.teleop.utils.teleop_transforms import webxr_to_robot from dimos.utils.logging_config import setup_logger diff --git a/dimos/teleop/quest/quest_types.py b/dimos/teleop/quest/quest_types.py index 7fd991a76c..7e7cfc7620 100644 --- a/dimos/teleop/quest/quest_types.py +++ b/dimos/teleop/quest/quest_types.py @@ -18,8 +18,8 @@ from dataclasses import dataclass, field from typing import ClassVar -from dimos.msgs.sensor_msgs import Joy -from dimos.msgs.std_msgs import UInt32 +from dimos.msgs.sensor_msgs.Joy import Joy +from dimos.msgs.std_msgs.UInt32 import UInt32 @dataclass diff --git a/dimos/teleop/utils/__init__.py b/dimos/teleop/utils/__init__.py deleted file mode 100644 index ae8c375e8f..0000000000 --- a/dimos/teleop/utils/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2025-2026 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Teleoperation utilities.""" diff --git a/dimos/teleop/utils/teleop_transforms.py b/dimos/teleop/utils/teleop_transforms.py index 15fd3be120..f1e9e9381d 100644 --- a/dimos/teleop/utils/teleop_transforms.py +++ b/dimos/teleop/utils/teleop_transforms.py @@ -22,7 +22,7 @@ import numpy as np from scipy.spatial.transform import Rotation as R # type: ignore[import-untyped] -from dimos.msgs.geometry_msgs import PoseStamped +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped from dimos.utils.transform_utils import matrix_to_pose, pose_to_matrix if TYPE_CHECKING: diff --git a/dimos/teleop/utils/teleop_visualization.py b/dimos/teleop/utils/teleop_visualization.py index a59b0666ef..5a7acd06e9 100644 --- a/dimos/teleop/utils/teleop_visualization.py +++ b/dimos/teleop/utils/teleop_visualization.py @@ -24,7 +24,7 @@ from dimos.utils.logging_config import setup_logger if TYPE_CHECKING: - from dimos.msgs.geometry_msgs import PoseStamped + from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped logger = setup_logger() diff --git a/dimos/perception/experimental/temporal_memory/__init__.py b/dimos/test_no_init_files.py similarity index 50% rename from dimos/perception/experimental/temporal_memory/__init__.py rename to dimos/test_no_init_files.py index 1056e82e8b..39efb7ad24 100644 --- a/dimos/perception/experimental/temporal_memory/__init__.py +++ b/dimos/test_no_init_files.py @@ -12,19 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Temporal memory package.""" +from dimos.constants import DIMOS_PROJECT_ROOT -from .frame_window_accumulator import Frame, FrameWindowAccumulator -from .temporal_memory import TemporalMemory, TemporalMemoryConfig, temporal_memory -from .temporal_state import TemporalState -from .window_analyzer import WindowAnalyzer -__all__ = [ - "Frame", - "FrameWindowAccumulator", - "TemporalMemory", - "TemporalMemoryConfig", - "TemporalState", - "WindowAnalyzer", - "temporal_memory", -] +def test_no_init_files(): + dimos_dir = DIMOS_PROJECT_ROOT / "dimos" + init_files = sorted(dimos_dir.rglob("__init__.py")) + if init_files: + listing = "\n".join(f" - {f.relative_to(dimos_dir)}" for f in init_files) + raise AssertionError( + f"Found __init__.py files in dimos/:\n{listing}\n\n" + "__init__.py files are not allowed because they lead to unnecessary " + "extraneous imports. Everything should be imported straight from the " + "source module." + ) diff --git a/dimos/types/ros_polyfill.py b/dimos/types/ros_polyfill.py index 4bad99740d..70140336b8 100644 --- a/dimos/types/ros_polyfill.py +++ b/dimos/types/ros_polyfill.py @@ -15,7 +15,7 @@ try: from geometry_msgs.msg import Vector3 # type: ignore[attr-defined] except ImportError: - from dimos.msgs.geometry_msgs import Vector3 + from dimos.msgs.geometry_msgs.Vector3 import Vector3 try: from geometry_msgs.msg import ( # type: ignore[attr-defined] diff --git a/dimos/types/test_timestamped.py b/dimos/types/test_timestamped.py index 7de82e8f9a..e62b275dfc 100644 --- a/dimos/types/test_timestamped.py +++ b/dimos/types/test_timestamped.py @@ -20,7 +20,7 @@ from reactivex.scheduler import ThreadPoolScheduler from dimos.memory.timeseries.inmemory import InMemoryStore -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.types.timestamped import ( Timestamped, TimestampedBufferCollection, @@ -28,9 +28,9 @@ to_datetime, to_ros_stamp, ) -from dimos.utils import testing from dimos.utils.data import get_data from dimos.utils.reactive import backpressure +from dimos.utils.testing.replay import TimedSensorReplay def test_timestamped_dt_method() -> None: @@ -296,7 +296,7 @@ def spy(image): # sensor reply of raw video frames video_raw = ( - testing.TimedSensorReplay( + TimedSensorReplay( "unitree_office_walk/video", autocast=lambda x: Image.from_numpy(x).to_rgb() ) .stream(speed) diff --git a/dimos/utils/cli/__init__.py b/dimos/utils/cli/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/utils/cli/agentspy/demo_agentspy.py b/dimos/utils/cli/agentspy/demo_agentspy.py index 5229295038..851229131b 100755 --- a/dimos/utils/cli/agentspy/demo_agentspy.py +++ b/dimos/utils/cli/agentspy/demo_agentspy.py @@ -24,7 +24,7 @@ ToolMessage, ) -from dimos.protocol.pubsub import lcm # type: ignore[attr-defined] +import dimos.protocol.pubsub.impl.lcmpubsub as lcm from dimos.protocol.pubsub.impl.lcmpubsub import PickleLCM diff --git a/dimos/utils/decorators/__init__.py b/dimos/utils/decorators/__init__.py deleted file mode 100644 index d0f91a4939..0000000000 --- a/dimos/utils/decorators/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Decorators and accumulators for rate limiting and other utilities.""" - -from .accumulators import Accumulator, LatestAccumulator, RollingAverageAccumulator -from .decorators import CachedMethod, limit, retry, simple_mcache, ttl_cache - -__all__ = [ - "Accumulator", - "CachedMethod", - "LatestAccumulator", - "RollingAverageAccumulator", - "limit", - "retry", - "simple_mcache", - "ttl_cache", -] diff --git a/dimos/utils/decorators/test_decorators.py b/dimos/utils/decorators/test_decorators.py index 98545a2e37..8923151667 100644 --- a/dimos/utils/decorators/test_decorators.py +++ b/dimos/utils/decorators/test_decorators.py @@ -16,7 +16,8 @@ import pytest -from dimos.utils.decorators import RollingAverageAccumulator, limit, retry, simple_mcache, ttl_cache +from dimos.utils.decorators.accumulators import RollingAverageAccumulator +from dimos.utils.decorators.decorators import limit, retry, simple_mcache, ttl_cache def test_limit() -> None: diff --git a/dimos/utils/demo_image_encoding.py b/dimos/utils/demo_image_encoding.py index 42374029f2..84b91acf79 100644 --- a/dimos/utils/demo_image_encoding.py +++ b/dimos/utils/demo_image_encoding.py @@ -34,7 +34,7 @@ from dimos.core.module_coordinator import ModuleCoordinator from dimos.core.stream import In, Out from dimos.core.transport import JpegLcmTransport, LCMTransport -from dimos.msgs.sensor_msgs import Image +from dimos.msgs.sensor_msgs.Image import Image from dimos.robot.foxglove_bridge import FoxgloveBridge from dimos.utils.fast_image_generator import random_image diff --git a/dimos/utils/docs/test_doclinks.py b/dimos/utils/docs/test_doclinks.py index 7da6a6281b..a5a50b03e5 100644 --- a/dimos/utils/docs/test_doclinks.py +++ b/dimos/utils/docs/test_doclinks.py @@ -16,7 +16,9 @@ from pathlib import Path -from doclinks import ( +import pytest + +from dimos.utils.docs.doclinks import ( build_doc_index, build_file_index, extract_other_backticks, @@ -27,7 +29,6 @@ score_path_similarity, split_by_ignore_regions, ) -import pytest # Use the actual repo root REPO_ROOT = Path(__file__).parent.parent.parent.parent diff --git a/dimos/utils/reactive.py b/dimos/utils/reactive.py index 4397e0171e..623556d6b7 100644 --- a/dimos/utils/reactive.py +++ b/dimos/utils/reactive.py @@ -24,7 +24,7 @@ from reactivex.observable import Observable from reactivex.scheduler import ThreadPoolScheduler -from dimos.rxpy_backpressure import BackPressure +from dimos.rxpy_backpressure.backpressure import BackPressure from dimos.utils.threadpool import get_scheduler T = TypeVar("T") diff --git a/dimos/utils/test_transform_utils.py b/dimos/utils/test_transform_utils.py index 7923124c9f..77852a7bb2 100644 --- a/dimos/utils/test_transform_utils.py +++ b/dimos/utils/test_transform_utils.py @@ -16,7 +16,10 @@ import pytest from scipy.spatial.transform import Rotation as R -from dimos.msgs.geometry_msgs import Pose, Quaternion, Transform, Vector3 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 from dimos.utils import transform_utils diff --git a/dimos/utils/testing/__init__.py b/dimos/utils/testing/__init__.py deleted file mode 100644 index 568cd3604f..0000000000 --- a/dimos/utils/testing/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "moment": ["Moment", "OutputMoment", "SensorMoment"], - "replay": ["SensorReplay", "TimedSensorReplay", "TimedSensorStorage"], - }, -) diff --git a/dimos/utils/testing/test_moment.py b/dimos/utils/testing/test_moment.py index 75f11d2657..dcca3d7d01 100644 --- a/dimos/utils/testing/test_moment.py +++ b/dimos/utils/testing/test_moment.py @@ -14,9 +14,12 @@ import time from dimos.core.transport import LCMTransport -from dimos.msgs.geometry_msgs import PoseStamped, Transform -from dimos.msgs.sensor_msgs import CameraInfo, Image, PointCloud2 -from dimos.protocol.tf import TF +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.sensor_msgs.CameraInfo import CameraInfo +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 +from dimos.protocol.tf.tf import TF from dimos.robot.unitree.go2 import connection from dimos.utils.data import get_data from dimos.utils.testing.moment import Moment, SensorMoment diff --git a/dimos/utils/testing/test_replay.py b/dimos/utils/testing/test_replay.py index e3020777b4..10ace353f7 100644 --- a/dimos/utils/testing/test_replay.py +++ b/dimos/utils/testing/test_replay.py @@ -16,7 +16,7 @@ from reactivex import operators as ops -from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.robot.unitree.type.lidar import pointcloud2_from_webrtc_lidar from dimos.robot.unitree.type.odometry import Odometry from dimos.utils.data import get_data diff --git a/dimos/utils/transform_utils.py b/dimos/utils/transform_utils.py index ed82f6116f..bfd38ce14f 100644 --- a/dimos/utils/transform_utils.py +++ b/dimos/utils/transform_utils.py @@ -16,7 +16,10 @@ import numpy as np from scipy.spatial.transform import Rotation as R # type: ignore[import-untyped] -from dimos.msgs.geometry_msgs import Pose, Quaternion, Transform, Vector3 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Transform import Transform +from dimos.msgs.geometry_msgs.Vector3 import Vector3 def normalize_angle(angle: float) -> float: diff --git a/dimos/visualization/rerun/bridge.py b/dimos/visualization/rerun/bridge.py index 6729f143cd..12f998d96d 100644 --- a/dimos/visualization/rerun/bridge.py +++ b/dimos/visualization/rerun/bridge.py @@ -38,7 +38,8 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig -from dimos.msgs.sensor_msgs import Image, PointCloud2 +from dimos.msgs.sensor_msgs.Image import Image +from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 from dimos.protocol.pubsub.impl.lcmpubsub import LCM from dimos.protocol.pubsub.patterns import Glob, pattern_matches from dimos.protocol.pubsub.spec import SubscribeAllCapable diff --git a/dimos/web/__init__.py b/dimos/web/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/web/dimos_interface/__init__.py b/dimos/web/dimos_interface/__init__.py deleted file mode 100644 index 3bdc622cee..0000000000 --- a/dimos/web/dimos_interface/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -Dimensional Interface package -""" - -import lazy_loader as lazy - -__getattr__, __dir__, __all__ = lazy.attach( - __name__, - submod_attrs={ - "api.server": ["FastAPIServer"], - }, -) diff --git a/dimos/web/dimos_interface/api/__init__.py b/dimos/web/dimos_interface/api/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dimos/web/websocket_vis/costmap_viz.py b/dimos/web/websocket_vis/costmap_viz.py index 21309c94bc..f24628e6c7 100644 --- a/dimos/web/websocket_vis/costmap_viz.py +++ b/dimos/web/websocket_vis/costmap_viz.py @@ -19,7 +19,7 @@ import numpy as np -from dimos.msgs.nav_msgs import OccupancyGrid +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid class CostmapViz: diff --git a/dimos/web/websocket_vis/path_history.py b/dimos/web/websocket_vis/path_history.py index 39b6be08a3..c69e7e9508 100644 --- a/dimos/web/websocket_vis/path_history.py +++ b/dimos/web/websocket_vis/path_history.py @@ -17,7 +17,7 @@ This is a minimal implementation to support websocket visualization. """ -from dimos.msgs.geometry_msgs import Vector3 +from dimos.msgs.geometry_msgs.Vector3 import Vector3 class PathHistory: diff --git a/dimos/web/websocket_vis/websocket_vis_module.py b/dimos/web/websocket_vis/websocket_vis_module.py index 7a5c9587e1..5514144570 100644 --- a/dimos/web/websocket_vis/websocket_vis_module.py +++ b/dimos/web/websocket_vis/websocket_vis_module.py @@ -48,11 +48,15 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out +from dimos.mapping.models import LatLon from dimos.mapping.occupancy.gradient import gradient from dimos.mapping.occupancy.inflation import simple_inflate -from dimos.mapping.types import LatLon -from dimos.msgs.geometry_msgs import PoseStamped, Twist, TwistStamped, Vector3 -from dimos.msgs.nav_msgs import OccupancyGrid, Path +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.TwistStamped import TwistStamped +from dimos.msgs.geometry_msgs.Vector3 import Vector3 +from dimos.msgs.nav_msgs.OccupancyGrid import OccupancyGrid +from dimos.msgs.nav_msgs.Path import Path from dimos.utils.logging_config import setup_logger from .optimized_costmap import OptimizedCostmapEncoder diff --git a/docs/capabilities/navigation/native/index.md b/docs/capabilities/navigation/native/index.md index a750d3bfba..6a8c5224e9 100644 --- a/docs/capabilities/navigation/native/index.md +++ b/docs/capabilities/navigation/native/index.md @@ -118,7 +118,7 @@ All visualization layers shown together ## Blueprint Composition -The navigation stack is composed in the [`unitree_go2`](/dimos/robot/unitree/go2/blueprints/__init__.py) blueprint: +The navigation stack is composed in the [`unitree_go2`](/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py) blueprint: ```python fold output=assets/go2_blueprint.svg from dimos.core.blueprints import autoconnect diff --git a/docs/usage/transports/index.md b/docs/usage/transports/index.md index b930671906..db931872bd 100644 --- a/docs/usage/transports/index.md +++ b/docs/usage/transports/index.md @@ -81,7 +81,7 @@ We’ll go through these layers top-down. See [Blueprints](/docs/usage/blueprints.md) for the blueprint API. -From [`unitree/go2/blueprints/__init__.py`](/dimos/robot/unitree/go2/blueprints/__init__.py). +From [`unitree/go2/blueprints/smart/unitree_go2.py`](/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py). Example: rebind a few streams from the default `LCMTransport` to `ROSTransport` (defined at [`transport.py`](/dimos/core/transport.py#L226)) so you can visualize in **rviz2**. diff --git a/docs/usage/visualization.md b/docs/usage/visualization.md index 809f7881e4..57ad460354 100644 --- a/docs/usage/visualization.md +++ b/docs/usage/visualization.md @@ -96,7 +96,7 @@ This happens on lower-end hardware (NUC, older laptops) with large maps. ### Increase Voxel Size -Edit [`dimos/robot/unitree/go2/blueprints/__init__.py`](/dimos/robot/unitree/go2/blueprints/__init__.py) line 82: +Edit [`dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py`](/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py): ```python # Before (high detail, slower on large maps) diff --git a/examples/simplerobot/simplerobot.py b/examples/simplerobot/simplerobot.py index 2a1867b37c..517684d7cd 100644 --- a/examples/simplerobot/simplerobot.py +++ b/examples/simplerobot/simplerobot.py @@ -30,7 +30,11 @@ from dimos.core.core import rpc from dimos.core.module import Module, ModuleConfig from dimos.core.stream import In, Out -from dimos.msgs.geometry_msgs import Pose, PoseStamped, Quaternion, Twist, Vector3 +from dimos.msgs.geometry_msgs.Pose import Pose +from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped +from dimos.msgs.geometry_msgs.Quaternion import Quaternion +from dimos.msgs.geometry_msgs.Twist import Twist +from dimos.msgs.geometry_msgs.Vector3 import Vector3 def apply_twist(pose: Pose, twist: Twist, dt: float) -> Pose: diff --git a/pyproject.toml b/pyproject.toml index 4370944b27..722e3b0485 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -377,6 +377,7 @@ python_version = "3.12" incremental = true strict = true warn_unused_ignores = false +explicit_package_bases = true exclude = "^dimos/models/Detic(/|$)|^dimos/rxpy_backpressure(/|$)|.*/test_.|.*/conftest.py*" [[tool.mypy.overrides]] @@ -429,7 +430,7 @@ env = [ "GOOGLE_MAPS_API_KEY=AIzafake_google_key", "PYTHONWARNINGS=ignore:cupyx.jit.rawkernel is experimental:FutureWarning", ] -addopts = "-v -r a -p no:warnings --color=yes -m 'not (tool or slow or mujoco)'" +addopts = "-v -r a -p no:warnings -p no:launch_testing -p no:launch_ros --import-mode=importlib --color=yes -m 'not (tool or slow or mujoco)'" asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function"