-
Notifications
You must be signed in to change notification settings - Fork 158
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
End-state deviates from goal state #532
End-state deviates from goal state #532
Conversation
If not within the threshold, mark solution as a failure and set comment.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #532 +/- ##
==========================================
+ Coverage 58.99% 59.09% +0.11%
==========================================
Files 90 90
Lines 8497 8504 +7
==========================================
+ Hits 5012 5025 +13
+ Misses 3485 3479 -6 ☔ View full report in Codecov by Sentry. |
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.
Reading your solution to #531, I think that this is not related to incompatible start and end states: What you check is that the end-state actually reaches the goal state.
I think, your issue is a duplicate of #485, which was caused by a bug in MoveIt2.
Are you using MoveIt1 or MoveIt2? If you were using MoveIt1, it would be great if you could setup a failing unittest for your issue. Then, I can search for the underlying problem instead of applying cosmetic corrections 😉
core/src/stages/connect.cpp
Outdated
if (jm->getType() == robot_state::JointModel::REVOLUTE) | ||
min_distance = angles::shortest_angular_distance(positions_last_waypoint[i], positions_goal[i]); | ||
else | ||
min_distance = positions_last_waypoint[i], positions_goal[i]; |
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 guess you want to compute the joint difference:
min_distance = positions_last_waypoint[i], positions_goal[i]; | |
min_distance = std::abs(positions_last_waypoint[i] - positions_goal[i]); |
core/src/stages/connect.cpp
Outdated
ROS_DEBUG_STREAM_NAMED("Connect", | ||
"angular deviation: " << min_distance << " between trajectory last waypoint and goal."); | ||
|
||
if (std::abs(min_distance) > 1e-4) { |
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.
The magic number 1e-4 should be configurable, e.g. via a stage property.
Yes ! Changed the title.
Just found the culprit. Even though LIN Pilz receives a JointConstraint, it will compute the FK to compute the goal pose. Currently the LIN planner only plans from a cartesian goal. Will create an issue in MoveIt. Not tested but I'm pretty sure I could recreate the problem by changing the demo pick and place and replacing this line with the LIN Pilz planner. Or would you prefer a unit-test in MoveIt ? For testing this PR, is there a way to fake a planner response that would offset the goal state outside the threshold limits ? |
To replicate this error, just use this mtc fork captain-yoshi/moveit_task_constructor/tree/trigger-error-532 and start the pick & place demo. This includes the validation in this PR. You should see that it's failing and that for some solution the end-state does not match the goal-state. |
After reading more on the Pilz LIN planner, it generates linear Cartesian trajectory between goal and start poses. The solution would be to feed the joint constraint goal instead of redoing an IK. EDIT Well you can use it, but it will only work for IK's who succeeded (in the ComputeIK stage) on their first attempt because the seed is wrt. the start state ? |
Yes, the Pilz planner performs linear interpolation in Cartesian space. If you want to perform linear interpolation in joint space, there is the
So you claim, that the Pilz planner generates incomplete trajectories, which are considered to be valid by MTC?
Why would you like to do so? If a planner behaves like that, this planner is buggy and should get fixed. |
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 see the need for this PR. Some planners, like Pilz or MTC's Cartesian interpolation, may not reach the exact goal state, although the Cartesian poses match.
See the comment below to address before merging.
core/src/stages/connect.cpp
Outdated
double min_distance; | ||
for (std::size_t i = 0; i < num; ++i) { | ||
if (jm->getType() == robot_state::JointModel::REVOLUTE) | ||
min_distance = angles::shortest_angular_distance(positions_last_waypoint[i], positions_goal[i]); |
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.
You must not use angles::shortest_angular_distance
here, as we need to reach the exact goal state - subsequent stages rely on this fact!
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.
Hum... I'm pretty sure it removed valid solutions... Will investigate more and report back soon.
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.
We cannot accept equality up to multiples to 360°. The goal state needs to be reached exactly. Otherwise subsequent stages will run into trouble because they relied on a different start state.
Exactly ! This is necessary to be able to use such planners, which does not respect the goal joint constraint. Furthermore, it can catch errors in other planners, e.g. #485. Finally, it guards against the |
The discontinuity doesn't happen between the end-state and start-state of to consecutive trajectories but between the next-to-last and last state of the Connect trajectories. Thus, MoveIt's task execution cannot guard against this discontinuity. |
I pushed a simplifying commit, using |
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 also added a unit test now. For me, this is ready to merge. @captain-yoshi, any objections to my changes?
All good on my end :) Great optimization by the way 🥇 |
This fixes #531 but may not fix the actual problem, e.g. it may be the planner that silently fails or something else in the framework.
I just validate the last trajectory waypoint with the goal in the
ConnectStage
. If there is a deviation, the solution is marked as failed and a comment is set. I'm pretty sure you can optimize some of the code ;)On a side note, I had to make sure that the joints where compared correctly (-pi = pi). Currently, when comparing joint position in the Connect::compatible method, this is not checked. You might reject some valid solutions, e.g the IK solver gives some joint positions in a negative defined angle versus the RobotState who may have a positive defined angle.
Solution 1 et 3 are valid but not 2 and 4.