@@ -28,6 +28,143 @@ namespace physics {
2828namespace bullet_featherstone {
2929
3030// ///////////////////////////////////////////////
31+ <<<<<<< HEAD
32+ =======
33+ bool hasConvexHullChildShapes (
34+ const btCollisionShape *_shape)
35+ {
36+ if (!_shape || !_shape->isCompound ())
37+ return false ;
38+
39+ const btCompoundShape *compoundShape =
40+ static_cast <const btCompoundShape *>(_shape);
41+ return (compoundShape->getNumChildShapes () > 0 &&
42+ compoundShape->getChildShape (0 )->getShapeType () ==
43+ CONVEX_HULL_SHAPE_PROXYTYPE );
44+ }
45+
46+ // ///////////////////////////////////////////////
47+ const btCollisionShape *findCollisionShape (
48+ const btCompoundShape *_compoundShape, int _childIndex)
49+ {
50+ // _childIndex should give us the index of the child shape within
51+ // _compoundShape which represents the collision.
52+ // One exception is when the collision is a convex decomposed mesh.
53+ // In this case, the child shape is another btCompoundShape (nested), and
54+ // _childIndex is the index of one of the decomposed convex hulls
55+ // in the nested compound shape. The nested compound shape is the collision.
56+ int childCount = _compoundShape->getNumChildShapes ();
57+ if (childCount > 0 )
58+ {
59+ if (_childIndex >= 0 && _childIndex < childCount)
60+ {
61+ // todo(iche033) We do not have sufficient info to determine which
62+ // child shape is the collision if the link has convex decomposed mesh
63+ // collisions alongside of other collisions. See following example:
64+ // parentLink -> boxShape0
65+ // -> boxShape1
66+ // -> compoundShape -> convexShape0
67+ // -> convexShape1
68+ // A _childIndex of 1 is ambiguous as it could refer to either
69+ // boxShape1 or convexShape1
70+ // return nullptr in this case to indicate ambiguity
71+ if (childCount > 1 )
72+ {
73+ for (int i = 0 ; i < childCount; ++i)
74+ {
75+ const btCollisionShape *shape = _compoundShape->getChildShape (i);
76+ if (hasConvexHullChildShapes (shape))
77+ {
78+ static bool informed{false };
79+ if (!informed)
80+ {
81+ gzwarn << " Unable to determine the collision id for a link with "
82+ << " both simple primitive and convex shape collisions."
83+ << std::endl;
84+ informed = true ;
85+ }
86+ return nullptr ;
87+ }
88+ }
89+ }
90+
91+ const btCollisionShape *shape =
92+ _compoundShape->getChildShape (_childIndex);
93+ return shape;
94+ }
95+ else
96+ {
97+ return _compoundShape->getChildShape (0 );
98+ }
99+ }
100+ return nullptr ;
101+ }
102+
103+ // ///////////////////////////////////////////////
104+ void enforceFixedConstraint (
105+ btMultiBodyFixedConstraint *_fixedConstraint)
106+ {
107+ // Update fixed constraint's child link pose to maintain a fixed transform
108+ // from the parent link.
109+ GzMultiBody *parent =
110+ dynamic_cast <GzMultiBody*> (_fixedConstraint->getMultiBodyA ());
111+ if (parent == nullptr )
112+ {
113+ std::cerr << " Internal error: Failed to cast parent btMultiBody to "
114+ " GzMultiBody!" << std::endl;
115+ return ;
116+ }
117+
118+ GzMultiBody *child =
119+ dynamic_cast <GzMultiBody*> (_fixedConstraint->getMultiBodyB ());
120+ if (child == nullptr )
121+ {
122+ std::cerr << " Internal error: Failed to cast child btMultiBody to "
123+ " GzMultiBody!" << std::endl;
124+ return ;
125+ }
126+
127+ btTransform parentToChildTf;
128+ parentToChildTf.setOrigin (_fixedConstraint->getPivotInA ());
129+ parentToChildTf.setBasis (_fixedConstraint->getFrameInA ());
130+
131+ int parentLinkIndex = _fixedConstraint->getLinkA ();
132+ int childLinkIndex = _fixedConstraint->getLinkB ();
133+
134+ btTransform parentLinkTf;
135+ btTransform childLinkTf;
136+ if (parentLinkIndex == -1 )
137+ {
138+ parentLinkTf = parent->getBaseWorldTransform ();
139+ }
140+ else
141+ {
142+ btMultiBodyLinkCollider *collider =
143+ parent->getLinkCollider (parentLinkIndex);
144+ parentLinkTf = collider->getWorldTransform ();
145+ }
146+ if (childLinkIndex == -1 )
147+ {
148+ childLinkTf = child->getBaseWorldTransform ();
149+ }
150+ else
151+ {
152+ btMultiBodyLinkCollider *collider =
153+ child->getLinkCollider (childLinkIndex);
154+ childLinkTf = collider->getWorldTransform ();
155+ }
156+
157+ btTransform expectedChildLinkTf = parentLinkTf * parentToChildTf;
158+ btTransform childBaseTf = child->getBaseWorldTransform ();
159+ btTransform childBaseToLink =
160+ childBaseTf.inverse () * childLinkTf;
161+ btTransform newChildBaseTf =
162+ expectedChildLinkTf * childBaseToLink.inverse ();
163+ child->SetBaseWorldTransform (newChildBaseTf);
164+ }
165+
166+ // ///////////////////////////////////////////////
167+ >>>>>>> 00e0fdd (bullet-featherstone: Fix get contacts (#838 ))
31168void SimulationFeatures::WorldForwardStep(
32169 const Identity &_worldID,
33170 ForwardStep::Output & _h,
@@ -112,34 +249,47 @@ SimulationFeatures::GetContactsFromLastStep(const Identity &_worldID) const
112249 {
113250 btPersistentManifold* contactManifold =
114251 world->world ->getDispatcher ()->getManifoldByIndexInternal (i);
115- const btMultiBodyLinkCollider* obA =
252+ const btMultiBodyLinkCollider* ob0 =
116253 dynamic_cast <const btMultiBodyLinkCollider*>(contactManifold->getBody0 ());
117- const btMultiBodyLinkCollider* obB =
254+ const btMultiBodyLinkCollider* ob1 =
118255 dynamic_cast <const btMultiBodyLinkCollider*>(contactManifold->getBody1 ());
119- std::size_t collision1ID = std::numeric_limits<std::size_t >::max ();
120- std::size_t collision2ID = std::numeric_limits<std::size_t >::max ();
121256
122- for (const auto & link : this ->links )
123- {
124- if (obA == link.second ->collider .get ())
125- {
126- for (const auto &v : link.second ->collisionNameToEntityId )
127- {
128- collision1ID = v.second ;
129- }
130- }
131- if (obB == link.second ->collider .get ())
132- {
133- for (const auto &v : link.second ->collisionNameToEntityId )
134- {
135- collision2ID = v.second ;
136- }
137- }
138- }
257+ if (!ob0 || !ob1)
258+ continue ;
259+
260+ const btCollisionShape *linkShape0 = ob0->getCollisionShape ();
261+ const btCollisionShape *linkShape1 = ob1->getCollisionShape ();
262+
263+ if (!linkShape0 || !linkShape1 ||
264+ !linkShape0->isCompound () || !linkShape1->isCompound ())
265+ continue ;
266+
267+ const btCompoundShape *compoundShape0 =
268+ static_cast <const btCompoundShape *>(linkShape0);
269+ const btCompoundShape *compoundShape1 =
270+ static_cast <const btCompoundShape *>(linkShape1);
271+
139272 int numContacts = contactManifold->getNumContacts ();
140273 for (int j = 0 ; j < numContacts; j++)
141274 {
142275 btManifoldPoint& pt = contactManifold->getContactPoint (j);
276+
277+ const btCollisionShape *colShape0 = findCollisionShape (
278+ compoundShape0, pt.m_index0 );
279+ const btCollisionShape *colShape1 = findCollisionShape (
280+ compoundShape1, pt.m_index1 );
281+
282+ std::size_t collision0ID = std::numeric_limits<std::size_t >::max ();
283+ std::size_t collision1ID = std::numeric_limits<std::size_t >::max ();
284+ if (colShape0)
285+ collision0ID = colShape0->getUserIndex ();
286+ else if (compoundShape0->getNumChildShapes () > 0 )
287+ collision0ID = compoundShape0->getChildShape (0 )->getUserIndex ();
288+ if (colShape1)
289+ collision1ID = colShape1->getUserIndex ();
290+ else if (compoundShape1->getNumChildShapes () > 0 )
291+ collision1ID = compoundShape1->getChildShape (0 )->getUserIndex ();
292+
143293 CompositeData extraData;
144294
145295 // Add normal, depth and wrench to extraData.
@@ -153,8 +303,8 @@ SimulationFeatures::GetContactsFromLastStep(const Identity &_worldID) const
153303 extraContactData.depth = pt.getDistance ();
154304
155305 outContacts.push_back (SimulationFeatures::ContactInternal {
306+ this ->GenerateIdentity (collision0ID, this ->collisions .at (collision0ID)),
156307 this ->GenerateIdentity (collision1ID, this ->collisions .at (collision1ID)),
157- this ->GenerateIdentity (collision2ID, this ->collisions .at (collision2ID)),
158308 convert (pt.getPositionWorldOnA ()), extraData});
159309 }
160310 }
0 commit comments