Skip to content

Commit 9d3bdc5

Browse files
committed
Fix use of action client options
Signed-off-by: Michael X. Grey <[email protected]>
1 parent 7a6b153 commit 9d3bdc5

File tree

3 files changed

+88
-25
lines changed

3 files changed

+88
-25
lines changed

rclrs/src/action/action_client.rs

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,70 @@ impl<'a> ActionClientOptions<'a> {
7575
}
7676
}
7777

78-
impl<'a, T: Borrow<str> + ?Sized + 'a> From<&'a T> for ActionClientOptions<'a> {
79-
fn from(value: &'a T) -> Self {
80-
Self::new(value.borrow())
78+
/// Trait to implicitly convert a compatible object into [`ActionClientOptions`].
79+
pub trait IntoActionClientOptions<'a>: Sized {
80+
/// Change this into an [`ActionClientOptions`].
81+
fn into_action_client_options(self) -> ActionClientOptions<'a>;
82+
83+
/// Set the quality of service profile for the goal service
84+
fn goal_service_qos(self, profile: QoSProfile) -> ActionClientOptions<'a> {
85+
let mut options = self.into_action_client_options();
86+
options.goal_service_qos = profile;
87+
options
88+
}
89+
90+
/// Set the quality of service profile for the result service
91+
fn result_service_qos(self, profile: QoSProfile) -> ActionClientOptions<'a> {
92+
let mut options = self.into_action_client_options();
93+
options.result_service_qos = profile;
94+
options
95+
}
96+
97+
/// Set the quality of service profile for the cancel service
98+
fn cancel_service_qos(self, profile: QoSProfile) -> ActionClientOptions<'a> {
99+
let mut options = self.into_action_client_options();
100+
options.cancel_service_qos = profile;
101+
options
102+
}
103+
104+
/// Set the quality of service profile for the feedback topic
105+
fn feedback_topic_qos(self, profile: QoSProfile) -> ActionClientOptions<'a> {
106+
let mut options = self.into_action_client_options();
107+
options.feedback_topic_qos = profile;
108+
options
109+
}
110+
111+
/// Set the quality of service profile for the status topic
112+
fn status_topic_qos(self, profile: QoSProfile) -> ActionClientOptions<'a> {
113+
let mut options = self.into_action_client_options();
114+
options.status_topic_qos = profile;
115+
options
116+
}
117+
}
118+
119+
impl<'a, T: Borrow<str> + ?Sized + 'a> IntoActionClientOptions<'a> for &'a T {
120+
fn into_action_client_options(self) -> ActionClientOptions<'a> {
121+
ActionClientOptions::new(self.borrow())
122+
}
123+
}
124+
125+
impl<'a> IntoActionClientOptions<'a> for ActionClientOptions<'a> {
126+
fn into_action_client_options(self) -> ActionClientOptions<'a> {
127+
self
128+
}
129+
}
130+
131+
impl<'a> From<&'_ ActionClientOptions<'a>> for rcl_action_client_options_t {
132+
fn from(value: &'_ ActionClientOptions<'a>) -> Self {
133+
rcl_action_client_options_s {
134+
goal_service_qos: value.goal_service_qos.into(),
135+
result_service_qos: value.result_service_qos.into(),
136+
cancel_service_qos: value.cancel_service_qos.into(),
137+
feedback_topic_qos: value.feedback_topic_qos.into(),
138+
status_topic_qos: value.status_topic_qos.into(),
139+
// SAFETY: No preconditions for this function
140+
allocator: unsafe { rcutils_get_default_allocator() },
141+
}
81142
}
82143
}
83144

@@ -225,9 +286,9 @@ impl<A: Action> ActionClientState<A> {
225286
/// Creates a new action client.
226287
pub(crate) fn create<'a>(
227288
node: &Node,
228-
options: impl Into<ActionClientOptions<'a>>,
289+
options: impl IntoActionClientOptions<'a>,
229290
) -> Result<Arc<Self>, RclrsError> {
230-
let options = options.into();
291+
let options = options.into_action_client_options();
231292
// SAFETY: Getting a zero-initialized value is always safe.
232293
let mut rcl_action_client = unsafe { rcl_action_get_zero_initialized_client() };
233294
let type_support = A::get_type_support() as *const rosidl_action_type_support_t;
@@ -238,7 +299,7 @@ impl<A: Action> ActionClientState<A> {
238299
})?;
239300

240301
// SAFETY: No preconditions for this function.
241-
let action_client_options = unsafe { rcl_action_client_get_default_options() };
302+
let action_client_options = (&options).into();
242303

243304
{
244305
let mut rcl_node = node.handle().rcl_node.lock().unwrap();

rclrs/src/action/action_server.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,6 @@ impl<'a> ActionServerOptions<'a> {
8383
goal_expiration_timeout: Duration::from_secs(60),
8484
}
8585
}
86-
87-
fn into_rcl(&self) -> rcl_action_server_options_t {
88-
rcl_action_server_options_s {
89-
goal_service_qos: self.goal_service_qos.into(),
90-
cancel_service_qos: self.cancel_service_qos.into(),
91-
result_service_qos: self.result_service_qos.into(),
92-
feedback_topic_qos: self.feedback_topic_qos.into(),
93-
status_topic_qos: self.status_topic_qos.into(),
94-
// SAFETY: No preconditions for this function
95-
allocator: unsafe { rcutils_get_default_allocator() },
96-
result_timeout: rcl_duration_s {
97-
nanoseconds: self.goal_expiration_timeout.as_nanos() as i64,
98-
},
99-
}
100-
}
10186
}
10287

10388
/// Trait to implicitly convert a compatible object into [`ActionServerOptions`].
@@ -148,7 +133,7 @@ pub trait IntoActionServerOptions<'a>: Sized {
148133
}
149134
}
150135

151-
impl<'a, T: Borrow<str> + 'a> IntoActionServerOptions<'a> for &'a T {
136+
impl<'a, T: Borrow<str> + ?Sized + 'a> IntoActionServerOptions<'a> for &'a T {
152137
fn into_action_server_options(self) -> ActionServerOptions<'a> {
153138
ActionServerOptions::new(self.borrow())
154139
}
@@ -160,6 +145,23 @@ impl<'a> IntoActionServerOptions<'a> for ActionServerOptions<'a> {
160145
}
161146
}
162147

148+
impl<'a> From<&'_ ActionServerOptions<'a>> for rcl_action_server_options_t {
149+
fn from(value: &ActionServerOptions<'a>) -> Self {
150+
rcl_action_server_options_s {
151+
goal_service_qos: value.goal_service_qos.into(),
152+
cancel_service_qos: value.cancel_service_qos.into(),
153+
result_service_qos: value.result_service_qos.into(),
154+
feedback_topic_qos: value.feedback_topic_qos.into(),
155+
status_topic_qos: value.status_topic_qos.into(),
156+
// SAFETY: No preconditions for this function
157+
allocator: unsafe { rcutils_get_default_allocator() },
158+
result_timeout: rcl_duration_s {
159+
nanoseconds: value.goal_expiration_timeout.as_nanos() as i64,
160+
},
161+
}
162+
}
163+
}
164+
163165
/// An action server that can respond to requests sent by ROS action clients.
164166
///
165167
/// Create an action server using [`NodeState::create_action_server`][1].
@@ -283,7 +285,7 @@ impl<A: Action> ActionServerState<A> {
283285
s: options.action_name.into(),
284286
})?;
285287

286-
let action_server_options = options.into_rcl();
288+
let action_server_options = (&options).into();
287289

288290
{
289291
let mut rcl_node = node.handle().rcl_node.lock().unwrap();

rclrs/src/node.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use async_std::future::timeout;
3030
use rosidl_runtime_rs::{Action, Message};
3131

3232
use crate::{
33-
rcl_bindings::*, ActionClient, ActionClientOptions, ActionClientState, ActionGoalReceiver,
33+
rcl_bindings::*, ActionClient, IntoActionClientOptions, ActionClientState, ActionGoalReceiver,
3434
ActionServer, ActionServerState, AnyTimerCallback, Client, ClientOptions, ClientState, Clock,
3535
ContextHandle, ExecutorCommands, IntoActionServerOptions, IntoAsyncServiceCallback,
3636
IntoAsyncSubscriptionCallback, IntoNodeServiceCallback, IntoNodeSubscriptionCallback,
@@ -364,7 +364,7 @@ impl NodeState {
364364
// TODO: make action client's lifetime depend on node's lifetime
365365
pub fn create_action_client<'a, A: Action>(
366366
self: &Arc<Self>,
367-
options: impl Into<ActionClientOptions<'a>>,
367+
options: impl IntoActionClientOptions<'a>,
368368
) -> Result<ActionClient<A>, RclrsError> {
369369
ActionClientState::create(self, options)
370370
}

0 commit comments

Comments
 (0)