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

Improve how links with no collision elements are handled in contact detection #334

Merged
merged 1 commit into from
Apr 28, 2021

Conversation

diegoferigo
Copy link
Collaborator

@diegoferigo diegoferigo commented Apr 27, 2021

Before this PR, if a scenario:gazebo::Link had no collisions, the method Link::contactsEnabled was returning true.

Refer to discussion below #334 (comment).

@traversaro
Copy link
Contributor

So if I call link.enableContacts(true) if link has no contacts, link::contactsEnabled() will return false if it has not collision? This is not really intuitive, can you add a line in the documentation of contactsEnabled clarifying this aspect?

@diegoferigo
Copy link
Collaborator Author

I checked again the logic in the case you described.

The desiderata is the following:

Contacts disabled

  1. If the link has collision elements, Link::enableContactDetection(true) returns true and enables contact support.
  2. If the link has no collision elements, Link::enableContactDetection(true) returns false and prints an error message.
  3. If the link has collision elements, Link::enableContactDetection(false) returns true and and does nothing.
  4. If the link has no collision elements, Link::enableContactDetection(false) returns true and and does nothing.

Contacts enabled

  1. If the link has collision elements, Link::enableContactDetection(true) returns true does nothing.
  2. If the link has no collision elements: cannot happen.
  3. If the link has collision elements, Link::enableContactDetection(false) returns true and and disables contact support.
  4. If the link has no collision elements: cannot happen.

I spotted a problem in 2, the method was returning true without error message. Fixed in 7aaa8d1.

So if I call link.enableContacts(true) if link has no contacts, link::contactsEnabled() will return false if it has not collision? This is not really intuitive, can you add a line in the documentation of contactsEnabled clarifying this aspect?

Now, this scenario remains as you described, but the exit status of link.enableContacts(true) will be false with an error message, therefore it makes sense that a lated call to link::contactsEnabled() returns false if the link has no collisions.

@traversaro
Copy link
Contributor

I think the thing that I do not understand why enabling contact on a link without collision should fail in the first place. Let's say I want to enable collision on all the links of a model, should I manually check if a link has a collision before calling enableContacts(true) ?

Copy link
Contributor

@traversaro traversaro left a comment

Choose a reason for hiding this comment

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

Some comments inline, not a big problem anyhow.

@diegoferigo
Copy link
Collaborator Author

I think the thing that I do not understand why enabling contact on a link without collision should fail in the first place.

Mmh. Let's assume a user enables contact on a link with link.enableContactDetection(true) (returning true). Everything seems ok but if they call later link.inContact(), it will return false even if they can see from the GUI the link touching (in this case, penetrating) other shapes.

Let's say I want to enable collision on all the links of a model, should I manually check if a link has a collision before calling enableContacts(true) ?

The model-wise methods are actually more convoluted. After the previous modifications, Model::enableContacts enables contacts for all links, but returns false if there is at least one link with no collision elements (and this is quite common). Furthermore, Model::contactsEnabled returns true only if all links have collision elements and contact detection is enabled for all of them.


You're right that the logic is not optimal, especially for the model-wise methods. Let's see if we can find a workaround that prevents any kind of surprise:

  • Let's assume to have a model that has some link with collisions elements, and some other without.
  • We can assume that the user knows enough about the model they are using, however I'd like to add at least a high-verbosity message (e.g. sDebug or sMessage) in case of ambiguity.
  • If a link has no collision elements, it will penetrate all other shapes (regardless if they belong to other models or self).
  • If a link has no collision elements, calling link.enableContactDetection() returns true (so that model-wise methods work fine) and produce a sDebug print saying that the link has no collision elements.
  • If a link has no collision elements, calling link.contactsEnabled always return true. This is the only weird point that is difficult to work around. Also here, a sDebug print could print that the link has no collision elements.
  • All links with collision elements will work as expected (functionality and exit statuses).
  • Calling Model::enableContacts(true) returns true if and only if contacts are successfully enabled on all links with collision elements. If the verbosity level is high, a lot of sDebug will be printed for links without collision elements.
  • Calling Model::contactsEnabled returns true if and only if contacts are enabled on all links with collision elements. If the verbosity level is high, a lot of sDebug will be printed for links without collision elements.

How does it sound?

@traversaro
Copy link
Contributor

traversaro commented Apr 28, 2021

I think the thing that I do not understand why enabling contact on a link without collision should fail in the first place.

Mmh. Let's assume a user enables contact on a link with link.enableContactDetection(true) (returning true). Everything seems ok but if they call later link.inContact(), it will return false even if they can see from the GUI the link touching (in this case, penetrating) other shapes.

In general, collision and visual shapes are different, so that can happen even if a link has a collision element, and that is the reason why I would personally prefer to keep the thing as simple as possible and just permit to enable collision on links without collisions. If a user want to check collision, it should visualize collision meshes, not the visual ones. However, if you think the complexity <--> advantaged tradeoff make sense, I think keeping things as they are is probably the safest option, not sure that even more complexity is helping.

@diegoferigo
Copy link
Collaborator Author

I think the thing that I do not understand why enabling contact on a link without collision should fail in the first place.

Mmh. Let's assume a user enables contact on a link with link.enableContactDetection(true) (returning true). Everything seems ok but if they call later link.inContact(), it will return false even if they can see from the GUI the link touching (in this case, penetrating) other shapes.

In general, collision and visual shapes are different, so that can happen even if a link has a collision element, and that is the reason why I would personally prefer to keep the thing as simple as possible and just permit to enable collision on links without collisions. If a user want to check collision, it should visualize collision meshes, not the visual ones. However, if you think the complexity <--> advantaged tradeoff make sense, I think keeping things as they are is probably the safest option, not sure that even more complexity is helping.

When writing my previous comment, I convinced myself that what wrote there, that I think complies with your comment, is the best approach. I try to implement it rolling back to a behavior that is more similar to the original implementation. At first sight, the real changes are a more verbose output for links with no collision elements.

@diegoferigo diegoferigo force-pushed the feature/optimize_contact_detection branch from 7aaa8d1 to 253c1d0 Compare April 28, 2021 15:45
@diegoferigo diegoferigo changed the title Fix Link::contactsEnabled output when the link has no collision elements Improve how links with no collision elements are handled in contact detection Apr 28, 2021
@diegoferigo
Copy link
Collaborator Author

diegoferigo commented Apr 28, 2021

PR updated with the logic described in #334 (comment). Title updated accordingly. @traversaro thanks for the feedback!

@diegoferigo diegoferigo force-pushed the feature/optimize_contact_detection branch from 253c1d0 to 19f6574 Compare April 28, 2021 15:52
@traversaro
Copy link
Contributor

This seems much simpler so it is good for me, but why link::contactsEnabled() should always return true for link without collisions? It is not easier to return the value set by enableContacts?

@diegoferigo
Copy link
Collaborator Author

diegoferigo commented Apr 28, 2021

This seems much simpler so it is good for me, but why link::contactsEnabled() should always return true for link without collisions? It is not easier to return the value set by enableContacts?

If I understood what you meant, I have to point out a very very subtle thing to consider. Implementing what you proposed would mean adding a boolean value in the Link object. This information cannot be stored in the ECM nor inferred from it.

All the ScenarIO Gazebo classes (World, Model, Link, ...) are in theory kind-of stateless. And this means that objects can be destroyed and re-created being able to restore their state just by reading the ECM.

If I managed to clarify the situation, by inspecting the logic used in Link::contactsEnabled you can see that there is no way to make its output match what the user passed to Link::enableContactDetection(true|false) by using just the ECM.

@traversaro
Copy link
Contributor

This seems much simpler so it is good for me, but why link::contactsEnabled() should always return true for link without collisions? It is not easier to return the value set by enableContacts?

If I understood what you meant, I have to point out a very very subtle thing to consider. Implementing what you proposed would mean adding a boolean value in the Link object. This information cannot be stored in the ECM nor inferred from it.

All the ScenarIO Gazebo classes (World, Model, Link, ...) are in theory kind-of stateless. And this means that objects can be destroyed and re-created being able to restore their state just by reading the ECM.

If I managed to clarify the situation, by inspecting the logic used in Link::contactsEnabled you can see that there is no way to make its output match what the user passed to Link::enableContactDetection(true|false) by using just the ECM.

I see, that make sense!

@diegoferigo diegoferigo merged commit 9b64910 into devel Apr 28, 2021
@diegoferigo diegoferigo deleted the feature/optimize_contact_detection branch April 28, 2021 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants