Robotyka · Async Rust
Dlaczego r2r wygrywa z klasycznym stosem ROS 2
ROS 2 to kręgosłup współczesnej robotyki, ale sposób, w jaki większość z nas pisze węzły (rclcpp lub rclpy budowane przez colcon), nie zestarzał się najlepiej. r2r daje idiomatyczny async Rust na tym samym rdzeniu ROS 2, a gdy raz spróbujesz, trudno wrócić.

Najpierw: czym właściwie jest r2r
r2r nie zastępuje samego ROS 2. To biblioteka kliencka Rust, która wiąże się bezpośrednio z rcl, tą samą warstwą C, na której stoją rclcpp i rclpy, więc Twoje węzły nadal rozmawiają z każdym innym węzłem ROS 2 przez DDS. Zmienia się wszystko powyżej tej warstwy: język, model współbieżności i narzędzia budowania. To porównanie dotyczy więc r2r i standardowego sposobu pisania węzłów ROS 2: C++ lub Pythona budowanych przez colcon.
8 zalet r2r
Asynchroniczność od podstaw
Subskrypcje to Streamy, wywołania usług i cele akcji to Future. Łączysz je przez tokio::select!, timeouty i kanały zamiast żonglować executorami, grupami callbacków i stanem współdzielonym między callbackami.
Zwykłe cargo, bez colcon
Wiązania wiadomości są generowane podczas budowania z załadowanego środowiska ROS 2. Bez package.xml, CMakeLists i ament: cargo build, cargo test i rust-analyzer po prostu działają.
Bezpieczeństwo pamięci i wątków
Kompilator wyklucza wyścigi danych, use-after-free i wiszące wskaźniki w callbackach, czyli klasyczne przyczyny awarii węzłów C++. Przy chodzącym humanoidzie to ma znaczenie.
Ten sam rdzeń ROS 2 pod spodem
Ponieważ r2r opakowuje rcl, działa z każdą implementacją RMW (Fast DDS, Cyclone DDS, Zenoh) i współpracuje z istniejącymi węzłami C++ i Python: topiki, usługi, akcje, parametry i zegary.
Natywna szybkość, bez GIL
Kompilowany Rust z abstrakcjami o zerowym koszcie i bez garbage collectora. W przeciwieństwie do rclpy nie ma Global Interpreter Lock dławiącego topiki o wysokiej częstotliwości, więc opóźnienia są przewidywalne.
Cały ekosystem crates.io
serde, nalgebra, tracing, axum, WebRTC: węzeł ROS 2, API webowe i strumień telemetrii w jednym pliku binarnym, bez ani jednego find_package w CMake.
Wiadomości bez typów dla mostów
subscribe_untyped i create_publisher_untyped działają z JSON przez serde, więc generyczne mosty, rejestratory i narzędzia debugujące nie potrzebują typów wiadomości w czasie kompilacji.
Nowoczesne narzędzia i wdrażanie
clippy, rustfmt, cargo test i powtarzalne buildy z Cargo.lock w CI. Wdrażasz jeden samodzielny plik binarny w lekkim kontenerze zamiast całego drzewa install/.
Jak to wygląda
Kompletny węzeł: subskrypcja stanów stawów i publikowanie komend prędkości, wszystko w runtime Tokio. Porównaj to z analogicznym boilerplate w rclcpp.
# 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(())
}Uczciwie: kompromisy
- r2r jest rozwijane przez społeczność i nie należy do oficjalnych bibliotek klienckich ROS 2, więc tutoriali i odpowiedzi jest mniej niż dla rclcpp czy rclpy.
- Budowanie wymaga załadowanej instalacji ROS 2, bo wiązania są generowane z pakietów wiadomości, które znajdzie.
- Pierwszy build jest wolny, bo bindgen i generowanie wiadomości działają dla każdego pakietu. Buildy przyrostowe są w porządku.
- Pliki launch i workspace colcon potrzebują odrobiny kleju (np. colcon-ros-cargo), by traktować crate cargo jak pakiet ROS.
Werdykt
Dla nowego middleware, mostów, teleoperacji i potoków sterowania r2r to lepszy wybór domyślny: asynchroniczność, która naprawdę pasuje do I/O w robotyce, bezpieczeństwo w czasie kompilacji i build, który jest po prostu cargo. rclcpp zostaw dla kodu legacy i sterowników producentów; po r2r sięgaj przy wszystkim nowym.