https://youtu.be/17XpwnqyCXs
New transmission type mjTRN_SO3: a relative orientation, targeting a ball
joint or a site+refsite pair. It is the first transmission with more than
one force output: its length is the norm of the expmap vector of the
relative rotation and its moment axes are the 3 rows of the
relative rotational Jacobian, without projecting onto per-actuator gears.
New force law mjGAIN_SO3/mjBIAS_SO3: a geodesic PD servo, force =
kp * log(q_current^-1 * q_target) - kv * velocity, exact for arbitrary axis
combinations with a unique equilibrium at every commanded orientation.
Error, moment rows and velocity all live in the child frame (joint or
site): the right-difference error is the gradient of the geodesic
potential in that frame. The parent-frame (left) error is not: driving
child-frame torques with it pumps energy at large angles, settling into
steady-spinning limit cycles (the SO3LargeAngleConvergence test). The
integrator variant stores the 3D orientation setpoint in act (actnum = 3,
re-anchored to a bounded representative at integration time). Exposed in
MJCF as <orientation joint=|site=+refsite= kp kv|dampratio>, or via
<general gaintype="so3" biastype="so3">.
The setpoint input has two charts: an expmap target (3 controls, default)
or a quaternion target (4 controls) -- <orientation input="quat">, the
first actuator with different input and output widths. The signature is
recorded in a new per-actuator field actuator_ctrlspec (mjtCtrlChart),
whose meaning is scoped by the gain type the way gain/bias parameters are;
ctrlnum is derived from it at compile time and remains the layout
authority. An explicit field rather than width inference or a prm slot:
width-as-chart cannot express same-width signatures (upcoming servo input
subsets), and prm slots are the input_mode pattern this stack retires.
The force law normalizes the commanded quaternion, making it scale- and
antipodally-invariant. The all-zero ctrl still maps to the identity via
mju_normalize4, but it is a degenerate point (a nudge of any component
commands a half-turn), so quat inputs reset to the identity quaternion:
new mj_resetCtrl sets neutral ctrl values (zero, except qw = 1), called
by mj_resetData and the viewers' Clear All. The quat chart is
restricted to dyntype 'none': integrating a quaternion setpoint linearly
is not meaningful on the manifold. New mjsActuator.ctrlspec field carries
the signature through the spec and XML round-trip.
Actuator sensors (actuatorpos/vel/frc) now report one value per force
output; dim = 3 on an SO3 actuator.
As the first actuator with nu != nactuator, this commit also makes the
viewers multi-input aware: the control sliders in simulate and studio,
which indexed per-actuator arrays by control index (out of bounds on
this model class), are generated per control and labeled with the
actuator name plus an input suffix ("orient/qw"), via the new
introspection helper mj_actuatorInputName -- the single source of truth
for input names, extended by each new multi-input type (quaternion
components are w-first: qw, qx, qy, qz). Slider ranges now honor a
defined ctrlrange even when ctrllimited is false: range is the UI hint,
limited is the clamp -- wrapped and expmap setpoints are unbounded but
still want finite sliders, while quat components are truly bounded.
The rotational demo model is orientation.xml under
test/engine/testdata/actuation/, upgraded to a three-way contrast:
per-axis wrapped servos vs an expmap-commanded vs a quat-commanded
orientation actuator, on identical checker-textured boxes. It is loaded
by the mixed-axis contrast and input-name tests, and doubles as the
viewer test model (slider groups of 3 independent, 3 grouped, 4 grouped).
PiperOrigin-RevId: 951607063
Change-Id: If235dba8e2f2ca72672e7c62531a27e967c6a373
For example when loading parent_merge.xml:
```
WARNING: Attach conflict when attaching 'child' to 'parent_merge', policy is 'merge'
timestep: parent has 0.005, child has 0.002, taking the minimum
iterations: parent has 50, child has 100, taking the maximum
flag 'Damper': added from child
```
When loading parent_error.xml:
```
XML Error: Attach conflict when attaching 'child' to 'parent_error', policy is 'error'
timestep: parent has 0.005, child has 0.002
iterations: parent has 50, child has 100
Element 'attach', line 10
```
PiperOrigin-RevId: 933620810
Change-Id: Ib477863b5ef763474d27fb4be5a4148be1d5d500
For example, `compile mujoco_menagerie/robotis_op3/scene.xml` now outputs
```
Compile 1 (cold cache):
total: 317.2 ms
assets: 284.8 ms (wall clock)
load: 616.1 ms
hull: 26.4 ms
poly: 137.8 ms
inert: 177.8 ms
bvh: 568.2 ms
octr: 1.6 ms
tex: 25.3 ms
other: 32.4 ms
Compile 2 (warm cache):
total: 79.9 ms
assets: 54.5 ms (wall clock)
load: 888.5 ms
hull: 0.0 ms
poly: 0.0 ms
inert: 0.0 ms
bvh: 0.0 ms
octr: 0.0 ms
tex: 21.4 ms
other: 25.3 ms
```
PiperOrigin-RevId: 917850214
Change-Id: Iaec86230bec0faf2e47820e20cbff61de5b2621e
This attribute allows specifying the intended output types (e.g., RGB, depth, normal) for each camera in the XML. The output types are stored as bit flags in `mjModel`.
PiperOrigin-RevId: 853316261
Change-Id: I1ad2e94102593cf402756f8f4c80509371ca86d2
- plugin system similar to mjpResourceProvider, but instead of loading a resource it converts an existing mjResource into an mjSpec.
- The returned spec is then composed into the referencing spec.
- This enables different file types to generate arbitrary specs, and allows us to separate format parsing from compilation code.
Follow up CLs will move some of the logic in src/engine for PNG, USD, KTX, OBJ loading into decoders.
The mj_parse function MjSpec from a given file, it's a more generic version of mj_parseXML.
In it's implementation, mj_parse as opposed to mj_parseXML will look for any registered decoder and
not assume we are striclty dealing with MJCF.
PiperOrigin-RevId: 826149497
Change-Id: I0ece26904280cb94bd5ded6dd5a565c539d60254
This is the correct location, this enum is only used in `mjData`, not `mjModel`.
PiperOrigin-RevId: 798860951
Change-Id: I48b9a2afc831bd9a6966cc9586429fd03605bdd2