Skip to content

Commit 57cfe92

Browse files
committed
Fix MPR infinite loop edge case.
1 parent d88a4fd commit 57cfe92

File tree

3 files changed

+14
-7
lines changed

3 files changed

+14
-7
lines changed

genesis/engine/simulator.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ def _add_force_field(self, force_field):
183183
solver._add_force_field(force_field)
184184

185185
def build(self):
186-
187186
self.n_envs = self.scene.n_envs
188187
self._B = self.scene._B
189188
self._para_level = self.scene._para_level

genesis/engine/solvers/rigid/collider_decomp.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,7 @@ def _func_convex_convex_contact(self, i_ga, i_gb, i_b):
12981298
# Because of this, it is necessary to run it twice and take the contact information
12991299
# associated with the point of deepest penetration.
13001300
try_sdf = True
1301+
13011302
### GJK
13021303
elif ti.static(self.ccd_algorithm == CCD_ALGORITHM_CODE.GJK):
13031304
# If it was not the first detection, only detect single contact point.
@@ -1312,12 +1313,11 @@ def _func_convex_convex_contact(self, i_ga, i_gb, i_b):
13121313
# Used MuJoCo's multi-contact algorithm to find multiple contact points. Therefore,
13131314
# add the discovered contact points and stop multi-contact search.
13141315
for i_c in range(n_contacts):
1315-
if i_c >= self._n_contacts_per_pair:
1316-
# Ignore contact points if the number of contacts exceeds the limit.
1317-
break
1318-
contact_pos = self._gjk.contact_pos[i_b, i_c]
1319-
normal = self._gjk.normal[i_b, i_c]
1320-
self._func_add_contact(i_ga, i_gb, normal, contact_pos, penetration, i_b)
1316+
# Ignore contact points if the number of contacts exceeds the limit.
1317+
if i_c < self._n_contacts_per_pair:
1318+
contact_pos = self._gjk.contact_pos[i_b, i_c]
1319+
normal = self._gjk.normal[i_b, i_c]
1320+
self._func_add_contact(i_ga, i_gb, normal, contact_pos, penetration, i_b)
13211321

13221322
break
13231323
else:

genesis/engine/solvers/rigid/mpr_decomp.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ def mpr_discover_portal(self, i_ga, i_gb, i_b, normal_ws):
476476
self.mpr_swap(1, 2, i_ga, i_gb, i_b)
477477
direction = -direction
478478

479+
# FIXME: This algorithm may get stuck in an infinite loop if the actually penetration is smaller
480+
# then `CCD_EPS` and at least one of the center of each geometry is outside their convex hull.
481+
# Since this deadlock happens very rarely, a simple fix is to abord computation after a few trials.
482+
num_trials = gs.ti_int(0)
479483
while self.simplex_size[i_b] < 4:
480484
v, v1, v2 = self.compute_support(direction, i_ga, i_gb, i_b)
481485
dot = v.dot(direction)
@@ -507,6 +511,10 @@ def mpr_discover_portal(self, i_ga, i_gb, i_b, normal_ws):
507511
vb = self.simplex_support[2, i_b].v - self.simplex_support[0, i_b].v
508512
direction = va.cross(vb)
509513
direction = direction.normalized()
514+
num_trials = num_trials + 1
515+
if num_trials == 15:
516+
ret = -1
517+
break
510518
else:
511519
self.simplex_support[3, i_b].v1 = v1
512520
self.simplex_support[3, i_b].v2 = v2

0 commit comments

Comments
 (0)