Why is the Future 'done callback' order reversed?
I'd like to attach multiple callbacks to a Future
provided by a ClientGoalHandle
. However, when I do this I find that the callbacks are being called in reverse order. I'm a little stumped as to why this is happening. When I look through the code for rclpy.executor
or rclpy.task
I can only see for callback in callbacks
.
Here's a snippet from my code:
@property
def logger(self):
return self._node.get_logger()
def foo(self, *args, **kwargs):
self.logger.info('foo')
def bar(self, *args, **kwargs):
self.logger.info('bar')
def baz(self, *args, **kwargs):
self.logger.info('baz')
def qux(self, *args, **kwargs):
self.logger.info('qux')
def next(self) -> Optional[Future]:
self._clear_cache()
if self.goal_handle is not None:
self.logger.info("Cancelling current guidance.")
future = self.goal_handle.cancel_goal_async()
future.add_done_callback(self.foo)
future.add_done_callback(self.bar)
self._goal_future.add_done_callback(self.baz)
self._goal_future.add_done_callback(self.qux)
return self._goal_future
else:
return None
Here is the console readout in which you can see bar
is called before foo
and qux
is called before baz
:
[simple_state_machine-2] [INFO] [1607502712.297026172] [state]: [GoalState] Cancelling current guidance.
[velocity_controller-3] [INFO] [1607502712.301784151] [vel_ctrl]: Received cancel request.
[simple_state_machine-2] [INFO] [1607502712.302841057] [state]: [GoalState] bar
[simple_state_machine-2] [INFO] [1607502712.303296070] [state]: [GoalState] foo
[velocity_controller-3] [INFO] [1607502712.397141220] [vel_ctrl]: Guidance cancelled.
[velocity_controller-3] [INFO] [1607502712.398128136] [vel_ctrl]: Goal status: 5.
[simple_state_machine-2] [INFO] [1607502712.399765926] [state]: [GoalState] qux
[simple_state_machine-2] [INFO] [1607502712.400109978] [state]: [GoalState] baz
[simple_state_machine-2] [WARN] [1607502712.400789882] [state]: [GoalState] Navigation ended with goal status code: 5 and guidance status code: 0.
I can 'fix' this by reversing the future callback order:
with future._lock:
future._callbacks.reverse()
But it feels like a hack to mess around with private variables within the future class. Any ideas?