11from copy import copy
22from itertools import chain
33from typing import Literal
4+ from typing import TYPE_CHECKING
45
56import numpy as np
67import taichi as ti
2526from .rigid_joint import RigidJoint
2627from .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
3035class 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 (
0 commit comments