Robotik · Async Rust
Varför r2r slår den klassiska ROS 2-stacken
ROS 2 är ryggraden i modern robotik, men sättet de flesta av oss skriver noder på, med rclcpp eller rclpy byggda av colcon, har inte åldrats väl. r2r ger dig idiomatisk async Rust ovanpå samma ROS 2-kärna, och när du väl har testat det är det svårt att gå tillbaka.

Först: vad r2r faktiskt är
r2r ersätter inte ROS 2 i sig. Det är ett Rust-klientbibliotek som binder direkt mot rcl, samma C-lager som rclcpp och rclpy vilar på, så dina noder pratar fortfarande med alla andra ROS 2-noder över DDS. Det som ändras är allt ovanför det lagret: språket, samtidighetsmodellen och byggverktygen. Jämförelsen gäller alltså r2r mot standardsättet att skriva ROS 2-noder: C++ eller Python, byggt med colcon.
8 fördelar med r2r
Asynkront från grunden
Prenumerationer är Streams, tjänsteanrop och action-mål är Futures. Du kombinerar dem med tokio::select!, tidsgränser och kanaler i stället för att jonglera executors, callback-grupper och tillstånd delat mellan callbacks.
Bara cargo, ingen colcon
Meddelandebindningar genereras vid bygget från den inlästa ROS 2-miljön. Ingen package.xml, inga CMakeLists, ingen ament: cargo build, cargo test och rust-analyzer fungerar direkt.
Minnes- och trådsäkerhet
Kompilatorn utesluter datakapplöpningar, use-after-free och hängande pekare i callbacks, de klassiska orsakerna till att C++-noder kraschar. På en gående humanoid spelar det roll.
Samma ROS 2-kärna under huven
Eftersom r2r kapslar in rcl fungerar det med alla RMW-implementationer (Fast DDS, Cyclone DDS, Zenoh) och samverkar med befintliga C++- och Python-noder: topics, tjänster, actions, parametrar och klockor.
Nativ hastighet, ingen GIL
Kompilerad Rust med nollkostnadsabstraktioner och utan skräpsamlare. Till skillnad från rclpy finns inget Global Interpreter Lock som stryper högfrekventa topics, så latensen förblir förutsägbar.
Hela crates.io-ekosystemet
serde, nalgebra, tracing, axum, WebRTC: en ROS 2-nod, ett webb-API och en telemetriström i en enda binär, utan ett enda CMake find_package.
Otypade meddelanden för bryggor
subscribe_untyped och create_publisher_untyped arbetar med JSON via serde, så generiska bryggor, inspelare och felsökningsverktyg behöver inga meddelandetyper vid kompilering.
Moderna verktyg och driftsättning
clippy, rustfmt, cargo test och reproducerbara Cargo.lock-byggen i CI. Leverera en fristående binär i en slimmad container i stället för ett helt install/-träd.
Så här ser det ut
En komplett nod: prenumerera på ledtillstånd och publicera hastighetskommandon, allt i en Tokio-runtime. Jämför med motsvarande rclcpp-boilerplate.
# Cargo.toml
[dependencies]
r2r = "0.9"
tokio = { version = "1", features = ["full"] }
futures = "0.3"
# build & run: no colcon, no package.xml
$ source /opt/ros/jazzy/setup.bash
$ cargo run --releaseuse futures::StreamExt;
use r2r::{geometry_msgs::msg::Twist, sensor_msgs::msg::JointState, QosProfile};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ctx = r2r::Context::create()?;
let mut node = r2r::Node::create(ctx, "teleop_bridge", "")?;
let mut joints = node.subscribe::<JointState>("/joint_states", QosProfile::default())?;
let cmd = node.create_publisher::<Twist>("/cmd_vel", QosProfile::default())?;
// rcl spins on its own thread, everything else is plain async Rust
tokio::task::spawn_blocking(move || loop {
node.spin_once(std::time::Duration::from_millis(5));
});
while let Some(state) = joints.next().await {
let mut twist = Twist::default();
twist.linear.x = state.velocity.first().copied().unwrap_or(0.0) * 0.5;
cmd.publish(&twist)?;
}
Ok(())
}För att vara rättvis: avvägningarna
- r2r underhålls av communityn och är inte ett av de officiella ROS 2-klientbiblioteken, så det finns färre guider och svar än för rclcpp eller rclpy.
- Bygget kräver en inläst ROS 2-installation, eftersom bindningarna genereras från de meddelandepaket den hittar.
- Första bygget är långsamt, eftersom bindgen och meddelandegenerering körs för varje paket. Inkrementella byggen går bra.
- Launch-filer och colcon-arbetsytor behöver lite lim (till exempel colcon-ros-cargo) för att behandla en cargo-crate som ett ROS-paket.
Slutsats
För ny mellanprogramvara, bryggor, teleoperation och styrpipelines är r2r det bättre standardvalet: asynkronitet som verkligen passar robotikens I/O, säkerhet vid kompilering och ett bygge som bara är cargo. Behåll rclcpp för äldre kod och leverantörsdrivrutiner; välj r2r för allt nytt.