Raisin Network

Introduction

raisin_network

Raisin Network is a package for transferring messages. Messages can be exchanged between different machines, different processes, or even different objects within the same process.

Raisin Network supports both local network connections (TCP/UDP) and remote network connections (WebSocket++). If a robot has a cellular network (LTE or 5G) with a static IP, you can connect to the robot using Raisin Network.

The Raisin Network API is highly inspired by ROS2. If you are familiar with ROS2, you will find Raisin Network intuitive, requiring minimal additional learning.

raisin_network

Raisin Network supports both compression and encryption. For instance, video data is compressed using FFmpeg.

Threadpool

To understand Raisin Network, it is essential to first understand Raisin Threadpool.

Raisin Threadpool preallocates threads and allows users to register tasks. If multiple tasks are registered within the same thread, they will not be executed concurrently. This minimizes the need for mutexes, reducing unnecessary wait times. Additionally, since mutexes are often overlooked, using a thread pool is a safer alternative to individually created std::thread objects.

Registered tasks fall into two categories: periodic and event-based. Periodic tasks run at a fixed frequency, while event-based tasks execute only when triggered. Raisin Network manages message handling through Raisin Threadpool. Further details are provided in the following sections.

When creating an instance of raisin::Network, you can specify the thread group configuration of a type std::vector<std::vector<std::string>>. The outer vector represents thread pools, each containing multiple thread groups. When creating a task, you can assign it to a specific thread group, ensuring execution within the corresponding thread pool.

Remotes and Connections

A key difference between ROS2 and Raisin Network is that Raisin Network requires an explicit connection to communicate. This is very different from ROS2 which broadcasts messages to all machines within the same local network.

A server can be started in any raisin::Network instance using the launchServer() method. By default, this creates a TCP server, but a webSocket server can also be launched by specifying the type as launchServer(Remote::NetworkType::WEBSOCKET). Both TCP and WebSocket servers can be initiated from the same raisin::Network instance. In fact, we recommend maintaining a single instance of raisin::Network per process.

Once the server is created, it can be discovered from another raisin::Network instance using the getAllConnections() method. To connect to a TCP server, use connect(const std::string & id). To connect to a WebSocket server, use connect(const std::string & ip, int port).

Note: The port number for the WebSocket server is currently fixed at 9002.

Publisher and Subscriber

Publishers are designed to deliver messages at a consistent rate. Thus they typically operate in a timed loop, implemented as a periodic task in the thread pool. However, to publish messages periodically, you must explicitly create a timed loop. Check out the example code in the below example.

Within a single Raisin Network instance, publishers must have unique names.

Subscribers listen to designated publishers and execute a callback whenever a message is received. This process is managed through an automatically created event task. When a message arrives from the publisher, the event task associated with the subscriber is triggered, and the corresponding callback is executed.

Message types are specified in .msg files. Since Raisin Network strictly adheres to ROS2 conventions, we recommend referring to the ROS2 documentation for details (https://design.ros2.org/articles/legacy_interface_definition.html).

.msg files in a Raisin package are converted into header files located at <raisin_package_name>/msg/<msg_file_name>.hpp. The header file names follow the snake_case convention, consistent with ROS2 standards.

The example code is available in https://github.com/railabatkaist/raisin_examples.git.

Service and Clients

Services facilitate infrequent communication between nodes. A client sends a Request to a service, which executes a callback and responds with a Response. Services are automatically registered as event tasks. Like publishers, services must have unique names within a raisin::Network instance.

Clients can optionally include a callback function. If not, they should use the std::shared_future returned by the service. Properly managing services can be complex, so we recommend referring to the example code below.

The example code is available in https://github.com/railabatkaist/raisin_examples.git.

Raisin CLI

██████╗   █████╗ ██╗███████╗██╗███╗   ██╗
██╔══██╗ ██╔══██╗██║██╔════╝██║████╗  ██║
███████═╗███████║██║███████╗██║██╔██╗ ██║
██╔═══██║██╔══██║██║╚════██║██║██║╚██╗██║
██║   ██║██║  ██║██║███████║██║██║ ╚████║
╚═╝   ╚═╝╚═╝  ╚═╝╚═╝╚══════╝╚═╝╚═╝  ╚═══╝
[Raisin Util] install directory is /home/raion/raisin_master/install/
[2025:07:23:10:17:17 network.cpp:194] Ip of this machine is
[2025:07:23:10:17:17 network.cpp:295] Encryption test passed
[2025:07:23:10:17:17 network.cpp:274] Raisin network is encrypted with empty
[2025:07:23:10:17:17 network.cpp:792] Received packet on unknown interface index: 0
╔═════════════════════════════ Command ═══════════════════════════╗
║ Connect: con [server_id] ║ List connections: list  ║ Quit: quit ║
╚═════════════════════════════════════════════════════════════════╝

The CLI tool provides a simple way to interact with available servers, monitor messages, and send service requests. Below is a guide to its main features and usage.

Custom msg and srv files

raisin_master workpsace looks like this

raisin_master/
├── include/
├── install/
├── src/
├── templates/
├── message/
├   └── custom_msg/
├       └── msg/
├          └── msg.msg
├       └── srv/
├          └── srv.srv
├── log
├── generated/
├   └── custom_msg/
├       └── msg/
├          └── msg.hpp
├       └── srv/
├          └── srv.hpp
├── raisin_workspace_setup/
└── CMakeLists.txt

Messages define the data structure used during communication. Matching message types are required for data exchange between Publishers and Subscribers, as well as between Services and Clients.

If you want to create custom messages and services, you need to pay attention to the message and generated folders. Create a custom message folder inside the message directory, and design the msg and srv files according to the required structure. The raisin_workspace_setup.py script converts these message definitions into usable code and places them into the generated folder.

Raisin Bridge

Raisin Bridge is a ros2 node that allows you to connect Raisin Network with ROS2. https://github.com/railabatkaist/raisin_bridge