Commit Graph

114 Commits

Author SHA1 Message Date
Yuval Tassa 2f1843f4a7 Redesign the dcmotor controller: setpoint inputs, torque-space gains.
The dcmotor input block is any subset of the canonical list [pos, vel,
ff, voltage], selected with input="pos vel ff voltage" and recorded as
mjtCtrlInput bits in actuator_ctrlspec like pid. Tokens are required in
canonical order: the attribute denotes a set, the block always packs
canonically, and accepting permutations invites reading the string as a
layout choice. The mode flag in gainprm[8] is retired (reserved,
written 0).

Controller gains are now in torque space, as for pid: the controller
commands tau = kp*(q*-l) + kd*(v*-ldot) + ki*x_I + tau_ff over the
present inputs (absent setpoints frozen at zero) and converts to drive
voltage V = R/K * tau + K*ldot. The second term compensates back-EMF,
as the current loop of a real torque-mode driver does (torque commands
are current commands): commanded torque is delivered exactly until a
limit binds, and the torque-speed envelope emerges from the Vmax clamp.
The map uses the nameplate R: thermal resistance growth is not
compensated, so a hot motor under-delivers by R/R(T). A stateless
setpoint dcmotor now matches <pid> exactly, for any K and R; the old
back-EMF droop remains available as the physical behavior of the raw
voltage path. Voltage-space datasheet gains convert by K/R. Controller
inputs require a positive motor constant (the map divides by K), and
controller gains require a controller input.

ff and voltage are distinct inputs, different in kind: ff is a torque
feedforward added to the controller output, uniform with pid's ff
(feedforward in the actuator's output space), while voltage is the raw
terminal voltage of the physical device, injected downstream of the
controller and its Vmax clamp, unclamped (ctrlrange bounds it if
desired). input="voltage" is the default: the plain voltage-commanded
motor, whose behavior is unchanged by this commit. The integrator
always accumulates position error; the old velocity mode's integral
term, ki*(int(u)dt - theta), which tracked the integral of the velocity
command, is retired without replacement, keeping ki mode-independent --
commanded integrated velocity belongs to an integrator activation
state, not to controller gains. slewmax rate-limits the first controller
input -- position setpoint (rad/s), velocity setpoint (rad/s^2) or torque
feedforward (N*m/s), each a real driver feature (reference ramping,
ramped-velocity and ramped-torque input modes); the raw voltage input
is never rate-limited and slewmax requires a controller input.

input="none" selects the empty signature: the actuator owns no controls
at all (nu = 0 is now legal with actuators present) and is purely
passive -- LuGre friction, cogging and back-EMF braking as passive
joint forces. This exists because auxiliary dynamic states (the LuGre
bristle) attach to actuators, not joints. The terminal voltage is
identically zero, i.e. a shorted motor (dynamic braking); motorconst=0
decouples the electrical branch. mjINPUT_NONE is a distinct enum value
because ctrlspec = 0 means "unset, use the type default". History and
delay require an input; the controller voltage override and input read
in mj_fwdActuation are gated on a nonempty block.

The analytic velocity derivative of the controller becomes
dV/dw = -kd*R/K + K, whose second term cancels the back-EMF bias
exactly: the net damping of an unclipped torque-mode motor is -kd, and
of a voltage-mode or passive motor -K^2/R. Viewers label inputs via
mj_actuatorInputName: pos, vel, ff, voltage.

The dcmotor LaTeX design doc is updated accordingly: torque-space
units, the tau->V map and its saturation-generated envelope, the
input-block pipeline figure, and a Passive Operation section.

PiperOrigin-RevId: 965795351
Change-Id: Ibc308ca21bd6bad014e77f950ee08feaad449b73
2026-08-17 00:43:48 -07:00
Yuval Tassa 790f8fac30 Generate the MJCF grammar table and enforce its constraints.
The hand-written MJCF[] table in xml_native_reader.cc is replaced by
mjcf_table.inc, emitted from mjcf.schema by generate_mjcf_table.py and
checked for freshness by doc_test. nMJCF is now self-sizing. The two
tables are identical as trees of (tag, cardinality, attribute-set);
within-row attribute order changes where the schema factors shared
groups and projects default-context rows, and top-level rows follow
the schema's dependency order -- neither affects validation, which is
set-based, nor XMLschema.rst, whose generator orders sections itself
(regenerated here, reading the .inc instead of the reader source).

The schema's constraint declarations become enforcement: the emitter
writes a companion MJCF_constraints[] array (row-indexed into MJCF[]),
and mjXSchema::Check evaluates each element's constraints after its
attribute check, with uniform messages derived from the declaration:
"at most one of 'fovy', 'sensorsize' can be specified", "attributes
'reftype', 'refname' must be specified together", and so on.
Multi-attribute bundles render as ('site1', 'site2').

Fifteen hand-written co-occurrence checks across fourteen elements are
deleted -- connect/weld semantics mixing and completeness, the actuator
transmission mutex, camera fovy/sensorsize, light directional/type,
inertial fullinertia-versus-orientation, rangefinder and the distance
family, contact's matching criteria, user-sensor pairing, the frame
family's reftype/refname, size memory exclusivities, mesh builtin
exclusions, and attach body/frame (newly declared). Tests assert the
uniform messages.

Two findings along the way: sensorsize-requires-resolution is a
value-level compiler rule (positive resolution), not a presence rule --
a presence constraint would be wrong and is not declared; and Size()'s
nstack/njmax range checks tested the spec value before assignment, so
they never validated the parsed value -- now they do.

Verified by compiling all 81 models in the model/ corpus.

PiperOrigin-RevId: 958064622
Change-Id: I802cf5c0aee08a62926e36a281320ff9e34c0668
2026-08-02 16:30:02 -07:00
Yuval Tassa 56a93979e0 Interpret position and intvelocity setpoints on 3D rotational transmissions (ball joints, site+refsite) on the circle. The force uses the setpoint representative nearest the current length for smooth tracking beyond pi.
- Wrapping in force path is local; act is re-anchored at integration time.
- Remove hardcoded `actrange` for intvelocity actuators.

PiperOrigin-RevId: 949566477
Change-Id: I349fdf17eedfbb2174d698cc1a6a91d52810b4a3
2026-07-17 07:49:30 -07:00
Google DeepMind faf0dabc32 Fix damper kv inheritance from default classes in XML native reader
Ensured dampers correctly read inherited values from gainprm[2].

PiperOrigin-RevId: 945086959
Change-Id: I10900f3ad057036115da88ad6d649d3d058e7373
2026-07-09 06:44:22 -07:00
Yuval Tassa 2d283b5e9d Allow self-attach in MJCF
PiperOrigin-RevId: 941676717
Change-Id: I9ff8fc89716bc14b438a41e2b4075bbe5fdb83cf
2026-07-02 06:51:46 -07:00
Yuval Tassa 0e58c48504 Clean up MJCF attach code.
PiperOrigin-RevId: 941603845
Change-Id: I94f275e2073b1eb81cfabdc0bed80021c6f15b1c
2026-07-02 03:45:39 -07:00
Kyle Bayes 1490336955 Change LoadModelFromString to return a smart pointer, add MakeData, and update tests to have C++ RAII clean up model and data.
PiperOrigin-RevId: 935980153
Change-Id: I41d25bfab4935494dc984168820cb7cad123cadf
2026-06-22 04:19:01 -07:00
Yuval Tassa cedaa47d61 Migrate tests to use MockWarningHandler for warning interception.
PiperOrigin-RevId: 933656759
Change-Id: Ia21514c302799034bf598445933dd90427284737
2026-06-17 05:06:57 -07:00
Yuval Tassa 410c73168c Add policies for global attribute conflict resolution upon attach
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
2026-06-17 03:36:10 -07:00
Yuval Tassa 67a1ea6dca Track authored flags for global attributes
PiperOrigin-RevId: 931585539
Change-Id: Ifdc8c59de6c5a553daf6e0af09d8192aff6b0610
2026-06-13 02:58:32 -07:00
Yuval Tassa d80a847bae Move CompareModel to a separate library.
PiperOrigin-RevId: 927174846
Change-Id: Ia8b8b2c8593133d8910399be755e614282bf3252
2026-06-05 02:44:53 -07:00
Yuval Tassa 4358a102cd Add manual test for CG converence
Also add MJTOL_SCALE to fixture to allow tests to be run with zero tolerance. This is useful when assesing the impact of code changes (A/B comparison of failure values)

PiperOrigin-RevId: 924219083
Change-Id: Ifdd09ac850904ca8dd79179930ce738a4b37d284
2026-05-31 03:15:54 -07:00
Yuval Tassa 393c1e4217 Migrate mjtByte to mjtBool for boolean-valued fields.
PiperOrigin-RevId: 921408093
Change-Id: Icb00457836359779f0f72fc02d6a7c0dc9f6bd23
2026-05-26 05:35:49 -07:00
Yuval Tassa 81720071b8 Changes to dcmotor:
- Remove `lugre:viscous`, should now be added directly to actuator `damping`. Trying to do this for the user was incompatible with default inheritance (compounding instead of overriding).
- Move voltage limiting from the `saturation` to the `controller` attribute.
- Fix indexing issues in default inheritance.

PiperOrigin-RevId: 897087642
Change-Id: I5388c2633e15c7e223992e7eb5d6a28db75a6438
2026-04-09 06:52:45 -07:00
Yuval Tassa 70a7647ad9 Add <dcmotor> actuator and related docs and tests.
PiperOrigin-RevId: 892927987
Change-Id: I38ed6412801341ba03ddf5fe7b93a6081df24d37
2026-04-01 07:50:23 -07:00
Yuval Tassa 510d75f4cf Allow actuators to add damping and armature to joint and tendon transmissions.
PiperOrigin-RevId: 886899849
Change-Id: I02200ee0d4f7c96096d8188b95f823b566562a30
2026-03-20 11:41:15 -07:00
Yuval Tassa 9fa3f6f77e Enable float32 testing for most MuJoCo engine and user tests.
PiperOrigin-RevId: 886697701
Change-Id: I4a96fae03ea18494c3fcef8eb17b3b6f0863e9b7
2026-03-20 04:05:06 -07:00
Adrian Collister d881e9e374 Change tex_adr type to mjtSize.
Adds a test which verifies that we can index into the texture buffer at offsets larger than can be represented by a 32-bit signed int.

PiperOrigin-RevId: 868756646
Change-Id: Ibc1a2b269fce41aec370611b0aab77803837e7a8
2026-02-11 11:09:36 -08:00
Yuval Tassa 6419534bad Add actuator and sensor delays. Fixes #1004
PiperOrigin-RevId: 866478839
Change-Id: Id21a6da0f98454c8fa39ea5af8a5e213d6eae497
2026-02-06 08:47:36 -08:00
Yuval Tassa 30b903b6c0 Migrate mjModel size fields from int to mjtSize.
This change updates all size-related members within the `mjModel` struct from `int` to `mjtSize`. This allows MuJoCo to handle models with a larger number of elements. Corresponding changes were made to macros, function signatures, and I/O routines to accommodate the new `mjtSize` type.

PiperOrigin-RevId: 860144595
Change-Id: I701c6d607715d240766b6210a9773cd9e4258c59
2026-01-23 09:41:49 -08:00
Yuval Tassa 608115ab95 Add output attribute to camera elements.
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
2026-01-07 10:22:27 -08:00
Yuval Tassa 158525269b Refactor camera intrinsic parameter handling.
Move logic from parser to compiler.

PiperOrigin-RevId: 847689906
Change-Id: I844746081973205e1b33a3845add842e8b8c3c07
2025-12-22 03:08:18 -08:00
Yuval Tassa b8a4ac5d48 Refactor camera orthographic attribute to projection enum.
PiperOrigin-RevId: 847069028
Change-Id: I7f686fe654e9b56519cab8bd2f37c9cc40091d3f
2025-12-20 03:28:29 -08:00
Alessio Quaglino b6f25ca623 Check mjs_getName return value in XML parser. Fixes #2898.
PiperOrigin-RevId: 819351410
Change-Id: I0807d71328068f6388991ae15274c7d61b4d3e53
2025-10-14 12:40:28 -07:00
Alessio Quaglino 9d5063799f Resize keyframes also at the start of compilation.
Previously, it was assumed that attaching was the last operation performed on the mjSpec, so keyframes resulted in the incorrect size. In order to prevent information loss, we now only allow the resize function to expand the keyframe array, since attach should never remove a degree of freedom.

PiperOrigin-RevId: 804917828
Change-Id: Icfacd207ced1c6aac600d514f8d9065ceff2d347
2025-09-09 08:16:32 -07:00
Yuval Tassa f077fd00a9 Compute sparse matrix sizes before making the mjModel in the compiler.
PiperOrigin-RevId: 794998215
Change-Id: Ib7d0a2479b18cc8b3168c0656d3c4be0eff43a0f
2025-08-14 05:51:17 -07:00
Yuval Tassa a5d4d1000e Add built-in supertoroid mesh.
PiperOrigin-RevId: 791180080
Change-Id: I3a70f50ff4a52a1bd4b88fc30334a574895145b4
2025-08-05 06:06:43 -07:00
Yuval Tassa a5a6379f83 Add built-in cone mesh type.
Also delete `prism` type since it is subsumed by cone.

PiperOrigin-RevId: 790992343
Change-Id: I7a9c6f2a4377489173acd64b23086c748d2cee8e
2025-08-04 19:35:32 -07:00
Alessio Quaglino 89f4789085 Add mjs_makeMesh to create a builtin mesh.
PiperOrigin-RevId: 788538127
Change-Id: I999733399a1a0da07b0f915f34d31364ab8b3b52
2025-07-29 11:31:18 -07:00
Yuval Tassa e1f5ceb65a Add mjModel.tendon_armature (in preparation, not yet implemented)
PiperOrigin-RevId: 743649968
Change-Id: I1d893e3e06afc48b652575bc7837750ab3573670
2025-04-03 12:06:27 -07:00
Alessio Quaglino 86c970bc23 Add error checking in mjs_setFrame.
Also raise error if the frame is not found in the mjCBody copy constructor.

Fixes #2543.

PiperOrigin-RevId: 742624013
Change-Id: I4999b3165c97f8d079412214d027ca7a8dae8cb3
2025-04-01 03:34:48 -07:00
Alessio Quaglino bae5175cf2 Accumulate rotation after updating pos and quat in replicate.
Fixes #2501.

PiperOrigin-RevId: 737929158
Change-Id: I0cad2de37190f1d30d427ae646acbde335b5be56
2025-03-18 02:51:05 -07:00
Alessio Quaglino 8e300eb628 Update list ids immediately during body detach.
Fixes #2499.

PiperOrigin-RevId: 736449320
Change-Id: Ieeae52bdbbbb896d886221ab088229c8287a32a3
2025-03-13 03:55:58 -07:00
Alessio Quaglino c52d1b3941 Remove the particle composite (replaced by replicate).
PiperOrigin-RevId: 730089997
Change-Id: If8d18fb56ae01241e76f84dbf7951e034026d829
2025-02-23 03:14:11 -08:00
Alessio Quaglino 0fcd20f0da Remove grid from composite types.
Replaced it with flexcomp in the models.

PiperOrigin-RevId: 730070619
Change-Id: Icbc69e4c6784c6252743f689a1eafb6482d0c393
2025-02-23 01:31:41 -08:00
Alessio Quaglino 6aabbc1892 Fixes an issue when self-attaching a model with pulley in tendons.
The decision to attach a tendon is taken by looking at whether any of the elements in its path exist when the namespace is added to them. This does not work when pulleys are present so we need to ignore them in the count of unreferenced element.

PiperOrigin-RevId: 729484365
Change-Id: I561a3a2eaa975a17421c8abe3ebfec8d4dd88951
2025-02-21 04:54:31 -08:00
Tom Power 89253d957d Changes to inertia inference from meshes.
PiperOrigin-RevId: 726051033
Change-Id: I6edfc118280d103a2dd9d07f29f0094858769761
2025-02-12 07:43:13 -08:00
Alessio Quaglino 6654d63438 Add spec lookup in the attached spec array using the compiler option pointer.
This enables to find the spec associated with the compiler option stored in the objects, which do not necessarily belong to the model that owns them.

PiperOrigin-RevId: 713259419
Change-Id: I579c770147ff07ed2a5edd20e7a795ee7cc27147
2025-01-08 05:44:00 -08:00
Alessio Quaglino 831d9881d3 Remove box, cylinder and ellipsoid composite types.
Also, fix a bug with Flex textures that was causing an incorrect allocation of the textures in mjModel. Fixes #2013.

PiperOrigin-RevId: 692510858
Change-Id: If781716216974e085244da27bc3aa57d91c3458c
2024-11-02 11:14:13 -07:00
Yuval Tassa a4a6248a06 Move AsVector utility to fixture.h
PiperOrigin-RevId: 690577546
Change-Id: I2cebcffa1f2e3b0789f43e772e364c4762719ab3
2024-10-28 05:52:25 -07:00
Yuval Tassa 61cb552f8a Refactor PBR texture layers from separate sub-elements to a single layer sub-element.
Add new element to PyMJCF schema.

PiperOrigin-RevId: 690115286
Change-Id: I7bb3f184cb321ca96037b2ca0ee160efef37469d
2024-10-26 07:41:38 -07:00
Alessio Quaglino bfa78614c8 Require prefix for the attach tag.
For `mjs_attachFrame` and `mjs_attachBody`, require either a prefix or suffix.

It is tempting for users to not use a prefix (see #2162), but this causes issues. For example, it creates a duplicate "main" default class in the parent as a child of the already existing "main" default.

PiperOrigin-RevId: 688535755
Change-Id: I653181ca35943f1e4eb89c70fca8b5289818324e
2024-10-22 07:08:33 -07:00
Alessio Quaglino c84f35b425 Do not delete pending keyframes during body detachment.
PiperOrigin-RevId: 685670895
Change-Id: Iadd0ba8ca7e74a280559168ac0ac855405a1cfd9
2024-10-14 05:23:46 -07:00
Alessio Quaglino 52a0149cd1 Resizes keyframes before storing them during attach/detach.
Improve keyframe tests.

PiperOrigin-RevId: 685450257
Change-Id: I97aa129c4d7a66f613290605b85657e8081700b6
2024-10-13 10:02:35 -07:00
Yuval Tassa 50f43b8745 Fix various issues with body inertial parsing and compiling.
- Add errors in body compiler for incorrect mixing of specifiers.
- Correctly process inertia orientation specifiers.

PiperOrigin-RevId: 676843326
Change-Id: I7e7eb22e25a6769754794f98fad5e0dcc0e5946f
2024-09-20 07:53:42 -07:00
Alessio Quaglino da15aa6a0e Improve error message for fullinertia and orientation specifiers.
Fixes #1888.

PiperOrigin-RevId: 661359190
Change-Id: Ibe38e88024b4a43922352b42347abf1026f168a2
2024-08-09 12:20:27 -07:00
Nimrod Gileadi 6a8e28f0e9 Prevent integer overflow when computing texture sizes and allocating memory for them.
Correctly check for failed allocations when resizing std::vector

PiperOrigin-RevId: 659488680
Change-Id: I7bf4c0b416e96eda2baec32b21be78456604f4b0
2024-08-05 02:58:46 -07:00
Kyle Bayes 5ac5cfb618 Support directories in VFS via mj_addBufferVFS.
PiperOrigin-RevId: 655286683
Change-Id: I846376a0571d8df28d979beb5981a0cbccd7a04f
2024-07-23 13:39:18 -07:00
Kyle Bayes 2746cb8559 Support FilePaths instead of raw strings in XML code.
PiperOrigin-RevId: 655177026
Change-Id: I55b055551384b01ba7a4baa5d75fbe3329b7d25d
2024-07-23 08:36:53 -07:00
Tom Erez 33e5960653 Allow multiple textures per material in MJCF.
PiperOrigin-RevId: 654795013
Change-Id: I418b72533484d00accaf801a342aa183e602a2d0
2024-07-22 09:57:51 -07:00