ros2_client/
action.rs

1use std::marker::PhantomData;
2
3use rustdds::*;
4use serde::{Deserialize, Serialize};
5pub use action_msgs::{CancelGoalRequest, CancelGoalResponse, GoalId, GoalInfo, GoalStatusEnum};
6#[allow(unused_imports)]
7use log::{debug, error, info, warn};
8
9use crate::{action_msgs, builtin_interfaces, message::Message};
10
11mod client;
12#[doc(inline)]
13pub use client::ActionClient;
14
15mod server;
16#[doc(inline)]
17pub use server::{
18  AcceptedGoalHandle, ActionServer, AsyncActionServer, CancelHandle, ExecutingGoalHandle,
19  GoalEndStatus, GoalError, NewGoalHandle,
20};
21
22/// A trait to define an Action type
23pub trait ActionTypes {
24  type GoalType: Message + Clone; // Used by client to set a goal for the server
25  type ResultType: Message + Clone; // Used by server to report result when action ends
26  type FeedbackType: Message; // Used by server to report progress during action execution
27
28  fn goal_type_name(&self) -> &str;
29  fn result_type_name(&self) -> &str;
30  fn feedback_type_name(&self) -> &str;
31}
32
33/// This is used to construct an ActionType implementation from pre-existing
34/// component types.
35pub struct Action<G, R, F> {
36  g: PhantomData<G>,
37  r: PhantomData<R>,
38  f: PhantomData<F>,
39  goal_typename: String,
40  result_typename: String,
41  feedback_typename: String,
42}
43
44impl<G, R, F> Action<G, R, F>
45where
46  G: Message + Clone,
47  R: Message + Clone,
48  F: Message,
49{
50  pub fn new(goal_typename: String, result_typename: String, feedback_typename: String) -> Self {
51    Self {
52      goal_typename,
53      result_typename,
54      feedback_typename,
55      g: PhantomData,
56      r: PhantomData,
57      f: PhantomData,
58    }
59  }
60}
61
62impl<G, R, F> ActionTypes for Action<G, R, F>
63where
64  G: Message + Clone,
65  R: Message + Clone,
66  F: Message,
67{
68  type GoalType = G;
69  type ResultType = R;
70  type FeedbackType = F;
71
72  fn goal_type_name(&self) -> &str {
73    &self.goal_typename
74  }
75
76  fn result_type_name(&self) -> &str {
77    &self.result_typename
78  }
79
80  fn feedback_type_name(&self) -> &str {
81    &self.feedback_typename
82  }
83}
84
85//TODO: Make fields private, add constructor and accessors.
86
87/// Collection of QoS policies requires for an Action client
88pub struct ActionClientQosPolicies {
89  pub goal_service: QosPolicies,
90  pub result_service: QosPolicies,
91  pub cancel_service: QosPolicies,
92  pub feedback_subscription: QosPolicies,
93  pub status_subscription: QosPolicies,
94}
95
96/// Collection of QoS policies requires for an Action server
97pub struct ActionServerQosPolicies {
98  pub goal_service: QosPolicies,
99  pub result_service: QosPolicies,
100  pub cancel_service: QosPolicies,
101  pub feedback_publisher: QosPolicies,
102  pub status_publisher: QosPolicies,
103}
104
105/// Emulating ROS2 IDL code generator: Goal sending/setting service request
106#[derive(Clone, Serialize, Deserialize, Debug)]
107pub struct SendGoalRequest<G> {
108  pub goal_id: GoalId,
109  pub goal: G,
110}
111impl<G: Message> Message for SendGoalRequest<G> {}
112
113/// Emulating ROS2 IDL code generator: Goal sending/setting service response
114#[derive(Clone, Serialize, Deserialize, Debug)]
115pub struct SendGoalResponse {
116  pub accepted: bool,
117  pub stamp: builtin_interfaces::Time,
118}
119impl Message for SendGoalResponse {}
120
121/// Emulating ROS2 IDL code generator: Result getting service request
122#[derive(Clone, Serialize, Deserialize, Debug)]
123pub struct GetResultRequest {
124  pub goal_id: GoalId,
125}
126impl Message for GetResultRequest {}
127
128/// Emulating ROS2 IDL code generator: Result getting service response
129#[derive(Clone, Serialize, Deserialize, Debug)]
130pub struct GetResultResponse<R> {
131  pub status: GoalStatusEnum, // interpretation same as in GoalStatus message?
132  pub result: R,
133}
134impl<R: Message> Message for GetResultResponse<R> {}
135
136/// Emulating ROS2 IDL code generator: Feedback Topic message type
137#[derive(Clone, Serialize, Deserialize, Debug)]
138pub struct FeedbackMessage<F> {
139  pub goal_id: GoalId,
140  pub feedback: F,
141}
142impl<F: Message> Message for FeedbackMessage<F> {}
143
144// Example topic names and types at DDS level:
145
146// rq/turtle1/rotate_absolute/_action/send_goalRequest :
147// turtlesim::action::dds_::RotateAbsolute_SendGoal_Request_ rr/turtle1/
148// rotate_absolute/_action/send_goalReply :
149// turtlesim::action::dds_::RotateAbsolute_SendGoal_Response_
150
151// rq/turtle1/rotate_absolute/_action/cancel_goalRequest  :
152// action_msgs::srv::dds_::CancelGoal_Request_ rr/turtle1/rotate_absolute/
153// _action/cancel_goalReply  : action_msgs::srv::dds_::CancelGoal_Response_
154
155// rq/turtle1/rotate_absolute/_action/get_resultRequest :
156// turtlesim::action::dds_::RotateAbsolute_GetResult_Request_ rr/turtle1/
157// rotate_absolute/_action/get_resultReply :
158// turtlesim::action::dds_::RotateAbsolute_GetResult_Response_
159
160// rt/turtle1/rotate_absolute/_action/feedback :
161// turtlesim::action::dds_::RotateAbsolute_FeedbackMessage_
162
163// rt/turtle1/rotate_absolute/_action/status :
164// action_msgs::msg::dds_::GoalStatusArray_