# UDP Forwarder and ROS2 Publisher

## `<span class="editor-theme-code">udp_forwarder_node.cpp</span>`

This is the main file running the communications logic on Jonny Boi's side. It is a ROS2 node that simultaneously acts as a UDP server and a ROS2 publisher/subscriber. Its primary responsibilities are:

- Receiving raw encoded PBEnvelope packets over UDP from the Basestation or hardware microcontrollers
- Deserializing the protobuf payload and converting it into a custom ROS2 message
- Publishing that ROS2 message over the appropriate topic for internal nodes to consume
- In the outbound direction, subscribing to ROS2 topics and converting messages back into protobufs to be sent as UDP packets

## The Handler Pattern

<span style="white-space: pre-wrap;">The most important architectural concept in this file is the </span>**registry-based handler dispatch system**<span style="white-space: pre-wrap;">. Rather than having a large switch statement that handles every possible message type, the node maintains an </span>`<span class="editor-theme-code">unordered_map</span>`<span style="white-space: pre-wrap;"> that maps each </span>`<span class="editor-theme-code">PBEnvelope::PayloadCase</span>`<span style="white-space: pre-wrap;"> enum value to a dedicated handler object.</span>

<span style="white-space: pre-wrap;">When a UDP packet arrives, the node parses it as a </span>`<span class="editor-theme-code">PBEnvelope</span>`<span style="white-space: pre-wrap;"> and calls </span>`<span class="editor-theme-code">payload_case()</span>`<span style="white-space: pre-wrap;"> to identify the message type. It then looks up the corresponding handler in the map and calls </span>`<span class="editor-theme-code">handle(envelope)</span>`<span style="white-space: pre-wrap;"> on it. Each handler is a class that extends the abstract </span>`<span class="editor-theme-code">Handler</span>`<span style="white-space: pre-wrap;"> base class and is solely responsible for one message type — deserializing the protobuf, mapping its fields to a ROS2 message, and publishing it on the correct topic.</span>

Registering a handler looks like this:

```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 publisher), the ROS2 topic name to publish on, and the publisher queue size. Adding support for a new message type is as simple as writing a new handler class and adding one </span>`<span class="editor-theme-code">emplace</span>`<span style="white-space: pre-wrap;"> call here — the rest of the dispatch logic requires no changes. See the </span>**Adding a New Message Type**<span style="white-space: pre-wrap;"> page for a step-by-step guide.</span>

## The rx\_loop Background Thread

<span style="white-space: pre-wrap;">UDP receiving does not happen on the ROS2 spin thread. Instead, the node spawns a dedicated background thread that runs </span>`<span class="editor-theme-code">rx_loop()</span>`<span style="white-space: pre-wrap;"> continuously, blocking on </span>`<span class="editor-theme-code">recvfrom()</span>`<span style="white-space: pre-wrap;"> until a datagram arrives. This design ensures that the ROS2 executor is never blocked waiting for network I/O, and that incoming packets are processed as fast as the network delivers them regardless of what the ROS2 stack is doing.</span>

<span style="white-space: pre-wrap;">This is worth keeping in mind when debugging. If you see unexpected behavior related to timing or message ordering, the source may be a race condition between the rx\_loop thread and the ROS2 spin thread. The </span>`<span class="editor-theme-code">running_</span>`<span style="white-space: pre-wrap;"> flag is declared as </span>`<span class="editor-theme-code">std::atomic<bool></span>`<span style="white-space: pre-wrap;"> specifically to ensure safe cross-thread signaling during shutdown.</span>

## UDP Forwarding Behavior

<span style="white-space: pre-wrap;">Before dispatching to a handler, the node forwards every raw UDP datagram to both </span>`<span class="editor-theme-code">dstA_</span>`<span style="white-space: pre-wrap;"> and </span>`<span class="editor-theme-code">dstB_</span>`<span style="white-space: pre-wrap;"> unconditionally. This means every message type, regardless of its intended destination, is forwarded to both addresses. This is a known architectural limitation — see the </span>**Known Limitations**<span style="white-space: pre-wrap;"> page for more context and the rationale behind it.</span>

## Configuration Parameters

The node's network configuration is fully driven by ROS2 parameters declared at startup:

<table class="align-center" id="bkmrk-parameterdefaultdesc"><colgroup><col></col><col></col><col></col></colgroup><tbody><tr><th class="align-center">Parameter

</th><th>Default

</th><th>Description

</th></tr><tr><td class="align-center">`<span class="editor-theme-code">listen_port</span>`

</td><td>5000

</td><td>UDP port the node listens on

</td></tr><tr><td>`<span class="editor-theme-code">dst_a_port</span>`

</td><td>6000

</td><td>First forwarding destination port

</td></tr><tr><td>`<span class="editor-theme-code">dst_b_port</span>`

</td><td>6001

</td><td>Second forwarding destination port

</td></tr><tr><td>`<span class="editor-theme-code">dst_ip</span>`

</td><td>127.0.0.1

</td><td>Destination IP for both forwarding targets

</td></tr></tbody></table>

<span style="white-space: pre-wrap;">These can be overridden at launch time via a ROS2 launch file or </span>`<span class="editor-theme-code">--ros-args</span>`<span style="white-space: pre-wrap;"> flags without recompiling, making it easy to reconfigure the node for different network environments such as the Jetson on the rover versus a local development machine.UDP Forwarding</span>

<span style="white-space: pre-wrap;">Currently, every received UDP packet is forwarded raw to both </span>`<span class="editor-theme-code">dstA_</span>`<span style="white-space: pre-wrap;"> and </span>`<span class="editor-theme-code">dstB_</span>`<span style="white-space: pre-wrap;"> before handler dispatch.</span>

<p class="callout warning">This implementation will CHANGE SOON. to forward ONLY to appropriate destinations.</p>