rosrust is a pure Rust implementation of a ROS client library.
rosrust is under development to implement all features of a ROS Client Library by fulfilling ROS requirements for implementing client libraries which are given in a more detailed form in the technical overview.
Currently implemented features: * ROS Master API, Parameter Server API and most of ROS Slave API (excluding 2 ambiguous methods) * Interface for handling parameters * Publisher, Subscriber, Client, Service fully working (until packet snooping for another undocumented feature is needed) * Simple bindings for messages, but ROS integration for generating them has yet to be done, and will be part of the catkin integration * Manual remapping is provided, and CLI parameter remapping is coming!
There are still quite some features to be implemented for this to become a stable API (for the library user's interface to stop changing). The most important ones are listed as Issues by the repository owner.
Integration with catkin will be handled once a satisfying set of features has been implemented.
The API is far from being stable, but this is the current desired functionality.
Most of the examples are followed by an infinite loop. ROS shutdown signal checking is coming!
Currently we don't have any support for message generation by ROS itself, because a 100% decision of how we'll integrate generated files hasn't been made. There is a prototype in the works, but in the meantime messages have to be manually generated. Looking from the bright side - at least you'll know what constitutes a ROS message.
Let's demonstrate the std_msgs/UInt64.msg
message.
```rust
struct UInt64 { data: u64, }
impl rosrust::Message for UInt64 { fn msg_definition() -> String { String::from("uint64 data\n") }
fn md5sum() -> String {
String::from("1b2a79973e8bf53d7b53acb71299cb57")
}
fn msg_type() -> String {
String::from("std_msgs/UInt64")
}
} ```
Services are not too different, so let's show the rospy_tutorials/AddTwoInts.srv
service, from the rospy
Service/Client tutorial.
```rust
struct AddTwoIntsReq { a: i64, b: i64, }
struct AddTwoIntsRes { sum: i64, }
struct AddTwoInts {}
impl rosrust::Service for AddTwoInts { type Request = AddTwoIntsReq; type Response = AddTwoIntsRes; }
impl rosrust::Message for AddTwoInts { fn msg_definition() -> String { String::from("") }
fn md5sum() -> String {
String::from("6a2e34150c00229791cc89ff309fff21")
}
fn msg_type() -> String {
String::from("rospy_tutorials/AddTwoInts")
}
} ```
This will all be unimportant information once message generation is done, but it's useful to know that ROS Messages and Services will just be normal structures. It's important to note that all of this depends on rustc-serialize
.
If we wanted to publish a defined message (let's use the previously described UInt64
) to topic some_topic
approximately every second, we can do it in the following way.
```rust extern crate rosrust; use rosrust::Ros; use std::{thread, time};
fn main() {
let mut ros = Ros::new("nodename").unwrap();
let mut publisher = ros.publish::
If we wanted to subscribe to an std_msgs/UInt64
topic some_topic
, we just declare a callback. An alternative extra interface with iterators is being considered, but for now this is the only option.
```rust extern crate rosrust; use rosrust::Ros; use std::{thread, time};
fn main() { let mut ros = Ros::new("nodename").unwrap(); ros.subscribe("sometopic", |v: UInt64| println!("{}", v.data)).unwrap(); loop { thread::sleep(time::Duration::from_secs(100)); } } ```
Creating a service is the easiest out of all the options. Just define a callback for each request. Let's make our own AddTwoInts
service on the topic /add_two_ints
.
```rust extern crate rosrust; use rosrust::Ros; use std::{thread, time};
fn main() {
let mut ros = Ros::new("nodename").unwrap();
ros.service::
Clients can handle requests synchronously and asynchronously. The sync method behaves like a function, while the async approach is via reading data afterwards. The async consumes the passed parameter, since we're passing the parameter between threads, and it's more common for users to pass and drop a parameter, so this being the default prevents needless cloning. Let's call requests from the AddTwoInts
service on the topic /add_two_ints
.
```rust extern crate rosrust; use rosrust::Ros; use std::{thread, time};
fn main() {
let mut ros = Ros::new("nodename").unwrap();
let client = ros.client::
```rust extern crate rosrust; use rosrust::Ros;
fn main() {
let ros = Ros::new("nodename").unwrap();
let param = ros.param("~cow").unwrap(); // access /nodename/cow parameter
println!("Exists? {:?}", param.exists()); // false
param.set(&UInt64 { data: 42 });
println!("Get {}", param.get::
rosrust is distributed under the MIT license.