Projectile parameters are positive scale factors, best adjusted
multiplicatively. Replace the input boxes with logarithmic sliders
spanning 0.1x to 10x the seeded default, which sits at the geometric
midpoint of the range; mass spans 0.1x to 100x since heavy projectiles
are a common want. Ctrl+Click still allows typing values outside the
slider range, and each slider gets a reset button restoring its
default. Adds an ImGui_SliderLog widget operating on mjtNum.
PiperOrigin-RevId: 957071873
Change-Id: Id46eae28f73308d98681ccbeb2764c949f98f9d9
The launch key binding was gated behind a checkbox because it stayed
active with the plugin window closed. Condition it on the window being
open instead: the arming state is visible, so the checkbox is redundant
and the press-proof chord can relax to plain Enter. Text fields and
dialogs are unaffected: plugin chords are not checked while ImGui
captures the keyboard, and built-in shortcuts dispatch first.
PiperOrigin-RevId: 956796864
Change-Id: I4e5b2bdcaafbcc1b1ba113dd37ef8314b3ade49e
Plugin windows could only be closed from the Plugins menu. Pass the
plugin's active flag to ImGui::Begin so the window gets a close button
that writes the same persisted state as the menu toggle. Skip the
update callback while the window is collapsed.
PiperOrigin-RevId: 956795070
Change-Id: I61cb5c26e7af935b6bb296f1b89142a72b0daca1
The classic renderer supports only directional and spot lights, but initLights() set GL light colors for every scene light before dispatching on type, and the render passes enabled GL light slots without filtering. Since no position was ever set for unsupported types (mjLIGHT_POINT, mjLIGHT_IMAGE), OpenGL's default eye-space position turned them into phantom headlights with the model light's diffuse color, washing out the scene. A cast-shadow image light additionally triggered a full shadow pass with an unset light projection.
Filter all light setup and enable sites on a shared type predicate, so unsupported light types contribute nothing. The no-lights ambient fallback now applies when no supported lights are present.
PiperOrigin-RevId: 956696548
Change-Id: Ic29763df7f9330f21d94f14501ae2559fd460f2b
Slider rows in the joints and controls tabs could only be reset through
a hidden right-click context menu. Replace it with a visible reset
button at the right edge of each row, disabled while the value is at
its reset target so the button column doubles as a modified indicator.
Rows split the remaining width equally between slider and label, and
labels clip at the button column. Adds an ImGui_ResetButton widget.
PiperOrigin-RevId: 956627705
Change-Id: I9c178f6cd1cc806c7ffd6f531acf7f2d470d9346
mj_nextActivation indexed actuator_velocity with the actuator id, but the
array is laid out by output address. The two coincide only when all
preceding actuators are single-output, so a DC motor placed after a
multi-output SO3 actuator integrated its bristle state with another
actuator's velocity, while act_dot (computed in mj_fwdActuation with the
correct velocity) disagreed with the actual evolution of the state.
Fixes DCMotorTest.LuGreBristleVelocityOrderInvariance.
The DC motor's LuGre bristle state must integrate the velocity of its own
transmission, so actuator ordering cannot affect it. The test places a
multi-output SO3 actuator before the DC motor, making the motor's actuator
id and output address diverge, and requires the bristle state to match the
motor-first ordering. Currently fails: the exact ZOH update in
mj_nextActivation reads actuator_velocity[actuator_id] instead of the
motor's own actuator_velocity[outadr], so the bristle integrates the SO3
actuator's velocity.
OpenFileDialog and SaveFileDialog hardcoded the user's Documents directory
and placed the full seed path in the name field. Studio seeds dialogs with
the current model's path, so File > Open now starts in the model's
directory with the filename pre-filled, falling back to Documents when no
path is available. Also avoids passing a potentially non-NUL-terminated
string_view to stringWithUTF8String.
PiperOrigin-RevId: 955869713
Change-Id: I7563f2cb2e39089883d5e37a3d259055c26e146c
Every step, the flex block of the implicit effective metric M + K was
factorized by sparse Cholesky, because K depends on the configuration. On
model/flex/bag.xml, added here, that is roughly half the step, against a
comparable share for the constraint solve it exists to accelerate.
Keep only the metric's per-vertex 3x3 diagonal blocks, prefactored. Neither
consumer needs the exact inverse: the CG constraint solver only wants a
preconditioner, and qacc_smooth can come from an iterative solve using those
blocks. They are O(n) to build and to apply, but weaker, so CG runs about twice
the iterations and qacc_smooth becomes an iteration rather than a direct solve.
Net, the bag model steps roughly twice as fast.
The preconditioner, by metric state. Inactive, meaning no flex elasticity or an
explicit integrator: M^-1, unchanged. Bending only (nefmK == 0): M^-1 plus the
exact constant bending factor from mj_setConst on the dofs it covers,
unchanged; that factor is built at model compile time and costs nothing per
step. Per-step stiffness: M^-1 plus the 3x3 blocks, where before it was a
per-step sparse Cholesky, or, when M couples across the flex block, an inner
PCG of up to 50 iterations run once per outer CG iteration.
Only models carrying per-step stretch stiffness change in wall-clock. Both
ponchos hold their timing and take slightly fewer CG iterations than before,
because the preconditioner is now symmetric: it applies M^-1 and the covered
blocks to disjoint sets of dofs, where previously the two overlapped and the
operator was not symmetric, which PCG requires.
mjd_effSolve is the accurate solve of (M + K)x = b; what used to carry that
name only preconditions and is now mjd_effPrec. Its CG guarded the division by
pAp with mjMINVAL, an absolute floor on a quantity that scales with the square
of the right-hand side, so a small b aborted the solve while the curvature was
healthy: four flex models were quietly left short of tolerance. For an SPD
metric the guard is positivity, and with that the same solves converge. The qacc_smooth call site in
mj_fwdAcceleration is textually unchanged but now reaches the iterative solve,
which converges on opt.tolerance rather than a hardcoded threshold, floored in
mjUSESINGLE builds where the squared target is unreachable in float. Reaching
the iteration cap names the ill-conditioned flex stiffness and then reports it
through mjWARN_INERTIA, rather than returning an under-converged result.
Covered dofs are located by walking the covered rows of the stiffness matrix,
as they need not be 3-aligned from dof 0: any joint declared before a flexcomp
shifts them.
mjData.efm_L_rownnz, efm_L_rowadr and efm_L_colind described the sparsity of
the deleted factorization and are removed: left NULL with nonzero mjxmacro
extents they made the Python bindings hand back uninitialized arrays.
efm_active loses the value 2 for the same reason, nothing selects a solve path
on preconditioner exactness any more. Both are recorded under breaking changes.
model/flex/bag.xml is added because no shipped model carried per-step stretch
stiffness. The ponchos are bending-only and trampoline.xml uses an explicit
integrator, so the metric never activates there. It is excluded from
WriteReadCompareTest: stretch stiffness amplifies rest geometry that XML rounds
on save.
needhull_ was only set while iterating geoms, so a mesh whose inertia is
computed from its convex hull never got one unless some geom pointed at
it. mjCMesh::ComputeVolume and ComputeInertia then read graph_[1] and
GraphFaces() off a null pointer and the compiler crashed.
Whether a mesh needs its hull for inertia is a property of the mesh, not
of any geom, so move that condition out of the geom loop and apply it to
every mesh.
Fixes#3431
Convert the four remaining mju_mulMat{,T}{Vec,Mat}3 call sites in this
file to their inlined mji_ equivalents, so the file is consistent after
the review change to the stretch paths. Aliasing is unaffected: the
inlined variants mark the result restrict, and every call already
required a distinct result (the public versions overwrite res while
reading vec).
Per review on #3437: add the missing blank line above the new comment
block, and use the internal inlined mji_mulMat{,T}{Vec,Mat}3 helpers
rather than the public mju_ ones, matching fe9dc584. Six call sites in
the two stretch paths; pre-existing mju_ calls elsewhere in the file are
left alone.
The implicit effective metric assembles the stretch stiffness from
world-space edge vectors, but a flex vertex body's slide dofs are
expressed in its parent body's frame. When that frame is rotated the
assembled operator is therefore not the Jacobian of the passive stretch
force, which mj_flexPassiveStretch already maps into the dof frame with
xmat^T. The metric is then inconsistent with the force it linearizes:
implicit integration loses its stability guarantee, and models that the
same flex handles comfortably in an unrotated frame diverge.
Apply the matching change of basis in both places that build or apply the
stretch stiffness: mjd_flexStretch_mul rotates the input dof vector into
world and the scattered result back, and mjd_flexStiff_assemble sandwiches
each 3x3 block as R_bi^T * blk * R_bj. Both are no-ops when the parent is
unrotated. Bending needs no change: its blocks are isotropic, and
R^T (q I) R = q I.
This completes the fix in fe9dc584, which covered the passive force paths
and the interp (trilinear) derivative but not the standard stretch one.
On a mesh flex inside a body with a 90-degree rotation, the metric's
directional agreement with the force Jacobian goes from cos = 0.57 to
cos = 1.0, and a hanging sheet that previously reached 176% strain
settles at 0.87%.
This change introduces a get_frame method to the viewer protocol, replacing the previous is_running check. This allows the viewer loop to skip rendering and lifecycle events when no active frame is ready (for example, when no browser is connected to the web viewer).
Additionally, this change:
- Adds a shutdown hook to ViewerHandle to wait for the viewer to cleanly release resources before exiting.
- Implements an ExitEvent handler in the viewer protocol to stop the run loop.
- Adds an http_port configuration option for the web viewer.
- Prevents double-closing in the viewer.
PiperOrigin-RevId: 954603868
Change-Id: Iaba7d131dc94191de51150464514dd10fa7834b0
Avoid mutating ImGui draw lists in place by scaling clip rects locally during scissor computation instead of calling ScaleClipRects. This prevents clip rects from growing exponentially on persistent draw lists, such as streamed remote UI. Additionally, clamp the scaled clip rects to the viewport boundaries to prevent Filament's scissor test from rejecting out-of-bounds rects, while avoiding resetting to full-window scissors which would disable clipping.
The draw geometry is now immutable in the Update function (ImGui texture state is still mutated).
PiperOrigin-RevId: 954277141
Change-Id: Ifdf6866bb4eabaca44b020ea40acc246428b4f0b
Also updates MuJoCo files needed to address changes in Filament.
- "build with clang on windows" patch to sync context lines, remove some
upstream conflicts, disable Clang thread-safety attribute errors, and
allow running on MSYS2.
- Skip building Filament samples.
- Add missing <string_view> to material_manager.cc.
This forces git to treat the current directory as the git checkout to apply the
patch to, which avoids issues where a non-git checkout (e.g. from an unpacked
cached tarball) can cause git to find a higher-level git checkout and try to
apply the patches there, which then fails when the files to patch aren't found.
PiperOrigin-RevId: 953377327
Change-Id: I86f51d4e2823b64c825070139479089c7f30e53e
Fast path in mj_flexPassiveInterp, mj_flexPassiveBendInterp, and
mj_flexPassiveStretch assumed body slide joints are world-aligned
(J = I). When parent body has a non-identity quaternion, joint axes
are rotated (J = R_body), causing wrong force mapping and instability
(NaN/Inf in QACC).
Fix: project world-frame forces onto body local frame via
mju_mulMatTVec3(R_body^T, force) before adding to qfrc_spring/damper.
Also fix the derivative paths:
- mjd_flexInterp_kernel fast path: R^T * K_rot * R * vec
- mjd_flexStiff_assemble (CSR): R_bi^T * K_rot_block * R_bj
The CSR-assembled stiffness matrix is the actual path used by the
implicit CG solver (mj_flexCG gate). The test uses solver="CG" to
activate this path; without it, flex stiffness is integrated
explicitly and no derivative fix can help.
Ported from GitHub PR https://github.com/google-deepmind/mujoco/pull/3379
Original author: Devansh (https://github.com/devansh0703)
Fixes https://github.com/google-deepmind/mujoco/issues/3364
PiperOrigin-RevId: 952789284
Change-Id: If924f7160dd16c0cc88170d80e6e605da0fe2e04
This var was missing from the "clean up" step for all the path vars, causing
the cmake cache lookups to silently fail due to path mismatch.
PiperOrigin-RevId: 952410036
Change-Id: I5c542e821317497e899de95e5c62d76f88836e60