FlexBE / flexbe_behavior_engine

Contains the behavior engine FlexBE.
Other
47 stars 14 forks source link

ActionClientProxy can't query goal status #3

Open drosen20 opened 2 years ago

drosen20 commented 2 years ago

I am able to set up, issue goals through, and get a result from an action client via the ActionClientProxy, but when I attempt to get the goal status I see 'ActionClient' object has no attribute 'status'.

I can instead capture the result of the action through get_result() and do some error checking on that, but is there a way to check the goal status in an action-agnostic sense?

dcconner commented 2 years ago

Let me ask some questions to clarify. ActionLIb has "Feedback" that is active while the action is processing , and then sends a "Result". Are you asking for status in the sense of where action is in the process of achieving goal? In that case, I think "Feedback" is what you want. The FlexBE ProxyActionClient should provide the interfaces you would normally get from an ActionClient, so is there something that you can normally do from an ActionClient node that you think is missing, or is this a new feature you're looking for? Given that we are only trying to provide an interface to an ActionServer, I'm not sure what you mean by "action-agnostic"

drosen20 commented 2 years ago

Just to give some context, I'm working on porting a ROS1/flexBE1 application in which it is possible to request the status of a goal that has finished execution, successfully or otherwise. This is relayed in the form of a actionlib_msgs.msg.GoalStatus, and it seems that this might no longer be accessible (or, at least, not accessible in the same way) from an ActionClient node in ROS2.

So in our application, we used this GoalStatus as the metric for whether the state is done/failed, i.e., for transitioning out to the next state. And we queried it through ProxyActionClient's get_state().

What I'm doing as a workaround is once the action has a result, I access that result directly and check it against its specific success status. This is not a GoalStatus (which now lives under action_msgs), but an enum defined in the action itself. And as I write this, I think I may have found the issue.

In migrating from ROS1 to ROS2, the ProxyActionClient stopped using an actionlib.SimpleActionClient and instead is now using a rclpy.ActionClient, which does not have a get_state() function in its API, hence the no attribute I mentioned earlier. It must have a different mechanism for accessing the state.

dcconner commented 2 years ago

I suggest you post question on the rclply.ActionClient and get answer there as to why get_state() was dropped (It's been a bit since I reviewed the internals of ActionClient). Our plan with FlexBE is that ProxyActionClient provides interface to all functionality of standard ActionClient. So if they are doing something that we don't handle, I am happy to take a look or consider any pull requests.

dcconner commented 2 years ago

In a bit of digging, it seems I have a bug to fix with get_state() being busted with new ActionClient implementation, but given question on ROS Answers it does not appear that there is a good fix to getting the status right now. It seems ActionClient is subscribing to hidden status topic, but I have yet to find a clear example on accessing this status via the ActionClient.

YBachmann commented 8 months ago

+1 I have the same problem. When using the normal ActionClient from rclpy.client it is still possible (in ROS2) to get the result status (actionlib_msgs.msg.GoalStatus) if you do something like this:


self._action_client = ActionClient(self.node, NavigateToPose, 'my_action')
self._action_client.wait_for_server()
send_goal_future = self._action_client.send_goal_async(
    goal_msg)
send_goal_future.add_done_callback(self.goal_response_callback)

def goal_response_callback(self, future):
    self.goal_handle = future.result()
    if not self.goal_handle.accepted:
        self.node.get_logger().info('Goal rejected :(')
        return
    self.node.get_logger().info('Goal accepted :)')
    get_result_future = self.goal_handle.get_result_async()
    get_result_future.add_done_callback(self.get_result_callback)

def get_result_callback(self, future):
    result = future.result()
    #################### HERE YOU CAN GET THE STATUS (actionlib_msgs.msg.GoalStatus) ####################
    self.node.get_logger().info(f'Got result from action server..  {result.status=}')

However in FlexBe you would use the flexbe_core.proxy ProxyActionClient. As far as I know you can´t access the goal handle and therefore the result status using the ProxyActionClient. The class does have a get_state function see here but it does not work. It tries to call get_state on the underlying ActionClient, however the ActionClient does not have such a function.

dcconner commented 8 months ago

I've pinged https://github.com/ros2/rclpy/issues/1127 to see if we get any clarification from the action server side.

dcconner commented 6 months ago

The underlying bug (fix #16) with get_state is incorporated into humble, iron, rolling, ros2-devel branches, but that only gets the final result state, and does not currently allow querying state during run. Still looking for answer to that