SOME/IP ↔ ROS 2 Gateway¶
The ROS 2 gateway connects OpenSOME/IP to ROS 2 for ADAS, autonomous driving, and robotics stacks. It reuses opensomeip-gateway-common (GatewayBase, ServiceMapping, translators, statistics, direction enums) so routing and observability stay consistent with other gateways.
Source repository
Implementation and examples live in opensomeip-gateways under gateway-ros2/.
Architecture¶
flowchart LR
subgraph SOMEIP["SOME/IP stack"]
EP[EventPublisher]
ES[EventSubscriber]
RC[RpcClient]
RS[RpcServer]
SDc[SdClient]
SDs[SdServer]
UDP[UdpTransport]
E2E[E2EProtection]
end
subgraph GW["Ros2Gateway"]
TR[Ros2Translator]
PI["Pimpl (rclcpp)"]
end
subgraph ROS2["ROS 2"]
PUB[Publishers]
SUB[Subscriptions]
end
ES --> GW
RC --> GW
UDP --> GW
GW --> TR
TR --> PI
PI --> PUB
SUB --> PI
GW --> RC
GW --> EP
- SOME/IP → ROS 2:
on_someip_message()resolvesServiceMapping, optionally validates E2E, converts payload withRos2Translator, then publishes via rclcpp asstd_msgs/msg/UInt8MultiArray(or a test callback when ROS is not linked). - ROS 2 → SOME/IP: Subscriptions call
inject_ros2_message(), which builds a SOME/IP request and dispatches viaRpcClientor an optionalsomeip_outbound_sink.
Features¶
| Capability | Description |
|---|---|
| Pub/sub | Event notifications become ROS publishes; command topics drive inbound traffic. |
| Request–response | SOME/IP RPC via RpcClient / RpcServer attachments; ROS side uses opaque byte payloads for commands. |
| QoS mapping | Ros2Translator::qos_for_someip_transport() maps a SOME/IP transport hint to Ros2QosProfile (reliability, history, durability). |
| E2E validation | Optional E2EProtection when use_e2e and config are enabled. |
| rclcpp integration | With rclcpp and std_msgs at configure time, OPENSOMEIP_GATEWAY_ROS2_HAS_RCLCPP is defined and the pimpl creates nodes, publishers, and subscriptions. |
| Opaque byte bridge | Payloads are raw bytes in UInt8MultiArray; no ROS .msg code generation per SOME/IP service is required for the default path. |
QoS mapping¶
Ros2QosProfile fields are consumed by the gateway implementation when building rclcpp QoS. Volatile means durability_transient_local == false.
SomeipTransportKind |
Reliable | history_depth |
Durability |
|---|---|---|---|
UDP_UNICAST |
no | 5 | volatile |
UDP_MULTICAST |
no | 5 | volatile |
TCP |
yes | 10 | volatile |
Set Ros2Config::default_someip_transport to match how events are delivered on the vehicle bus.
Topic naming¶
Default ROS topic shape built by Ros2Translator::build_ros2_topic():
Each of service_id, instance_id, and event_id is formatted as uppercase hex with 0x prefix and four digits (for example 0x1234).
If ServiceMapping::external_identifier is set, it overrides this pattern for that mapping (for example a stable name like /vehicle/adas/speed_ms).
Namespace
ros_namespace should usually start with / (for example /vehicle). The translator normalizes a leading slash and trims trailing slashes.
OpenSOME/IP APIs used¶
| API | Role in gateway |
|---|---|
someip::Message, MessageId, RequestId, MessageType, ReturnCode |
Core message model. |
someip::serialization::Serializer / Deserializer |
Examples and typed payloads. |
someip::events::EventPublisher / EventSubscriber |
Events in/out of SOME/IP. |
someip::rpc::RpcClient / RpcServer |
Method calls and servers. |
someip::sd::SdClient / SdServer |
Optional SD. |
someip::transport::UdpTransport, Endpoint |
Optional UDP bridge. |
someip::e2e::E2EProtection, E2EConfig |
Optional E2E. |
someip::Result |
Lifecycle and on_someip_message results. |
Configuration reference (YAML)¶
Reference layout from examples/ros2_config.yaml. Runtime loading is application-specific; fields align with Ros2Config and feature flags.
ros2:
node_name: opensomeip_ros2_gateway
namespace: /vehicle
topic_prefix: someip
someip:
bind_address: 0.0.0.0
bind_port: 30500
rpc_client_id: 0x5100
default_instance_id: 0x0001
features:
enable_udp_transport: false
enable_rpc_client: true
enable_rpc_server: false
enable_sd_client: false
enable_sd_server: false
enable_event_subscriber: true
use_e2e: false
service_mappings:
- someip_service_id: 0x6001
someip_instance_id: 0x0001
ros_topic: /vehicle/adas/speed_ms
direction: someip_to_ros2
someip_method_ids: []
someip_event_group_ids: [0x0001]
- someip_service_id: 0x6002
someip_instance_id: 0x0001
ros_topic: /vehicle/adas/steering_command
direction: ros2_to_someip
someip_method_ids: [0x0001]
someip_event_group_ids: []
| Area | Maps to |
|---|---|
ros2.node_name |
Ros2Config::node_name |
ros2.namespace |
ros_namespace |
ros2.topic_prefix |
topic_prefix |
someip.* |
Bind address/port, rpc_client_id, default_someip_instance_id |
features.* |
enable_* and use_e2e toggles |
service_mappings[] |
ServiceMapping (external_identifier from ros_topic or equivalent) |
Directions in C++ are GatewayDirection::SOMEIP_TO_EXTERNAL, EXTERNAL_TO_SOMEIP, or BIDIRECTIONAL (YAML may use snake_case aliases depending on your loader).
C++ usage example¶
From examples/ros2_adas_bridge.cpp: set Ros2Config, add mappings with external_identifier as the ROS topic, call start(), then drive on_someip_message() and/or ROS publishers and inject_ros2_message().
#include "opensomeip/gateway/ros2/ros2_gateway.h"
#include "serialization/serializer.h"
#include "someip/types.h"
opensomeip::gateway::ros2::Ros2Config cfg;
cfg.node_name = "ros2_adas_bridge";
cfg.ros_namespace = "/vehicle";
cfg.topic_prefix = "someip";
cfg.rpc_client_id = 0x7101;
cfg.enable_event_subscriber = true;
cfg.default_someip_transport = opensomeip::gateway::ros2::SomeipTransportKind::UDP_UNICAST;
opensomeip::gateway::ros2::Ros2Gateway gateway(cfg);
opensomeip::gateway::ServiceMapping speed_out;
speed_out.someip_service_id = 0x6001;
speed_out.someip_instance_id = 0x0001;
speed_out.external_identifier = "/vehicle/adas/speed_ms";
speed_out.direction = opensomeip::gateway::GatewayDirection::SOMEIP_TO_EXTERNAL;
gateway.add_service_mapping(speed_out);
if (gateway.start() != someip::Result::SUCCESS) {
return 1;
}
someip::Message speed_msg(
someip::MessageId{0x6001, 0x8001},
someip::RequestId{0x0001, 0x0001},
someip::MessageType::NOTIFICATION,
someip::ReturnCode::E_OK);
// attach payload bytes, then:
gateway.on_someip_message(speed_msg);
gateway.stop();
Register command paths with EXTERNAL_TO_SOMEIP or BIDIRECTIONAL and someip_method_ids populated so inject_ros2_message(topic, bytes) targets the correct method.
Build instructions¶
The library opensomeip-gateway-ros2 always builds; full ROS integration requires rclcpp and std_msgs at CMake configure time.
# Source ROS 2 so find_package(rclcpp) and find_package(std_msgs) succeed
cmake -S opensomeip-gateways -B build -DBUILD_GATEWAY_ROS2=ON -DBUILD_TESTS=ON
cmake --build build
ctest --test-dir build -R Ros2Gateway --output-on-failure
Examples (ros2_adas_bridge) require -DBUILD_EXAMPLES=ON and OPENSOMEIP_GATEWAY_ROS2_HAS_RCLCPP:
cmake -S opensomeip-gateways -B build \
-DBUILD_GATEWAY_ROS2=ON \
-DBUILD_EXAMPLES=ON \
-DBUILD_TESTS=ON
cmake --build build
Headers
When rclcpp is enabled, link targets that use the gateway should pull rclcpp and std_msgs transitively via opensomeip-gateway-ros2.
Tracking¶
Design discussion and roadmap: GitHub issue #5 — ROS 2 gateway.