-
Notifications
You must be signed in to change notification settings - Fork 938
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
Add ability to request detailed distance information from fcl #662
Add ability to request detailed distance information from fcl #662
Conversation
great contribution! looks like clang-format is off |
30e6d5a
to
ab9d3d9
Compare
@davetcoleman As a result of this PR it implements a request and response structure like the collision checking methods which eliminate the need for several methods which I have marked with the deprecated macro. As a result this creates about 260 warning messages throughout MoveIt, how would you like this to be handled? |
Is there an issue with changing the collision checking calls throughout the codebase to the new API? This shouldn't break any public-facing APIs, correct? |
I will update the codebase to use the new methods. |
I have restarted the build |
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 for this great contribution. However, I have some general remarks:
- I think, the collision world functionality should be implemented as well ;-)
- You should prepare another commit, removing the now deprecated functions. I guess the use of the old CollisionData structure becomes obsolete then as well?
Having prepared this cleanup commit, will facilitate (or enable at all) the code cleanup in a later release.
{ | ||
} | ||
|
||
DistanceRequest(bool detailed, bool global, const std::set<const robot_model::LinkModel*>* active_components_only, |
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.
These are a lot of very similar constructors and it's rather hard to figure out their actual differences.
As we are using C++11, could you please change them to use constructor forwarding, e.g.:
DistanceRequest(bool detailed, bool global, const std::set<const robot_model::LinkModel*>& active_components_only, const AllowedCollisionMatrix& acm, double distance_threshold = std::numeric_limits<double>::max())
: DistanceRequest(detailed, global, &active_components_only, &acm, distance_threshold)
{}
I think the documentation should point out, that the set of active components as well as the acm should stay in memory as long as the DistanceRequest exists, because you only store pointers to them.
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, the collision world functionality should be implemented as well ;-)
I believe they have been implemented as part of the PR. Is there something missing?
You should prepare another commit, removing the now deprecated functions.
So you want me to remove the deprecated function as part of this PR, wont that break others code?
I guess the use of the old CollisionData structure becomes obsolete then as well?
This should not have any affect on the Collision checking data structure but they are similar.
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 should prepare another commit, removing the now deprecated functions.
So you want me to remove the deprecated function as part of this PR, wont that break others code?
No, the new commit should become another PR, that we can apply e.g. to the Lunar branch (or the next release branch). Just, not to forget about cleaning up...
} | ||
|
||
/// Update structure data given DistanceResultsData object | ||
void update(const DistanceResultsData& results) |
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.
Should this read void operator=(const DistanceResultsData& other)
?
@@ -163,16 +164,19 @@ class CollisionRobot | |||
const AllowedCollisionMatrix& acm) const = 0; | |||
|
|||
/** \brief The distance to self-collision given the robot is at state \e state. */ | |||
MOVEIT_DEPRECATED |
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.
Deprecation should indicate the replacement method. Same applies for the following methods.
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.
Ok
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.
Not yet addressed.
double min_distance; | ||
|
||
/// The nearest points | ||
Eigen::Vector3d nearest_points[2]; |
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 nearest_points[i]
refers to a point on link_name[i]
Rename to nearest_point
to be consistent with link_name
.
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.
Ok
std::string link_name[2]; | ||
|
||
/// The gradient | ||
Eigen::Vector3d gradient; |
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.
Specify the direction of the gradient: nearest_point[1] - nearest_point[0]
or the other way around?
Is the vector normalized?
/// The gradient | ||
Eigen::Vector3d gradient; | ||
|
||
/// Indicates if gradient was calculated. |
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.
Aren't nearest points and gradient coupled? What do I miss?
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.
Yes they are coupled
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.
Actually my statement is not correct. In the case where there is not a collision the statement is true but in the case of a collision the nearest points are the same for the fcl case so and the normal comes from contact structure. I recently ran into this and I am pushing changes along with your other requested changes.
/// Indicates if two objects were in collision | ||
bool collision; | ||
|
||
/// The results for the two objects with the minimum distance |
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 this needs more documentation. What's the difference between minimum_distance
and distance
?
What exactly is stored in the DistanceMap
?
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 DistanceMap stores distance results information for every link in active components list.
virtual void distanceRobot(const DistanceRequest& req, DistanceResult& res, | ||
const CollisionRobot& robot, const robot_state::RobotState& state) const | ||
{ | ||
logWarn("Not implemented"); |
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 this should be logError
.
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 agree, this is the way it was originally, but I am happy to update them.
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.
Not yet addressed.
This reverts commit b5d0e32.
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 for the cleanups. One major question remains: Why don't you get correct distance from fcl, but need to compute that manually?
/// Indicate if a signed distance should be calculated in a collision. | ||
bool enable_signed_distance; | ||
|
||
/// Indicate if the global minimum should only be found be found. If this is true |
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.
typo: "be found be found"
|
||
/// Indicate if the global minimum should only be found be found. If this is true | ||
/// it will only try to find the global minimum distance and not store information | ||
/// on a link by link bases. If this is set to false it will store distance information |
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.
typo: bases -> basis
|
||
/// Indicates if gradient was calculated. | ||
bool hasGradient; | ||
/// A normalized vector pointing from link_names[0] to link_names[1]. |
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.
Shouldn't that read:
A normalized vector pointing from nearest_points[0] to nearest_points[1]
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.
Yep
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.
Sorry, I believe it should be link_names[0] to link_names[1] mainly because in the event of a collision the nearest_points are the same but the normal is always calculate such that it points from link_names[0] to link_names[1].
{ | ||
} | ||
|
||
DistanceRequest(bool detailed, bool global, const std::set<const robot_model::LinkModel*>* active_components_only, |
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 a nice cleanup! +1
dist_result.normal = (dist_result.nearest_points[1] - dist_result.nearest_points[0]).normalized(); | ||
} | ||
|
||
if (d <= 0 && cdata->req->enable_signed_distance) |
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.
Why do you need this extra code block? Shouldn't fcl::distance
compute the correct distance?
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 is what I had hoped, but in fcl 0.5 if two objects are in collision it returns 0 or -1 depending on the object type. Now fcl has been making a lot of improvements over the past year and in version 0.6 which has not been release will return this information directly. This interim fix to get this information until the 0.6 release. I also have another branch which I will push this week that make the necessary change for 0.6 since they reorganized everything and switch to using Eigen instead of custom matrix types.
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.
Could you, please, also rebase your branch onto the latest kinetic-devel head? |
…anceDetailedCallback
71304c0
to
9a2ef68
Compare
@rhaschke I believe I have addressed the requested changes. |
@davetcoleman and @rhaschke, I am currently making one more change to improve the storage of distance information similar to collision contacts. In some cases (Optimization Motion Planning) it would be useful to have all objects within a distance to a given link instead of just the closest one. |
@davetcoleman and @rhaschke I have made the change let me know if you would like anything changed. |
@@ -221,12 +221,21 @@ struct CollisionRequest | |||
bool verbose; | |||
}; | |||
|
|||
enum DistanceRequestType |
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.
Namespaceify your enums, e.g.: namespace DistanceRequestType {
"This prevents enums from polluting the namespace they're inside. Individual items within the enum are referenced by: Choices::Choice1, but the typedef still allows declaration of the Choice enum without the namespace."
http://wiki.ros.org/CppStyleGuide
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 will fix it.
{ | ||
cdata->res->collision = true; | ||
std::vector<DistanceResultsData> data; | ||
data.reserve(cdata->req->max_contacts_per_body); |
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 understand why you reserve this vector then only push_back
one item. i don't see a for loop anywhere else to fill this in.
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 loop is hidden within fcl, it calls the callback function multiple times.
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.
please add this as a comment since its not clear why reserve
is otherwise needed and it would run fine without it (its a hidden optimization)
|
||
if (cdata->req->active_components_only) | ||
|
||
if (it != cdata->res->distances.end()) |
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.
all this logic you've modified could really use some explanation comments
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.
Before the latest commit it was only possible to get the global minimum distance or the minimum distance for a given link. This logic change adds the ability to get all of the contacts for a given pair of links. This is useful if a link is composed of multiple geometries and by getting all of the contacts you can accurately define a gradient for those pair of links to move them out of collision.
d4ee595
to
e1ce04a
Compare
@davetcoleman and @rhaschke I have made the requested changes. |
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.
@rhaschke let's get this great addition merged in!
{ | ||
cdata->res->collision = true; | ||
std::vector<DistanceResultsData> data; | ||
data.reserve(cdata->req->max_contacts_per_body); |
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.
please add this as a comment since its not clear why reserve
is otherwise needed and it would run fine without it (its a hidden optimization)
This is on my todo list. But there is a more urgent deadline this week. Please be patient some more days. |
return cdata->done; | ||
} | ||
} | ||
else if (cdata->req->type != DistanceRequestType::GLOBAL) |
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.
These if-checks do not make sense to me. Shouldn't they equality instead of inequality checks?
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.
Good catch, you are correct those should be equality.
dist_result.distance = -contact.penetration_depth; | ||
dist_result.nearest_points[0] = Eigen::Vector3d(contact.pos.data.vs); | ||
dist_result.nearest_points[1] = Eigen::Vector3d(contact.pos.data.vs); | ||
dist_result.normal = Eigen::Vector3d(contact.normal.data.vs); |
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.
Here you deviate from your definition that the normal vector connects nearest points. This should be documented.
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 is a deviation. If you are using convex to convex checking and in contact it would be as documented but in the case of non-convex to non-convex fcl provides the contact normal (One of the triangle normals). From what I could tell the way it choose which triangle normal to use it picked the one with the least penetration. Also for non-convex to non-convex if the objects are not in contact it is as documented. I something along what I just described sufficient to add?
In the case of moveit there is not a way to tell fcl to use convex representation so currently everything uses non-convex but it would be nice to support this in the future.
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.
Yes, such an explanation will be fine.
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 posed one remaining questions. Otherwise LGTM.
@davetcoleman and @rhaschke the remaining two requests should be complete. |
There's a minor clang-format issue failing Travis @Levi-Armstrong |
Hurray!! 👏 @Levi-Armstrong want to announce this change on the Discourse channel? |
Thanks for doing this @Levi-Armstrong! Just caught up here, from this ROS-answers thread where I asked about a collision distance per robot link. How can I now implement this feature? Currently I have something like,
|
I've been using the new functionality in one of my feature projects, working off the tip of kinetic-devel. For our workflow, however, the rest of the system uses the most recent release (i.e. 0.9.11). When can we expect a new release to be cut (that includes this merged PR)? @davetcoleman @rhaschke |
Good question, please move this release discussion to #886 |
… same node (moveit#662) Co-authored-by: Dave Coleman <dave@picknik.ai>
This PR expose the ability to request detailed distance information from FCL. I followed a similar architecture to the collision request and response. I wanted to get this submitted, but there a few remaining items: Update Collision World FCL and correct formatting.