-
Notifications
You must be signed in to change notification settings - Fork 342
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
Fix bugs for grabbed self col checking due to asymmetricity and unordered-ness. #1438
base: production
Are you sure you want to change the base?
Conversation
- Issue - This commit tries to improve the reported issue1, issue2, and issue3 : #1436 - Previously, _listNonCollidingLinksWhenGrabbed is asymmetric : the results obtained from grabbedBody1 is not same as the results obtained from grabbedBody2. - However, many codes in CheckSelfCollision assumes it's symmetric. The assumption was broken. In addition, such breakage was amplified after #1421. - Resolution - Instead of store the target link like the previous _listNonCollidingLinksWhenGrabbed_, store the information about the link pairs. This is more accurate and the same methodologies as non-adjacent-links in self colision checking. - Separate grabbed-grabber link pair and inter-grabbed link pair. - grabbed-grabber link pair, e.g. object-robot link pair, still exists in the Grabbed class as before. - inter-grabbed link pair now exists in the KinBody class, since if it's held in Grabbed, it becomes inconsistent and asymmetric. - Following the same methodologies in #1421, inter-grabbed link pairs are stored as unordered_map, and its key is combined env body indices of two grabbed bodies.
…ating the vector.
…CollidingGrabbedGrabberLinkPairsWhenGrabbed in CheckSelfCollisionChecking
…nkCollisions==false. also share the utilities for CollisioReport update and printing.
97ce218
to
d7b510e
Compare
…fixGrabbedSelfColCheckAsym
…fixGrabbedSelfColCheckAsym
…fixGrabbedSelfColCheckAsym
…fixGrabbedSelfColCheckAsym
…fixGrabbedSelfColCheckAsym
…inbodystatesaver.cpp.
…vBodyIndex should be always smaller than the second envBodyIndex to simplify the searching.
@Puttichai can you review? Thanks |
Looks good to me. |
@snozawa I have one concern regarding the conventions of ordering of elements of From the codes, there are two cases:
Functions like I think there are no problems with the current codes. But I wonder what we can do to make sure that in the future, people don't mistakenly use How do you think? |
@@ -2438,6 +2438,9 @@ class OPENRAVE_API KinBody : public InterfaceBase | |||
typedef boost::shared_ptr<KinBodyInfo> KinBodyInfoPtr; | |||
typedef boost::shared_ptr<KinBodyInfo const> KinBodyInfoConstPtr; | |||
|
|||
/// \brief Alias for list of non-colliding link pairs, mostly used for Grabbed checking. |
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.
/// \brief Alias for list of non-colliding link pairs, mostly used for Grabbed checking. | |
/// \brief Alias for list of non-colliding link pairs, mainly used for collision checking for Grabbed. |
/// \brief Compute environment body indices pair. pack the two bodies' envBodyIndices (32bit int) into one environment body indices pair (uint64_t). | ||
/// Here, environment body indices pair is uint64_t, which higher 32bits are for body2 envBodyIndex, and which lower 32bits are for body1 envBodyIndex. | ||
/// Note that index1 < index2. |
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.
/// \brief Compute environment body indices pair. pack the two bodies' envBodyIndices (32bit int) into one environment body indices pair (uint64_t). | |
/// Here, environment body indices pair is uint64_t, which higher 32bits are for body2 envBodyIndex, and which lower 32bits are for body1 envBodyIndex. | |
/// Note that index1 < index2. | |
/// \brief Returns a uint64_t that encodes the two given environment body indices. Body1's envBodyIndex is the lower | |
/// 32 bits. Body2's envBodyIndex is the higher 32 bits. This function is used to produce a key to | |
/// _mapListNonCollidingInterGrabbedLinkPairsWhenGrabbed, which is used for managing non-colliding link pairs | |
/// information between two grabbed bodies. | |
/// | |
/// The inputs must be such that index1 < index2. Raises an exception if index1 < index2 is not satisfied. |
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.
@snozawa Are there any particular reasons why you chose to force the caller to give correct ordering of indices instead of letting the function _ComputeEnvironmentBodyIndicesPair
take care of ordering?
@@ -3798,6 +3820,7 @@ class OPENRAVE_API KinBody : public InterfaceBase | |||
mutable std::string __hashKinematicsGeometryDynamics; ///< hash serializing kinematics, dynamics and geometry properties of the KinBody | |||
int64_t _lastModifiedAtUS=0; ///< us, linux epoch, last modified time of the kinbody when it was originally loaded from the environment. | |||
int64_t _revisionId = 0; ///< the webstack revision for this loaded kinbody | |||
std::unordered_map<uint64_t, ListNonCollidingLinkPairs> _mapListNonCollidingInterGrabbedLinkPairsWhenGrabbed; ///< map of list of link pairs. This is computed when grabbed bodies are grabbed, and at taht time, two grabbed bodies are not touching each other. Since these links are not colliding at the time of grabbing, they should remain non-colliding with the grabbed body throughout. If, while grabbing, they collide with the grabbed body at some point, CheckSelfCollision should return true. It is important to note that the enable state of a link does *not* affect its membership of this list. Each pair in the list should be [Grabbed1-link, Grabbed2-link]. Note that this does not contain link pairs of [Grabbed-link, Grabber-link], c.f. Grabbed::_listNonCollidingGrabbedGrabberLinkPairsWhenGrabbed. Note that the key of this map is 'environment body indices pair', which lower 32bits are for the first KinBody's envBodyIndex, and which higher 32bits are for the second KinBody's envBodyIndex. The first envBodyIndex should be always smaller than the second envBodyIndex to simplify searching. Please also see _ComputeEnvironmentBodyIndicesPair. |
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.
std::unordered_map<uint64_t, ListNonCollidingLinkPairs> _mapListNonCollidingInterGrabbedLinkPairsWhenGrabbed; ///< map of list of link pairs. This is computed when grabbed bodies are grabbed, and at taht time, two grabbed bodies are not touching each other. Since these links are not colliding at the time of grabbing, they should remain non-colliding with the grabbed body throughout. If, while grabbing, they collide with the grabbed body at some point, CheckSelfCollision should return true. It is important to note that the enable state of a link does *not* affect its membership of this list. Each pair in the list should be [Grabbed1-link, Grabbed2-link]. Note that this does not contain link pairs of [Grabbed-link, Grabber-link], c.f. Grabbed::_listNonCollidingGrabbedGrabberLinkPairsWhenGrabbed. Note that the key of this map is 'environment body indices pair', which lower 32bits are for the first KinBody's envBodyIndex, and which higher 32bits are for the second KinBody's envBodyIndex. The first envBodyIndex should be always smaller than the second envBodyIndex to simplify searching. Please also see _ComputeEnvironmentBodyIndicesPair. | |
/// _mapListNonCollidingInterGrabbedLinkPairsWhenGrabbed maps a pair of envBodyIndices of two grabbed bodies | |
/// (encoded into one uint64_t via _ComputeEnvironmentBodyIndicesPair) to a list of initially non-colliding link | |
/// pairs between the two. The ListNonCollidingLinkPairs for body1 and body2 is computed from state when the latest | |
/// body between body1 and body2 has been grabbed. Since these links in each pair are not colliding with each other | |
/// at the time of grabbing, they should remain non-colliding throughout (i.e. until either of them is released). | |
/// Notes: | |
/// - The enable states of links do *not* affect the membership of this ListNonCollidingLinkPair. | |
/// - ListNonCollidingLinkPair, which is the values of this map, only contains link pairs of *grabbed* bodies (i.e. | |
/// not grabber's links). | |
/// - Each link pair (grabbed1Link, grabbed2Link) in ListNonCollidingLinkPair must be such that the first element | |
/// corresponds to the grabbed body with lower environment body index. | |
std::unordered_map<uint64_t, ListNonCollidingLinkPairs> _mapListNonCollidingInterGrabbedLinkPairsWhenGrabbed; |
/// \brief Push link to listNonCollidingLinkPairs if the given links are not in collision each other. This is for grabbed-grabber link pairs. | ||
static void _PushLinkIfNonColliding(std::list<std::pair<KinBody::LinkConstPtr, KinBody::LinkConstPtr> >& listNonCollidingLinkPairs, |
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.
/// \brief Push link to listNonCollidingLinkPairs if the given links are not in collision each other. This is for grabbed-grabber link pairs. | |
static void _PushLinkIfNonColliding(std::list<std::pair<KinBody::LinkConstPtr, KinBody::LinkConstPtr> >& listNonCollidingLinkPairs, | |
/// \brief Push (grabbedBodyLink, grabberLink) pairs to the given listNonCollidingLinkPairs if they are not colliding | |
/// with each other. Note that the order of pair will always be such that the first element is the grabbed | |
/// body's link and the second element is the grabber's link. | |
static void _PushLinkIfNonColliding(KinBody::ListNonCollidingLinkPairs& listNonCollidingLinkPairs, | |
CollisionCheckerBasePtr& pchecker, | |
const KinBody::LinkPtr& pGrabberLinkToCheck, const KinBody& grabbedBody) |
/// \brief Check if link pair is included in the list. Note that envBodyIndex for pLink1ToSearch's parent KinBody should be smaller than envBodyIndex for pLink2ToSearch's parent KinBody. | ||
/// \param[in] pLink1ToSearch, pLink2ToSearch : ptr of links to check. | ||
/// \param[in] listNonCollidingLinkPairs : taret list. | ||
static bool _IsLinkPairIncluded(const KinBody::Link* pLink1ToSearch, | ||
const KinBody::Link* pLink2ToSearch, | ||
const std::list<std::pair<KinBody::LinkConstPtr, KinBody::LinkConstPtr> >& listNonCollidingLinkPairs) |
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.
/// \brief Check if link pair is included in the list. Note that envBodyIndex for pLink1ToSearch's parent KinBody should be smaller than envBodyIndex for pLink2ToSearch's parent KinBody. | |
/// \param[in] pLink1ToSearch, pLink2ToSearch : ptr of links to check. | |
/// \param[in] listNonCollidingLinkPairs : taret list. | |
static bool _IsLinkPairIncluded(const KinBody::Link* pLink1ToSearch, | |
const KinBody::Link* pLink2ToSearch, | |
const std::list<std::pair<KinBody::LinkConstPtr, KinBody::LinkConstPtr> >& listNonCollidingLinkPairs) | |
/// \brief Return true if the link pair (pLink1ToSearch, pLink2ToSearch) is already in the given | |
/// listNonCollidingLinkPairs. Note that the order of the links must be such that body1.GetEnvironmentBodyIndex() | |
/// < body2.GetEnvironmentBodyIndex() where body1 is the kinbody pLink1ToSearch belongs to and body2 is the | |
/// kinbody pLink2ToSearch belongs to. | |
/// \param[in] pLink1ToSearch, pLink2ToSearch : ptr of links to check. | |
/// \param[in] listNonCollidingLinkPairs : taret list. | |
static bool _IsLinkPairIncluded(const KinBody::Link* pLink1ToSearch, | |
const KinBody::Link* pLink2ToSearch, | |
const KinBody::ListNonCollidingLinkPairs& listNonCollidingLinkPairs) |
/// \brief Push link to listNonCollidingLinkPairs if the given grabbed bodies links are not in collision each other. This is inter-grabbed link pairs. | ||
/// Note that envBodyIndex of grabbedBody1 should be smaller than envBodyIndex of grabbedBody2. | ||
static void _PushLinkPairsIfNonCollidingWithOtherGrabbedBody(std::list<std::pair<KinBody::LinkConstPtr, KinBody::LinkConstPtr> >& listNonCollidingLinkPairs, |
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.
/// \brief Push link to listNonCollidingLinkPairs if the given grabbed bodies links are not in collision each other. This is inter-grabbed link pairs. | |
/// Note that envBodyIndex of grabbedBody1 should be smaller than envBodyIndex of grabbedBody2. | |
static void _PushLinkPairsIfNonCollidingWithOtherGrabbedBody(std::list<std::pair<KinBody::LinkConstPtr, KinBody::LinkConstPtr> >& listNonCollidingLinkPairs, | |
/// \brief Push to the given listNonCollidingLinkPairs the pairs of non-colliding links between grabbedBody1 and grabbedBody2. | |
/// | |
/// This function assumes that grabbedBody1.GetEnvironmentBodyIndex() < grabbedBody2.GetEnvironmentBodyIndex(). | |
static void _PushLinkPairsIfNonCollidingWithOtherGrabbedBody(KinBody::ListNonCollidingLinkPairs& listNonCollidingLinkPairs, |
Summary
CheckSelfCollision
about grabbed bodies, which is caused by asymmetricity of internal information, and thus, amplified after Optimize IsGrabbing / ResetGrabbed #1421.Issue1, Issue2, and Issue3
in Grabbed, CheckSelfCollision, and unordered grabbed bodies issues. #1436Issue
Asymmetricity of the data
CheckSelfCollision
assumes that the internal data like_listNonCollidingLinksWhenGrabbed
is kind of symmetric. Let's say, there are two grabbed bodiesA
andB
. If we check collision by usingA->_listNonCollidingLinksWhenGrabbed
,CheckSelfCollision
assumes that it should be same asB->_listNonCollidingLinksWhenGrabbe
. But, actually, it's not symmetric. In addition, such assumption is more broken after we lose the order of grabbed bodies due tounordered_map
.Resolution 1
We need to make data symmetric. To do so, instead of storing the target link like
_listNonColidingLinksWhenGrabbed
, this PR introduces the list of link pairs.There might be several ways for the link pairs.
ComputeListNonCollidingLinks
is called, the red is considered as colliding. the blue is considered as not colliding.A
andB
are both two-linked grabbed bodies. In the following explanation, we discuss the case when we computeComputeListNonCollindngLinks
forGrabbed
forA
.policy1
is the one inproduction
branch now.B
's links are checked with the wholeA
. It cannot be symmetric, so we need link pairs as data.policy2
andpolicy3
.policy2
ignores the whole links inB
if at least one link is colliding withA
. SinceA2
andB2
are collided, any link pairs betweenA
andB
are ignored inCheckSelfCollision
.policy3
ignores the only link pair which collides. The link pair(A2, B2)
is only ignored, and other pairs are still checked inCheckSelfCollision
.policy2
andpolicy3
, this PR goes for thepolicy3
, because:policy2
is too optimistic, and it might ignore dangerous physical collision.policy3
is actually same methodologies with non-adjacent-link pairs. so, it should be fine.CheckSelfCollision
consists of complex nestedfor
loop. in addition, it caused unnecessary iteration and checking if the pairs are already checked or not. By introducing the link pairs, i hopeCheckSelfCollision
code is more readable, predictable, and reducing the overhead.Resolution 2
Resolution 1
, it's bit odd thatGrabbed
class holds such information. Actually,Grabbed
forA
andGrabbed
forB
need to hold it.grabbed
andgrabber (e.g. robot)
: still inGrabbed::_listNonCollidingGrabbedGrabberLinkPairsWhenGrabbed
.grabbed
and anothergrabbed
: now inKinBody::_mapListNonCollidingInterGrabbedLinkPairsWhenGrabbed
.unordered_map
for the data. Note that this PR computes thekey
of theunordered_map
by combining two environment body indices into oneuint64_t
.CheckSelfCollision
for
loop simpler.