Skip to content
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

Merged
merged 23 commits into from
Apr 18, 2018

Conversation

Levi-Armstrong
Copy link
Contributor

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.

@davetcoleman
Copy link
Member

great contribution! looks like clang-format is off

@Levi-Armstrong
Copy link
Contributor Author

@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?

@davetcoleman
Copy link
Member

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?

@Levi-Armstrong
Copy link
Contributor Author

Levi-Armstrong commented Oct 23, 2017

I will update the codebase to use the new methods.

@davetcoleman
Copy link
Member

I have restarted the build

BryceStevenWilley added a commit to BryceStevenWilley/moveit that referenced this pull request Dec 8, 2017
BryceStevenWilley added a commit to BryceStevenWilley/moveit that referenced this pull request Dec 8, 2017
Copy link
Contributor

@rhaschke rhaschke left a 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:

  1. I think, the collision world functionality should be implemented as well ;-)
  2. 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,
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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)
Copy link
Contributor

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
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

Copy link
Contributor

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];
Copy link
Contributor

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.

Copy link
Contributor Author

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;
Copy link
Contributor

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.
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes they are coupled

Copy link
Contributor Author

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
Copy link
Contributor

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?

Copy link
Contributor Author

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");
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet addressed.

BryceStevenWilley added a commit to BryceStevenWilley/moveit that referenced this pull request Dec 9, 2017
BryceStevenWilley added a commit to BryceStevenWilley/moveit that referenced this pull request Dec 9, 2017
This reverts commit 58240d4, reversing
changes made to 7f90a85.
Copy link
Contributor

@rhaschke rhaschke left a 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
Copy link
Contributor

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
Copy link
Contributor

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].
Copy link
Contributor

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]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

Copy link
Contributor Author

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,
Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

@rhaschke
Copy link
Contributor

rhaschke commented Jan 5, 2018

Could you, please, also rebase your branch onto the latest kinetic-devel head?

@Levi-Armstrong
Copy link
Contributor Author

@rhaschke I believe I have addressed the requested changes.

@rhaschke rhaschke self-assigned this Jan 9, 2018
@Levi-Armstrong
Copy link
Contributor Author

Levi-Armstrong commented Feb 28, 2018

@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.

@Levi-Armstrong
Copy link
Contributor Author

@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
Copy link
Member

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

Copy link
Contributor Author

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);
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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())
Copy link
Member

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

Copy link
Contributor Author

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.

@Levi-Armstrong
Copy link
Contributor Author

@davetcoleman and @rhaschke I have made the requested changes.

Copy link
Member

@davetcoleman davetcoleman left a 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);
Copy link
Member

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)

@rhaschke
Copy link
Contributor

This is on my todo list. But there is a more urgent deadline this week. Please be patient some more days.

@davetcoleman davetcoleman mentioned this pull request Mar 29, 2018
5 tasks
@davetcoleman
Copy link
Member

@rhaschke its been 5 months, I think we should really move forward with this so other PRs like #746 don't break this one

return cdata->done;
}
}
else if (cdata->req->type != DistanceRequestType::GLOBAL)
Copy link
Contributor

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?

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor

@rhaschke rhaschke left a 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 davetcoleman mentioned this pull request Apr 11, 2018
5 tasks
@Levi-Armstrong
Copy link
Contributor Author

@davetcoleman and @rhaschke the remaining two requests should be complete.

@davetcoleman
Copy link
Member

davetcoleman commented Apr 17, 2018

There's a minor clang-format issue failing Travis @Levi-Armstrong

@rhaschke rhaschke merged commit f235eac into moveit:kinetic-devel Apr 18, 2018
@davetcoleman
Copy link
Member

Hurray!! 👏

@Levi-Armstrong want to announce this change on the Discourse channel?

@BoltzmannBrain
Copy link

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,

auto req = collision_detection::CollisionRequest();
req.distance = true;  // Compute single proximity distance value

@BoltzmannBrain
Copy link

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

@davetcoleman
Copy link
Member

davetcoleman commented May 5, 2018

Good question, please move this release discussion to #886

JafarAbdi added a commit to JafarAbdi/moveit that referenced this pull request Mar 24, 2022
… same node (moveit#662)

Co-authored-by: Dave Coleman <dave@picknik.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants