Crates.io | roslibrust |
lib.rs | roslibrust |
version | |
source | src |
created_at | 2022-08-28 20:59:41.321701 |
updated_at | 2025-01-08 20:12:12.072829 |
description | An library for interfacing with the ROS's rosbridge_server |
homepage | |
repository | https://github.com/roslibrust/roslibrust |
max_upload_size | |
id | 654068 |
Cargo.toml error: | TOML parse error at line 21, column 1 | 21 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
This crate provides a convenient "async first" library for interacting with ROS. This crate defines generic traits for interacting with ROS-like systems, and implementations of those traits for various backends.
This crate is pure rust and requires no ROS1 or ROS2 dependencies or installation.
This allows writing generic behaviors like:
# use roslibrust_test::ros1::*;
use roslibrust::{TopicProvider, Publish, Subscribe};
async fn relay<T: TopicProvider>(ros: T) -> roslibrust::Result<()> {
let mut subscriber = ros.subscribe::<std_msgs::String>("in").await?;
let mut publisher = ros.advertise::<std_msgs::String>("out").await?;
while let Ok(msg) = subscriber.next().await {
println!("Got message: {}", msg.data);
publisher.publish(&msg).await?;
}
Ok(())
}
#[tokio::main]
async fn main() -> roslibrust::Result<()> {
// Relay messages over a rosbridge connection with either ROS1 or ROS2!
#[cfg(feature = "rosbridge")]
{
let ros = roslibrust::rosbridge::ClientHandle::new("ws://localhost:9090").await?;
relay(ros).await?;
}
// Relay messages over a native ROS1 connection
#[cfg(feature = "ros1")]
{
let ros = roslibrust::ros1::NodeHandle::new("http://localhost:11311", "relay").await?;
relay(ros).await?;
}
// Relay messages over a mock ROS connection for testing
#[cfg(feature = "mock")]
{
let ros = roslibrust::mock::MockRos::new();
relay(ros).await?;
}
// Relay messages over a zenoh connection compatible with zenoh-ros1-plugin / zenoh-ros1-bridge
#[cfg(feature = "zenoh")]
{
let ros = roslibrust::zenoh::ZenohClient::new(zenoh::open(zenoh::Config::default()).await.unwrap());
relay(ros).await?;
}
// TODO - not supported yet!
// Relay messages over a native ROS2 connection
// let ros = roslibrust::ros2::NodeHandle::new("http://localhost:11311", "relay").await?;
// relay(ros).await?;
Ok(())
}
All of this is backed by common traits for ROS messages, topics, and services. roslibrust_codegen
provides generation of Rust types from both ROS1 and ROS2 .msg/.srv files and
roslibrust_codegen_macro
provides a convenient macro for generating these types:
// Will generate types from all packages in ROS_PACKAGE_PATH
roslibrust_codegen_macro::find_and_generate_ros_messages!();
If you want to see what the generated code looks like check here.
While the macro is useful for getting started, we recommend using roslibrust_codegen
with a build.rs
as shown in example_package.
This allows cargo to know when message files are edited and automatically re-generate the code.
Examples can be found in examples.
We recommend looking at the examples prefixed with generic_
first, these examples show the recommended style of using roslibrust
through the generic traits.
Code written this way can be used with any backend, and critically can be tested with the mock backend.
Examples prefixed with ros1_
, rosbridge_
, and zenoh_
show direct use of specific backends if you are only interested in a single backend.
Some backends may provide additional functionality not available through the generic traits.
To get started with writing a node with roslibrust
we recommend looking at example_package and setting up your
Cargo.toml
and build.rs
in a similar way.
Some important tips to keep in mind with using the crate:
TopicProvider
and ServiceProvider
are not object safe due to their generic parameters. This means you cannot use them as trait objects with Box<dyn TopicProvider>
or Box<dyn ServiceProvider>
. Instead, they should be used as compile time generics like fn foo(ros: impl TopicProvider)
or struct MyNode<T: TopicProvider> { ros: T }
.Cargo.toml
like roslibrust = { version = "0.12", features = ["ros1"] }
.Contribution through reporting of issues encountered and implementation in PRs is welcome! Before landing a large PR with lots of code implemented, please open an issue if there isn't a relevant one already available and chat with a maintainer to make sure the design fits well with all supported platforms and any in-progress implementation efforts.
We uphold the rust lang Code of Conduct.
MSRV is currently set to 1.75 to enable async fn
in traits.
We are likely to increase the MSRV to 1.83 when support for async closures
lands.