Skip to content

Commit 04b8c58

Browse files
committed
Hook up ServerGoalHandle callbacks into the ActionServer
These aren't actually implemented as callbacks like in rclcpp, but rather just regular method calls. This required making some of the ActionServer and ActionServerBase methods use an Arc receiver, but the ActionServer is only ever created within an Arc, so this is fine.
1 parent 24cc611 commit 04b8c58

File tree

2 files changed

+24
-14
lines changed

2 files changed

+24
-14
lines changed

rclrs/src/action/server.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub trait ActionServerBase: Send + Sync {
5555
/// Returns the number of underlying entities for the action server.
5656
fn num_entities(&self) -> &WaitableNumEntities;
5757
/// Tries to run the callback for the given readiness mode.
58-
fn execute(&self, mode: ReadyMode) -> Result<(), RclrsError>;
58+
fn execute(self: Arc<Self>, mode: ReadyMode) -> Result<(), RclrsError>;
5959
}
6060

6161
pub(crate) enum ReadyMode {
@@ -228,7 +228,7 @@ where
228228
}
229229
}
230230

231-
fn execute_goal_request(&self) -> Result<(), RclrsError> {
231+
fn execute_goal_request(self: Arc<Self>) -> Result<(), RclrsError> {
232232
let (request, request_id) = match self.take_goal_request() {
233233
Ok(res) => res,
234234
Err(RclrsError::RclError {
@@ -275,6 +275,7 @@ where
275275
} else {
276276
Arc::new(ServerGoalHandle::<T>::new(
277277
goal_handle_ptr,
278+
Arc::downgrade(&self),
278279
todo!("Create an Arc holding the goal message"),
279280
uuid,
280281
))
@@ -582,7 +583,7 @@ where
582583
Ok(())
583584
}
584585

585-
fn publish_status(&self) -> Result<(), RclrsError> {
586+
pub(crate) fn publish_status(&self) -> Result<(), RclrsError> {
586587
let mut goal_statuses = DropGuard::new(
587588
unsafe {
588589
// SAFETY: No preconditions
@@ -642,7 +643,7 @@ where
642643
&self.num_entities
643644
}
644645

645-
fn execute(&self, mode: ReadyMode) -> Result<(), RclrsError> {
646+
fn execute(self: Arc<Self>, mode: ReadyMode) -> Result<(), RclrsError> {
646647
match mode {
647648
ReadyMode::GoalRequest => self.execute_goal_request(),
648649
ReadyMode::CancelRequest => self.execute_cancel_request(),

rclrs/src/action/server_goal_handle.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::{rcl_bindings::*, GoalUuid, RclrsError, ToResult};
2-
use std::sync::{Arc, Mutex};
1+
use crate::{action::ActionServer, rcl_bindings::*, GoalUuid, RclrsError, ToResult};
2+
use std::sync::{Arc, Mutex, Weak};
33

44
// Values defined by `action_msgs/msg/GoalStatus`
55
#[repr(i8)]
@@ -22,9 +22,10 @@ enum GoalStatus {
2222
/// passed to the user in the associated `handle_accepted` callback.
2323
pub struct ServerGoalHandle<ActionT>
2424
where
25-
ActionT: rosidl_runtime_rs::Action,
25+
ActionT: rosidl_runtime_rs::Action + rosidl_runtime_rs::ActionImpl,
2626
{
2727
rcl_handle: Mutex<*mut rcl_action_goal_handle_t>,
28+
action_server: Weak<ActionServer<ActionT>>,
2829
goal_request: Arc<ActionT::Goal>,
2930
uuid: GoalUuid,
3031
}
@@ -34,20 +35,22 @@ where
3435
// mutex, guaranteeing that the underlying data is never simultaneously accessed on the rclrs side
3536
// by multiple threads. Moreover, the rcl_action functions taking these handles are able to be run
3637
// from any thread.
37-
unsafe impl<ActionT> Send for ServerGoalHandle<ActionT> where ActionT: rosidl_runtime_rs::Action {}
38-
unsafe impl<ActionT> Sync for ServerGoalHandle<ActionT> where ActionT: rosidl_runtime_rs::Action {}
38+
unsafe impl<ActionT> Send for ServerGoalHandle<ActionT> where ActionT: rosidl_runtime_rs::Action + rosidl_runtime_rs::ActionImpl {}
39+
unsafe impl<ActionT> Sync for ServerGoalHandle<ActionT> where ActionT: rosidl_runtime_rs::Action + rosidl_runtime_rs::ActionImpl {}
3940

4041
impl<ActionT> ServerGoalHandle<ActionT>
4142
where
42-
ActionT: rosidl_runtime_rs::Action,
43+
ActionT: rosidl_runtime_rs::Action + rosidl_runtime_rs::ActionImpl,
4344
{
4445
pub(crate) fn new(
4546
rcl_handle: *mut rcl_action_goal_handle_t,
47+
action_server: Weak<ActionServer<ActionT>>,
4648
goal_request: Arc<ActionT::Goal>,
4749
uuid: GoalUuid,
4850
) -> Self {
4951
Self {
5052
rcl_handle: Mutex::new(rcl_handle),
53+
action_server,
5154
goal_request: Arc::clone(&goal_request),
5255
uuid,
5356
}
@@ -148,7 +151,10 @@ where
148151
pub fn execute(&self) -> Result<(), RclrsError> {
149152
self.update_state(rcl_action_goal_event_t::GOAL_EVENT_EXECUTE)?;
150153

151-
// TODO: Invoke on_executing callback
154+
// Publish the state change.
155+
if let Some(action_server) = self.action_server.upgrade() {
156+
action_server.publish_status()?;
157+
}
152158
Ok(())
153159
}
154160

@@ -188,14 +194,17 @@ where
188194
///
189195
/// Returns an error if the goal is in any state other than executing.
190196
pub fn publish_feedback(&self, feedback: Arc<ActionT::Feedback>) -> Result<(), RclrsError> {
191-
// TODO: Invoke public_feedback callback
192-
todo!()
197+
// If the action server no longer exists, simply drop the message.
198+
if let Some(action_server) = self.action_server.upgrade() {
199+
action_server.publish_feedback(&self.uuid, &*feedback)?;
200+
}
201+
Ok(())
193202
}
194203
}
195204

196205
impl<ActionT> Drop for ServerGoalHandle<ActionT>
197206
where
198-
ActionT: rosidl_runtime_rs::Action,
207+
ActionT: rosidl_runtime_rs::Action + rosidl_runtime_rs::ActionImpl,
199208
{
200209
/// Cancel the goal if its handle is dropped without reaching a terminal state.
201210
fn drop(&mut self) {

0 commit comments

Comments
 (0)