"Native" subscribers for when you want to manage data by yourself

This commit is contained in:
Martin Dahl 2019-08-20 13:16:36 +02:00
parent 8502a3a7d4
commit 05959d1fe8
3 changed files with 73 additions and 6 deletions

View File

@ -1,25 +1,23 @@
R2R - Minimal ROS2 Rust bindings
=============
Minimal bindings for ROS2 that does *not* require hooking in to the ROS2 build infrastructure, in contrast to <https://github.com/ros2-rust/ros2_rust>. Message definitions are instead created by calling into the c introspection libraries to avoid the .msg/.idl pipeline.
Minimal bindings for ROS2 that does *not* require hooking in to the ROS2 build infrastructure. If you want a more ROS-oriented approach, see <https://github.com/ros2-rust/ros2_rust>. In these bindings, convenience Rust types are created by calling into the c introspection libraries to circumvent the .msg/.idl pipeline. Another benefit of basing the code entirely on the exported shared libraries is that the native c types are still there when you need to trade convenience for performance. E.g. for looking into a large array of image data you can still get a pointer to the raw message.
How to use
------------
You need to source your ros installation before building/running. A couple of examples are included in examples/
You need to source your ROS2 installation before building/running. A couple of examples are included in examples/
```
. /opt/ros/dashing/setup.sh
cargo build
cargo run --example subscriber_with_thread
```
In order to avoid building everything, put the message types you need in msgs.txt.
In order to avoid building everything, put the message types you need in `msgs.txt` before building. (Or just `ros2 msg list > msgs.txt`).
What works?
--------
- Only tested with ROS2 Dashing
- Simple publish/subscribe, see examples.
TODO
------------
- The code generation is currently just a big hack. Needs cleanup and refactoring.

View File

@ -25,11 +25,16 @@ fn main() -> Result<(), ()> {
println!("JTP serialized as: {}", serialized);
};
let cb3 = move |raw_c:&WrappedNativeMsg<JointTrajectoryPoint>| {
println!("Raw c data: {:?}", (*raw_c).positions);
};
let sub1 = rcl_create_subscription(&mut node, "/hopp", Box::new(cb))?;
let sub2 = rcl_create_subscription(&mut node, "/hej", Box::new(cb2))?;
let sub3 = rcl_create_subscription_native(&mut node, "/hej", Box::new(cb3))?;
// TODO: group subscriptions in a "node" struct
let mut subst: Vec<Box<Sub>> = vec![Box::new(sub1), Box::new(sub2)];
let mut subst: Vec<Box<Sub>> = vec![Box::new(sub1), Box::new(sub2), Box::new(sub3)];
// run for 10 seconds
let mut count = 0;

View File

@ -94,6 +94,15 @@ where
pub rcl_msg: WrappedNativeMsg<T>,
}
pub struct WrappedSubNative<T>
where
T: WrappedTypesupport,
{
pub rcl_handle: rcl_subscription_t,
pub callback: Box<dyn FnMut(&WrappedNativeMsg<T>) -> ()>,
pub rcl_msg: WrappedNativeMsg<T>,
}
impl<T> Sub for WrappedSubT<T>
where
T: WrappedTypesupport,
@ -113,6 +122,25 @@ where
}
}
impl<T> Sub for WrappedSubNative<T>
where
T: WrappedTypesupport,
{
fn handle(&self) -> &rcl_subscription_t {
&self.rcl_handle
}
fn rcl_msg(&mut self) -> *mut std::os::raw::c_void {
self.rcl_msg.void_ptr_mut()
}
fn run_cb(&mut self) -> () {
// *dont't* copy native msg to rust type.
// e.g. if you for instance have large image data...
(self.callback)(&self.rcl_msg);
}
}
pub fn rcl_create_context() -> Result<rcl_context_t, ()> {
let mut ctx = unsafe { rcl_get_zero_initialized_context() };
let isok = unsafe {
@ -248,6 +276,42 @@ where
}
}
pub fn rcl_create_subscription_native<T>(
node: &mut rcl_node_t,
topic: &str,
callback: Box<dyn FnMut(&WrappedNativeMsg<T>) -> ()>,
) -> Result<WrappedSubNative<T>, ()>
where
T: WrappedTypesupport,
{
let mut subscription_handle = unsafe { rcl_get_zero_initialized_subscription() };
let topic_c_string = CString::new(topic).unwrap();
let result = unsafe {
let mut subscription_options = rcl_subscription_get_default_options();
subscription_options.qos = rmw_qos_profile_t::default();
rcl_subscription_init(
&mut subscription_handle,
node,
T::get_ts(),
topic_c_string.as_ptr(),
&subscription_options,
)
};
if result == RCL_RET_OK as i32 {
let wrapped_sub = WrappedSubNative {
rcl_handle: subscription_handle,
rcl_msg: WrappedNativeMsg::<T>::new(),
callback: callback,
};
Ok(wrapped_sub)
} else {
eprintln!("{}", result);
Err(())
}
}
pub fn rcl_take_subst(
ctx: &mut rcl_context_t,
subs: &mut Vec<Box<dyn Sub>>,