@@ -89,6 +89,7 @@ def __init__(self, default_world: bool = False):
8989 self ._num_joint_dynamic_cts : int = 0
9090 self ._num_joint_bounded_cts : int = 0
9191 self ._num_joint_friction_cts : int = 0
92+ self ._num_joint_effort_cts : int = 0
9293
9394 # Contact capacity settings
9495 self ._max_contacts_per_pair : int | None = None
@@ -205,6 +206,11 @@ def num_friction_joint_cts(self) -> int:
205206 """Returns the number of Coulomb joint friction constraint rows contained in the model."""
206207 return self ._num_joint_friction_cts
207208
209+ @property
210+ def num_effort_joint_cts (self ) -> int :
211+ """Returns the number of effort-limit implicit-PD constraint rows contained in the model."""
212+ return self ._num_joint_effort_cts
213+
208214 @property
209215 def worlds (self ) -> list [WorldDescriptor ]:
210216 """Returns the list of world descriptors contained in the model."""
@@ -396,7 +402,7 @@ def add_rigid_body_descriptor(self, body: RigidBodyDescriptor, world_index: int
396402
397403 def add_joint (
398404 self ,
399- act_type : JointActuationType ,
405+ act_type : JointActuationType | list [ JointActuationType ] ,
400406 dof_type : JointDoFType ,
401407 bid_B : int ,
402408 bid_F : int ,
@@ -421,7 +427,8 @@ def add_joint(
421427 Add a joint entity to the model using explicit specifications.
422428
423429 Args:
424- act_type: The actuation type of the joint.
430+ act_type: Actuation type applied to every DoF, or the actuation
431+ type of each DoF.
425432 dof_type: The degree of freedom type of the joint.
426433 bid_B: The index of the body on the "base" side of the joint.
427434 bid_F: The index of the body on the "follower" side of the joint.
@@ -446,13 +453,15 @@ def add_joint(
446453 Returns:
447454 The index of the newly added joint.
448455 """
449- # Check if the actuation type is valid
450- if not isinstance (act_type , JointActuationType ):
451- raise TypeError (f"Invalid actuation type: { act_type } . Must be `JointActuationType`." )
452-
453456 # Check if the DoF type is valid
454457 if not isinstance (dof_type , JointDoFType ):
455458 raise TypeError (f"Invalid DoF type: { dof_type } . Must be `JointDoFType`." )
459+ if isinstance (act_type , JointActuationType ):
460+ dof_act_types = [act_type ] * dof_type .num_dofs
461+ elif isinstance (act_type , list ):
462+ dof_act_types = act_type
463+ else :
464+ raise TypeError (f"Invalid actuation type: { act_type } . Must be `JointActuationType` or a list of them." )
456465
457466 # Create a joint descriptor from the provided specifications
458467 # NOTE: Specifying a name is required by the base descriptor class,
@@ -461,7 +470,7 @@ def add_joint(
461470 joint = JointDescriptor (
462471 name = name if name is not None else f"joint_{ self ._num_joints } " ,
463472 uid = uid ,
464- act_type = act_type ,
473+ dof_act_types = dof_act_types ,
465474 dof_type = dof_type ,
466475 bid_B = bid_B ,
467476 bid_F = bid_F ,
@@ -523,6 +532,7 @@ def add_joint_descriptor(self, joint: JointDescriptor, world_index: int = 0) ->
523532 self ._num_joint_kinematic_cts += joint .num_kinematic_cts
524533 self ._num_joint_bounded_cts += joint .num_bounded_cts
525534 self ._num_joint_friction_cts += joint .num_friction_cts
535+ self ._num_joint_effort_cts += joint .num_effort_cts
526536
527537 # Return the new joint index
528538 return joint .jid
@@ -744,6 +754,7 @@ def add_builder(self, other: ModelBuilderKamino):
744754 self ._num_joint_kinematic_cts += world .num_kinematic_joint_cts
745755 self ._num_joint_bounded_cts += world .num_bounded_joint_cts
746756 self ._num_joint_friction_cts += world .num_friction_joint_cts
757+ self ._num_joint_effort_cts += world .num_effort_joint_cts
747758
748759 # Update the number of worlds
749760 self ._num_worlds += other ._num_worlds
@@ -982,6 +993,7 @@ def finalize(
982993 info_njkc = []
983994 info_nbc = []
984995 info_nfc = []
996+ info_nec = []
985997 info_bio = []
986998 info_jio = []
987999 info_gio = []
@@ -997,6 +1009,7 @@ def finalize(
9971009 info_jkcio = []
9981010 info_jbcio = []
9991011 info_jfcio = []
1012+ info_jecio = []
10001013 info_base_bid = []
10011014 info_base_jid = []
10021015
@@ -1019,8 +1032,9 @@ def finalize(
10191032 joints_label = []
10201033 joints_wid = []
10211034 joints_jid = []
1022- joints_dofid = []
1023- joints_actid = []
1035+ joints_dof_type = []
1036+ joints_act_type = []
1037+ joints_dof_act_types = []
10241038 joints_fk_act_flag = []
10251039 joints_q_j_0 = []
10261040 joints_dq_j_0 = []
@@ -1045,7 +1059,12 @@ def finalize(
10451059 joints_nkincts_j = []
10461060 joints_nbccts_j = []
10471061 joints_nfriccts_j = []
1062+ joints_neffortcts_j = []
10481063 joints_ndyncts_j = []
1064+ joints_dof_act_paths = []
1065+ joints_dynamic_cts_axis = []
1066+ joints_friction_cts_axis = []
1067+ joints_effort_cts_axis = []
10491068 joints_q_start = []
10501069 joints_dq_start = []
10511070 joints_pq_start = []
@@ -1057,6 +1076,7 @@ def finalize(
10571076 joints_kcts_start = []
10581077 joints_bcts_start = []
10591078 joints_fcts_start = []
1079+ joints_ects_start = []
10601080
10611081 # Initialize the collision geometry data collections
10621082 geoms_label = []
@@ -1105,6 +1125,7 @@ def collect_model_info_data():
11051125 info_njkc .append (world .num_kinematic_joint_cts )
11061126 info_nbc .append (world .num_bounded_joint_cts )
11071127 info_nfc .append (world .num_friction_joint_cts )
1128+ info_nec .append (world .num_effort_joint_cts )
11081129 info_bio .append (world .bodies_idx_offset )
11091130 info_jio .append (world .joints_idx_offset )
11101131 info_gio .append (world .geoms_idx_offset )
@@ -1123,6 +1144,7 @@ def collect_model_info_data():
11231144 info_jkcio .append (world .joint_kinematic_cts_idx_offset )
11241145 info_jbcio .append (world .joint_bounded_cts_idx_offset )
11251146 info_jfcio .append (world .joint_friction_cts_idx_offset )
1147+ info_jecio .append (world .joint_effort_cts_idx_offset )
11261148 info_base_bid .append ((world .base_body_idx + world .bodies_idx_offset ) if world .has_base_body else - 1 )
11271149 info_base_jid .append ((world .base_joint_idx + world .joints_idx_offset ) if world .has_base_joint else - 1 )
11281150
@@ -1153,8 +1175,10 @@ def collect_joint_model_data():
11531175 joints_label .append (joint .name )
11541176 joints_wid .append (joint .wid )
11551177 joints_jid .append (joint .jid )
1156- joints_dofid .append (joint .dof_type .value )
1157- joints_actid .append (joint .act_type .value )
1178+ joints_dof_type .append (joint .dof_type .value )
1179+ joints_act_type .append (joint .act_type .value )
1180+ joints_dof_act_types .extend (act_type .value for act_type in joint .dof_act_types )
1181+ joints_dof_act_paths .extend (path .value for path in joint .dof_act_paths ())
11581182 joints_fk_act_flag .append (joint .fk_act_flag )
11591183 joints_B_r_Bj .append (joint .B_r_Bj )
11601184 joints_F_r_Fj .append (joint .F_r_Fj )
@@ -1193,6 +1217,10 @@ def collect_joint_model_data():
11931217 joints_nkincts_j .append (joint .num_kinematic_cts )
11941218 joints_nbccts_j .append (joint .num_bounded_cts )
11951219 joints_nfriccts_j .append (joint .num_friction_cts )
1220+ joints_neffortcts_j .append (joint .num_effort_cts )
1221+ joints_dynamic_cts_axis .extend (joint .dynamic_cts_axes ())
1222+ joints_friction_cts_axis .extend (joint .friction_cts_axes ())
1223+ joints_effort_cts_axis .extend (joint .effort_cts_axes ())
11961224 joints_q_start .append (joint .coords_offset + world .joint_coords_idx_offset )
11971225 joints_dq_start .append (joint .dofs_offset + world .joint_dofs_idx_offset )
11981226 joints_pq_start .append (joint .passive_coords_offset + world .joint_passive_coords_idx_offset )
@@ -1204,6 +1232,7 @@ def collect_joint_model_data():
12041232 joints_kcts_start .append (joint .kinematic_cts_offset + world .joint_kinematic_cts_idx_offset )
12051233 joints_bcts_start .append (joint .bounded_cts_offset + world .joint_bounded_cts_idx_offset )
12061234 joints_fcts_start .append (joint .friction_cts_offset + world .joint_friction_cts_idx_offset )
1235+ joints_ects_start .append (joint .effort_cts_offset + world .joint_effort_cts_idx_offset )
12071236 joints_bid_B .append (joint .bid_B + world_bio if joint .bid_B >= 0 else - 1 )
12081237 joints_bid_F .append (joint .bid_F + world_bio if joint .bid_F >= 0 else - 1 )
12091238
@@ -1219,6 +1248,7 @@ def collect_joint_model_data():
12191248 joints_kcts_start .append (self ._num_joint_kinematic_cts )
12201249 joints_bcts_start .append (self ._num_joint_bounded_cts )
12211250 joints_fcts_start .append (self ._num_joint_friction_cts )
1251+ joints_ects_start .append (self ._num_joint_effort_cts )
12221252
12231253 # A helper function to collect model collision geometries data
12241254 def collect_geometry_model_data ():
@@ -1317,6 +1347,8 @@ def collect_material_pairs_model_data():
13171347 max_of_num_bounded_joint_cts = max ([world .num_bounded_joint_cts for world in self ._worlds ]),
13181348 sum_of_num_friction_joint_cts = self ._num_joint_friction_cts ,
13191349 max_of_num_friction_joint_cts = max ([world .num_friction_joint_cts for world in self ._worlds ]),
1350+ sum_of_num_effort_joint_cts = self ._num_joint_effort_cts ,
1351+ max_of_num_effort_joint_cts = max ([world .num_effort_joint_cts for world in self ._worlds ]),
13201352 # Initialize inequality entity counts to zero
13211353 sum_of_max_limits = 0 ,
13221354 max_of_max_limits = 0 ,
@@ -1383,6 +1415,7 @@ def collect_material_pairs_model_data():
13831415 num_joint_kinematic_cts = to_warp_int32_array (info_njkc ),
13841416 num_joint_bounded_cts = to_warp_int32_array (info_nbc ),
13851417 num_joint_friction_cts = to_warp_int32_array (info_nfc ),
1418+ num_joint_effort_cts = to_warp_int32_array (info_nec ),
13861419 bodies_offset = to_warp_int32_array (info_bio ),
13871420 joints_offset = to_warp_int32_array (info_jio ),
13881421 geoms_offset = to_warp_int32_array (info_gio ),
@@ -1398,6 +1431,7 @@ def collect_material_pairs_model_data():
13981431 joint_kinematic_cts_offset = to_warp_int32_array (info_jkcio ),
13991432 joint_bounded_cts_offset = to_warp_int32_array (info_jbcio ),
14001433 joint_friction_cts_offset = to_warp_int32_array (info_jfcio ),
1434+ joint_effort_cts_offset = to_warp_int32_array (info_jecio ),
14011435 base_body_index = to_warp_int32_array (info_base_bid ),
14021436 base_joint_index = to_warp_int32_array (info_base_jid ),
14031437 has_world_without_base_body = has_world_without_base_body ,
@@ -1432,8 +1466,10 @@ def collect_material_pairs_model_data():
14321466 label = joints_label ,
14331467 wid = to_warp_int32_array (joints_wid ),
14341468 jid = to_warp_int32_array (joints_jid ),
1435- dof_type = to_warp_int32_array (joints_dofid ),
1436- act_type = to_warp_int32_array (joints_actid ),
1469+ dof_type = to_warp_int32_array (joints_dof_type ),
1470+ act_type = to_warp_int32_array (joints_act_type ),
1471+ dof_act_types = to_warp_int32_array (joints_dof_act_types ),
1472+ dof_act_paths = to_warp_int32_array (joints_dof_act_paths ),
14371473 fk_act_flag = to_warp_int32_array (joints_fk_act_flag )
14381474 if any (act_flag != - 1 for act_flag in joints_fk_act_flag )
14391475 else None ,
@@ -1461,6 +1497,7 @@ def collect_material_pairs_model_data():
14611497 num_kinematic_cts = to_warp_int32_array (joints_nkincts_j ),
14621498 num_bounded_cts = to_warp_int32_array (joints_nbccts_j ),
14631499 num_friction_cts = to_warp_int32_array (joints_nfriccts_j ),
1500+ num_effort_cts = to_warp_int32_array (joints_neffortcts_j ),
14641501 coords_offset = to_warp_int32_array (joints_q_start ),
14651502 dofs_offset = to_warp_int32_array (joints_dq_start ),
14661503 passive_coords_offset = to_warp_int32_array (joints_pq_start ),
@@ -1472,6 +1509,10 @@ def collect_material_pairs_model_data():
14721509 kinematic_cts_offset = to_warp_int32_array (joints_kcts_start ),
14731510 bounded_cts_offset = to_warp_int32_array (joints_bcts_start ),
14741511 friction_cts_offset = to_warp_int32_array (joints_fcts_start ),
1512+ effort_cts_offset = to_warp_int32_array (joints_ects_start ),
1513+ dynamic_cts_axis = to_warp_int32_array (joints_dynamic_cts_axis ),
1514+ friction_cts_axis = to_warp_int32_array (joints_friction_cts_axis ),
1515+ effort_cts_axis = to_warp_int32_array (joints_effort_cts_axis ),
14751516 )
14761517
14771518 # Create the collision geometries model
@@ -1864,6 +1905,7 @@ def _compute_world_offsets(self):
18641905 joint_kinematic_cts_idx_offset : int = 0
18651906 joint_bounded_cts_idx_offset : int = 0
18661907 joint_friction_cts_idx_offset : int = 0
1908+ joint_effort_cts_idx_offset : int = 0
18671909 # Iterate over each world and set their model offsets
18681910 for world in self ._worlds :
18691911 # Set the offsets in the world descriptor to the current values
@@ -1882,6 +1924,7 @@ def _compute_world_offsets(self):
18821924 world .joint_kinematic_cts_idx_offset = int (joint_kinematic_cts_idx_offset )
18831925 world .joint_bounded_cts_idx_offset = int (joint_bounded_cts_idx_offset )
18841926 world .joint_friction_cts_idx_offset = int (joint_friction_cts_idx_offset )
1927+ world .joint_effort_cts_idx_offset = int (joint_effort_cts_idx_offset )
18851928 # Update the offsets for the next world
18861929 bodies_idx_offset += world .num_bodies
18871930 joints_idx_offset += world .num_joints
@@ -1898,6 +1941,7 @@ def _compute_world_offsets(self):
18981941 joint_kinematic_cts_idx_offset += world .num_kinematic_joint_cts
18991942 joint_bounded_cts_idx_offset += world .num_bounded_joint_cts
19001943 joint_friction_cts_idx_offset += world .num_friction_joint_cts
1944+ joint_effort_cts_idx_offset += world .num_effort_joint_cts
19011945
19021946 def _collect_geom_max_contact_hints (self ) -> tuple [int , list [int ]]:
19031947 """
0 commit comments