-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Re-write readme for re-org and rename examples
- Loading branch information
carter
committed
Jan 6, 2025
1 parent
20dc166
commit d17c2a6
Showing
7 changed files
with
74 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,97 @@ | ||
# RosLibRust | ||
[![Noetic](https://github.com/Carter12s/roslibrust/actions/workflows/noetic.yml/badge.svg)](https://github.com/Carter12s/roslibrust/actions/workflows/noetic.yml) | ||
[![Galactic](https://github.com/Carter12s/roslibrust/actions/workflows/galactic.yml/badge.svg)](https://github.com/Carter12s/roslibrust/actions/workflows/galactic.yml) | ||
[![Humble](https://github.com/Carter12s/roslibrust/actions/workflows/humble.yml/badge.svg)](https://github.com/Carter12s/roslibrust/actions/workflows/humble.yml) | ||
[![Iron](https://github.com/Carter12s/roslibrust/actions/workflows/iron.yml/badge.svg)](https://github.com/Carter12s/roslibrust/actions/workflows/iron.yml) | ||
[![License:MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) | ||
|
||
This package aims to provide a convenient "async first" library for interacting with ROS. | ||
[![Noetic](https://github.com/roslibrust/roslibrust/actions/workflows/noetic.yml/badge.svg)](https://github.com/roslibrust/roslibrust/actions/workflows/noetic.yml) | ||
[![Galactic](https://github.com/roslibrust/roslibrust/actions/workflows/galactic.yml/badge.svg)](https://github.com/roslibrust/roslibrust/actions/workflows/galactic.yml) | ||
[![Humble](https://github.com/roslibrust/roslibrust/actions/workflows/humble.yml/badge.svg)](https://github.com/roslibrust/roslibrust/actions/workflows/humble.yml) | ||
[![Iron](https://github.com/roslibrust/roslibrust/actions/workflows/iron.yml/badge.svg)](https://github.com/roslibrust/roslibrust/actions/workflows/iron.yml) | ||
[![License:MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) | ||
|
||
Currently this packaged provides support for both ROS1 native communication (TCPROS) and rosbridge's protocol which provides support for both ROS1 and ROS2 albeit with some overhead. | ||
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. | ||
|
||
Information about the rosbridge protocol can be found [here](https://github.com/RobotWebTools/rosbridge_suite). | ||
This crate is **pure rust and requires no ROS1 or ROS2 dependencies or installation**. | ||
|
||
Note on documentation: | ||
All information about the crate itself (examples, documentation, tutorials, etc.) lives in the source code and can be viewed on [docs.rs](https://docs.rs/roslibrust). | ||
This readme is for "Meta" information about developing for the crate. | ||
This allows writing generic behaviors like: | ||
|
||
Fully Supported via rosbridge: Noetic, Galactic, Humble, Iron. | ||
```rust | ||
async fn relay<T: TopicProvider>(ros: T) -> RosResult<()> { | ||
let mut subscriber = ros.subscribe::<std_msgs::String>("in").await?; | ||
let mut publisher = ros.advertise::<std_msgs::String>("out").await?; | ||
while let Some(msg) = subscriber.next().await { | ||
println!("Got message: {}", msg.data); | ||
publisher.publish(&msg).await?; | ||
} | ||
Ok(()) | ||
} | ||
``` | ||
|
||
Fully Supported via ROS1 native: Noetic | ||
That can then be used with any backend: | ||
|
||
## Code Generation of ROS Messages | ||
```rust | ||
#[tokio::main] | ||
async fn main() -> RosResult<()> { | ||
// Relay messages over a rosbridge connection with either ROS1 or ROS2! | ||
let ros = roslibrust::rosbridge::ClientHandle::new("ws://localhost:9090").await?; | ||
relay(ros).await?; | ||
|
||
// Relay messages over a native ROS1 connection | ||
let ros = roslibrust::ros1::NodeHandle::new("http://localhost:11311", "relay").await?; | ||
relay(ros).await?; | ||
|
||
// Relay messages over a mock ROS connection for testing | ||
let ros = roslibrust::mock::MockRos::new(); | ||
relay(ros).await?; | ||
|
||
// Relay messages over a zenoh connection compatible with zenoh-ros1-plugin / zenoh-ros1-bridge | ||
let ros = roslibrust::zenoh::ZenohClient::new(zenoh::open(zenoh::Config::default()).await?); | ||
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(()) | ||
} | ||
``` | ||
|
||
The crates `roslibrust_codegen` and `roslibrust_codegen_macro` support code generation in Rust for ROS1 and ROS2 message, service, and action files. Many of the examples use the macro for convenience. `find_and_generate_ros_messages` is a macro which accepts an optional list of paths relative to the project workspace directory and will additionally check the `ROS_PACKAGE_PATH` environment variable for paths to ROS packages. | ||
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: | ||
|
||
It's used like this: | ||
```rust | ||
roslibrust_codegen_macro::find_and_generate_ros_messages!("assets/ros1_common_interfaces/std_msgs"); | ||
// Will generate types from all packages in ROS_PACKAGE_PATH | ||
roslibrust_codegen_macro::find_and_generate_ros_messages!(); | ||
``` | ||
|
||
Code generation can also be done with a build.rs script using the same code generation backend called by the macro. See the contents of `example_package` for a detailed example of how this can be done. While the proc_macros are extremely convenient for getting started | ||
there is currently no (good) way for a proc_macro to inform the compiler that it needs to be re-generated when an external file | ||
changes. Using a build script requires more setup, but can correctly handling re-building when message files are edited. | ||
If you want to see what the generated code looks like check [here](https://github.com/RosLibRust/roslibrust/blob/master/roslibrust_test/src/ros1.rs). | ||
While the macro is useful for getting started, we recommend using `roslibrust_codegen` with a `build.rs` as shown in [example_package](https://github.com/RosLibRust/roslibrust/tree/master/example_package). | ||
This allows cargo to know when message files are edited and automatically re-generate the code. | ||
|
||
Generated message types are compatible with both the ROS1 native and RosBridge backends. | ||
## Getting Started / Examples | ||
|
||
## Roadmap | ||
Examples can be found in [examples](https://github.com/RosLibRust/roslibrust/tree/master/roslibrust/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. | ||
|
||
| Feature | rosbridge | ROS1 | ROS2 | | ||
|------------------------------|-------------------------------------------------------------|------|------| | ||
| examples | ✅ | ✅ | x | | ||
| message_gen | ✅ | ✅ | ✅ | | ||
| advertise / publish | ✅ | ✅ | x | | ||
| unadvertise | ✅ | ✅ | x | | ||
| subscribe | ✅ | ✅ | x | | ||
| unsubscribe | ✅ | ✅ | x | | ||
| services | ✅ | ✅ | x | | ||
| actions | (codgen of message types only) | | ||
| rosapi | ✅ | x | x | | ||
| TLS / wss:// | Should be working, untested | N/A | N/A | | ||
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. | ||
|
||
Upcoming features in rough order: | ||
To get started with writing a node with `roslibrust` we recommend looking at [example_package](https://github.com/RosLibRust/roslibrust/tree/master/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: | ||
|
||
- Ability to write generic clients via ROS trait | ||
- In memory backend that can be used for testing | ||
- Support for parameter server | ||
* This crate is built around the [tokio runtime](https://docs.rs/tokio/latest/tokio/) and requires tokio to work. All backends expect to be created inside a tokio runtime. | ||
* The generic traits `TopicProvider` and `ServiceProvider` are not [object safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety) 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 }`. | ||
* By default the roslibrust crate does not include any backends. You must enable the specific backends you want to use with features in `Cargo.toml` like `roslibrust = { version = "0.12", features = ["ros1"] }`. | ||
|
||
## Contributing | ||
|
||
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. | ||
|
||
### Minimum Supported Rust Version / MSRV | ||
|
||
We don't have an official MSRV yet. | ||
We uphold the rust lang [Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct). | ||
|
||
Due to cargo 1.72 enabling "doctest-in-workspace" by default it is recommended to use Rust 1.72+ for development. | ||
Previous rust versions are support but will require some incantations when executing doctests. | ||
|
||
The experimental topic_provider feature currently relies on `async fn` in traits from Rust 1.75. | ||
When that feature standardizes that will likely become our MSRV. | ||
### Minimum Supported Rust Version / MSRV | ||
|
||
### Running Tests | ||
MSRV is currently set to 1.75 to enable `async fn` in traits. | ||
|
||
There are various unit tests and integration tests behind feature flags. For tests with ROS1, both through rosbridge and native clients, you'll need a locally running `rosbridge_websocket` node and `rosmaster`. Then run with `cargo test --features "ros1_test ros1"`. For tests with ROS2, you'll need a running rosbridge server, then run with `cargo test --features "ros2_test"`. You can find relevant `Dockerfile`s and docker compose configurations udner the `docker` directory. | ||
We are likely to increase the MSRV to 1.83 when support for `async closures` lands. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.