Allow creating timers of type ClockType::RosTime

This adds Node::create_timer() method. The method is similar to
already existing Node::create_wall_timer(), but the timer is based on
ClockType::RosTime rather than on ClockType::SteadyTime.

The advantage of ClockType::RosTime is that one can drive the clock
from a different time source. This will be used in the next commits to
implement for clock source on the /clock topic.
This commit is contained in:
Martin Škoudlil 2024-01-08 10:42:34 +01:00
parent 04c24bf47b
commit 66af3f49c9
1 changed files with 49 additions and 12 deletions

View File

@ -54,6 +54,8 @@ pub struct Node {
timers: Vec<Timer_>,
// and the publishers, whom we allow to be shared.. hmm.
pubs: Vec<Arc<Publisher_>>,
// RosTime clock used by all timers created by create_timer()
ros_clock: Arc<Mutex<Clock>>,
}
unsafe impl Send for Node {}
@ -179,6 +181,8 @@ impl Node {
};
if res == RCL_RET_OK as i32 {
let clock = Clock::create(ClockType::RosTime)?;
let mut node = Node {
params: Arc::new(Mutex::new(HashMap::new())),
context: ctx,
@ -190,6 +194,7 @@ impl Node {
action_servers: Vec::new(),
timers: Vec::new(),
pubs: Vec::new(),
ros_clock: Arc::new(Mutex::new(clock)),
};
node.load_params()?;
Ok(node)
@ -1214,9 +1219,52 @@ impl Node {
/// Create a ROS wall timer.
///
/// Create a ROS timer that is woken up by spin every `period`.
///
/// This timer uses [`ClockType::SteadyTime`] clock.
pub fn create_wall_timer(&mut self, period: Duration) -> Result<Timer> {
let mut clock = Clock::create(ClockType::SteadyTime)?;
let timer_handle = self.create_timer_helper(&mut clock, period)?;
let (tx, rx) = mpsc::channel::<Duration>(1);
let timer = Timer_ {
timer_handle,
_clock: Some(clock), // The timer owns the clock.
sender: tx,
};
self.timers.push(timer);
let out_timer = Timer { receiver: rx };
Ok(out_timer)
}
/// Create a ROS timer
///
/// Create a ROS timer that is woken up by spin every `period`.
///
/// This timer uses node's [`ClockType::RosTime`] clock.
pub fn create_timer(&mut self, period: Duration) -> Result<Timer> {
let mut clock = self.ros_clock.lock().unwrap();
let timer_handle = self.create_timer_helper(&mut clock, period)?;
let (tx, rx) = mpsc::channel::<Duration>(1);
let timer = Timer_ {
timer_handle,
_clock: None, // The timer does not own the clock (the node owns it).
sender: tx,
};
self.timers.push(timer);
let out_timer = Timer { receiver: rx };
Ok(out_timer)
}
fn create_timer_helper(
&self, clock: &mut Clock, period: Duration,
) -> Result<Pin<Box<RclTimer>>> {
// rcl expects that the address of the rcl_timer_t does not change.
let mut timer_handle = unsafe { Box::pin(RclTimer::new()) };
@ -1237,18 +1285,7 @@ impl Node {
return Err(Error::from_rcl_error(ret));
}
let (tx, rx) = mpsc::channel::<Duration>(1);
let timer = Timer_ {
timer_handle,
_clock: Some(clock),
sender: tx,
};
self.timers.push(timer);
let out_timer = Timer { receiver: rx };
Ok(out_timer)
Ok(timer_handle)
}
/// Get the ros logger name for this node.