Check if a ComputePathThroughPoses action goal has been achieved from another node

Hi evenryone,
I would like to know if it’s possible to check the status of the ComputePathThroughPoses action from a node different to the one that sends the message goal.
Thanks in advance again!

Hi @lfernandez ,

I can think of a solution for your problem. I am not sure if this would be the best solution, but I think of this as one possible solution.

Here is what I understand as your problem:
Your Problem (in simple words): How to know if NavigateThroughPoses goal is complete from another ROS2 node that does not communicate the goal to the action server?

My (proposed) Solution is as follows:
If we take a look into NavigateThroughPoses interface definition, it looks as follows:

user:~$ ros2 interface show nav2_msgs/action/NavigateThroughPoses
#goal definition
geometry_msgs/PoseStamped[] poses
        std_msgs/Header header
                builtin_interfaces/Time stamp
                        int32 sec
                        uint32 nanosec
                string frame_id
        Pose pose
                Point position
                        float64 x
                        float64 y
                        float64 z
                Quaternion orientation
                        float64 x 0
                        float64 y 0
                        float64 z 0
                        float64 w 1
string behavior_tree
---
#result definition
std_msgs/Empty result
---
#feedback definition
geometry_msgs/PoseStamped current_pose
        std_msgs/Header header
                builtin_interfaces/Time stamp
                        int32 sec
                        uint32 nanosec
                string frame_id
        Pose pose
                Point position
                        float64 x
                        float64 y
                        float64 z
                Quaternion orientation
                        float64 x 0
                        float64 y 0
                        float64 z 0
                        float64 w 1
builtin_interfaces/Duration navigation_time
        int32 sec
        uint32 nanosec
builtin_interfaces/Duration estimated_time_remaining
        int32 sec
        uint32 nanosec
int16 number_of_recoveries
float32 distance_remaining
int16 number_of_poses_remaining

What I (we) can infer from the message is that, Result is an Empty message.
So, Result will be of no use to the problem, if you want to know the goal status.

The better way to know if the goal is complete or not, is by subscribing to the feedback messages from the action server /navigate_through_poses.

But here is a problem, unlike in ROS1 where you would have something like /navigate_through_poses/feedback, in ROS2, you do not have that facility.

What you can instead do is:
In the action client program that you use to send goal to the /navigate_through_poses action server, make a new topic into which you will publish the action server’s feedback messages.
So in the action client program, create a publisher which publishes NavigateThroughPoses feedback message into a topic, say, nav_thru_poses_feedback.
Use a feedback_callback in your action client to get the feedback messages from the /navigate_through_poses action server and transfer the feedback message into this new topic that you created.
Now you have a topic that will always publish the feedback from the action server.
Finally, all that you need to do is to subscribe to this new topic nav_thru_poses_feedback from any program you want and check if the goal is complete.

Now to check if goal is complete or not, you can refer the feedback message contents:

#feedback definition
geometry_msgs/PoseStamped current_pose
        std_msgs/Header header
                builtin_interfaces/Time stamp
                        int32 sec
                        uint32 nanosec
                string frame_id
        Pose pose
                Point position
                        float64 x
                        float64 y
                        float64 z
                Quaternion orientation
                        float64 x 0
                        float64 y 0
                        float64 z 0
                        float64 w 1
builtin_interfaces/Duration navigation_time
        int32 sec
        uint32 nanosec
builtin_interfaces/Duration estimated_time_remaining
        int32 sec
        uint32 nanosec
int16 number_of_recoveries
float32 distance_remaining
int16 number_of_poses_remaining

From the message, you can know things like:
Elapsed Navigation Time (navigation_time), Estimated time to goal (estimated_time_remaining), Distance to Goal (distance_remaining) and Number of poses passed through (number_of_poses_remaining).

Since this new topic would contain the same message as the feedback message, if you feel adventurous, you can also add few additional info like:
int16 total_number_of_poses, float32 distance_travelled, etc.
But for this, you will have to create a custom message.

I hope you understood the idea here. I do not know any other method that exists at the moment.
[If anyone else knows an easier method, please do share!]

Regards,
Girish

Hi @lfernandez ,

Here is some additional info on how to access the “hidden objects” of an action server:
Refer link: ROS 2 Design - Action

Note: These are made “hidden” because I believe accessing these objects this way is not allowed.
But I am just sharing it here. The choice is yours if you want to use this or not !

Copy-Pasted from the above Link:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Example: fully qualified action name

Given:

  • Action name: /action/name
  • Namespace: /name/space
  • Node name: nodename

Topic Names:

  • /action/name/_action/status
  • /action/name/_action/feedback

Service Names:

  • /action/name/_action/send_goal
  • /action/name/_action/cancel_goal
  • /action/name/_action/get_result

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Here is an example for feedback (Note: with /navigate_to_pose/_action/feedback):

user:~$ ros2 topic echo /navigate_to_pose/_action/feedback
goal_id:
  uuid:
  - 135
  - 214
  - 140
  - 69
  - 66
  - 174
  - 209
  - 202
  - 237
  - 42
  - 136
  - 93
  - 218
  - 11
  - 132
  - 25
feedback:
  current_pose:
    header:
      stamp:
        sec: 822
        nanosec: 52000000
      frame_id: map
    pose:
      position:
        x: -0.8107613845265607
        y: 3.8175188204708506
        z: 0.010020873174514104
      orientation:
        x: -0.0008153909995892053
        y: 0.00014670012515843696
        z: 0.15764740991413292
        w: 0.9874951178430992
  navigation_time:
    sec: 6
    nanosec: 688000000
  estimated_time_remaining:
    sec: 0
    nanosec: 0
  number_of_recoveries: 0
  distance_remaining: 0.2095082849264145
---
goal_id:
  uuid:
  - 135
  - 214
  - 140
  - 69
  - 66
  - 174
  - 209
  - 202
  - 237
  - 42
  - 136
  - 93
  - 218
  - 11
  - 132
  - 25
feedback:
  current_pose:
    header:
      stamp:
        sec: 822
        nanosec: 52000000
      frame_id: map
    pose:
      position:
        x: -0.8107613845265607
        y: 3.8175188204708506
        z: 0.010020873174514104
      orientation:
        x: -0.0008153909995892053
        y: 0.00014670012515843696
        z: 0.15764740991413292
        w: 0.9874951178430992
  navigation_time:
    sec: 6
    nanosec: 688000000
  estimated_time_remaining:
    sec: 0
    nanosec: 0
  number_of_recoveries: 0
  distance_remaining: 0.2095082849264145
---
goal_id:
  uuid:
  - 135
  - 214
  - 140
  - 69
  - 66
  - 174
  - 209
  - 202
  - 237
  - 42
  - 136
  - 93
  - 218
  - 11
  - 132
  - 25
feedback:
  current_pose:
    header:
      stamp:
        sec: 822
        nanosec: 86000000
      frame_id: map
    pose:
      position:
        x: -0.8097764156961952
        y: 3.818921130181496
        z: 0.010020819939318963
      orientation:
        x: -0.0007171364445165051
        y: 0.00013427438924933433
        z: 0.15511446200627343
        w: 0.9878962351189585
  navigation_time:
    sec: 6
    nanosec: 688000000
  estimated_time_remaining:
    sec: 0
    nanosec: 0
  number_of_recoveries: 0
  distance_remaining: 0.2095082849264145
---
goal_id:
  uuid:
  - 135
  - 214
  - 140
  - 69
  - 66
  - 174
  - 209
  - 202
  - 237
  - 42
  - 136
  - 93
  - 218
  - 11
  - 132
  - 25
feedback:
  current_pose:
    header:
      stamp:
        sec: 822
        nanosec: 86000000
      frame_id: map
    pose:
      position:
        x: -0.8097764156961952
        y: 3.818921130181496
        z: 0.010020819939318963
      orientation:
        x: -0.0007171364445165051
        y: 0.00013427438924933433
        z: 0.15511446200627343
        w: 0.9878962351189585
  navigation_time:
    sec: 6
    nanosec: 688000000
  estimated_time_remaining:
    sec: 0
    nanosec: 0
  number_of_recoveries: 0
  distance_remaining: 0.2095082849264145
---
goal_id:
  uuid:
  - 135
  - 214
  - 140
  - 69
  - 66
  - 174
  - 209
  - 202
  - 237
  - 42
  - 136
  - 93
  - 218
  - 11
  - 132
  - 25
feedback:
  current_pose:
    header:
      stamp:
        sec: 822
        nanosec: 86000000
      frame_id: map
    pose:
      position:
        x: -0.8097764156961952
        y: 3.818921130181496
        z: 0.010020819939318963
      orientation:
        x: -0.0007171364445165051
        y: 0.00013427438924933433
        z: 0.15511446200627343
        w: 0.9878962351189585
  navigation_time:
    sec: 6
    nanosec: 786000000
  estimated_time_remaining:
    sec: 0
    nanosec: 0
  number_of_recoveries: 0
  distance_remaining: 0.2095082849264145
---

Here is an example for status (Note: with /navigate_to_pose/_action/status):

user:~$ ros2 topic echo /navigate_to_pose/_action/status
status_list:
- goal_info:
    goal_id:
      uuid:
      - 7
      - 24
      - 75
      - 237
      - 161
      - 108
      - 39
      - 135
      - 143
      - 61
      - 157
      - 217
      - 232
      - 175
      - 83
      - 101
    stamp:
      sec: 236
      nanosec: 574000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 94
      - 2
      - 40
      - 13
      - 223
      - 181
      - 151
      - 255
      - 37
      - 15
      - 49
      - 15
      - 208
      - 126
      - 214
      - 150
    stamp:
      sec: 247
      nanosec: 744000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 188
      - 255
      - 232
      - 107
      - 118
      - 247
      - 24
      - 59
      - 221
      - 206
      - 51
      - 65
      - 182
      - 217
      - 64
      - 47
    stamp:
      sec: 279
      nanosec: 151000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 221
      - 238
      - 45
      - 143
      - 41
      - 242
      - 80
      - 163
      - 230
      - 152
      - 224
      - 2
      - 116
      - 216
      - 74
      - 129
    stamp:
      sec: 383
      nanosec: 565000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 141
      - 250
      - 143
      - 129
      - 54
      - 36
      - 173
      - 17
      - 221
      - 164
      - 238
      - 4
      - 104
      - 48
      - 183
      - 16
    stamp:
      sec: 438
      nanosec: 598000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 135
      - 214
      - 140
      - 69
      - 66
      - 174
      - 209
      - 202
      - 237
      - 42
      - 136
      - 93
      - 218
      - 11
      - 132
      - 25
    stamp:
      sec: 815
      nanosec: 325000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 228
      - 127
      - 227
      - 249
      - 54
      - 2
      - 146
      - 229
      - 235
      - 161
      - 22
      - 37
      - 55
      - 36
      - 4
      - 180
    stamp:
      sec: 978
      nanosec: 500000000
  status: 2
---
status_list:
- goal_info:
    goal_id:
      uuid:
      - 7
      - 24
      - 75
      - 237
      - 161
      - 108
      - 39
      - 135
      - 143
      - 61
      - 157
      - 217
      - 232
      - 175
      - 83
      - 101
    stamp:
      sec: 236
      nanosec: 574000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 94
      - 2
      - 40
      - 13
      - 223
      - 181
      - 151
      - 255
      - 37
      - 15
      - 49
      - 15
      - 208
      - 126
      - 214
      - 150
    stamp:
      sec: 247
      nanosec: 744000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 188
      - 255
      - 232
      - 107
      - 118
      - 247
      - 24
      - 59
      - 221
      - 206
      - 51
      - 65
      - 182
      - 217
      - 64
      - 47
    stamp:
      sec: 279
      nanosec: 151000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 221
      - 238
      - 45
      - 143
      - 41
      - 242
      - 80
      - 163
      - 230
      - 152
      - 224
      - 2
      - 116
      - 216
      - 74
      - 129
    stamp:
      sec: 383
      nanosec: 565000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 141
      - 250
      - 143
      - 129
      - 54
      - 36
      - 173
      - 17
      - 221
      - 164
      - 238
      - 4
      - 104
      - 48
      - 183
      - 16
    stamp:
      sec: 438
      nanosec: 598000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 135
      - 214
      - 140
      - 69
      - 66
      - 174
      - 209
      - 202
      - 237
      - 42
      - 136
      - 93
      - 218
      - 11
      - 132
      - 25
    stamp:
      sec: 815
      nanosec: 325000000
  status: 4
- goal_info:
    goal_id:
      uuid:
      - 228
      - 127
      - 227
      - 249
      - 54
      - 2
      - 146
      - 229
      - 235
      - 161
      - 22
      - 37
      - 55
      - 36
      - 4
      - 180
    stamp:
      sec: 978
      nanosec: 500000000
  status: 4
---

So, yes, you can use these methods to get your results. You can subscribe to these topics from any program.
Note: These topics will NOT be shown when you do ros2 topic list OR with ros2 topic --include-hidden-topics list.

Summary:
The topics used for an Action can be accessed by subscribing to above topics.
But, this would not be a good practice from my understanding. On the other hand, nobody restricts you from using these! So you can decide to use this or not!

Regards,
Girish

Thanks @girishkumar.kannan for your detailed answer!!
In case I wouldnt be able to modify the client that sends the goal,the options that I have are based on the use of the hidden topics, aren’t they?
What I dont really understand is why is not allowed to access the “hidden objects” through this way.
Thanks again!!

Hi @lfernandez ,

Unfortunately, Yes!. If you cannot modify the action client for some reason, the only viable option that I see is using these “hidden topics”. I do not have an ethical option as a solution right now.

I honestly have no idea what is the intent of ROS creators making these topics as “hidden”. But from a framework point-of-view, I am going to say that it is to not overload a topic by abusing it.
For example, You could create 5 different programs that read from the same topic simultaneously. This could actually prevent the program to be accessible to the actual client.

To say it simpler, these topics are made hidden so that the communication between the action server and the action client is the fastest. So if you have 5 programs that would subscribe to the action server’s feedback, then the data load on the feedback topic would increase thereby reducing the throughput of messages to the action client. This is one possible reason that I could think of. That is why my initial solution was to copy the feedback into a new topic so that you will not overload the actual action feedback topic.

I hope this explanation makes sense to you. [To say this again, the above is just my speculation. I do not have proof that this is the reason why these topics are hidden from user.]

Regards,
Girish

Thanks @girishkumar.kannan
Of course ti makes sense to me.
Thanks again!!

Hi @girishkumar.kannan,
I’m trying to use the service to get the result of hte navigate_to_pose action but I get nothing when trying to get its type. Do you know what I’m doing wrong? Thanks again!

`ros2 service type /navigate_to_pose/_action/get_result`

Hi @lfernandez ,

Actually you are not doing anything wrong. Since this service is “hidden”, the type method does not work.

I did some research and found out another way:
The following command does not work and gives no output:

user:~$ ros2 service type /navigate_to_pose/_action/get_result

But here is another way: you need to type the command from ros2 ... /get_result and hit tab key twice

user:~$ ros2 service call /navigate_to_pose/_action/get_result # press TAB twice here
--rate
-r
nav2_msgs/action/NavigateToPose_GetResult   # the type of message/interface is listed here
user:~$ ros2 service call /navigate_to_pose/_action/get_result

But if you try to do the below command, it will produce error.

user:~$ ros2 interface show nav2_msgs/action/NavigateToPose_GetResult
Could not find the interface '/opt/ros/foxy/share/nav2_msgs/action/NavigateToPose_GetResult.idl'

The better option for you here is to subscribe to /action_name/_action/status and get the goal status by reading the status message id. (Refer my previous post).

Also refer to “Goal Status Topic” in this link: ROS 2 Design - Action

You can then relate the status ids to their actual references:
(From my previous post about status topic outputs, I see status values 2 and 4).
So I am assuming 2 means Executing and 4 means Succeeded. (I may be wrong though.)

==========
Copy-Pasted from the Action Design Link:

  • Accepted - The goal has been accepted by the action server === 1
  • Executing - The goal is currently being executing by the action server === 2
  • Canceling - The action server will try to cancel the indicated goal === 3
  • Succeeded - The action server successfully reached the goal === 4
  • Aborted - The action server failed reached the goal === 5
  • Canceled - The action server successfully canceled the goal === 6

==========

This is what I will do if I have to implement something like what you want to do.
Even I wanted to do something similar to what you are planning to do and did my own experiments and research.
I am not yet aware of a better method. I would like to know from other ROS2 experts though or do more research.

I hope this post is helpful.

Regards,
Girish

Thanks @girishkumar.kannan!!
It helped a lot! I will use the topics as you recommend. Thanks again!

1 Like

One last question @girishkumar.kannan
When I check the type of the messages sent to the ros2 topic info /navigate_to_pose/_action/feedback topic I get

ros2 topic info /navigate_to_pose/_action/feedback
Type: nav2_msgs/action/NavigateToPose_FeedbackMessage
Publisher count: 1
Subscription count: 4

Nevertheless the interface doesn’t seem to have been defined

ros2 interface show nav2_msgs/action/NavigateToPose_FeedbackMessage
Could not find the interface '/opt/ros/galactic/share/nav2_msgs/action/NavigateToPose_FeedbackMessage.idl'

ImportError: cannot import name ‘NavigateToPose_FeedbackMessage’ from ‘nav2_msgs.action’ (/opt/ros/galactic/lib/python3.8/site-packages/nav2_msgs/action/init.py)


Does anyone know if I’m missing something in my ROS 2 installation?
Thanks again in advance!

Hi @lfernandez ,

This is why I told you in my earlier post to create a new topic called nav_to_pose_feedback and publish the data acquired from the feedback callback on your action client into this new topic.

In the event where you cannot or not allowed to modify the action client of the program then there is only one way - use python’s subprocess to open a virtual terminal and communicate with that process.
This is a very bad idea. But I cannot think of any better option at the moment.

My advice would be not to consider the above second option.
Instead, you can do some research with remapping using remap.

The best way is to create your own action client to the action server. Try to create a copy of the action client code and modify that file instead of modifying the original file. That way you are not “tampering” with the original files.

Regards,
Girish

Thanks @girishkumar.kannan! I’ll try to do it in that way!

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.