Skip to content

Commit ab9ee2d

Browse files
authored
[FEATURE] Add option to force batching of fixed vertices. (#1998)
* Add option to force batching of fixed vertices. * Add collision-free franka benchmark. * Report large performance improvement as success.
1 parent fa4bc7a commit ab9ee2d

File tree

12 files changed

+150
-47
lines changed

12 files changed

+150
-47
lines changed

.github/workflows/alarm.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,6 @@ jobs:
396396
fi
397397
398398
# Export status
399-
echo "CONCLUSION=$([ "$EXIT_CODE" = "0" ] && echo 'success' || echo 'failure')" >> "$GITHUB_ENV"
400399
echo "HAS_REGRESSIONS=$([ "$EXIT_CODE" = "$EXIT_CODE_REGRESSION" ] && echo 1 || echo 0)" >> "$GITHUB_ENV"
401400
echo "HAS_ALERTS=$([ "$EXIT_CODE" = "$EXIT_CODE_ALERT" ] && echo 1 || echo 0)" >> "$GITHUB_ENV"
402401
@@ -416,7 +415,6 @@ jobs:
416415
env:
417416
CHECK_NAME: Benchmark Comparison
418417
CHECK_OUTPUT: ${{ env.CHECK_OUTPUT }}
419-
CONCLUSION: ${{ env.CONCLUSION }}
420418
HAS_REGRESSIONS: ${{ env.HAS_REGRESSIONS }}
421419
HAS_ALERTS: ${{ env.HAS_ALERTS }}
422420
ARTIFACT_URL: ${{ steps.upload.outputs.artifact-url }}
@@ -429,8 +427,10 @@ jobs:
429427
}
430428
431429
let summary;
430+
let conclusion = 'success';
432431
if ((process.env.HAS_REGRESSIONS || '0') === '1') {
433432
summary = '🔴 Regressions detected. See tables below.';
433+
conclusion = 'failure';
434434
} else if ((process.env.HAS_ALERTS || '0') === '1') {
435435
summary = '⚠️ Large deviation detected. See tables below.';
436436
} else {
@@ -443,7 +443,7 @@ jobs:
443443
head_sha: context.payload.workflow_run.head_sha,
444444
name: process.env.CHECK_NAME,
445445
status: 'completed',
446-
conclusion: process.env.CONCLUSION,
446+
conclusion: conclusion,
447447
output: {
448448
title: process.env.CHECK_NAME,
449449
summary,

examples/manipulation/grasp_env.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ def __init__(
7575
size=env_cfg["box_size"],
7676
fixed=env_cfg["box_fixed"],
7777
collision=env_cfg["box_collision"],
78+
batch_fixed_verts=True,
7879
),
7980
# material=gs.materials.Rigid(gravity_compensation=1),
8081
surface=gs.surfaces.Rough(

examples/sensors/lidar_teleop.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def main():
8787
max_FPS=60,
8888
),
8989
profiling_options=gs.options.ProfilingOptions(
90-
show_FPS=True,
90+
show_FPS=False,
9191
),
9292
show_viewer=True,
9393
)

genesis/engine/entities/rigid_entity/rigid_entity.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ def __init__(
8686

8787
self._free_verts_idx_local = torch.tensor([], dtype=gs.tc_int, device=gs.device)
8888
self._fixed_verts_idx_local = torch.tensor([], dtype=gs.tc_int, device=gs.device)
89-
9089
self._base_links_idx = torch.tensor([self.base_link_idx], dtype=gs.tc_int, device=gs.device)
9190

91+
self._batch_fixed_verts = morph.batch_fixed_verts
92+
9293
self._visualize_contact: bool = visualize_contact
9394

9495
self._is_built: bool = False
@@ -565,7 +566,7 @@ def _build(self):
565566
free_verts_idx_local, fixed_verts_idx_local = [], []
566567
for link in self.links:
567568
verts_idx = torch.arange(verts_start, verts_start + link.n_verts, dtype=gs.tc_int, device=gs.device)
568-
if link.is_fixed:
569+
if link.is_fixed and not self._batch_fixed_verts:
569570
fixed_verts_idx_local.append(verts_idx)
570571
else:
571572
free_verts_idx_local.append(verts_idx)
@@ -643,7 +644,7 @@ def _add_by_info(self, l_info, j_infos, g_infos, morph, surface):
643644
joint_start = self.n_joints + self._joint_start
644645
free_verts_start, fixed_verts_start = self._free_verts_state_start, self._fixed_verts_state_start
645646
for link in self.links:
646-
if link.is_fixed:
647+
if link.is_fixed and not self._batch_fixed_verts:
647648
fixed_verts_start += link.n_verts
648649
else:
649650
free_verts_start += link.n_verts

genesis/engine/entities/rigid_entity/rigid_geom.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ def get_verts(self):
384384
"""
385385
self._solver.update_verts_for_geoms(self._idx)
386386

387-
if self.is_fixed:
387+
if self.is_fixed and not self._entity._batch_fixed_verts:
388388
tensor = torch.empty((self.n_verts, 3), dtype=gs.tc_float, device=gs.device)
389389
_kernel_get_fixed_verts(tensor, self._verts_state_start, self.n_verts, self._solver.fixed_verts_state)
390390
else:

genesis/engine/entities/rigid_entity/rigid_link.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ def __init__(
7979
self._root_idx: int = root_idx
8080
self._is_fixed: bool = is_fixed
8181

82+
if is_fixed and not entity._batch_fixed_verts:
83+
verts_state_start = fixed_verts_state_start
84+
else:
85+
verts_state_start = free_verts_state_start
86+
8287
self._joint_start: int = joint_start
8388
self._n_joints: int = n_joints
8489

@@ -87,7 +92,7 @@ def __init__(
8792
self._vert_start: int = vert_start
8893
self._face_start: int = face_start
8994
self._edge_start: int = edge_start
90-
self._verts_state_start: int = fixed_verts_state_start if is_fixed else free_verts_state_start
95+
self._verts_state_start: int = verts_state_start
9196
self._vgeom_start: int = vgeom_start
9297
self._vvert_start: int = vvert_start
9398
self._vface_start: int = vface_start
@@ -302,7 +307,7 @@ def get_verts(self):
302307
"""
303308
self._solver.update_verts_for_geoms(range(self.geom_start, self.geom_end))
304309

305-
if self.is_fixed:
310+
if self.is_fixed and not self._entity._batch_fixed_verts:
306311
tensor = torch.empty((self.n_verts, 3), dtype=gs.tc_float, device=gs.device)
307312
_kernel_get_fixed_verts(tensor, self._verts_state_start, self.n_verts, self._solver.fixed_verts_state)
308313
else:

genesis/engine/solvers/rigid/rigid_solver_decomp.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,10 @@ def _init_vert_fields(self):
598598
[np.arange(geom.verts_state_start, geom.verts_state_start + geom.n_verts) for geom in geoms],
599599
dtype=gs.np_int,
600600
),
601-
is_fixed=np.concatenate([np.full(geom.n_verts, geom.is_fixed) for geom in geoms], dtype=gs.np_bool),
601+
is_fixed=np.concatenate(
602+
[np.full(geom.n_verts, geom.is_fixed and not geom.entity._batch_fixed_verts) for geom in geoms],
603+
dtype=gs.np_bool,
604+
),
602605
# taichi variables
603606
verts_info=self.verts_info,
604607
faces_info=self.faces_info,
@@ -1484,13 +1487,18 @@ def set_base_links_pos(
14841487
if not unsafe and not torch.isin(links_idx, self._base_links_idx).all():
14851488
gs.raise_exception("`links_idx` contains at least one link that is not a base link.")
14861489

1487-
# Raise exception for fixed links with at least one geom, except if setting same location for all envs at once
1490+
# Raise exception for fixed links with at least one geom and non-batched fixed vertices, except if setting same
1491+
# location for all envs at once
14881492
set_all_envs = torch.equal(torch.sort(envs_idx).values, self._scene._envs_idx)
1489-
has_fixed_geoms = any(
1490-
link.is_fixed and (link.geoms or link.vgeoms) for link in (self.links[i_l] for i_l in links_idx)
1493+
has_fixed_verts = any(
1494+
link.is_fixed and (link.geoms or link.vgeoms) and not link.entity._batch_fixed_verts
1495+
for link in (self.links[i_l] for i_l in links_idx)
14911496
)
1492-
if has_fixed_geoms and not (set_all_envs and (torch.diff(pos, dim=0).abs() < gs.EPS).all()):
1493-
gs.raise_exception("Impossible to set env-specific pos for fixed links with at least one geometry.")
1497+
if has_fixed_verts and not (set_all_envs and (torch.diff(pos, dim=0).abs() < gs.EPS).all()):
1498+
gs.raise_exception(
1499+
"Specifying env-specific pos for fixed links with at least one geometry requires setting morph "
1500+
"option 'batch_fixed_verts=True'."
1501+
)
14941502

14951503
kernel_set_links_pos(
14961504
relative,
@@ -1537,10 +1545,11 @@ def set_base_links_quat(
15371545
gs.raise_exception("`links_idx` contains at least one link that is not a base link.")
15381546

15391547
set_all_envs = torch.equal(torch.sort(envs_idx).values, self._scene._envs_idx)
1540-
has_fixed_geoms = any(
1541-
link.is_fixed and (link.geoms or link.vgeoms) for link in (self.links[i_l] for i_l in links_idx)
1548+
has_fixed_verts = any(
1549+
link.is_fixed and (link.geoms or link.vgeoms) and not link.entity._batch_fixed_verts
1550+
for link in (self.links[i_l] for i_l in links_idx)
15421551
)
1543-
if has_fixed_geoms and not (set_all_envs and (torch.diff(quat, dim=0).abs() < gs.EPS).all()):
1552+
if has_fixed_verts and not (set_all_envs and (torch.diff(quat, dim=0).abs() < gs.EPS).all()):
15441553
gs.raise_exception("Impossible to set env-specific quat for fixed links with at least one geometry.")
15451554

15461555
kernel_set_links_quat(
@@ -2435,13 +2444,13 @@ def n_verts(self):
24352444
def n_free_verts(self):
24362445
if self.is_built:
24372446
return self._n_free_verts
2438-
return sum(link.n_verts if not link.is_fixed else 0 for link in self.links)
2447+
return sum(link.n_verts if not link.is_fixed or link.entity._batch_fixed_verts else 0 for link in self.links)
24392448

24402449
@property
24412450
def n_fixed_verts(self):
24422451
if self.is_built:
24432452
return self._n_fixed_verts
2444-
return sum(link.n_verts if link.is_fixed else 0 for link in self.links)
2453+
return sum(link.n_verts if link.is_fixed and not link.entity._batch_fixed_verts else 0 for link in self.links)
24452454

24462455
@property
24472456
def n_vverts(self):
@@ -4953,7 +4962,6 @@ def func_update_geoms(
49534962
links_state.pos[geoms_info.link_idx[i_g], i_b],
49544963
links_state.quat[geoms_info.link_idx[i_g], i_b],
49554964
)
4956-
49574965
geoms_state.verts_updated[i_g, i_b] = False
49584966
else:
49594967
for i_g in range(n_geoms):
@@ -4967,7 +4975,6 @@ def func_update_geoms(
49674975
links_state.pos[geoms_info.link_idx[i_g], i_b],
49684976
links_state.quat[geoms_info.link_idx[i_g], i_b],
49694977
)
4970-
49714978
geoms_state.verts_updated[i_g, i_b] = False
49724979

49734980

@@ -4998,23 +5005,22 @@ def func_update_verts_for_geom(
49985005
fixed_verts_state: array_class.VertsState,
49995006
):
50005007
if not geoms_state.verts_updated[i_g, i_b]:
5001-
if geoms_info.is_fixed[i_g]:
5002-
for i_v in range(geoms_info.vert_start[i_g], geoms_info.vert_end[i_g]):
5008+
i_g_start = geoms_info.vert_start[i_g]
5009+
if verts_info.is_fixed[i_g_start]:
5010+
for i_v in range(i_g_start, geoms_info.vert_end[i_g]):
50035011
verts_state_idx = verts_info.verts_state_idx[i_v]
50045012
fixed_verts_state.pos[verts_state_idx] = gu.ti_transform_by_trans_quat(
50055013
verts_info.init_pos[i_v], geoms_state.pos[i_g, i_b], geoms_state.quat[i_g, i_b]
50065014
)
5007-
50085015
_B = geoms_state.verts_updated.shape[1]
50095016
for j_b in range(_B):
50105017
geoms_state.verts_updated[i_g, j_b] = True
50115018
else:
5012-
for i_v in range(geoms_info.vert_start[i_g], geoms_info.vert_end[i_g]):
5019+
for i_v in range(i_g_start, geoms_info.vert_end[i_g]):
50135020
verts_state_idx = verts_info.verts_state_idx[i_v]
50145021
free_verts_state.pos[verts_state_idx, i_b] = gu.ti_transform_by_trans_quat(
50155022
verts_info.init_pos[i_v], geoms_state.pos[i_g, i_b], geoms_state.quat[i_g, i_b]
50165023
)
5017-
50185024
geoms_state.verts_updated[i_g, i_b] = True
50195025

50205026

genesis/options/morphs.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ class Primitive(Morph):
166166
Defaults to False. **This is only used for RigidEntity.**
167167
fixed : bool, optional
168168
Whether the baselink of the entity should be fixed. Defaults to False. **This is only used for RigidEntity.**
169+
batch_fixed_verts : bool, optional
170+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
171+
significantly increasing memory usage. Default to true. **This is only used for RigidEntity.**
169172
contype : int, optional
170173
The 32-bit integer bitmasks used for contact filtering of contact pairs. When the contype of one geom and the
171174
conaffinity of the other geom share a common bit set to 1, two geoms can collide. Defaults to 0xFFFF.
@@ -176,6 +179,7 @@ class Primitive(Morph):
176179

177180
# Rigid specific
178181
fixed: bool = False
182+
batch_fixed_verts: bool = True
179183
contype: int = 0xFFFF
180184
conaffinity: int = 0xFFFF
181185

@@ -215,6 +219,9 @@ class Box(Primitive, TetGenMixin):
215219
**This is only used for RigidEntity.**
216220
fixed : bool, optional
217221
Whether the baselink of the entity should be fixed. Defaults to False. **This is only used for RigidEntity.**
222+
batch_fixed_verts : bool, optional
223+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
224+
significantly increasing memory usage. Default to true. **This is only used for RigidEntity.**
218225
contype : int, optional
219226
The 32-bit integer bitmasks used for contact filtering of contact pairs. When the contype of one geom and the
220227
conaffinity of the other geom share a common bit set to 1, two geoms can collide. Defaults to 0xFFFF.
@@ -297,6 +304,9 @@ class Cylinder(Primitive, TetGenMixin):
297304
**This is only used for RigidEntity.**
298305
fixed : bool, optional
299306
Whether the baselink of the entity should be fixed. Defaults to False. **This is only used for RigidEntity.**
307+
batch_fixed_verts : bool, optional
308+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
309+
significantly increasing memory usage. Default to true. **This is only used for RigidEntity.**
300310
contype : int, optional
301311
The 32-bit integer bitmasks used for contact filtering of contact pairs. When the contype of one geom and the
302312
conaffinity of the other geom share a common bit set to 1, two geoms can collide. Defaults to 0xFFFF.
@@ -359,6 +369,9 @@ class Sphere(Primitive, TetGenMixin):
359369
**This is only used for RigidEntity.**
360370
fixed : bool, optional
361371
Whether the baselink of the entity should be fixed. Defaults to False. **This is only used for RigidEntity.**
372+
batch_fixed_verts : bool, optional
373+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
374+
significantly increasing memory usage. Default to true. **This is only used for RigidEntity.**
362375
contype : int, optional
363376
The 32-bit integer bitmasks used for contact filtering of contact pairs. When the contype of one geom and the
364377
conaffinity of the other geom share a common bit set to 1, two geoms can collide. Defaults to 0xFFFF.
@@ -422,6 +435,9 @@ class Plane(Primitive):
422435
`visualization` and `collision` cannot both be False. **This is only used for RigidEntity.**
423436
fixed : bool, optional
424437
Whether the baselink of the entity should be fixed. Defaults to False. **This is only used for RigidEntity.**
438+
batch_fixed_verts : bool, optional
439+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
440+
significantly increasing memory usage. Default to false. **This is only used for RigidEntity.**
425441
contype : int, optional
426442
The 32-bit integer bitmasks used for contact filtering of contact pairs. When the contype of one geom and the
427443
conaffinity of the other geom share a common bit set to 1, two geoms can collide. Defaults to 0xFFFF.
@@ -435,6 +451,7 @@ class Plane(Primitive):
435451
"""
436452

437453
fixed: bool = True
454+
batch_fixed_verts: bool = False
438455
normal: tuple = (0, 0, 1)
439456
plane_size: tuple = (1e3, 1e3)
440457
tile_size: tuple = (1, 1)
@@ -510,6 +527,9 @@ class FileMorph(Morph):
510527
collision : bool, optional
511528
Whether the entity needs to be considered for collision checking. Defaults to True.
512529
`visualization` and `collision` cannot both be False. **This is only used for RigidEntity.**
530+
batch_fixed_verts : bool, optional
531+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
532+
significantly increasing memory usage. Default to true. **This is only used for RigidEntity.**
513533
requires_jac_and_IK : bool, optional
514534
Whether this morph, if created as `RigidEntity`, requires jacobian and inverse kinematics. Defaults to False.
515535
**This is only used for RigidEntity.**
@@ -526,6 +546,7 @@ class FileMorph(Morph):
526546
decompose_robot_error_threshold: float = float("inf")
527547
coacd_options: Optional[CoacdOptions] = None
528548
recompute_inertia: bool = False
549+
batch_fixed_verts: bool = False
529550

530551
def __init__(self, **data):
531552
super().__init__(**data)
@@ -646,6 +667,9 @@ class Mesh(FileMorph, TetGenMixin):
646667
Whether to use zup to load glb files. Defaults to False.
647668
fixed : bool, optional
648669
Whether the baselink of the entity should be fixed. Defaults to False. **This is only used for RigidEntity.**
670+
batch_fixed_verts : bool, optional
671+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
672+
significantly increasing memory usage. Default to false. **This is only used for RigidEntity.**
649673
contype : int, optional
650674
The 32-bit integer bitmasks used for contact filtering of contact pairs. When the contype of one geom and the
651675
conaffinity of the other geom share a common bit set to 1, two geoms can collide. Defaults to 0xFFFF.
@@ -779,6 +803,9 @@ class MJCF(FileMorph):
779803
`visualization` and `collision` cannot both be False.
780804
requires_jac_and_IK : bool, optional
781805
Whether this morph, if created as `RigidEntity`, requires jacobian and inverse kinematics. Defaults to True.
806+
batch_fixed_verts : bool, optional
807+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
808+
significantly increasing memory usage. Default to true. **This is only used for RigidEntity.**
782809
default_armature : float, optional
783810
Default rotor inertia of the actuators. In practice it is applied to all joints regardless of whether they are
784811
actuated. None to disable. Default to 0.1.
@@ -882,6 +909,9 @@ class URDF(FileMorph):
882909
Whether this morph, if created as `RigidEntity`, requires jacobian and inverse kinematics. Defaults to True.
883910
fixed : bool, optional
884911
Whether the baselink of the entity should be fixed. Defaults to False.
912+
batch_fixed_verts : bool, optional
913+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
914+
significantly increasing memory usage. Default to true. **This is only used for RigidEntity.**
885915
prioritize_urdf_material : bool, optional
886916
Sometimes a geom in a urdf file will be assigned a color, and the geom asset file also contains its own visual
887917
material. This parameter controls whether to prioritize the URDF-defined material over the asset's own material.
@@ -1103,8 +1133,12 @@ class Terrain(Morph):
11031133
This parameter is deprecated.
11041134
subterrain_parameters : dictionary, optional
11051135
Lets users pick their own subterrain parameters.
1136+
batch_fixed_verts : bool, optional
1137+
Whether to batch fixed vertices. This will allow setting env-specific poses to fixed geometries, at the cost of
1138+
significantly increasing memory usage. Default to false. **This is only used for RigidEntity.**
11061139
"""
11071140

1141+
batch_fixed_verts: bool = False
11081142
randomize: bool = False # whether to randomize the terrain
11091143
n_subterrains: Tuple[int, int] = (3, 3) # number of subterrains in x and y directions
11101144
subterrain_size: Tuple[float, float] = (12.0, 12.0) # meter

tests/test_examples.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"genesis_ipc_motion_test.py", # TODO: wait for IPC's wheel to be released
3434
}
3535

36-
TIMEOUT = 400.0
36+
TIMEOUT = 450.0
3737

3838

3939
pytestmark = [

0 commit comments

Comments
 (0)