Skip to content

Commit 69fc142

Browse files
committed
actions fixed
1 parent b6e918a commit 69fc142

File tree

4 files changed

+47
-11
lines changed

4 files changed

+47
-11
lines changed

simple_node/include/simple_node/actions/action_client.hpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class ActionClient : public rclcpp_action::Client<ActionT> {
6868

6969
void send_goal(Goal goal, FeedbackCallback feedback_cb = nullptr) {
7070

71+
this->goal_handle = nullptr;
7172
this->result = nullptr;
7273
this->set_status(rclcpp_action::ResultCode::UNKNOWN);
7374

@@ -93,7 +94,11 @@ class ActionClient : public rclcpp_action::Client<ActionT> {
9394
void cancel_goal() {
9495
std::lock_guard<std::mutex> lock(this->goal_handle_mutex);
9596
if (this->goal_handle) {
96-
this->async_cancel_goal(this->goal_handle);
97+
this->async_cancel_goal(this->goal_handle,
98+
std::bind(&ActionClient::cancel_done, this));
99+
100+
std::unique_lock<std::mutex> lock(this->action_done_mutex);
101+
this->action_done_cond.wait(lock);
97102
}
98103
}
99104

@@ -118,8 +123,8 @@ class ActionClient : public rclcpp_action::Client<ActionT> {
118123
}
119124

120125
bool is_working() {
121-
return !this->is_terminated() &&
122-
this->get_status() != rclcpp_action::ResultCode::UNKNOWN;
126+
std::lock_guard<std::mutex> lock(this->goal_handle_mutex);
127+
return this->goal_handle != nullptr;
123128
}
124129

125130
bool is_terminated() {
@@ -130,6 +135,9 @@ class ActionClient : public rclcpp_action::Client<ActionT> {
130135
std::condition_variable action_done_cond;
131136
std::mutex action_done_mutex;
132137

138+
std::condition_variable cancel_done_cond;
139+
std::mutex cancel_done_mutex;
140+
133141
Result result;
134142
rclcpp_action::ResultCode status;
135143
std::mutex status_mtx;
@@ -155,6 +163,8 @@ class ActionClient : public rclcpp_action::Client<ActionT> {
155163
this->set_status(result.code);
156164
this->action_done_cond.notify_one();
157165
}
166+
167+
void cancel_done() { this->action_done_cond.notify_all(); }
158168
};
159169

160170
} // namespace actions

simple_node/include/simple_node/actions/action_server.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class ActionServer : public rclcpp_action::Server<ActionT> {
8888
private:
8989
UserExecuteCallback execute_callback;
9090
UserCancelCallback cancel_callback;
91+
std::unique_ptr<std::thread> cancel_thread;
9192
std::mutex handle_accepted_mtx;
9293

9394
rclcpp_action::GoalResponse handle_goal(const rclcpp_action::GoalUUID &uuid,
@@ -113,13 +114,20 @@ class ActionServer : public rclcpp_action::Server<ActionT> {
113114
rclcpp_action::CancelResponse
114115
handle_cancel(const std::shared_ptr<GoalHandle> goal_handle) {
115116
(void)goal_handle;
117+
118+
this->cancel_thread = std::make_unique<std::thread>(this->cancel_callback);
119+
116120
return rclcpp_action::CancelResponse::ACCEPT;
117121
}
118122

119123
void handle_execute(const std::shared_ptr<GoalHandle> goal_handle) {
120-
124+
this->cancel_thread = nullptr;
121125
this->execute_callback(this->goal_handle);
122126
this->goal_handle = nullptr;
127+
128+
if (this->cancel_thread != nullptr) {
129+
this->cancel_thread->join();
130+
}
123131
}
124132
};
125133
} // namespace actions

simple_node/simple_node/actions/action_client.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def __init__(
3434
) -> None:
3535

3636
self._action_done_event = Event()
37+
self._cancel_done_event = Event()
3738

3839
self._result = None
3940
self._status = GoalStatus.STATUS_UNKNOWN
@@ -69,7 +70,8 @@ def is_aborted(self) -> bool:
6970
return self.get_status() == GoalStatus.STATUS_ABORTED
7071

7172
def is_working(self) -> bool:
72-
return not self.is_terminated() and self.get_status() != GoalStatus.STATUS_UNKNOWN
73+
with self._goal_handle_lock:
74+
return self._goal_handle is not None
7375

7476
def is_terminated(self) -> bool:
7577
return (self.is_succeeded() or self.is_canceled() or self.is_aborted())
@@ -83,6 +85,8 @@ def get_result(self) -> Any:
8385

8486
def send_goal(self, goal, feedback_cb: Callable = None) -> None:
8587

88+
with self._goal_handle_lock:
89+
self._goal_handle = None
8690
self._result = None
8791
self._set_status(GoalStatus.STATUS_UNKNOWN)
8892

@@ -108,4 +112,13 @@ def _get_result_callback(self, future) -> None:
108112
def cancel_goal(self) -> None:
109113
with self._goal_handle_lock:
110114
if self._goal_handle is not None:
111-
self._goal_handle.cancel_goal()
115+
116+
cancel_goal_future = self._cancel_goal_async(
117+
self._goal_handle)
118+
cancel_goal_future.add_done_callback(self._cancel_done)
119+
120+
self._cancel_done_event.clear()
121+
self._cancel_done_event.wait()
122+
123+
def _cancel_done(self, future) -> None:
124+
self._cancel_done_event.set()

simple_node/simple_node/actions/action_server.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
""" Custom action server that add goals to a queue """
1818

19-
from threading import Lock
2019
from typing import Callable
20+
from threading import Lock, Thread
2121

2222
from rclpy.node import Node
2323
from rclpy.action import ActionServer as ActionServer2
@@ -41,6 +41,7 @@ def __init__(
4141
self.__goal_lock = Lock()
4242
self.__user_execute_callback = execute_callback
4343
self.__user_cancel_callback = cancel_callback
44+
self.__cancel_thread = None
4445
self._goal_handle = None
4546
self.node = node
4647

@@ -78,18 +79,22 @@ def __handle_accepted_callback(self, goal_handle: ServerGoalHandle) -> None:
7879
def __cancel_callback(self, goal_handle: ServerGoalHandle) -> int:
7980
""" cancel calback """
8081

82+
if self.__user_cancel_callback is not None:
83+
self.__cancel_thread = Thread(target=self.__user_cancel_callback)
84+
self.__cancel_thread.start()
85+
8186
return CancelResponse.ACCEPT
8287

8388
def __execute_callback(self, goal_handle: ServerGoalHandle):
8489
"""
8590
execute callback
8691
"""
8792

93+
self.__cancel_thread = None
8894
results = self.__user_execute_callback(self._goal_handle)
89-
self._goal_handle = None
9095

91-
if goal_handle.is_cancel_requested:
92-
if self.__user_cancel_callback is not None:
93-
self.__user_cancel_callback()
96+
if self.__cancel_thread is not None:
97+
self.__cancel_thread.join()
9498

99+
self._goal_handle = None
95100
return results

0 commit comments

Comments
 (0)