# How to Integrate ROS2 Topics into DimOS Using the ROSTransport Bridge

> Integrate ROS2 topics into DimOS seamlessly. Learn to use the ROSTransport bridge by binding DimOS streams to ROSTransport instances and attaching them to blueprints. Simplify your robotics development.

- Repository: [Dimensional/dimos](https://github.com/dimensionalOS/dimos)
- Tags: how-to-guide
- Published: 2026-03-15

---

**You can integrate ROS2 topics into DimOS by creating a transport map that binds DimOS typed streams to `ROSTransport` instances, then attaching that map to a blueprint via the `transports()` method.**

DimOS (dimensionalOS/dimos) provides a **transport layer** that connects its typed streams (`In[T]` / `Out[T]`) to external messaging systems without requiring ROS-specific code in your modules. The `ROSTransport` class in [`dimos/core/transport.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/transport.py) implements a complete bridge to ROS2, handling node initialization, message conversion, and lazy topic creation automatically.

## Understanding the ROSTransport Architecture

The bridge consists of four core components that work together to map DimOS streams to ROS2 topics:

- **`ROSTransport`** ([`dimos/core/transport.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/transport.py), lines 251-283): A subclass of `PubSubTransport` that wraps ROS2 publishing and subscribing. It lazily instantiates a `DimosROS` helper on first use, then forwards `publish` and `subscribe` calls to the underlying ROS2 node.

- **`Blueprint.transports()`** ([`dimos/core/blueprints.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/blueprints.py), lines 33-35): A method that accepts a mapping dictionary and attaches transport configurations to a blueprint. During the wiring phase, the blueprint looks up transports via `_get_transport_for` and binds them to the appropriate streams.

- **`DimosROS`**: An internal ROS2 client that handles node initialization, topic creation, and message serialization. It starts when `ROSTransport.start()` is called and shuts down automatically when the blueprint tears down.

- **Typed streams**: DimOS message definitions in `dimos.msgs` (e.g., `sensor_msgs/Image`, `geometry_msgs/PoseStamped`) serve as the ROS2 message type for the bridge, preserving type safety across the system boundary.

When a module publishes on an `Out[Msg]` stream with an attached `ROSTransport`, the `broadcast()` method forwards the message to the ROS2 topic. Conversely, incoming ROS2 messages trigger the `subscribe()` method to call the module's `In[Msg]` callback.

## Step-by-Step Integration Guide

Follow these five steps to bridge any DimOS stream to a ROS2 topic:

1. **Import the transport class**

   ```python
   from dimos.core.transport import ROSTransport
   ```

2. **Select ROS2 message classes** from the `dimos.msgs` package. These thin wrappers around standard ROS2 definitions enable automatic conversion.

   ```python
   from dimos.msgs.geometry_msgs import PoseStamped
   from dimos.msgs.sensor_msgs import Image, PointCloud2
   ```

3. **Create a transport map** that pairs each DimOS stream name with a `ROSTransport` instance containing the target ROS2 topic name and message type.

   ```python
   ros_map = {
       ("lidar", PointCloud2): ROSTransport("lidar", PointCloud2),
       ("global_map", PointCloud2): ROSTransport("global_map", PointCloud2),
       ("odom", PoseStamped): ROSTransport("odom", PoseStamped),
       ("color_image", Image): ROSTransport("color_image", Image),
   }
   ```

4. **Attach the map to a blueprint** using the `transports()` method. This example extends the Unitree Go2 robot blueprint.

   ```python
   from dimos.robot.unitree.go2.blueprints.smart.unitree_go2 import unitree_go2

   unitree_go2_ros = unitree_go2.transports(ros_map)
   ```

5. **Run the blueprint** normally with `dimos run unitree_go2_ros`. DimOS automatically initializes the ROS2 node, creates publishers for outbound topics, and starts subscribers for inbound mappings defined in your transport map.

## Practical Code Examples

### Minimal Image Stream Bridge

This example bridges a single camera stream from a Go2 robot to a standard ROS2 image topic:

```python

# file: my_robot/blueprints/ros_image_bridge.py

from dimos.core.transport import ROSTransport
from dimos.msgs.sensor_msgs import Image
from dimos.robot.unitree.go2.blueprints.smart.unitree_go2 import unitree_go2

# Bridge the DimOS "color_image" stream to ROS2 topic "camera/image_raw"

ros_transport_map = {
    ("color_image", Image): ROSTransport("camera/image_raw", Image)
}

# Extend the original Go2 blueprint

unitree_go2_image = unitree_go2.transports(ros_transport_map)

__all__ = ["unitree_go2_image"]

```

Execute the bridge:

```bash
dimos run unitree_go2_image

```

The robot's `color_image` output now publishes to the ROS2 topic **`/camera/image_raw`** as standard `sensor_msgs/Image` messages.

### Full Navigation Stack Bridge (Bidirectional)

For autonomous navigation, you typically need both inbound and outbound transports to interface with ROS2 navigation stacks:

```python

# file: navigation/rosnav_bridge.py

from dimos.core.transport import ROSTransport
from dimos.msgs.geometry_msgs import PoseStamped
from dimos.msgs.sensor_msgs import TwistStamped, PointCloud2
from dimos.msgs.std_msgs import Bool, Int8, Joy, Path
from dimos.navigation.rosnav import RosNav  # existing navigation module

nav_ros_map = {
    # Outbound (DimOS → ROS2)

    ("ros_goal_pose", PoseStamped): ROSTransport("/goal_pose", PoseStamped),
    ("ros_cmd_vel", TwistStamped): ROSTransport("/cmd_vel", TwistStamped),
    ("ros_way_point", PoseStamped): ROSTransport("/way_point", PoseStamped),
    ("ros_registered_scan", PointCloud2): ROSTransport("/registered_scan", PointCloud2),
    ("ros_global_map", PointCloud2): ROSTransport("/terrain_map_ext", PointCloud2),
    ("ros_path", Path): ROSTransport("/path", Path),

    # Inbound (ROS2 → DimOS)

    ("ros_goal_reached", Bool): ROSTransport("/goal_reached", Bool),
    ("ros_cancel_goal", Bool): ROSTransport("/cancel_goal", Bool),
    ("ros_soft_stop", Int8): ROSTransport("/stop", Int8),
    ("ros_joy", Joy): ROSTransport("/joy", Joy),
}

# Attach transports to the navigation blueprint

ros_nav = RosNav.transports(nav_ros_map)

__all__ = ["ros_nav"]

```

Running `dimos run ros_nav` creates a bidirectional bridge compatible with standard ROS2 navigation interfaces like Nav2 or custom planners.

### Robot-Specific Velocity Command Bridge

For direct motor control, bridge the low-level command velocity stream:

```python

# file: unitree/b1/ros_bridge.py

from dimos.core.transport import ROSTransport
from dimos.msgs.geometry_msgs import TwistStamped
from dimos.robot.unitree.b1.unitree_b1 import unitree_b1

b1_ros_map = {
    ("ros_cmd_vel", TwistStamped): ROSTransport("/cmd_vel", TwistStamped),
}

unitree_b1_ros = unitree_b1.transports(b1_ros_map)

__all__ = ["unitree_b1_ros"]

```

This exposes the B1 robot's velocity commands on the standard ROS2 `cmd_vel` topic, allowing control via `teleop_twist_keyboard` or similar ROS2 tools.

## Advanced Configuration Options

**Bidirectional Bridges**: Define separate `ROSTransport` instances for the same ROS2 topic to enable both reading and writing. The bridge treats each direction independently, so you can have a module both publish to and subscribe from a topic by including the stream name in both `Out` and `In` definitions with appropriate transports.

**Custom ROS2 Node Arguments**: Pass additional keyword arguments to `ROSTransport` to configure the underlying ROS2 node. These parameters forward directly to the `DimosROS` constructor.

```python
ROSTransport("/cmd_vel", TwistStamped, namespace="my_robot")

```

**Dynamic Topic Creation**: The transport layer creates ROS2 publishers and subscribers lazily upon the first `broadcast` or `subscribe` call. This allows you to declare transports for optional topics that may not exist at startup without causing initialization errors.

## Summary

- **ROSTransport** in [`dimos/core/transport.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/transport.py) provides the bridge between DimOS streams and ROS2 topics without requiring ROS-specific code in your modules.
- Use **Blueprint.transports()** in [`dimos/core/blueprints.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/blueprints.py) to attach a transport mapping dictionary to any blueprint.
- Import message types from `dimos.msgs` to maintain type safety across the bridge.
- Create bidirectional integrations by defining transports for both inbound and outbound streams.
- The **DimosROS** helper handles node lifecycle management automatically, starting lazily and shutting down with the blueprint.

## Frequently Asked Questions

### Do I need to manually initialize a ROS2 node to use ROSTransport?

No. The `DimosROS` helper instantiated by `ROSTransport.start()` handles ROS2 node initialization automatically when the blueprint begins execution. You do not need to write any `rclpy.init()` or node creation code in your application.

### Can I use custom ROS2 message types with the bridge?

Yes, provided you have corresponding DimOS message definitions in the `dimos.msgs` namespace. The `ROSTransport` class uses these typed stream definitions to serialize and deserialize messages, so any message type available in `dimos.msgs` (or your custom extensions) works with the bridge.

### How do I configure ROS2 namespaces for my topics?

Pass the `namespace` parameter (and other ROS2 node arguments) directly to the `ROSTransport` constructor. These keyword arguments forward to the underlying `DimosROS` client, allowing you to scope all topics under a specific robot namespace or remap topic names as needed.

### Is the ROSTransport bridge bidirectional by default?

Each `ROSTransport` instance handles one direction. To create a bidirectional bridge, you must explicitly define separate transport mappings for both the `In` (subscribe) and `Out` (publish) streams. The blueprint wiring logic treats these as independent connections, giving you full control over which streams participate in each direction.