-
Notifications
You must be signed in to change notification settings - Fork 947
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
fix race conditions when updating PlanningScene #350
Conversation
…ue_) Due to an upstream bug, it's not possible to start multiple AsyncSpinners from different threads. Filed PR: ros/ros_comm#867 The spinner is now only needed to serve our own callback_queue_ for scene updates, which is only required for syncSceneUpdates() that syncs all kind of scene updates, not only the robot state.
... because we might wait up to 1s for a robot state update
This reverts commit e3ef9a6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks - seems like a great addition, though I haven't tested it in runtime
ros::WallTime start = ros::WallTime::now(); | ||
ros::WallDuration timeout(wait_time); | ||
|
||
ROS_DEBUG_NAMED("planning_scene_monitor", "sync robot state to: %.3fs", fmod(t.toSec(), 10.)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"planning_scene_monitor" can just be LOGNAME for consistency
@@ -1430,6 +1437,61 @@ bool TrajectoryExecutionManager::executePart(std::size_t part_index) | |||
} | |||
} | |||
|
|||
bool TrajectoryExecutionManager::waitForRobotToStop(const TrajectoryExecutionContext &context, double wait_time) | |||
{ | |||
if (allowed_start_tolerance_ == 0) // skip validation on this magic number |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
< epsilon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is not a comparison against a small value.
Rather, we agreed that a value of zero would mean to skip validation completely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
allowed_start_tolerance_
is a double, which as I understand it you should never compare directly to 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true if the result is an outcome of some computation. However, in this case, allowed_start_tolerance_ should be set from parameter server to be exactly zero.
prev_state->enforceBounds(); | ||
|
||
// assume robot stopped when 3 consecutive checks yield the same robot state | ||
unsigned int no_motion_count = 0; // count iterations with no motion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this class (and most of moveit) uses std::size_t
rather than unsigned int
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::size_t is required for array access. Here we count up to 3 only. No need for a 64bit integer ;-)
|
||
// assume robot stopped when 3 consecutive checks yield the same robot state | ||
unsigned int no_motion_count = 0; // count iterations with no motion | ||
while (time_remaining > 0. && no_motion_count < 3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> epsilon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a reason to compare against epsilon here. time_remaining is not affected by precision issues. The resolution is defined by the clock only.
|
||
// check for motion in effected joints of execution context | ||
bool moved = false; | ||
for (const auto &trajectory : context.trajectory_parts_) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you plan on picking this to previous ROS versions? if so we should avoid auto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should exploit C++ features in new code as much as possible. If we decide for backporting, this needs to be adapted indeed. But I mentioned that in the initial comment.
"but the full state is not known."); | ||
if (!current_state_monitor_->waitForCurrentState(ros::Time::now(), wait_seconds)) | ||
{ | ||
ROS_ERROR("Failed to fetch current robot state"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_NAMED
@@ -5,4 +5,5 @@ if (CATKIN_ENABLE_TESTING) | |||
target_link_libraries(test_cleanup moveit_move_group_interface) | |||
|
|||
add_rostest(python_move_group.test) | |||
add_rostest(robot_state_update.test) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome, thanks!
rospy.init_node(NODENAME) | ||
rostest.rosrun(PKGNAME, NODENAME, RobotStateUpdateTest) | ||
|
||
# suppress cleanup segfault |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you expand this comment to explain when this can be removed? this isn't necessary in kinetic right?
robot_state::RobotState start = *planning_display_->getQueryStartState(); | ||
updateQueryStateHelper(start, ui_->start_state_selection->currentText().toStdString()); | ||
planning_display_->setQueryStartState(start); | ||
} | ||
|
||
void MotionPlanningFrame::useGoalStateButtonClicked() | ||
{ | ||
planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::useGoalStateButtonExec, this), "update goal " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment on why a background job is used for this click?
} | ||
|
||
void MotionPlanningFrame::useStartStateButtonClicked() | ||
{ | ||
planning_display_->addBackgroundJob(boost::bind(&MotionPlanningFrame::useStartStateButtonExec, this), "update start " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment on why a background job is used for this click?
format checking failed. |
Damn formatting. clang essentially reformats long code line every time again... |
@v4hn can someone in your lab test this at runtime? |
@davetcoleman what exactly do you want tested? I am in Indigo and now have this issue after recently reinstalling from source. I can try to pick this into indigo-devel and test on a real robot if it will help. |
@BrettHemes I'm not exactly sure - that updating the planning scene with collision objects still works and waiting until the robot trajectory stops executing before doing the next command? @rhaschke could better answer this question Note that a few small changes are required for indigo |
@BrettHemes It would be cool, if you could repeat the unit test ( |
@BrettHemes have you gotten a chance to test this on real hardware? |
I have run the test script locally without issue. Given the elapsed time of this PR I think we should merge this. |
…ate(1.0) in TrajectoryExecutionManager::validate, cherry pick part of moveit#350
…ate(1.0) in TrajectoryExecutionManager::validate, cherry pick part of #350
I'm not sure if this issue is completely resolved. I'm still getting "Invalid Trajectory: start point deviates from current robot state" message. When using the moveitcommander and the group.go() command without delays to move the robot. The speed of the robot is quite high, this seems to increase the frequency of the problem. I'm on kinetic and build move it from source using the I spent quite some time at debugging and I can say the following things:
I found out that if I set So this probably has something to do with the callbacks that are called on line 405 of the |
@mmoerdijk Can you please verify that the unittest passes without issues. |
Just to be sure I removed my old moveit repo and freshly cloned the latest kinetic branch. The unittest you mention passed without errors using Obviously my setup has something to do with it. I'm using moveit in combination with the I will try to make a minimal example setup but i don't have much time until the beginning of may. As for the callbacks, there is only one callback and that is the call to |
This function actually performs the scene update, i.e. applies changes to the current state within the planning scene. Looks like that not all scene updates are triggered as necessary. @mmoerdijk, could you please check whether this fix solves your issue. |
@rhaschke I tried out your fix and now and it seems to solve my problem. Thanks |
This a new attempt to resolve #232. The core new idea is to wait until the robot has stopped moving before claiming the execution of a trajectory has finished.