Skip to content

Commit 3e784b1

Browse files
authored
Fix action cancelling/aborting (#1013)
* Wait for goal handle before canceling action goal * Abort action goal if action unadvertised * Fix failing action unadvertise test * Speed up action unit tests * Fix mypy error
1 parent 52d39c1 commit 3e784b1

File tree

3 files changed

+45
-37
lines changed

3 files changed

+45
-37
lines changed

rosbridge_library/src/rosbridge_library/capabilities/advertise_action.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ def done_callback(fut: Future) -> None:
8686
# Send an empty result to avoid stack traces
8787
fut.set_result(get_action_class(self.action_type).Result())
8888
else:
89+
if goal_id not in self.goal_statuses:
90+
goal.abort()
91+
return
92+
8993
status = self.goal_statuses[goal_id]
9094
if status == GoalStatus.STATUS_SUCCEEDED:
9195
goal.succeed()

rosbridge_library/src/rosbridge_library/internal/actions.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,15 @@ def send_goal(
185185
return json_response
186186

187187
def cancel_goal(self) -> None:
188-
if self.goal_handle is None:
188+
while self.goal_handle is None and self.result is None:
189+
time.sleep(self.sleep_time)
190+
191+
if self.result is not None:
192+
# The action has already completed
189193
return
190194

195+
assert self.goal_handle is not None
196+
191197
cancel_goal_future = self.goal_handle.cancel_goal_async()
192198
cancel_goal_future.add_done_callback(self.goal_cancel_cb)
193199
while not cancel_goal_future.done():

rosbridge_library/test/capabilities/test_action_capabilities.py

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,10 @@ def test_execute_advertised_action(self):
127127
)
128128
Thread(target=self.send_goal.send_action_goal, args=(goal_msg,)).start()
129129

130-
loop_iterations = 0
130+
start_time = time.monotonic()
131131
while self.received_message is None:
132-
time.sleep(0.5)
133-
loop_iterations += 1
134-
if loop_iterations > 5:
132+
time.sleep(0.1)
133+
if time.monotonic() - start_time > 1.0:
135134
self.fail("Timed out waiting for action goal message.")
136135

137136
self.assertIsNotNone(self.received_message)
@@ -164,14 +163,20 @@ def test_execute_advertised_action(self):
164163
)
165164
)
166165
self.feedback.action_feedback(feedback_msg)
167-
loop_iterations = 0
168-
while self.latest_feedback is None:
169-
time.sleep(0.5)
170-
loop_iterations += 1
171-
if loop_iterations > 5:
166+
167+
start_time = time.monotonic()
168+
while self.received_message is None:
169+
# self.executor.spin_once(timeout_sec=0.1)
170+
time.sleep(0.1)
171+
if time.monotonic() - start_time > 1.0:
172172
self.fail("Timed out waiting for action feedback message.")
173173

174-
self.assertIsNotNone(self.latest_feedback)
174+
start_time = time.monotonic()
175+
while self.latest_feedback is None:
176+
time.sleep(0.1)
177+
if time.monotonic() - start_time > 1.0:
178+
self.fail("Timed out waiting for action feedback callback.")
179+
175180
self.assertEqual(list(self.latest_feedback.feedback.sequence), [0, 1, 1])
176181

177182
# Now send the result
@@ -190,11 +195,10 @@ def test_execute_advertised_action(self):
190195
self.received_message = None
191196
self.result.action_result(result_msg)
192197

193-
loop_iterations = 0
198+
start_time = time.monotonic()
194199
while self.received_message is None:
195-
time.sleep(0.5)
196-
loop_iterations += 1
197-
if loop_iterations > 5:
200+
time.sleep(0.1)
201+
if time.monotonic() - start_time > 1.0:
198202
self.fail("Timed out waiting for action result message.")
199203

200204
self.assertIsNotNone(self.received_message)
@@ -232,11 +236,10 @@ def test_cancel_advertised_action(self):
232236
)
233237
Thread(target=self.send_goal.send_action_goal, args=(goal_msg,)).start()
234238

235-
loop_iterations = 0
239+
start_time = time.monotonic()
236240
while self.received_message is None:
237-
time.sleep(0.5)
238-
loop_iterations += 1
239-
if loop_iterations > 5:
241+
time.sleep(0.1)
242+
if time.monotonic() - start_time > 1.0:
240243
self.fail("Timed out waiting for action goal message.")
241244

242245
self.assertIsNotNone(self.received_message)
@@ -257,12 +260,11 @@ def test_cancel_advertised_action(self):
257260
self.received_message = None
258261
self.send_goal.cancel_action_goal(cancel_msg)
259262

260-
loop_iterations = 0
263+
start_time = time.monotonic()
261264
while self.received_message is None:
262-
time.sleep(0.5)
263-
loop_iterations += 1
264-
if loop_iterations > 5:
265-
self.fail("Timed out waiting for action result message.")
265+
time.sleep(0.1)
266+
if time.monotonic() - start_time > 1.0:
267+
self.fail("Timed out waiting for cancel action message.")
266268

267269
self.assertIsNotNone(self.received_message)
268270
self.assertEqual(self.received_message["op"], "cancel_action_goal")
@@ -283,11 +285,10 @@ def test_cancel_advertised_action(self):
283285
self.received_message = None
284286
self.result.action_result(result_msg)
285287

286-
loop_iterations = 0
288+
start_time = time.monotonic()
287289
while self.received_message is None:
288-
time.sleep(0.5)
289-
loop_iterations += 1
290-
if loop_iterations > 5:
290+
time.sleep(0.1)
291+
if time.monotonic() - start_time > 1.0:
291292
self.fail("Timed out waiting for action result message.")
292293

293294
self.assertIsNotNone(self.received_message)
@@ -326,11 +327,10 @@ def test_unadvertise_action(self):
326327
)
327328
Thread(target=self.send_goal.send_action_goal, args=(goal_msg,)).start()
328329

329-
loop_iterations = 0
330+
start_time = time.monotonic()
330331
while self.received_message is None:
331-
time.sleep(0.5)
332-
loop_iterations += 1
333-
if loop_iterations > 5:
332+
time.sleep(0.1)
333+
if time.monotonic() - start_time > 1.0:
334334
self.fail("Timed out waiting for action goal message.")
335335

336336
self.assertIsNotNone(self.received_message)
@@ -343,12 +343,10 @@ def test_unadvertise_action(self):
343343
self.received_message = None
344344
self.unadvertise.unadvertise_action(unadvertise_msg)
345345

346-
loop_iterations = 0
346+
start_time = time.monotonic()
347347
while self.received_message is None:
348-
rclpy.spin_once(self.node, timeout_sec=0.1)
349-
time.sleep(0.5)
350-
loop_iterations += 1
351-
if loop_iterations > 5:
348+
time.sleep(0.1)
349+
if time.monotonic() - start_time > 1.0:
352350
self.fail("Timed out waiting for unadvertise action message.")
353351

354352

0 commit comments

Comments
 (0)