|
1 | 1 | use super::empty_goal_status_array; |
2 | 2 | use crate::{ |
3 | | - log_warn, rcl_bindings::*, CancelResponse, CancelResponseCode, DropGuard, GoalStatus, |
4 | | - GoalStatusCode, GoalUuid, MultiCancelResponse, Node, NodeHandle, QoSProfile, RclPrimitive, |
5 | | - RclPrimitiveHandle, RclPrimitiveKind, RclrsError, ReadyKind, TakeFailedAsNone, ToResult, |
6 | | - Waitable, WaitableLifecycle, ENTITY_LIFECYCLE_MUTEX, |
| 3 | + log_warn, rcl_bindings::*, ActionClientReady, CancelResponse, CancelResponseCode, DropGuard, |
| 4 | + GoalStatus, GoalStatusCode, GoalUuid, MultiCancelResponse, Node, NodeHandle, QoSProfile, |
| 5 | + RclPrimitive, RclPrimitiveHandle, RclPrimitiveKind, RclrsError, ReadyKind, TakeFailedAsNone, |
| 6 | + ToResult, Waitable, WaitableLifecycle, ENTITY_LIFECYCLE_MUTEX, |
7 | 7 | }; |
8 | 8 | use ros_env::{action_msgs::srv::CancelGoal_Response, builtin_interfaces::msg::Time}; |
9 | 9 | use rosidl_runtime_rs::{Action, Message, RmwFeedbackMessage, RmwGoalResponse, RmwResultResponse}; |
@@ -872,6 +872,115 @@ impl<A: Action> RclPrimitive for ActionClientExecutable<A> { |
872 | 872 | fn handle(&self) -> crate::RclPrimitiveHandle<'_> { |
873 | 873 | RclPrimitiveHandle::ActionClient(self.board.handle.lock()) |
874 | 874 | } |
| 875 | + |
| 876 | + fn register_on_ready( |
| 877 | + &self, |
| 878 | + on_ready: Box<dyn Fn(ReadyKind, usize) + Send + Sync>, |
| 879 | + ) -> Result<Option<Box<dyn crate::OnReadyHandle>>, RclrsError> { |
| 880 | + use crate::executor::event_callback::{CompositeOnReady, OnReadyRegistration}; |
| 881 | + |
| 882 | + // An action client bundles two subscriptions (feedback/status) and three |
| 883 | + // service clients (goal/cancel/result). Register a push callback on each, |
| 884 | + // tagging events with the matching readiness flag so the executor runs the |
| 885 | + // right handler. |
| 886 | + let on_ready = Arc::new(on_ready); |
| 887 | + let handle = &self.board.handle; |
| 888 | + let mk = |bits: ActionClientReady| -> Box<dyn Fn(usize) + Send + Sync> { |
| 889 | + let on_ready = Arc::clone(&on_ready); |
| 890 | + Box::new(move |n| on_ready(ReadyKind::ActionClient(bits), n)) |
| 891 | + }; |
| 892 | + |
| 893 | + let regs: Vec<Box<dyn crate::OnReadyHandle>> = vec![ |
| 894 | + Box::new(OnReadyRegistration::new( |
| 895 | + Arc::clone(handle), |
| 896 | + set_action_client_feedback_callback, |
| 897 | + mk(ActionClientReady { |
| 898 | + feedback: true, |
| 899 | + ..Default::default() |
| 900 | + }), |
| 901 | + )?), |
| 902 | + Box::new(OnReadyRegistration::new( |
| 903 | + Arc::clone(handle), |
| 904 | + set_action_client_status_callback, |
| 905 | + mk(ActionClientReady { |
| 906 | + status: true, |
| 907 | + ..Default::default() |
| 908 | + }), |
| 909 | + )?), |
| 910 | + Box::new(OnReadyRegistration::new( |
| 911 | + Arc::clone(handle), |
| 912 | + set_action_client_goal_callback, |
| 913 | + mk(ActionClientReady { |
| 914 | + goal_response: true, |
| 915 | + ..Default::default() |
| 916 | + }), |
| 917 | + )?), |
| 918 | + Box::new(OnReadyRegistration::new( |
| 919 | + Arc::clone(handle), |
| 920 | + set_action_client_cancel_callback, |
| 921 | + mk(ActionClientReady { |
| 922 | + cancel_response: true, |
| 923 | + ..Default::default() |
| 924 | + }), |
| 925 | + )?), |
| 926 | + Box::new(OnReadyRegistration::new( |
| 927 | + Arc::clone(handle), |
| 928 | + set_action_client_result_callback, |
| 929 | + mk(ActionClientReady { |
| 930 | + result_response: true, |
| 931 | + ..Default::default() |
| 932 | + }), |
| 933 | + )?), |
| 934 | + ]; |
| 935 | + |
| 936 | + Ok(Some(Box::new(CompositeOnReady(regs)))) |
| 937 | + } |
| 938 | +} |
| 939 | + |
| 940 | +/// Install (or, with a null callback/user_data, clear) the "on new feedback" |
| 941 | +/// push callback on an action client. Encapsulates the handle lock and rcl call. |
| 942 | +unsafe fn set_action_client_feedback_callback( |
| 943 | + handle: &ActionClientHandle, |
| 944 | + callback: rcl_event_callback_t, |
| 945 | + user_data: *const std::os::raw::c_void, |
| 946 | +) -> rcl_ret_t { |
| 947 | + rcl_action_client_set_feedback_subscription_callback(&*handle.lock(), callback, user_data) |
| 948 | +} |
| 949 | + |
| 950 | +/// As [`set_action_client_feedback_callback`], for the status subscription. |
| 951 | +unsafe fn set_action_client_status_callback( |
| 952 | + handle: &ActionClientHandle, |
| 953 | + callback: rcl_event_callback_t, |
| 954 | + user_data: *const std::os::raw::c_void, |
| 955 | +) -> rcl_ret_t { |
| 956 | + rcl_action_client_set_status_subscription_callback(&*handle.lock(), callback, user_data) |
| 957 | +} |
| 958 | + |
| 959 | +/// As [`set_action_client_feedback_callback`], for the goal service client. |
| 960 | +unsafe fn set_action_client_goal_callback( |
| 961 | + handle: &ActionClientHandle, |
| 962 | + callback: rcl_event_callback_t, |
| 963 | + user_data: *const std::os::raw::c_void, |
| 964 | +) -> rcl_ret_t { |
| 965 | + rcl_action_client_set_goal_client_callback(&*handle.lock(), callback, user_data) |
| 966 | +} |
| 967 | + |
| 968 | +/// As [`set_action_client_feedback_callback`], for the cancel service client. |
| 969 | +unsafe fn set_action_client_cancel_callback( |
| 970 | + handle: &ActionClientHandle, |
| 971 | + callback: rcl_event_callback_t, |
| 972 | + user_data: *const std::os::raw::c_void, |
| 973 | +) -> rcl_ret_t { |
| 974 | + rcl_action_client_set_cancel_client_callback(&*handle.lock(), callback, user_data) |
| 975 | +} |
| 976 | + |
| 977 | +/// As [`set_action_client_feedback_callback`], for the result service client. |
| 978 | +unsafe fn set_action_client_result_callback( |
| 979 | + handle: &ActionClientHandle, |
| 980 | + callback: rcl_event_callback_t, |
| 981 | + user_data: *const std::os::raw::c_void, |
| 982 | +) -> rcl_ret_t { |
| 983 | + rcl_action_client_set_result_client_callback(&*handle.lock(), callback, user_data) |
875 | 984 | } |
876 | 985 |
|
877 | 986 | /// Manage the lifecycle of an `rcl_action_client_t`, including managing its dependencies |
|
0 commit comments