Preparation for MIMO actuators: split actuator counts: nu (inputs), nactuator (objects), nout (outputs).

An actuator now owns a block of consecutive controls
(actuator_ctrladr/ctrlnum, width defined by the actuator type) and a block
of consecutive force outputs (actuator_outadr/outnum, width defined by the
transmission type). Force outputs are the scalars of actuation space: one
force, length, velocity and moment row each. nout = dim(actuator_force) is
derived from transmission types; all current types have width 1, so all
three counts coincide for every existing model and behavior is bit-exact.

Array re-keying: ctrlrange/ctrllimited by nu; forcerange/forcelimited/gear/
acc0/length0/lengthrange and the moment row structure by nout; everything
else per actuator. The mjModel actuator block is re-sorted by size key.

Layout-breaking, not behavior-breaking: saved .mjb files are invalidated
(size list changed) and recompilation is required.

PiperOrigin-RevId: 948351772
Change-Id: Icbc196ffa083cb1eaa6f1a3710869c89d8f62540
This commit is contained in:
Yuval Tassa
2026-07-15 08:29:38 -07:00
committed by Copybara-Service
parent 06f12a9372
commit d507e92198
27 changed files with 750 additions and 538 deletions
+161 -119
View File
@@ -946,7 +946,17 @@ STRUCTS: Mapping[str, StructDecl] = dict([
StructFieldDecl(
name='nu',
type=ValueType(name='mjtSize'),
doc='number of actuators/controls = dim(ctrl)',
doc='number of scalar controls = dim(ctrl)',
),
StructFieldDecl(
name='nactuator',
type=ValueType(name='mjtSize'),
doc='number of actuators',
),
StructFieldDecl(
name='nout',
type=ValueType(name='mjtSize'),
doc='number of force outputs, derived from transmission type',
),
StructFieldDecl(
name='na',
@@ -4311,7 +4321,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='transmission type (mjtTrn)',
array_extent=('nu',),
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_dyntype',
@@ -4319,7 +4329,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='dynamics type (mjtDyn)',
array_extent=('nu',),
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_gaintype',
@@ -4327,7 +4337,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='gain type (mjtGain)',
array_extent=('nu',),
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_biastype',
@@ -4335,39 +4345,39 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='bias type (mjtBias)',
array_extent=('nu',),
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_trnid',
name='actuator_ctrladr',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='transmission id: joint, tendon, site',
array_extent=('nu', 2),
doc='address of first control',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_damping',
name='actuator_ctrlnum',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
inner_type=ValueType(name='int'),
),
doc='linear damping coefficient',
array_extent=('nu',),
doc='number of controls',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_dampingpoly',
name='actuator_outadr',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
inner_type=ValueType(name='int'),
),
doc='high-order damping coefficients',
array_extent=('nu', 'mjNPOLY'),
doc='address of first force output',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_armature',
name='actuator_outnum',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
inner_type=ValueType(name='int'),
),
doc='armature added to target (joint, tendon)',
array_extent=('nu',),
doc='number of force outputs, from trntype',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_actadr',
@@ -4375,7 +4385,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='first activation address; -1: stateless',
array_extent=('nu',),
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_actnum',
@@ -4383,63 +4393,23 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='number of activation variables',
array_extent=('nu',),
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_group',
name='actuator_trnid',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='group for visibility',
array_extent=('nu',),
doc='transmission id: joint, tendon, site',
array_extent=('nactuator', 2),
),
StructFieldDecl(
name='actuator_history',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='history buffer: [nsample, interp]',
array_extent=('nu', 2),
),
StructFieldDecl(
name='actuator_historyadr',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='address in history buffer; -1: none',
array_extent=('nu',),
),
StructFieldDecl(
name='actuator_delay',
name='actuator_cranklength',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='delay time in seconds; 0: no delay',
array_extent=('nu',),
),
StructFieldDecl(
name='actuator_ctrllimited',
type=PointerType(
inner_type=ValueType(name='mjtBool'),
),
doc='is control limited',
array_extent=('nu',),
),
StructFieldDecl(
name='actuator_forcelimited',
type=PointerType(
inner_type=ValueType(name='mjtBool'),
),
doc='is force limited',
array_extent=('nu',),
),
StructFieldDecl(
name='actuator_actlimited',
type=PointerType(
inner_type=ValueType(name='mjtBool'),
),
doc='is activation limited',
array_extent=('nu',),
doc='crank length for slider-crank',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_dynprm',
@@ -4447,7 +4417,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='mjtNum'),
),
doc='dynamics parameters',
array_extent=('nu', 'mjNDYN'),
array_extent=('nactuator', 'mjNDYN'),
),
StructFieldDecl(
name='actuator_gainprm',
@@ -4455,7 +4425,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='mjtNum'),
),
doc='gain parameters',
array_extent=('nu', 'mjNGAIN'),
array_extent=('nactuator', 'mjNGAIN'),
),
StructFieldDecl(
name='actuator_biasprm',
@@ -4463,7 +4433,23 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='mjtNum'),
),
doc='bias parameters',
array_extent=('nu', 'mjNBIAS'),
array_extent=('nactuator', 'mjNBIAS'),
),
StructFieldDecl(
name='actuator_actlimited',
type=PointerType(
inner_type=ValueType(name='mjtBool'),
),
doc='is activation limited',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_actrange',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='range of activations',
array_extent=('nactuator', 2),
),
StructFieldDecl(
name='actuator_actearly',
@@ -4471,6 +4457,86 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='mjtBool'),
),
doc='step activation before force',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_history',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='history buffer: [nsample, interp]',
array_extent=('nactuator', 2),
),
StructFieldDecl(
name='actuator_historyadr',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='address in history buffer; -1: none',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_delay',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='delay time; 0: no delay',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_damping',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='linear damping coefficient',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_dampingpoly',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='high-order damping coefficients',
array_extent=('nactuator', 'mjNPOLY'),
),
StructFieldDecl(
name='actuator_armature',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='armature added to target (joint, tendon)',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_group',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='group for visibility',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_user',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='user data',
array_extent=('nactuator', 'nuser_actuator'),
),
StructFieldDecl(
name='actuator_plugin',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='plugin instance id; -1: not a plugin',
array_extent=('nactuator',),
),
StructFieldDecl(
name='actuator_ctrllimited',
type=PointerType(
inner_type=ValueType(name='mjtBool'),
),
doc='is control limited',
array_extent=('nu',),
),
StructFieldDecl(
@@ -4481,37 +4547,29 @@ STRUCTS: Mapping[str, StructDecl] = dict([
doc='range of controls',
array_extent=('nu', 2),
),
StructFieldDecl(
name='actuator_forcerange',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='range of forces',
array_extent=('nu', 2),
),
StructFieldDecl(
name='actuator_actrange',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='range of activations',
array_extent=('nu', 2),
),
StructFieldDecl(
name='actuator_gear',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='scale length and transmitted force',
array_extent=('nu', 6),
array_extent=('nout', 6),
),
StructFieldDecl(
name='actuator_cranklength',
name='actuator_forcelimited',
type=PointerType(
inner_type=ValueType(name='mjtBool'),
),
doc='is force limited',
array_extent=('nout',),
),
StructFieldDecl(
name='actuator_forcerange',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='crank length for slider-crank',
array_extent=('nu',),
doc='range of forces',
array_extent=('nout', 2),
),
StructFieldDecl(
name='actuator_acc0',
@@ -4519,7 +4577,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='mjtNum'),
),
doc='acceleration from unit force in qpos0',
array_extent=('nu',),
array_extent=('nout',),
),
StructFieldDecl(
name='actuator_length0',
@@ -4527,7 +4585,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='mjtNum'),
),
doc='actuator length in qpos0',
array_extent=('nu',),
array_extent=('nout',),
),
StructFieldDecl(
name='actuator_lengthrange',
@@ -4535,23 +4593,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='mjtNum'),
),
doc='feasible actuator length range',
array_extent=('nu', 2),
),
StructFieldDecl(
name='actuator_user',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='user data',
array_extent=('nu', 'nuser_actuator'),
),
StructFieldDecl(
name='actuator_plugin',
type=PointerType(
inner_type=ValueType(name='int'),
),
doc='plugin instance id; -1: not a plugin',
array_extent=('nu',),
array_extent=('nout', 2),
),
StructFieldDecl(
name='sensor_type',
@@ -5015,7 +5057,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='actuator name pointers',
array_extent=('nu',),
array_extent=('nactuator',),
),
StructFieldDecl(
name='name_sensoradr',
@@ -6082,8 +6124,8 @@ STRUCTS: Mapping[str, StructDecl] = dict([
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='actuator lengths',
array_extent=('nu',),
doc='actuator lengths, one per force output',
array_extent=('nout',),
),
StructFieldDecl(
name='moment_rownnz',
@@ -6091,7 +6133,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='number of non-zeros in actuator_moment row',
array_extent=('nu',),
array_extent=('nout',),
),
StructFieldDecl(
name='moment_rowadr',
@@ -6099,7 +6141,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='int'),
),
doc='row start address in colind array',
array_extent=('nu',),
array_extent=('nout',),
),
StructFieldDecl(
name='moment_colind',
@@ -6218,8 +6260,8 @@ STRUCTS: Mapping[str, StructDecl] = dict([
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='actuator velocities',
array_extent=('nu',),
doc='actuator velocities, one per force output',
array_extent=('nout',),
),
StructFieldDecl(
name='cvel',
@@ -6339,14 +6381,14 @@ STRUCTS: Mapping[str, StructDecl] = dict([
inner_type=ValueType(name='mjtNum'),
),
doc='actuator force in actuation space',
array_extent=('nu',),
array_extent=('nout',),
),
StructFieldDecl(
name='qfrc_actuator',
type=PointerType(
inner_type=ValueType(name='mjtNum'),
),
doc='actuator force',
doc='actuator force in joint space',
array_extent=('nv',),
),
StructFieldDecl(