-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changing behavior_tree from Simple Commander API causes navigation on cancelled goal #3156
Comments
Do you only see this through the simple commander API for the first request or with specific behavior trees? I regularly cancel and reissue goals in rviz2 for testing using the default BT and do not see that behavior. Do you have logs? What are they saying? If you send a new goal, that should be immediately overridden unless you set the parameter for the blackboard goal ID to something else - let alone the fact that the entire BT should be deleted and reconstructed if you change BTs. https://github.com/ros-planning/navigation2/blob/main/nav2_bt_navigator/src/navigators/navigate_to_pose.cpp#L87 What rviz tool are you using to request the goal? The nav2 provided one or the default rviz one? CC @jwallace42 |
Hi @SteveMacenski Here are the logs:
Here, the new requested goal x ,y :: (3.90, 2.00) is not respected (even though it is logged correctly by bt_navigator), but instead navigates to old cancelled goal. Also, I am using rviz tool provided by nav2 but the issue can be reproduced just using python API. from geometry_msgs.msg import PoseStamped
from nav2_simple_commander.robot_navigator import BasicNavigator, TaskResult
import rclpy
from rclpy.duration import Duration
from time import sleep
def main():
rclpy.init()
navigator = BasicNavigator()
navigator.waitUntilNav2Active()
#Pose 1 to be cancelled
goal_pose1 = PoseStamped()
goal_pose1.header.frame_id = 'map'
goal_pose1.header.stamp = navigator.get_clock().now().to_msg()
goal_pose1.pose.position.x = 3.9
goal_pose1.pose.position.y = 2.0
goal_pose1.pose.orientation.w = 1.0
#Pose 2 to be navigated
goal_pose2 = PoseStamped()
goal_pose2.header.frame_id = 'map'
goal_pose2.header.stamp = navigator.get_clock().now().to_msg()
goal_pose2.pose.position.x = 1.13
goal_pose2.pose.position.y = -8.16
goal_pose2.pose.orientation.w = 1.0
navigator.goToPose(goal_pose1)
sleep(5.0)
# Cancel goal_pose1
navigator.cancelTask()
sleep(5.0)
navigator.goToPose(goal_pose2, '/home/navigate_w_recovery_and_replanning_only_if_path_becomes_invalid.xml')
i = 0
while not navigator.isTaskComplete():
i = i + 1
feedback = navigator.getFeedback()
if feedback and i % 10 == 0:
print('Estimated time of arrival: ' + '{0:.0f}'.format(
Duration.from_msg(feedback.estimated_time_remaining).nanoseconds / 1e9)
+ ' seconds.')
# Do something depending on the return code
result = navigator.getResult()
if result == TaskResult.SUCCEEDED:
print('Goal succeeded!')
elif result == TaskResult.CANCELED:
print('Goal was canceled!')
elif result == TaskResult.FAILED:
print('Goal failed!')
else:
print('Goal has an invalid return status!')
exit(0)
if __name__ == '__main__':
main() |
So, just to recap. We see the issue only when using the nav2_simple_commander(to cancel the goal) with the https://github.com/ros-planning/navigation2/blob/main/nav2_bt_navigator/behavior_trees/navigate_w_recovery_and_replanning_only_if_path_becomes_invalid.xml. It seems that the cancel from the nav2_simple_commander does something different that the cancel from the rviz panel. We know the cancel is not correctly canceling the computePathToPose action due to the old path still being present. (Could there be some other exit flow? i.e I think the next step would be to run with the log level set to debug so we can take a look and see if the cancel request is actually cancelling the active actions in the behavior tree. The other thing I would like to do is send these goals manually though the command line to see if get the same results(you should :)). I might have some free time to track this down by the E.O.W. |
I see that we share the same The correct The 2 nodes that happen before computing the path to the pose are If I were to make a guess based on a few minutes of looking @jwallace42 but without actually tracking down the error itself to validate; I think what's happening is that this part of the BT under @automech-rb this only happens when the second request uses the |
@SteveMacenski Yeah, this only occurs when using As you both commented earlier, I feel this is more of issue of how blackboard_ is handled when using |
This is where we're really missing each other and need a clear statement of what specifically works and what specifically doesn't. Are you saying that if you just |
Hello @SteveMacenski A. This error does not occur:Set default behavior tree B. This error occurs:Case 1 (original bug report method): Case 2 (script method): In both error cases, I am specifying behavior file in python API, which led to my conclusion that using xml file in python API is one of the cause of this error. |
The goal message is populated each time - so I don't think its from the Python API unless something very odd is happening - it seems more likely with the BT XML handling or something in BT navigator - since I think you said it happens via rviz too. |
Can edit the bringup_launch.py file by switching the log level from info to debug. Then launch rqt_console by Once it is starting to record, run the simulation and reproduce the error. Then stop the recording, save the file and set it to me so I can take a look :). The other thing you should try so we can eliminate the nav2_simple_commander as an issue is sending the goals manually though the command line.
If you can reproduce the error then we definitely know that it is something below the nav2_simple commander. I bet @SteveMacenski is right and we will see the error again. |
Or you can send me your branch :) |
Hello @jwallace42 I tested the pr but still leads to same error behaviour. I am also adding the log debug file as you stated. Setup:Gazebo + Nav2 (with Python script and log debug fileIn |
Not surprised, that PR does something in the same direction as the previous work just resetting the path between runs, but that's not the root cause of why things aren't passing correctly around. Its definitely not bad to do (especially since I love defensive programming + helps solve some future issues with people making bad BTs), but not addressing root cause. |
Yeah, I though halt() would be called when the behavior tree completed which was a misunderstanding. Pretty much, what is happening is the path gets planned. When the task is cancelled the computePathToPose is already completed so the blackboard still contains the old path. So, when ever a behavior tree ever gets loaded we need to make sure the path is empty. The simplest thing (which I just put in my pr and works, only able to reproduce case2, not case1) is to reset the path every time the behavior tree is loaded. To clean this up, we would just clear the blackboard on reloading but this causes another issue. There are parameters for the blackboard that get passed down from the bt_navigator to be loaded by the navigator.hpp. As a result, we can't clear all the parameters. @automech-rb The pr now works if you want to give it a try. |
Shouldn't a new path be being computed in that BT either way before the controller is called? I'd like to understand the exact reason why a new path isn't available already in that BT when FollowPath BT node is invoked. That to me seems more like the bug -- because even if the path is reset on the blackboard, that means the FollowPath is still being called on an empty path. |
@jwallace42 I tested the PR, it is working now as expected! |
Just pushed the complete fix to the pr. (got some time to look at the logs closer) The issue was the globalUpdatedGoal condition node was returning failure on the first cycle instead of success. This would cause the compute path to pose to never get hit and thus leaving the old path on the blackboard. The FollowPath node would then operate on this path. The reason resetting the path also worked is because isPathValid would fail causing computePathtoPose to trigger. This solution should be good for review :). |
Got it! Why didn't this cause problems before though when calling the same tree as the default multiple times in a row? |
So, first time through planning gets triggered by is path valid. Then, when we send a action to the behavior tree again the tree does not get reloaded so the globalUpdatedGoal works correctly and causes us to replan. There is quite a few moving peices... So let me know if my explanation is bad :). |
Ah, I understand, thanks! |
PR is approved, just needs updates for test failures |
Merged! |
Bug report
Required Info:
Steps to reproduce issue
Set default behavior tree
default_nav_to_pose_bt_xml
as navigate_w_recovery_and_replanning_only_if_path_becomes_invalid.xml in param file.Use Simple Commander API and request any goal using:
Expected behavior
Navigate to new goal(pose2) according to default behaviour tree.
Actual behavior
Nav2 navigates to cancelled goal(pose1) instead of new requested goal.
Gif is shown below as example.
Additional information
In this video I am using follow_point.xml as 2nd behavior (bug can be reproduced with any behavior), and then using nav2 API to cancel it.
Then rviz2 for another goal request.
I fell like this should have been solved by this PR. But maybe changing bt xml leads to some unforeseen circumstances.
The text was updated successfully, but these errors were encountered: