Skip to content

Commit 0efb72d

Browse files
Remove deprecated joint target aliases and deprecate the DOF target layout (#3617)
Co-authored-by: Eric Heiden <eheiden@nvidia.com>
1 parent 2747663 commit 0efb72d

63 files changed

Lines changed: 720 additions & 1023 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,11 @@
9696
- Deprecate `SensorTiledCamera(..., config=...)` in favor of `SensorTiledCamera(..., default_render_config=...)`; migrate constructor calls that pass a render config to the new keyword.
9797
- Deprecate `SensorTiledCamera.render_config` in favor of `SensorTiledCamera.default_render_config`; migrate `sensor.render_config.enable_shadows = True` to `sensor.default_render_config.enable_shadows = True`.
9898
- Deprecate `SensorTiledCamera.utils.compute_pinhole_camera_rays()` in favor of `SensorTiledCamera.utils.compute_camera_rays_pinhole()`.
99+
- Deprecate the legacy DOF-shaped `joint_target_q` layout (`newton.use_coord_layout_targets = False`) for models whose joint coordinate and DOF counts differ (free/ball/distance joints); `ModelBuilder.finalize()` now emits a `DeprecationWarning` for such models. Set `newton.use_coord_layout_targets = True` before building models and index targets via `Model.joint_target_q_start`. A future release will make the coordinate layout the only layout and remove the flag.
99100

100101
### Removed
101102

103+
- Remove the deprecated `joint_target_pos` / `joint_target_vel` aliases from `Model`, `Control`, and `ModelBuilder` (deprecated in 1.3.0); use `joint_target_q` / `joint_target_qd` instead. Reading or assigning the removed names raises `AttributeError` naming the replacement, so a stale `control.joint_target_pos = targets` fails loudly instead of being silently ignored. `Actuator` now always defaults `control_target_pos_attr` / `control_target_vel_attr` to the canonical `joint_target_q` / `joint_target_qd` names; passing `None` explicitly selects the same defaults.
102104
- Remove the deprecated SDF compatibility attributes `Model.shape_sdf_index`, `Model.texture_sdf_data`, `Model.texture_sdf_coarse_textures`, `Model.texture_sdf_subgrid_textures`, `Model.texture_sdf_subgrid_start_slots`, `Model.sdf_block_coords`, `Model.sdf_index2blocks`, and `SDF.texture_block_coords` (deprecated in 1.3.0); the hydroelastic broadphase derives block coordinates arithmetically and the remaining storage is internal.
103105
- Remove the deprecated `newton.geometry.build_bvh_shape()`, `refit_bvh_shape()`, `build_bvh_particle()`, and `refit_bvh_particle()` helpers (deprecated in 1.3.0); use `Model.bvh_build_shapes()`, `Model.bvh_refit_shapes()`, `Model.bvh_build_particles()`, and `Model.bvh_refit_particles()` instead.
104106
- Remove the deprecated `Model.has_heightfields` property (deprecated in 1.3.0); use `Model.heightfield_count`, or `model.heightfield_count > 0` for boolean checks, instead.
@@ -155,6 +157,7 @@
155157
- Fix `FastKitchenG1` ASV metrics to build the kitchen scene instead of a plain G1 model.
156158
- Fix the `diffsim_bear` example crashing with its default CUDA configuration and diverging after a few training iterations.
157159
- Fix masked PID state reset to execute on the integral-state device. (#3447)
160+
- Fix `eval_inverse_dynamics_passive()` reading past a DOF-sized scratch buffer under `newton.use_coord_layout_targets = True`, producing intermittent NaNs for models with free, ball, or distance joints.
158161
- Fix MJCF imports ignoring `fromto` transforms and lengths on sites.
159162
- Reject invalid hollow primitive shell thickness before computing inertia.
160163
- Fix `ModelBuilder.add_mjcf()` ignoring positive explicit mass on mesh geoms. (#3595)

docs/migration.rst

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,14 @@ corresponds to :attr:`newton.JointTargetMode.EFFORT` together with
146146
Joint-target layout (``newton.use_coord_layout_targets``)
147147
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
148148

149-
Historically ``Control.joint_target_pos`` was shaped ``(joint_dof_count,)`` — the same layout as
150-
:attr:`~newton.State.joint_qd` — even though position targets semantically match
151-
:attr:`~newton.State.joint_q`. The two layouts diverge whenever an articulation contains a free
152-
joint (7 coords vs. 6 DOFs) or ball joint (4 coords vs. 3 DOFs); every actuated DOF downstream
153-
then ends up indexed with the wrong stride.
149+
In ``warp.sim`` the target array was DOF-shaped like ``joint_qd``. Newton is moving position
150+
targets to the coordinate layout of :attr:`~newton.State.joint_q` instead, since that is what a
151+
position semantically is: the two layouts diverge whenever an articulation contains a free or
152+
distance joint (7 coords vs. 6 DOFs) or ball joint (4 coords vs. 3 DOFs), and under the DOF layout
153+
every actuated DOF downstream of such a joint is indexed with the wrong stride.
154154

155-
Newton 1.3 introduces an opt-in flag to switch ``Model.joint_target_q`` / ``Control.joint_target_q``
156-
to the coord-aligned layout that matches ``joint_q``:
155+
New code should opt into the coordinate layout, which will become the only layout in a future
156+
release:
157157

158158
.. code-block:: python
159159
@@ -167,26 +167,25 @@ to the coord-aligned layout that matches ``joint_q``:
167167
# model.joint_target_q has shape (joint_coord_count,) — matches joint_q
168168
# model.joint_target_qd has shape (joint_dof_count,) — matches joint_qd
169169
170-
Migration steps:
171-
172-
- Replace ``Control.joint_target_pos`` / ``Model.joint_target_pos`` with
173-
:attr:`Control.joint_target_q` / :attr:`Model.joint_target_q`. The legacy names emit a
174-
:class:`DeprecationWarning` and raise :class:`AttributeError` when
175-
``newton.use_coord_layout_targets`` is ``True``.
176-
- Replace ``Control.joint_target_vel`` / ``Model.joint_target_vel`` with
177-
:attr:`Control.joint_target_qd` / :attr:`Model.joint_target_qd`.
178-
- On :class:`ModelBuilder`, ``joint_target_pos`` and ``joint_target_vel`` have been removed.
179-
Configure per-axis targets via :attr:`ModelBuilder.JointDofConfig.target_pos` /
180-
:attr:`~ModelBuilder.JointDofConfig.target_vel` before calling ``add_joint*()``, or write
181-
to :attr:`ModelBuilder.joint_target_q` / :attr:`~ModelBuilder.joint_target_qd` directly.
170+
Under the coordinate layout, ball and free joint position targets are quaternions (plus a
171+
translation for free joints), matching ``joint_q``. Migration notes coming from ``warp.sim``:
172+
173+
- Replace writes to the ``warp.sim`` target arrays with
174+
:attr:`Control.joint_target_q` / :attr:`Control.joint_target_qd`. Configure per-axis initial
175+
targets via :attr:`ModelBuilder.JointDofConfig.target_pos` /
176+
:attr:`~ModelBuilder.JointDofConfig.target_vel` before calling ``add_joint*()``, or write to
177+
:attr:`ModelBuilder.joint_target_q` / :attr:`~ModelBuilder.joint_target_qd` directly.
182178
- When indexing ``joint_target_q`` from user code, use :attr:`Model.joint_target_q_start` (which
183179
aliases :attr:`Model.joint_q_start` when the flag is ``True`` and
184180
:attr:`Model.joint_qd_start` otherwise). Solvers and the actuator library already do this.
185181
- When constructing an :class:`Actuator` with a custom ``pos_indices``, drop the
186182
``target_pos_indices`` argument: with the coord layout it defaults to ``pos_indices``.
187183

188-
A subsequent release will flip the flag's default to ``True`` and remove the legacy
189-
attributes.
184+
The default is still the legacy DOF-shaped layout for backward compatibility with existing Newton
185+
code, but it is deprecated: building a model whose joint coordinate and DOF counts differ
186+
(free/ball/distance joints) under ``use_coord_layout_targets = False`` emits a
187+
:class:`DeprecationWarning` from ``finalize()``. For models without such joints the two layouts
188+
are identical, so no warning is emitted and the switch is invisible.
190189

191190

192191
``ModelBuilder``

docs/solvers/mujoco.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ angular axis behaves as a revolute closure and three as a ball closure;
434434
any other configuration is skipped.
435435

436436
Only the kinematic coupling implied by the joint type is enforced. Any
437-
drive (``joint_target_pos`` / ``joint_target_vel``, PD gains,
437+
drive (``joint_target_q`` / ``joint_target_qd``, PD gains,
438438
``control.joint_f``), joint limits, armature, friction, and
439439
effort/velocity limits authored on the loop-closing joint are **ignored**
440440
by :class:`~newton.solvers.SolverMuJoCo`. Loop-joint DOFs and coordinates

newton/__init__.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,28 @@
1414
use_coord_layout_targets: bool = False
1515
"""Use :attr:`joint_q`-aligned layout for joint position targets.
1616
17-
When ``False`` (the default in 1.3), :class:`~newton.Model` and
18-
:class:`~newton.Control` expose :attr:`joint_target_pos` and
19-
:attr:`joint_target_vel`, both shaped ``(joint_dof_count,)``. Accessing these
20-
attributes emits a :class:`DeprecationWarning` since the position-target layout
21-
is misaligned with :attr:`~newton.State.joint_q` whenever an articulation
22-
contains a free or ball joint upstream of a position-controlled DOF.
17+
Controls the shape of :attr:`~newton.Model.joint_target_q` and
18+
:attr:`~newton.Control.joint_target_q`:
2319
24-
When ``True``, :class:`~newton.Model` and :class:`~newton.Control` instead
25-
expose:
26-
27-
- :attr:`joint_target_q` with shape ``(joint_coord_count,)``, matching
20+
- ``True``: shape ``(joint_coord_count,)``, matching
2821
:attr:`~newton.State.joint_q`.
29-
- :attr:`joint_target_qd` with shape ``(joint_dof_count,)``, matching
30-
:attr:`~newton.State.joint_qd` (same layout as the legacy
31-
:attr:`joint_target_vel`).
22+
- ``False`` (the default): legacy shape ``(joint_dof_count,)``, which is
23+
misaligned with :attr:`~newton.State.joint_q` whenever an articulation
24+
contains a free, ball, or distance joint upstream of a position-controlled
25+
DOF.
26+
27+
:attr:`joint_target_qd` is shaped ``(joint_dof_count,)`` in both layouts,
28+
matching :attr:`~newton.State.joint_qd`.
29+
30+
Solvers, the actuator library, importers, and viewers honor this flag. Toggle
31+
it before constructing a :class:`~newton.ModelBuilder`.
3232
33-
Solvers, the actuator library, importers, and viewers honor this flag and read
34-
whichever attributes are active. Toggle the flag before constructing a
35-
:class:`~newton.ModelBuilder`; a subsequent release will flip the default to
36-
``True``, then remove the flag and the legacy attributes.
33+
.. deprecated:: 1.5
34+
The legacy DOF-shaped layout is deprecated. In a future release the
35+
coordinate layout becomes the only layout and this flag is removed;
36+
``finalize()`` warns when building an affected model (one whose joint
37+
coordinate and DOF counts differ) under ``False``. Set the flag to
38+
``True`` now to migrate.
3739
"""
3840

3941
__all__ = [

newton/_src/actuators/actuator.py

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ def __init__(
8888
effort_indices: wp.array[wp.uint32] | None = None,
8989
state_pos_attr: str = "joint_q",
9090
state_vel_attr: str = "joint_qd",
91-
control_target_pos_attr: str | None = None,
92-
control_target_vel_attr: str | None = None,
91+
control_target_pos_attr: str | None = "joint_target_q",
92+
control_target_vel_attr: str | None = "joint_target_qd",
9393
control_feedforward_attr: str | None = "joint_act",
9494
control_output_attr: str = "joint_f",
9595
control_computed_output_attr: str | None = None,
@@ -107,8 +107,8 @@ def __init__(
107107
``state.joint_q``). Defaults to *indices*. Differs from
108108
*indices* when position and velocity arrays have different
109109
layouts (e.g. floating-base or ball-joint articulations).
110-
target_pos_indices: Indices into ``control.joint_target_pos`` /
111-
``joint_target_q``. Defaults to *pos_indices* when
110+
target_pos_indices: Indices into ``control.joint_target_q``.
111+
Defaults to *pos_indices* when
112112
:attr:`newton.use_coord_layout_targets` is ``True`` (coord
113113
layout), otherwise to *indices* (legacy DOF layout). The flag is
114114
read once here, so toggling ``newton.use_coord_layout_targets``
@@ -119,13 +119,9 @@ def __init__(
119119
state_pos_attr: Attribute on sim_state for positions.
120120
state_vel_attr: Attribute on sim_state for velocities.
121121
control_target_pos_attr: Attribute on sim_control for target positions.
122-
``None`` (default) resolves at construction time based on
123-
:data:`newton.use_coord_layout_targets`: ``True`` →
124-
``"joint_target_q"``; ``False`` → legacy ``"joint_target_pos"``.
122+
``None`` selects the default ``"joint_target_q"``.
125123
control_target_vel_attr: Attribute on sim_control for target velocities.
126-
``None`` (default) resolves at construction time based on
127-
:data:`newton.use_coord_layout_targets`: ``True`` →
128-
``"joint_target_qd"``; ``False`` → legacy ``"joint_target_vel"``.
124+
``None`` selects the default ``"joint_target_qd"``.
129125
control_feedforward_attr: Attribute on sim_control for feedforward effort. None to skip.
130126
control_output_attr: Attribute on sim_control for clamped output effort.
131127
control_computed_output_attr: Attribute on sim_control for raw (pre-clamp)
@@ -159,31 +155,11 @@ def __init__(
159155

160156
self.state_pos_attr = state_pos_attr
161157
self.state_vel_attr = state_vel_attr
162-
if control_target_pos_attr is None or control_target_vel_attr is None:
163-
import warnings # noqa: PLC0415
164-
165-
import newton # noqa: PLC0415
166-
167-
if newton.use_coord_layout_targets:
168-
default_pos_attr, default_vel_attr = "joint_target_q", "joint_target_qd"
169-
else:
170-
default_pos_attr, default_vel_attr = "joint_target_pos", "joint_target_vel"
171-
warnings.warn(
172-
"Actuator default control_target_pos_attr/control_target_vel_attr "
173-
"currently resolves to legacy 'joint_target_pos'/'joint_target_vel' "
174-
"under newton.use_coord_layout_targets=False. The default will switch "
175-
"to canonical 'joint_target_q'/'joint_target_qd' in a future release. "
176-
"Pass control_target_pos_attr='joint_target_q' (and the velocity "
177-
"counterpart) explicitly to lock in the new behaviour now.",
178-
DeprecationWarning,
179-
stacklevel=2,
180-
)
181-
self.control_target_pos_attr = (
182-
control_target_pos_attr if control_target_pos_attr is not None else default_pos_attr
183-
)
184-
self.control_target_vel_attr = (
185-
control_target_vel_attr if control_target_vel_attr is not None else default_vel_attr
186-
)
158+
# These used to default to None and resolve against the target layout.
159+
# Normalize so callers still passing None explicitly keep working
160+
# instead of tripping getattr() with a non-string name in step().
161+
self.control_target_pos_attr = "joint_target_q" if control_target_pos_attr is None else control_target_pos_attr
162+
self.control_target_vel_attr = "joint_target_qd" if control_target_vel_attr is None else control_target_vel_attr
187163
self.control_feedforward_attr = control_feedforward_attr
188164
self.control_output_attr = control_output_attr
189165
self.control_computed_output_attr = control_computed_output_attr

0 commit comments

Comments
 (0)