Skip to content

Commit d5c648c

Browse files
committed
Distinguish user-specified material from default.
1 parent 51d296e commit d5c648c

File tree

14 files changed

+174
-184
lines changed

14 files changed

+174
-184
lines changed

genesis/engine/entities/base_entity.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,96 @@ def __init__(
1919
material,
2020
surface,
2121
):
22+
if isinstance(material, gs.materials.Rigid):
23+
# small sdf res is sufficient for primitives regardless of size
24+
if isinstance(morph, gs.morphs.Primitive):
25+
material._sdf_max_res = 32
26+
27+
# some morph should not smooth surface normal
28+
if isinstance(morph, (gs.morphs.Box, gs.morphs.Cylinder, gs.morphs.Terrain)):
29+
surface.smooth = False
30+
31+
if isinstance(morph, (gs.morphs.URDF, gs.morphs.MJCF, gs.morphs.Terrain)):
32+
if not isinstance(material, (gs.materials.Rigid, gs.materials.Avatar, gs.materials.Hybrid)):
33+
gs.raise_exception(f"Unsupported material for morph: {material} and {morph}.")
34+
35+
if surface.double_sided is None:
36+
surface.double_sided = isinstance(material, gs.materials.PBD.Cloth)
37+
38+
# validate and populate default surface.vis_mode considering morph type
39+
if isinstance(material, (gs.materials.Rigid, gs.materials.Avatar, gs.materials.Tool)):
40+
if surface.vis_mode is None:
41+
surface.vis_mode = "visual"
42+
43+
if surface.vis_mode not in ("visual", "collision", "sdf"):
44+
gs.raise_exception(
45+
f"Invalid `surface.vis_mode` for material {material}: '{surface.vis_mode}'. Only supporting "
46+
"'visual', 'collision' and 'sdf'."
47+
)
48+
elif isinstance(
49+
material,
50+
(
51+
gs.materials.PBD.Liquid,
52+
gs.materials.PBD.Particle,
53+
gs.materials.MPM.Liquid,
54+
gs.materials.MPM.Sand,
55+
gs.materials.MPM.Snow,
56+
gs.materials.SPH.Liquid,
57+
),
58+
):
59+
if surface.vis_mode is None:
60+
surface.vis_mode = "particle"
61+
62+
if surface.vis_mode not in ("particle", "recon"):
63+
gs.raise_exception(
64+
f"Invalid `surface.vis_mode` for material {material}: '{surface.vis_mode}'. Only supporting "
65+
"'particle' and 'recon'."
66+
)
67+
elif isinstance(material, (gs.materials.SF.Smoke)):
68+
if surface.vis_mode is None:
69+
surface.vis_mode = "particle"
70+
71+
if surface.vis_mode not in ("particle",):
72+
gs.raise_exception(
73+
f"Invalid `surface.vis_mode` for material {material}: '{surface.vis_mode}'. Only supporting "
74+
"'particle'."
75+
)
76+
elif isinstance(material, (gs.materials.PBD.Base, gs.materials.MPM.Base, gs.materials.SPH.Base)):
77+
if surface.vis_mode is None:
78+
surface.vis_mode = "visual"
79+
80+
if surface.vis_mode not in ("visual", "particle", "recon"):
81+
gs.raise_exception(
82+
f"Invalid `surface.vis_mode` for material {material}: '{surface.vis_mode}'. Only supporting "
83+
"'visual', 'particle' and 'recon'."
84+
)
85+
elif isinstance(material, (gs.materials.FEM.Base)):
86+
if surface.vis_mode is None:
87+
surface.vis_mode = "visual"
88+
89+
if surface.vis_mode not in ("visual",):
90+
gs.raise_exception(
91+
f"Invalid `surface.vis_mode` for material {material}: '{surface.vis_mode}'. Only supporting "
92+
"'visual'."
93+
)
94+
elif isinstance(material, (gs.materials.Hybrid)): # determine the visual of the outer soft part
95+
if surface.vis_mode is None:
96+
surface.vis_mode = "particle"
97+
98+
if surface.vis_mode not in ["particle", "visual"]:
99+
gs.raise_exception(
100+
f"Invalid `surface.vis_mode` for material {material}: '{surface.vis_mode}'. Only supporting "
101+
"'particle' and 'visual'."
102+
)
103+
else:
104+
gs.raise_exception(f"Material not supported.: {material}")
105+
106+
# Set material-dependent default options
107+
if isinstance(morph, gs.morphs.FileMorph):
108+
# Rigid entities will convexify geom by default
109+
if morph.convexify is None:
110+
morph.convexify = isinstance(material, (gs.materials.Rigid, gs.materials.Avatar))
111+
22112
self._uid = gs.UID()
23113
self._idx = idx
24114
self._scene = scene

genesis/engine/entities/rigid_entity/rigid_entity.py

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from copy import copy
22
from itertools import chain
33
from typing import Literal
4+
from typing import TYPE_CHECKING
45

56
import numpy as np
67
import taichi as ti
@@ -25,6 +26,10 @@
2526
from .rigid_joint import RigidJoint
2627
from .rigid_link import RigidLink
2728

29+
if TYPE_CHECKING:
30+
from genesis.engine.solvers.base_solver import Solver
31+
from genesis.engine.scene import Scene
32+
2833

2934
@ti.data_oriented
3035
class RigidEntity(Entity):
@@ -57,6 +62,9 @@ def __init__(
5762
equality_start=0,
5863
visualize_contact=False,
5964
):
65+
if material is None:
66+
material = gs.materials.Rigid()
67+
6068
super().__init__(idx, scene, morph, solver, material, surface)
6169

6270
self._idx_in_solver = idx_in_solver
@@ -83,36 +91,29 @@ def __init__(
8391

8492
self._is_built = False
8593

86-
self._load_model()
94+
self._load_model(morph, material, self.surface)
8795

88-
def _load_model(self):
96+
def _load_model(self, morph, material, surface):
8997
self._links = gs.List()
9098
self._joints = gs.List()
9199
self._equalities = gs.List()
92100

93-
if isinstance(self._morph, gs.morphs.Mesh):
94-
self._load_mesh(self._morph, self._surface)
95-
elif isinstance(self._morph, (gs.morphs.MJCF, gs.morphs.URDF, gs.morphs.Drone)):
96-
self._load_scene(self._morph, self._surface)
97-
elif isinstance(self._morph, gs.morphs.Primitive):
98-
self._load_primitive(self._morph, self._surface)
99-
elif isinstance(self._morph, gs.morphs.Terrain):
100-
self._load_terrain(self._morph, self._surface)
101+
if isinstance(morph, gs.morphs.Mesh):
102+
self._load_mesh(morph, material, surface)
103+
elif isinstance(morph, (gs.morphs.MJCF, gs.morphs.URDF, gs.morphs.Drone)):
104+
self._load_scene(morph, material, surface)
105+
elif isinstance(morph, gs.morphs.Primitive):
106+
self._load_primitive(morph, material, surface)
107+
elif isinstance(morph, gs.morphs.Terrain):
108+
self._load_terrain(morph, material, surface)
101109
else:
102-
gs.raise_exception(f"Unsupported morph: {self._morph}.")
110+
gs.raise_exception(f"Unsupported morph: {morph}.")
103111

104-
self._requires_jac_and_IK = self._morph.requires_jac_and_IK
112+
self._requires_jac_and_IK = morph.requires_jac_and_IK
105113

106114
self._update_child_idxs()
107115

108-
def _update_child_idxs(self):
109-
for link in self._links:
110-
if link.parent_idx != -1:
111-
parent_link = self._links[link.parent_idx_local]
112-
if link.idx not in parent_link.child_idxs:
113-
parent_link.child_idxs.append(link.idx)
114-
115-
def _load_primitive(self, morph, surface):
116+
def _load_primitive(self, morph, material, surface):
116117
if morph.fixed:
117118
joint_type = gs.JOINT_TYPE.FIXED
118119
n_qs = 0
@@ -180,7 +181,7 @@ def _load_primitive(self, morph, surface):
180181
link, (joint,) = self._add_by_info(
181182
l_info=dict(
182183
is_robot=False,
183-
name=f"{link_name_prefix}_baselink",
184+
name=f"{link_name_prefix}_base",
184185
pos=np.array(morph.pos),
185186
quat=np.array(morph.quat),
186187
inertial_pos=gu.zero_pos(),
@@ -189,7 +190,7 @@ def _load_primitive(self, morph, surface):
189190
),
190191
j_infos=[
191192
dict(
192-
name=f"{link_name_prefix}_baselink_joint",
193+
name=f"{link_name_prefix}_root_joint",
193194
n_qs=n_qs,
194195
n_dofs=n_dofs,
195196
type=joint_type,
@@ -198,10 +199,10 @@ def _load_primitive(self, morph, surface):
198199
],
199200
g_infos=g_infos,
200201
morph=morph,
201-
surface=surface,
202+
material=material,
202203
)
203204

204-
def _load_mesh(self, morph, surface):
205+
def _load_mesh(self, morph, material, surface):
205206
if morph.fixed:
206207
joint_type = gs.JOINT_TYPE.FIXED
207208
n_qs = 0
@@ -247,12 +248,13 @@ def _load_mesh(self, morph, surface):
247248
)
248249
)
249250

250-
link_name = morph.file.rsplit("/", 1)[-1].replace(".", "_")
251+
*_, link_name = morph.file.rsplit("/", 1)
252+
link_name.replace(".", "_")
251253

252254
link, (joint,) = self._add_by_info(
253255
l_info=dict(
254256
is_robot=False,
255-
name=f"{link_name}_baselink",
257+
name=f"{link_name}_base",
256258
pos=np.array(morph.pos),
257259
quat=np.array(morph.quat),
258260
inertial_pos=gu.zero_pos(),
@@ -261,7 +263,7 @@ def _load_mesh(self, morph, surface):
261263
),
262264
j_infos=[
263265
dict(
264-
name=f"{link_name}_baselink_joint",
266+
name=f"{link_name}_root_joint",
265267
n_qs=n_qs,
266268
n_dofs=n_dofs,
267269
type=joint_type,
@@ -270,10 +272,10 @@ def _load_mesh(self, morph, surface):
270272
],
271273
g_infos=g_infos,
272274
morph=morph,
273-
surface=surface,
275+
material=material,
274276
)
275277

276-
def _load_terrain(self, morph, surface):
278+
def _load_terrain(self, morph, material, surface):
277279
vmesh, mesh, self.terrain_hf = tu.parse_terrain(morph, surface)
278280
self.terrain_scale = np.array((morph.horizontal_scale, morph.vertical_scale), dtype=gs.np_float)
279281

@@ -300,7 +302,7 @@ def _load_terrain(self, morph, surface):
300302
link, (joint,) = self._add_by_info(
301303
l_info=dict(
302304
is_robot=False,
303-
name="baselink",
305+
name="base",
304306
pos=np.array(morph.pos),
305307
quat=np.array(morph.quat),
306308
inertial_pos=None,
@@ -312,18 +314,18 @@ def _load_terrain(self, morph, surface):
312314
),
313315
j_infos=[
314316
dict(
315-
name="joint_baselink",
317+
name="root_joint",
316318
n_qs=0,
317319
n_dofs=0,
318320
type=gs.JOINT_TYPE.FIXED,
319321
)
320322
],
321323
g_infos=g_infos,
322324
morph=morph,
323-
surface=surface,
325+
material=material,
324326
)
325327

326-
def _load_scene(self, morph, surface):
328+
def _load_scene(self, morph, material, surface):
327329
# Mujoco's unified MJCF+URDF parser is not good enough for now to be used for loading both MJCF and URDF files.
328330
# First, it would happen when loading visual meshes having supported format (i.e. Collada files '.dae').
329331
# Second, it does not take into account URDF 'mimic' joint constraints. However, it does a better job at
@@ -517,7 +519,7 @@ def _load_scene(self, morph, surface):
517519
# Exclude joints with 0 dofs to align with Mujoco
518520
link_j_infos = [j_info for j_info in link_j_infos if j_info["n_dofs"] > 0]
519521

520-
self._add_by_info(l_info, link_j_infos, link_g_infos, morph, surface)
522+
self._add_by_info(l_info, link_j_infos, link_g_infos, morph, material)
521523

522524
# Add equality constraints sequentially
523525
for eq_info in eqs_info:
@@ -529,6 +531,13 @@ def _load_scene(self, morph, surface):
529531
sol_params=eq_info["sol_params"],
530532
)
531533

534+
def _update_child_idxs(self):
535+
for link in self._links:
536+
if link.parent_idx != -1:
537+
parent_link = self._links[link.parent_idx_local]
538+
if link.idx not in parent_link.child_idxs:
539+
parent_link.child_idxs.append(link.idx)
540+
532541
def _build(self):
533542
for link in self._links:
534543
link._build()
@@ -600,7 +609,7 @@ def _init_jac_and_IK(self):
600609
dtype=gs.ti_float, shape=self._solver._batch_shape((self.n_dofs, self._IK_error_dim))
601610
)
602611

603-
def _add_by_info(self, l_info, j_infos, g_infos, morph, surface):
612+
def _add_by_info(self, l_info, j_infos, g_infos, morph, material):
604613
if len(j_infos) > 1 and any(j_info["type"] in (gs.JOINT_TYPE.FREE, gs.JOINT_TYPE.FIXED) for j_info in j_infos):
605614
raise ValueError(
606615
"Compounding joints of types 'FREE' or 'FIXED' with any other joint on the same body not supported"
@@ -760,7 +769,10 @@ def _add_by_info(self, l_info, j_infos, g_infos, morph, surface):
760769

761770
# Add collision geometries
762771
for g_info in cg_infos:
763-
friction = g_info.get("friction", self.material.friction)
772+
if material is not None:
773+
friction = material.friction
774+
else:
775+
friction = g_info.get("friction", self.material.friction)
764776
if friction is None:
765777
friction = gu.default_friction()
766778
link._add_geom(

genesis/engine/entities/tool_entity/tool_entity.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,7 @@
1818
@ti.data_oriented
1919
class ToolEntity(Entity):
2020
# Mesh-based tool body entity
21-
def __init__(
22-
self,
23-
scene,
24-
idx,
25-
solver,
26-
material,
27-
morph,
28-
surface,
29-
):
21+
def __init__(self, scene, idx, solver, material, morph, surface):
3022
super().__init__(idx, scene, morph, solver, material, surface)
3123

3224
self._init_pos = np.array(morph.pos, dtype=gs.np_float)

0 commit comments

Comments
 (0)