Skip to main content

pamoja_ros2/
lib.rs

1#![cfg_attr(not(any(test, feature = "bridge")), no_std)]
2
3//! ROS 2 bridge logic for the pamoja SDK.
4//!
5//! Bridging a ROS 2 robot onto the pamoja device model means speaking ROS 2's wire conventions
6//! exactly: the rules a topic or service name must obey, how that name maps onto the middleware,
7//! how a message type is named and hashed, the Zenoh key a `rmw_zenoh` peer expects, and how a
8//! message is serialized as CDR. Each is precise, specified, and a classic place for a from-memory
9//! bug, so it lives here as checked logic anchored to the ROS 2 and OMG specifications, ahead of
10//! the live `r2r`/Zenoh bridge that carries the bytes.
11//!
12//! The modules are:
13//!
14//! - [`name`] - validate ROS 2 topic and service names and map them to DDS topic names with the
15//!   `rt`/`rq`/`rr` prefixes, plus the `%`-mangling `rmw_zenoh` uses in liveliness tokens.
16//! - [`typehash`] - parse and format the `RIHS01` type hash (REP-2011) and turn a ROS type like
17//!   `std_msgs/msg/String` into its DDS type name `std_msgs::msg::dds_::String_`.
18//! - [`key`] - assemble the `rmw_zenoh` key expression `<domain>/<name>/<type>/<hash>` a Zenoh peer
19//!   subscribes to, validated as a Zenoh key expression through [`pamoja_zenoh`].
20//! - [`msg`] - encode and decode messages as CDR (the OMG Common Data Representation, the format
21//!   DDS and `rmw_zenoh` put on the wire), starting with the geometry messages a robot is driven by.
22//!
23//! With the `bridge` feature on, `bridge` adds the live layer: a `bridge::Ros2Node` over `r2r`
24//! whose publishers and subscribers are exposed as the core
25//! `Actuator` and `Sensor`, so a ROS 2 robot drives
26//! like any other pamoja device. That layer needs a sourced ROS 2 install (r2r generates message
27//! bindings at build time), so it is built and tested in the ros:jazzy container.
28//!
29//! # Examples
30//!
31//! ```
32//! use pamoja_ros2::msg::{Twist, Vector3};
33//! use pamoja_ros2::name::{dds_topic, EntityKind};
34//!
35//! // A fully-qualified topic maps onto its DDS topic name.
36//! assert_eq!(dds_topic("/cmd_vel", EntityKind::Topic).as_deref(), Some("rt/cmd_vel"));
37//!
38//! // A command velocity round-trips through CDR.
39//! let cmd = Twist { linear: Vector3::new(0.5, 0.0, 0.0), angular: Vector3::new(0.0, 0.0, 0.2) };
40//! let bytes = cmd.to_cdr();
41//! assert_eq!(Twist::from_cdr(&bytes), Some(cmd));
42//! ```
43
44extern crate alloc;
45
46pub mod key;
47pub mod msg;
48pub mod name;
49pub mod typehash;
50
51#[cfg(feature = "bridge")]
52pub mod bridge;