# Integration with ROS2

## Overview

The Communications node bridges the gap between raw UDP/protobuf packets and the ROS2 ecosystem running on Jonny Boi. This page explains how incoming protobuf messages get converted into ROS2 messages and published on topics, the handler pattern that makes this extensible, and how custom ROS2 message types are defined.

## Custom ROS2 Message Types

ROS2 uses its own message format (`<span class="editor-theme-code">.msg</span>`<span style="white-space: pre-wrap;"> files) to define the structure of data exchanged between nodes over topics. These are separate from protobuf definitions, they exist so that internal ROS2 nodes like the Behavior Node can work with typed, idiomatic ROS2 messages rather than raw protobuf objects.</span>

<span style="white-space: pre-wrap;">All custom message definitions live in the </span>`<span class="editor-theme-code">msg/</span>`<span style="white-space: pre-wrap;"> folder of the </span>`<span class="editor-theme-code">comms</span>`<span style="white-space: pre-wrap;"> package:</span>

```
comms/msg/
  ImuSensorInformation.msg
  SensorBoardGPSInfo.msg
  SensorBoardPHInfo.msg
  SensorBoardDiagnostics.msg
  SensorState.msg
```

<span style="white-space: pre-wrap;">These are registered in </span>`<span class="editor-theme-code">CMakeLists.txt</span>`<span style="white-space: pre-wrap;"> via </span>`<span class="editor-theme-code">rosidl_generate_interfaces</span>`<span style="white-space: pre-wrap;">, which generates the corresponding C++ types at build time. The generated types follow the naming convention </span>`<span class="editor-theme-code">comms::msg::MessageName</span>`<span style="white-space: pre-wrap;"> and can be included in any C++ file as </span>`<span class="editor-theme-code">#include "comms/msg/message_name.hpp"</span>`<span style="white-space: pre-wrap;">. For more on ROS2 interfaces, refer to the official documentation: </span>[https://docs.ros.org/en/humble/Concepts/Basic/About-Interfaces.html](https://docs.ros.org/en/humble/Concepts/Basic/About-Interfaces.html)

## The Handler Pattern

<span style="white-space: pre-wrap;">The handler pattern is the core architectural decision that makes adding new message types straightforward without ever touching the dispatch logic in </span>`<span class="editor-theme-code">udp_forwarder_node.cpp</span>`.

<span style="white-space: pre-wrap;">Every message type that needs to be converted and published as a ROS2 topic is represented by a handler class. All handlers extend the abstract </span>`<span class="editor-theme-code">Handler</span>`<span style="white-space: pre-wrap;"> base class defined in </span>`<span class="editor-theme-code">include/comms/udp/handler.hpp</span>`:

```cpp
class Handler {
public:
    virtual ~Handler() = default;
    virtual void handle(const PBEnvelope& envelope) = 0;
};
```

<span style="white-space: pre-wrap;">Each concrete handler class — one per message type — lives in </span>`<span class="editor-theme-code">include/comms/udp/handlers/</span>`<span style="white-space: pre-wrap;"> and its corresponding </span>`<span class="editor-theme-code">.cpp</span>`<span style="white-space: pre-wrap;"> in </span>`<span class="editor-theme-code">src/handlers/</span>`. Its job is exactly three things:

1. <span style="white-space: pre-wrap;">Extract the specific protobuf message from the </span>`<span class="editor-theme-code">PBEnvelope</span>`
2. Map the protobuf fields to the equivalent ROS2 message fields
3. Publish the ROS2 message on the appropriate topic

<span style="white-space: pre-wrap;">As an example, </span>`<span class="editor-theme-code">ImuHandler</span>`<span style="white-space: pre-wrap;"> extracts </span>`<span class="editor-theme-code">SensorBoardIMUInfo</span>`<span style="white-space: pre-wrap;"> from the envelope, maps its accelerometer, gyroscope and magnetometer fields to a </span>`<span class="editor-theme-code">comms::msg::ImuSensorInformation</span>`<span style="white-space: pre-wrap;"> message, and publishes it on the </span>`<span class="editor-theme-code">imu_data</span>`<span style="white-space: pre-wrap;"> topic.</span>

## Handler Registration

<span style="white-space: pre-wrap;">Handlers are registered in the constructor of </span>`<span class="editor-theme-code">udp_forwarder_node.cpp</span>`<span style="white-space: pre-wrap;"> using a simple </span>`<span class="editor-theme-code">unordered_map</span>`<span style="white-space: pre-wrap;"> keyed by </span>`<span class="editor-theme-code">PBEnvelope::PayloadCase</span>`:

```cpp
handlers_.emplace(
    static_cast<int>(PBEnvelope::kImuInfo),
    std::make_unique<ImuHandler>(this, "imu_data", 10)
);
```

<span style="white-space: pre-wrap;">The three constructor arguments are the node pointer (so the handler can create a ROS2 publisher), the topic name to publish on, and the publisher queue size. To add support for a new message type, you write a new handler class and add one line here. The dispatch logic in </span>`<span class="editor-theme-code">rx_loop</span>`<span style="white-space: pre-wrap;"> requires no changes at all.</span>

## The Full Inbound Flow

The complete path from a raw UDP packet to a ROS2 topic looks like this:

[![image.png](https://bookstack.roboteamtwente.nl/uploads/images/gallery/2026-04/scaled-1680-/Mjfimage.png)](https://bookstack.roboteamtwente.nl/uploads/images/gallery/2026-04/Mjfimage.png)

<span style="white-space: pre-wrap;">If no handler is registered for a given </span>`<span class="editor-theme-code">payload_case</span>`, the node logs a throttled warning and drops the packet. This means unhandled message types fail silently, keep this in mind when debugging missing data.

## The Outbound Flow

The outbound direction works in reverse, the Communications node subscribes to a ROS2 topic, converts the incoming message back into a protobuf, wraps it in a PBEnvelope, and sends it as a UDP packet to the appropriate destination. This path is not yet fully implemented for all message types and will be extended as the Behavior Node develops.

## Adding a New Message Type

<span style="white-space: pre-wrap;">For a step-by-step guide on adding a new message type end-to-end, from the proto definition all the way to a registered handler — see the dedicated </span>[Adding a new message](https://bookstack.roboteamtwente.nl/books/jonny-boi/page/adding-a-new-message "Adding a new message")<span style="white-space: pre-wrap;"> page.</span>