[isaacsim.robot_setup.gain_tuner.ui] Gain Tuner UI#

Version: 2.2.0

Overview#

The isaacsim.robot_setup.gain_tuner.ui extension provides the interactive Gain Tuner window for tuning PD gains on robot articulations. Open it from Tools > Robotics > Asset Editors > Gain Tuner.

../../../../_images/preview34.png

Core tuning logic and test runners live in isaacsim.robot_setup.gain_tuner; this extension is the presentation layer only.

Key Components#

The UI is composed of small, focused widgets that the top-level UIBuilder assembles into the window:

UIBuilder: Owns the window layout — a sticky header plus a scrollable body with a Gain Settings page and a Charts page — and wires the widgets to timeline, physics-step, stage, and render events to keep the interface synchronized with the simulation.

Gain Settings page (table view): A single continuous TreeView table lists every tunable joint as one row (index number, joint name, then the gain / advanced columns), above a retained focused-joint detail area. Rows are multi-selected with standard Ctrl+click (toggle) and Shift+click (range) semantics — there are no per-row checkboxes. A search field filters rows by name and a hamburger column-picker button on the toolbar chooses which columns are shown. The table uses fractional column widths so it scales cleanly as the window is expanded or contracted.

The visible columns are driven by the shown joints and the column picker. Stiffness / Kp and Damping / Kd are always present; a Ki column appears when a shown joint has a PID Newton actuator. Dynamic advanced columns (Armature, Max Force, Max Joint Velocity, Joint Friction) auto-select only when at least one shown joint authors the backing schema/attribute and auto-hide when none do; a joint that lacks a given parameter renders that cell blank and uneditable. The hamburger column picker (like the Joint Inspector) is built dynamically from the loaded articulation, not from a fixed catalog: it lists only the categories/columns applicable to the shown joints — Drives Kp/Kd always, Ki only when a PID Newton actuator is present, and each advanced column (and its category, e.g. MuJoCo Joint) only when a shown joint authors the backing schema/attribute — so a pure UsdPhysics.DriveAPI asset shows no MuJoCo-joint category or Ki entry. The read-only BACKENDS row likewise offers only the relevant backends: PhysX always, and MuJoCo only when a shown joint authors mjc:* gains, marking the active solver. Each listed column starts from the schema-driven auto-selection, and toggling a checkbox records a manual override (scoped to the applicable columns) that forces that column on or off. Column visibility and per-cell values are computed by the UI-independent gain_table_model row/column model on top of the core gain_sources helpers (resolve_joint_gains, visible_advanced_gain_columns, read_advanced_gain_cell), so each joint’s gains still default to the source that actually drives it — a Newton actuator when authored, otherwise MuJoCo-native gains while the Newton MuJoCo solver runs, otherwise the PhysicsDriveAPI drive. Newton actuators are backend-independent (the application-side actuator runtime evaluates them, zeroing the joint’s DriveAPI gains while active), so the active source is not decided by the selected backend. Read-only rules carry over unchanged: a cell whose viewed source is not the one driving the joint (a non-active DriveAPI view, or MuJoCo params under a non-MuJoCo solver) is displayed but not editable. The DriveAPI maxForce column stays authored-only (shown only once a joint authors an explicit value, not its +inf schema fallback).

Selection-driven editing (edit applies to the selection). There is no separate “set all” field: editing a gain field on a selected row applies the new value to every selected, editable joint in that column at once. Read-only and blank/inapplicable cells are skipped (Ki only writes PID-actuator rows), matching the same is_viewed_source_editable gating the detail editor uses (selection_edit_row_indices). If only one row is selected, the edit is a plain single-row edit. This means a multi-selection turns any per-cell edit into a bulk edit across the selection.

Units. Stiffness/Damping columns and detail-view fields show a backend-dependent unit: revolute (angular) DOFs read in degrees under PhysX and radians under the Newton backend (any solver, including MuJoCo), while prismatic DOFs use the stage’s linear unit. The column header names the unit for a homogeneous selection (or mixed when angular and linear DOFs are combined) and each cell’s exact unit is available in its tooltip; the units come from the core gain_dof_unit helper driven by the active BackendContext.

Focused-joint detail / test / save area (retained). Selecting a row focuses that joint and rebuilds a compact detail editor below the table — the Controller Gains form (labeled and unit-annotated from the viewed source: Stiffness / Damping for a PhysicsDriveAPI drive, Kp / Kd plus Ki for a Newton actuator, MuJoCo-native Stiffness (mjc) / Damping (mjc) for mjc:* gains), the Advanced Actuator Parameters section, and a validation summary. When a joint authors more than one gain source it shows a per-joint viewed-source toggle (PhysicsDriveAPI / MuJoCo-native / Newton Actuator, the active one tagged (Active)); switching is a pure inspection/comparison view and only the active source is editable. Mimic joints are constraint-driven and are excluded from the tunable joint list (and from the Test Gains and plot pickers), so they never appear as rows.

For editable PhysX PhysicsDriveAPI gains, the detail editor keeps its Stiffness / DampingNatural Frequency / Damping Ratio toggle, which swaps the two gain fields. In natural-frequency mode the fields show the target natural frequency (Hz) and dimensionless damping ratio, converted to drive stiffness/damping using the joint’s effective inertia (from the gain tuner’s accumulated-inertia computation) and the drive type (force vs acceleration). Edits are written back to the same DriveAPI attributes, so the existing save / MuJoCo-mirror plan persists them unchanged. The toggle is hidden for Newton actuator gains, MuJoCo raw parameters, and mimic joints.

Advanced Actuator Parameters (in the detail editor, both backends): PhysicsDriveAPI joints expose armature and max drive limits (max drive force, max joint velocity, joint friction) read from and written back to USD; Newton actuators show control-range / force-limit / saturation / anti-windup as read-only pending the actuator introspection API.

Test Gains page (validation): Hosts the whole validation workflow — Test Gains Settings (run test, duration, mode, and the per-joint test-configuration table from test_table_widget) plus the Position and Effort result charts. The mode selector offers Snap to Limits, Sinusoidal, Step Function, Stress, and dt Sweep (a physics-timestep sweep that probes how each joint’s position-control accuracy degrades from a coarse to a fine timestep and classifies it at a target dt). Validation results live here, not in the per-joint Gain Settings view. Joints driven by a Newton actuator or by active MuJoCo-native gains are commanded during tests too: because the actuator runtime zeros their DriveAPI stiffness/damping, the tuner classifies them from their actuator / mjc gains (position, or velocity when only a damping-like gain is present) so every test type (step / sinusoidal, snap-to-limits, and stress) sends them position/velocity targets that the actuator or MuJoCo solver converts to motion.

Table widgets (base_table_widget, cell_widget, color_table_widget, test_table_widget): Shared table infrastructure and per-joint color coding used by the test-configuration table and the Charts color picker.

Supporting widgets (frame_widget, dropdown_widget): Collapsible frames and combo boxes.

Visualization (chart_widget, plot_widget): Position and effort plots for reviewing test results.

BackendContext: A single data object describing the active physics backend (PhysX / Newton), gain source, and save target. The UI reads all backend state from this object; its derived helpers (show_solver, solver_label, solver_display, backend_display, solver_short, is_mujoco_solver, show_ki, source_label, save_target_resolved, has_mirror_sources) drive the read-only Backend:/Solver: info tags in the header and the Save Target row (is_mujoco_solver also gates whether MuJoCo-native gains are editable/testable). BackendContext.from_app(stage) detects the live backend and Newton solver from the running app (falling back to PhysX when unavailable), resolving the solver from the stage’s Newton physics scene before Newton has initialized. The solver is load-bearing rather than cosmetic: solver_type carries the raw token that selects the schema-resolver order the advanced joint parameters are read through, and solver_known reports when that order cannot be determined. BackendContext.apply_save_targets() populates the resolved DriveAPI save-target candidates and the mjc/Newton mirror state from the core resolve_gain_write_targets helper.

gains_tuner_backend: Bridges the UI to the core extension, re-exporting GainTuner and GainsTestMode from isaacsim.robot_setup.gain_tuner.

Test results summary#

Every test mode presents an overall results summary at the top of the Test Gains tab, above the Position and Effort charts, so the scene-level outcome is read first. The summary is a scene-level verdict banner above an all-joints results table (one row per tested joint) with consistent column styling across modes:

  • Snap to Limits. Verdict banner (ALL JOINTS PASSED, ALL GAINS OK - SOME JOINTS BLOCKED, or SOME JOINTS FAILED) above a table: Joint | Lower Mean | Lower Max | Lower Settle | Upper Mean | Upper Max | Upper Settle | Result. The Result cell is color-coded (green pass, amber blocked, red fail).

  • Stress. A mode/seed context line and verdict banner (ALL JOINTS STABLE or INSTABILITY DETECTED) above a table: Joint | Max Vel | Trigger Time | Trigger Vel | Result. The Result cell is color-coded (green stable, red unstable).

  • dt Sweep. Verdict banner (ALL ACCURATE AT TARGET DT, ACCURACY DEGRADED AT TARGET DT, JOINTS DID NOT SETTLE AT TARGET DT, or REFERENCE DT DID NOT SETTLE (INDETERMINATE)) above a table: Joint | Result | Settle @ Target | SS Error | Accuracy Cliff (dt / Hz). The Result cell is color-coded (green accurate, amber degraded/indeterminate, red did-not-settle). A joint is reported indeterminate when its finest-dt reference run never settled, so there is no valid baseline to measure degradation against. A header line names the target dt (Target dt: <s> s (<Hz> Hz)  |  reference = finest dt), and tooltips on the Settle @ Target and Accuracy Cliff columns explain that degradation is measured against the finest-dt reference run.

dt Sweep specifics#

The dt Sweep mode characterizes how each joint’s position-control accuracy changes with the physics timestep, and adds the following to its results:

  • Settle time / steady-state error vs dt charts. For the joints selected in the color picker, the sweep plots settling time and steady-state error against the physics timestep (dt on the x axis in milliseconds, fine to coarse), with a caption naming the target dt.

  • Target-dt Position / Effort charts. The retained Position and Effort trajectories show the run at the target dt level (not the finest swept level).

  • During-run progress. While the sweep runs, the progress readout names the current timestep level, for example dt level 3/10: 120 Hz (dt=0.00833 s).

  • Options panel. The dt Sweep settings are grouped into Timestep range, Probe, and Accuracy thresholds, each field carrying a units label and an explanatory tooltip.

  • Timestep-range validation. The independently editable dt Max / dt Min bounds are validated before the sweep runs: reversed, equal, non-positive, or non-finite bounds (or an invalid target dt) are rejected with a clear notification and the sweep does not start, so a bounds inversion cannot silently produce a wrong accuracy cliff or verdict.

Save targets & backend mirroring#

Tuned gains persist to USD layers through the core save plan (resolve_gain_write_targets / build_gain_save_plan / apply_gain_save_plan), surfaced in the Save Target row below the joint split pane.

  • DriveAPI save target (default physics.usda). DriveAPI stiffness/damping default to the neutral, human-editable payloads/Physics/physics.usda layer, which stays first in the Save Target dropdown. The dropdown also lists every other payloads/Physics/*.usda layer discovered on the stage — for example a backend-specific physx.usda overlay — so the user can route the DriveAPI write to that layer instead to tune per backend. Selecting a layer routes the DriveAPI edits to it in the save plan; the neutral physics.usda remains the default when no explicit choice is made. Candidate layers are gathered from the composed stage’s layer stack, so a physx.usda sibling is offered even when the joint’s current DriveAPI opinion is authored in a different (for example root) layer.

  • MuJoCo (mjc:*) editing / opt-in mirror. There are two distinct MuJoCo paths. (1) When the Newton MuJoCo solver is the active solver, the MuJoCo-native gains are the joint’s editable active source: edits are authored directly into the mjc:* arrays and the save plan preserves those edited values. (2) When DriveAPI is the active/tuned source (PhysX, or any non-MuJoCo Newton solver), the DriveAPI→MuJoCo mirror is an explicit opt-in that is OFF by default — a save writes only the DriveAPI gains and never touches any mjc:* actuator prim. If the user ticks the mirror checkbox, saving additionally mirrors the tuned Kp/Kd into the joint’s MjcActuator parameters (MuJoCo stays a mirror; it does not become the active source). The mapping matches the MJCF importer: position control (kp > 0) → gainPrm = [kp, 0, ...], biasPrm = [0, -kp, -kd, ...]; velocity control (kp == 0, kd > 0) → gainPrm = [kd, 0, ...], biasPrm = [0, 0, -kd, ...], with gainType = fixed / biasType = affine.

  • Newton actuator writeback. When a joint is driven by a Newton actuator, saving writes the tuned gains back onto the actuator prim’s newton:kp / newton:kd / newton:ki attributes (its own active source), on by default.

  • Mirror checkbox + target pickers. The Mirror tuned DriveAPI gains to MuJoCo checkbox is OFF by default so a save never authors MuJoCo actuator prims unless the user opts in; it appears only when the robot has MuJoCo-native gains and the MuJoCo solver is not the active solver. When ticked, the mjc target is selectable (default mujoco.usda). The Newton writeback and its target picker (default the actuator prim’s own defining layer) appear when the robot has Newton actuators. Note: because the DriveAPI→MuJoCo mirror is off by default, mjc:* values are left unchanged unless the user opts in, so PhysX and MuJoCo can intentionally differ until the mirror is enabled.

  • Asset context. Shipped MuJoCo Menagerie assets carry DriveAPI gains in physics.usda with parallel mjc:* gains in mujoco.usda; none ship Newton actuators. (robotiq_2f85_v4 carries a NewtonMimicAPI kinematic coupling, which is not a gain source.)

Preview

Enable Extension#

The extension can be enabled (if not already) in one of the following ways:

Define the next entry as an application argument from a terminal.

APP_SCRIPT.(sh|bat) --enable isaacsim.robot_setup.gain_tuner.ui

Define the next entry under [dependencies] in an experience (.kit) file or an extension configuration (extension.toml) file.

[dependencies]
"isaacsim.robot_setup.gain_tuner.ui" = {}

Open the Window > Extensions menu in a running application instance and search for isaacsim.robot_setup.gain_tuner.ui. Then, toggle the enable control button if it is not already active.

Actions in isaacsim.robot_setup.gain_tuner.ui#

ID

Display Name

Description

CreateUIExtension:Gain Tuner

Add Gain Tuner to UI toolbar