Skip to content

Commit 9f10a85

Browse files
committed
checkin
1 parent 6ca7d1f commit 9f10a85

File tree

6 files changed

+144
-8
lines changed

6 files changed

+144
-8
lines changed
Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,51 @@
11
use std::env;
2+
use std::sync::Arc;
3+
use std::thread;
24

35
use anyhow::{Error, Result};
46

7+
type Fibonacci = example_interfaces::action::Fibonacci;
8+
type GoalHandleFibonacci = rclrs::ServerGoalHandle<Fibonacci>;
9+
10+
fn handle_goal(
11+
_uuid: &rclrs::GoalUUID,
12+
goal: Arc<example_interfaces::action::rmw::Fibonacci_Goal>,
13+
) -> rclrs::GoalResponse {
14+
println!("Received goal request with order {}", goal.order);
15+
if goal.order > 9000 {
16+
rclrs::GoalResponse::Reject
17+
} else {
18+
rclrs::GoalResponse::AcceptAndExecute
19+
}
20+
}
21+
22+
fn handle_cancel(_goal_handle: Arc<GoalHandleFibonacci>) -> rclrs::CancelResponse {
23+
println!("Got request to cancel goal");
24+
rclrs::CancelResponse::Accept
25+
}
26+
27+
fn execute(goal_handle: Arc<GoalHandleFibonacci>) {
28+
println!("Executing goal");
29+
thread::sleep(std::time::Duration::from_millis(100));
30+
}
31+
32+
fn handle_accepted(goal_handle: Arc<GoalHandleFibonacci>) {
33+
thread::spawn(move || {
34+
execute(goal_handle);
35+
});
36+
}
37+
538
fn main() -> Result<(), Error> {
639
let context = rclrs::Context::new(env::args())?;
740

8-
let node = rclrs::create_node(&context, "minimal_action_server")?;
41+
let mut node = rclrs::create_node(&context, "minimal_action_server")?;
42+
43+
let _action_server = node.create_action_server::<example_interfaces::action::Fibonacci>(
44+
"fibonacci",
45+
handle_goal,
46+
handle_cancel,
47+
handle_accepted,
48+
);
949

1050
rclrs::spin(&node).map_err(|err| err.into())
1151
}

rclrs/src/action.rs

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
11
use crate::{rcl_bindings::*, RclrsError};
22
use std::sync::{Arc, Mutex, MutexGuard};
33

4+
// SAFETY: The functions accessing this type, including drop(), shouldn't care about the thread
5+
// they are running in. Therefore, this type can be safely sent to another thread.
6+
unsafe impl Send for rcl_action_goal_handle_t {}
7+
8+
unsafe impl Sync for rcl_action_goal_handle_t {}
9+
410
use std::marker::PhantomData;
511

12+
pub type GoalUUID = [u8; RCL_ACTION_UUID_SIZE];
13+
14+
pub enum GoalResponse {
15+
Reject = 1,
16+
AcceptAndExecute = 2,
17+
AcceptAndDefer = 3,
18+
}
19+
20+
pub enum CancelResponse {
21+
Reject = 1,
22+
Accept = 2,
23+
}
24+
625
pub struct ActionClient<T>
726
where
827
T: rosidl_runtime_rs::Action,
@@ -16,8 +35,6 @@ where
1635
{
1736
/// Creates a new action client.
1837
pub(crate) fn new(rcl_node_mtx: Arc<Mutex<rcl_node_t>>, topic: &str) -> Result<Self, RclrsError>
19-
// This uses pub(crate) visibility to avoid instantiating this struct outside
20-
// [`Node::create_client`], see the struct's documentation for the rationale
2138
where
2239
T: rosidl_runtime_rs::Action,
2340
{
@@ -26,3 +43,52 @@ where
2643
})
2744
}
2845
}
46+
47+
pub struct ActionServer<T>
48+
where
49+
T: rosidl_runtime_rs::Action,
50+
{
51+
_marker: PhantomData<T>,
52+
}
53+
54+
impl<T> ActionServer<T>
55+
where
56+
T: rosidl_runtime_rs::Action,
57+
{
58+
/// Creates a new action server.
59+
pub(crate) fn new(rcl_node_mtx: Arc<Mutex<rcl_node_t>>, topic: &str) -> Result<Self, RclrsError>
60+
where
61+
T: rosidl_runtime_rs::Action,
62+
{
63+
Ok(Self {
64+
_marker: Default::default(),
65+
})
66+
}
67+
}
68+
69+
pub struct ServerGoalHandle<T>
70+
where
71+
T: rosidl_runtime_rs::Action,
72+
{
73+
rcl_handle: Arc<rcl_action_goal_handle_t>,
74+
_marker: PhantomData<T>,
75+
}
76+
77+
impl<T> ServerGoalHandle<T>
78+
where
79+
T: rosidl_runtime_rs::Action,
80+
{
81+
pub(crate) fn new(rcl_handle: Arc<rcl_action_goal_handle_t>) {}
82+
83+
pub(crate) fn is_canceling() -> bool {
84+
false
85+
}
86+
87+
pub(crate) fn is_active() -> bool {
88+
false
89+
}
90+
91+
pub(crate) fn is_executing() -> bool {
92+
false
93+
}
94+
}

rclrs/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub use node::*;
3838
pub use parameter::*;
3939
pub use publisher::*;
4040
pub use qos::*;
41+
use rcl_bindings::rcl_context_is_valid;
42+
use rcl_bindings::rcl_action_goal_handle_t;
4143
pub use rcl_bindings::rmw_request_id_t;
4244
pub use service::*;
4345
pub use subscription::*;

rclrs/src/node.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ pub use self::builder::*;
1313
pub use self::graph::*;
1414
use crate::rcl_bindings::*;
1515
use crate::{
16-
ActionClient, Client, ClientBase, Context, GuardCondition, ParameterOverrideMap, Publisher,
17-
QoSProfile, RclrsError, Service, ServiceBase, Subscription, SubscriptionBase,
16+
ActionClient, ActionServer, CancelResponse, Client, ClientBase, Context,
17+
GoalResponse, GoalUUID, GuardCondition, ParameterOverrideMap, Publisher, QoSProfile,
18+
RclrsError, ServerGoalHandle, Service, ServiceBase, Subscription, SubscriptionBase,
1819
SubscriptionCallback, ToResult,
1920
};
2021

@@ -189,7 +190,7 @@ impl Node {
189190
Ok(client)
190191
}
191192

192-
/// Creates a [`Client`][1].
193+
/// Creates an [`ActionClient`][1].
193194
///
194195
/// [1]: crate::ActionClient
195196
// TODO: make action client's lifetime depend on node's lifetime
@@ -200,13 +201,36 @@ impl Node {
200201
where
201202
T: rosidl_runtime_rs::Action,
202203
{
203-
let client = Arc::new(ActionClient::<T>::new(
204+
let action_client = Arc::new(ActionClient::<T>::new(
204205
Arc::clone(&self.rcl_node_mtx),
205206
topic,
206207
)?);
207208
// self.clients
208209
// .push(Arc::downgrade(&client) as Weak<dyn ClientBase>);
209-
Ok(client)
210+
Ok(action_client)
211+
}
212+
213+
/// Creates an [`ActionServer`][1].
214+
///
215+
/// [1]: crate::ActionServer
216+
// TODO: make action server's lifetime depend on node's lifetime
217+
pub fn create_action_server<T>(
218+
&mut self,
219+
topic: &str,
220+
handle_goal: fn(&crate::action::GoalUUID, Arc<T::Goal>) -> GoalResponse,
221+
handle_cancel: fn(Arc<ServerGoalHandle<T>>) -> CancelResponse,
222+
handle_accepted: fn(Arc<ServerGoalHandle<T>>),
223+
) -> Result<Arc<ActionServer<T>>, RclrsError>
224+
where
225+
T: rosidl_runtime_rs::Action,
226+
{
227+
let action_server = Arc::new(ActionServer::<T>::new(
228+
Arc::clone(&self.rcl_node_mtx),
229+
topic,
230+
)?);
231+
// self.servers
232+
// .push(Arc::downgrade(&server) as Weak<dyn ClientBase>);
233+
Ok(action_server)
210234
}
211235

212236
/// Creates a [`GuardCondition`][1] with no callback.

rclrs/src/rcl_bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@
1313
include!(concat!(env!("OUT_DIR"), "/rcl_bindings_generated.rs"));
1414

1515
pub const RMW_GID_STORAGE_SIZE: usize = rmw_gid_storage_size_constant;
16+
pub const RCL_ACTION_UUID_SIZE: usize = rcl_action_uuid_size_constant;

rclrs/src/rcl_wrapper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include <rcl/graph.h>
22
#include <rcl/rcl.h>
3+
#include <rcl_action/types.h>
4+
#include <rcl_action/goal_handle.h>
35
#include <rcl_yaml_param_parser/parser.h>
46
#include <rcutils/error_handling.h>
57
#include <rmw/types.h>
68
#include <rosidl_typesupport_introspection_c/field_types.h>
79
#include <rosidl_typesupport_introspection_c/message_introspection.h>
810

911
const size_t rmw_gid_storage_size_constant = RMW_GID_STORAGE_SIZE;
12+
const size_t rcl_action_uuid_size_constant = UUID_SIZE;

0 commit comments

Comments
 (0)