-
Notifications
You must be signed in to change notification settings - Fork 116
Fix MoveGroup::setStartStateToCurrentState() (issue 442) #671
Fix MoveGroup::setStartStateToCurrentState() (issue 442) #671
Conversation
It has surprised me as well a couple of times how badly synchronized stuff can be in MoveIt!. I somehow manage to forget after some time about all the sleep() calls I had to put into my code. I like your idea about saving the last update time. However I think this should be stored in the RobotState itself. Ideally the timestamp of when the position information entered the ros system (ie when the joint position message arrived from the robot controller). |
Works like a charm for me. Glad someone finally digged into this :) |
@simonschmeisser I would appreciate to have time stamps inside the |
@andreaskoepf Could you rebase to the latest source of |
@130s Rebasing would be no problem. My hope was that some MoveIt! expert would review the changes and give me some hints how to fix this in a more general way. E.g. I have not yet checked how planning scene changes (e.g. addition/removal of collision objects) is incorporated in the planning process and if that faces the same problem e.g. it might not be guaranteed that the most recent changes are considered during planning. I can set this on my todo list and try to find 1-2 days of time to build up a deeper understanding about the code-structure and then come up with a cleaner solution. But I will not be able to do this before June 6th... |
if (age < ros::Duration(0)) | ||
break; | ||
|
||
if (i >= 200) |
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.
instead of a less intuitive iteration count, can you have a timeout variable in seconds? i know its basically the same thing
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.
@davetcoleman yes, sure. thx for having a look. Still had no time to do more complete analysis if integration of changes in the planning-scene suffers from a similar issue (I think I observed a couple of times that collision objects were not correcty added/removed before the the planning but that is not verified).
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.
@andreaskoepf: see #686 for integrating changes to the planning scene synchronously.
I'm not super familiar with the architecture of this part of MoveIt! but overall it seems like a reasonable fix. |
Maybe we should deprecate this method? |
} | ||
|
||
ros::Duration(0.001).sleep(); | ||
} |
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 believe this whole block should only be executed if planning_scene::isEmpty(goal->request.start_state)
.
If you just want to plan with a complete state, there is no need to wait for a state update.
On the other hand, if the start_state is empty that means we should plan with the current state, so we should wait for the next update as you proposed @andreaskoepf .
The current state is that the MoveGroupAction fails to fulfill its specification for the case where `request.start_state` is empty.
In this case the action might accidentally use an outdated state instead of the current state
and I don't see a different solution than the one proposed here.
I think a cleaned version of patch should definitely be applied.
@andreaskoepf could you please address the comments by dave and me?
I think the sleep is fine for now to fix this hazardous behavior.
If later on someone steps up to replace it by a mechanism using
condition_variable et. al. that would be great, but not mandatory.
|
Hello,
I think, as I said before, that it is a problem with how callbacks are processed. To show that, in move_group/move_group.cpp line 152 you can change: In any case, changing from 1 to 0 improved the smoothness of the display so I think I'll open a PR just for that. |
@alainsanguinetti raised an important point: Having only a single spinner thread, all traffic is processed strictly in order. There are some blocking services, e.g. In case of a waiting To fix the problem in a more fundamental fashion, I suggest to modify Another issue might be bad locking behaviour of the PlanningScene in PlanningSceneMonitor. Increasing the number of spinner threads is a quick fix. However, we should carefully look for those blocking services and put them actively in threads (instead of running them in the spinner thread only). |
On Thu, Jul 14, 2016 at 07:12:37PM -0700, Robert Haschke wrote:
Yes, we should work on that front. This does not solve #422 in theory though. The problem there is basically the same one as previously noticed with the ObjectRecognitionAction: We have the same problem with the planning scene/robot state to use for the action request, and I believe we should change that somehow. |
As far as I can see, Martin Günther proposes exactly the same concept as me: Make sure that the input data is current (here: all input to PSM previous to a timestamp is processed) w.r.t. the timestamp of the call of an action. Please continue this discussion in #716. |
Please continue this discussion in #716. |
We ran into #442 in our lab too and observed some very threatening and dangerous high-speed motions of our UR5 robotic arm. On a real industrial robot this issue is extremely safety-critical since it can lead to plans that start far away from the current robot joint position even though
MoveGroup::setStartStateToCurrentState()
has been called. I am personally quite shocked that this was not fixed by somebody else before since #442 is more than two years old.Some background details about the problem as understood by us:
Calling
MoveGroup::setStartStateToCurrentState()
internally nulls theconsidered_start_state_
and sends a move-group planning request action goal with an empty start state (joint-names & positions arrays are emtpy). This makes MoveIt! directly use the RobotState which is stored inside the planning scene, e.g. when using OMPLModelBasedPlanningContext::setCompleteInitialState()
will be called fromompl_interface::PlanningContextManager::getPlanningContext()
with a state generated byrobot_state::RobotStatePtr start_state = planning_scene->getCurrentStateUpdated(req.start_state);
.. whenreq.start_state
is 'empty' this means effectively that the current state of the planning scene is is used.Unfortunately the action server callback
MoveGroupMoveAction::executeMoveCallback
does not ensure that a robot state newer than the planning request is available. This leads to plans that use an outdated start state. Actually I am not quite sure how far back in time the invalid start state can be since from the motions that we saw it must have been significantly > 0.1s... maybe somebody from the MoveIt! team with more expertise in this specific area can explain why we saw such severe movements....How we address the problem:
This PR makes sure that a new JointState message is received by CurrentStateMonitor and is indeed written to the RobotState of the PlanningScene before the planning request is being processed. In our tests this fixed the problem (which otherwise is quickly reproductible). In this PR the change is done only exemplary for the
MoveGroupMoveAction
.. other actions might be affected by an outdated current state too.Since the MoveIt! source base is new to me and the project is quite large this PR is intended as a discussion basis on how to best address the problem. E.g. the sleep-based wait loop should better be replaced by a
boost::condition_variable
or some other more direct signalling mechanism, etc.Special thanks to @alemme for debugging this issue together with me.