"Native" subscribers for when you want to manage data by yourself
This commit is contained in:
parent
8502a3a7d4
commit
05959d1fe8
|
|
@ -1,25 +1,23 @@
|
||||||
R2R - Minimal ROS2 Rust bindings
|
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
|
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
|
. /opt/ros/dashing/setup.sh
|
||||||
cargo build
|
cargo build
|
||||||
cargo run --example subscriber_with_thread
|
cargo run --example subscriber_with_thread
|
||||||
```
|
```
|
||||||
|
In order to avoid building everything, put the message types you need in `msgs.txt` before building. (Or just `ros2 msg list > msgs.txt`).
|
||||||
In order to avoid building everything, put the message types you need in msgs.txt.
|
|
||||||
|
|
||||||
What works?
|
What works?
|
||||||
--------
|
--------
|
||||||
- Only tested with ROS2 Dashing
|
- Only tested with ROS2 Dashing
|
||||||
- Simple publish/subscribe, see examples.
|
- Simple publish/subscribe, see examples.
|
||||||
|
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
------------
|
------------
|
||||||
- The code generation is currently just a big hack. Needs cleanup and refactoring.
|
- The code generation is currently just a big hack. Needs cleanup and refactoring.
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,16 @@ fn main() -> Result<(), ()> {
|
||||||
println!("JTP serialized as: {}", serialized);
|
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 sub1 = rcl_create_subscription(&mut node, "/hopp", Box::new(cb))?;
|
||||||
let sub2 = rcl_create_subscription(&mut node, "/hej", Box::new(cb2))?;
|
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
|
// 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
|
// run for 10 seconds
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
|
||||||
64
src/lib.rs
64
src/lib.rs
|
|
@ -94,6 +94,15 @@ where
|
||||||
pub rcl_msg: WrappedNativeMsg<T>,
|
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>
|
impl<T> Sub for WrappedSubT<T>
|
||||||
where
|
where
|
||||||
T: WrappedTypesupport,
|
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, ()> {
|
pub fn rcl_create_context() -> Result<rcl_context_t, ()> {
|
||||||
let mut ctx = unsafe { rcl_get_zero_initialized_context() };
|
let mut ctx = unsafe { rcl_get_zero_initialized_context() };
|
||||||
let isok = unsafe {
|
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(
|
pub fn rcl_take_subst(
|
||||||
ctx: &mut rcl_context_t,
|
ctx: &mut rcl_context_t,
|
||||||
subs: &mut Vec<Box<dyn Sub>>,
|
subs: &mut Vec<Box<dyn Sub>>,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue