Support Multi-Backend for Demo Scripts#5938
Conversation
There was a problem hiding this comment.
Code Review Summary
This PR migrates demo scripts from the legacy AppLauncher pattern to the new launch_simulation context-manager approach, adding multi-backend support (PhysX / Newton MJWarp) and multi-visualizer support (Kit / Newton). The structural changes are consistent and well-organized.
Below are some findings to consider:
Findings
| # | Severity | File | Finding |
|---|---|---|---|
| 1 | 🟡 Medium | bin_packing.py |
string_to_callable used instead of direct import |
| 2 | 🟡 Medium | simulation_context.py |
is_headless_or_exist_active_visualizer() naming & semantics |
| 3 | 🟠 Low | Multiple demos | Duplicated MJWarp solver tuning blocks |
| 4 | 🟠 Low | newton_visualizer.py |
set_camera_view silently ignores calls before initialization |
| 5 | 🟠 Low | bin_packing.py |
Prim path change may break existing saved scenes |
| 6 | 🟢 Nit | arl_robot_1.py |
Unused import from isaaclab_contrib.assets import Multirotor removed but Multirotor class usage replaced silently |
Overall this is a solid, well-tested migration. The inline comments below provide more detail on the actionable items.---
Update (2eeea78): Reviewed incremental changes (1 commit, 6 files).
Changes observed:
arl_robot_1.pyreverted to legacyAppLauncherpattern (removed from multi-backend migration scope)- Added
TYPE_CHECKINGguards for runtime-unused type annotations (Articulation,RigidObjectCollection) inarms.py,bipeds.py,hands.py,quadrupeds.py,bin_packing.py - Import ordering: moved
isaaclab_newton.physicsimports aboveisaaclab.simimports
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): Still present — awaiting maintainer decision (discussion ongoing) - Finding 2 (
is_headless_or_exist_active_visualizernaming): No change — resolved in discussion - Finding 3 (Duplicated MJWarp tuning): No change — accepted as intentional for demo clarity
- Finding 4 (
set_camera_viewearly return): No change — resolved in discussion - Finding 5 (Prim path change): No change — resolved in discussion
- Finding 6 (
arl_robot_1.py): ✅ Moot — script reverted toAppLauncherpattern, no longer part of multi-backend migration
New observations:
- The
TYPE_CHECKINGguards are a clean approach to avoid circular/heavy imports at runtime while maintaining type safety for static analysis. 👍 - Import reordering of
isaaclab_newton.physicsaboveisaaclab.simis consistent across all modified demo scripts.
No new issues found. The incremental changes are clean.
Update (f8d7e25): Reviewed incremental changes (1 commit, 3 files).
Changes observed:
- Import reordering fix in
arms.py,bipeds.py,hands.py: movedisaaclab_newton.physicsimport belowisaaclab.sim/isaaclab.physicsimports and added# isort:skipannotation - This corrects the import ordering from the previous commit (which had placed the newton import above isaaclab imports) to follow the project's import convention: first-party (
isaaclab.*) before extension packages (isaaclab_newton.*,isaaclab_assets.*), with# isort:skipto prevent automated reordering
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): No change — awaiting maintainer decision - Findings 2–6: Previously resolved in discussion
No new issues. The import ordering fix is clean and consistent across all three files. ✅
Update (5ebc064): Reviewed incremental changes (1 commit, 1 file).
Changes observed:
hands.py: MJWarp solver tuning parameters updated —njmax128→200,impratio100→10.0, removedls_iterations/ls_parallel/integrator, addedupdate_data_interval=2,ccd_iterations=50,debug_mode=False- These are physics solver configuration refinements (likely for improved simulation stability/performance)
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): No change — awaiting maintainer decision - Findings 2–6: Previously resolved in discussion
No new issues. The solver parameter changes are straightforward configuration tuning. ✅
Update (44473f5): Reviewed incremental changes (1 commit, 1 file).
Changes observed:
hands.py: Added Shadow Hand Newton MJWarp-specific robot configuration- New import:
ImplicitActuatorCfgfromisaaclab.actuators - New import:
ShadowHandRobotCfgfromisaaclab_tasks.core.shadow_hand.shadow_hand_env_cfg - Created
SHADOW_HAND_NEWTON_MJWARP_CFGthat overrides actuator settings:fingersactuator: stiffness=20.0, damping=2.0- New
distal_passiveactuator for tendon-coupled joints ((FF|MF|RF)J4,LFJ5) with stiffness=10.0, damping=0.1, friction=1e-2, armature=2e-3
- Scene now conditionally uses
SHADOW_HAND_NEWTON_MJWARP_CFGwhen--physics newton_mjwarpis specified - Camera position adjusted: eye
[0.0, -0.35, 1.1]→[0.0, -0.5, 1.5](pulled back for better view)
- New import:
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): No change — awaiting maintainer decision - Findings 2–6: Previously resolved in discussion
New observations:
- The
distal_passiveactuator correctly targets the tendon-coupled distal joints (J4/J5) that require different control parameters than the active finger joints - Using
ShadowHandRobotCfg().newton_mjwarpas a base and then customizing actuators is a clean pattern that reuses existing validated configurations - The camera adjustment improves visibility for the dexterous hand demo
No new issues found. The tendon configuration fix is well-structured. ✅
Update (439a91d): Reviewed incremental changes (1 commit, 1 file).
Changes observed:
quadcopter.py: Method call renamed fromset_forces_and_torques()toset_forces_and_torques_index()— likely aligning with a renamed API method in the wrench composer class.
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): No change — awaiting maintainer decision - Findings 2–6: Previously resolved in discussion
No new issues. Single method name correction to match updated API. ✅
Update (444f582): Reviewed incremental changes (1 commit, 3 files in isaaclab_newton package).
Changes observed:
newton_manager.py: Fixed deferred CUDA graph capture to preserve first-step external wrenches during warmup. State is now snapshot/restored around the warmup step so staged writes (e.g., external forces) aren't consumed before the user-visible graph replay.- New test
test_deferred_relaxed_capture_preserves_first_step_external_wrench: Validates that applying an upward force exactly cancelling gravity results in zero net velocity after one step with deferred graph capture. - New changelog entry documenting the fix.
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): No change — awaiting maintainer decision - Findings 2–6: Previously resolved in discussion
No new issues. The state snapshot/restore pattern is correct and the test coverage is thorough. ✅
Update (656fd2b): Reviewed incremental changes (1 commit, 1 file).
Changes observed:
hands.py: Removed the customSHADOW_HAND_NEWTON_MJWARP_CFGconfiguration block (custom actuator stiffness/damping/friction/armature overrides) and theImplicitActuatorCfgimport. Now usesShadowHandRobotCfg().newton_mjwarpdirectly in the scene design function — a simplification indicating the upstream robot config has been updated with appropriate defaults.
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): No change — awaiting maintainer decision - Findings 2–6: Previously resolved in discussion
No new issues. The simplification is clean — removing demo-local actuator overrides in favor of using the canonical robot config is the right direction. ✅
Update (8527930): Previous concern addressed. No new issues.
- ✅ Fixed:
quadrupeds.pynow usesscene_origins.to(sim.device)instead of wrapping withtorch.tensor()— exactly as suggested. - Finding 1 (
string_to_callableinbin_packing.py): No change — still awaiting maintainer decision. - Findings 2–6: Previously resolved in discussion.
Clean single-line fix, no new issues introduced.
Update (4090883): PR rebased/force-pushed. Reviewed incremental changes vs previous HEAD.
Changes observed:
quadrupeds.py: Addedparser.set_defaults(visualizer=["kit"])for consistency with other demos;define_originsnow returnstorch.Tensordirectly (avoids the.tolist()→torch.tensor()round-trip); removed unusedsim_timevariable; split joint pos/vel writes for clarityscripts/demos/sensors/cameras.py: Fixedsave_images_gridsubtitle lists — added missing "TiledCamera" label for RGB and depth grids- All demos: rebased onto latest
develop(commit timestamps updated); no content changes to the multi-backend migration logic
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): No change — still present, awaiting maintainer decision - Findings 2–6: Previously resolved in discussion
No new issues found. The incremental changes are clean housekeeping (type annotation improvement, missing subtitle fix, unused variable removal). ✅---
Update (47b38b8): ✅ Finding 1 resolved! All previous concerns now addressed.
Changes observed:
bin_packing.py: Removedstring_to_callableimport and replacedstring_to_callable("isaaclab.scene:InteractiveScene")(scene_cfg)withscene_cfg.class_type(scene_cfg)— clean, type-safe, no dynamic string resolution at runtimeinteractive_scene_cfg.py: Addedclass_type: type[InteractiveScene] | str = "{DIR}.interactive_scene:InteractiveScene"attribute toInteractiveSceneCfgwith properTYPE_CHECKINGguard for the type annotation
Previous findings status:
- Finding 1 (
string_to_callableinbin_packing.py): ✅ Resolved — replaced withclass_typepattern from the cfg class, which is the idiomatic IsaacLab approach - Findings 2–6: Previously resolved in discussion
Assessment: The class_type pattern on the cfg dataclass is consistent with how other IsaacLab components (e.g., AssetBaseCfg, SensorBaseCfg) handle class resolution — much better than runtime string_to_callable. All originally flagged issues are now resolved. This PR is ready from a code quality perspective. ✅
Update (d96bf14): New commits only add changelog entries (source/isaaclab/changelog.d/yizew-support-multi-backends.rst and source/isaaclab_visualizers/changelog.d/yizew-support-multi-backends.rst). No code changes. No new issues. All previously flagged concerns remain resolved. ✅
| sim.reset() | ||
| # Now we are ready! | ||
| print("[INFO]: Setup complete...") | ||
| # Run the simulator |
There was a problem hiding this comment.
🟡 Medium: Indirect construction via string_to_callable
Using string_to_callable("isaaclab.scene:InteractiveScene")(scene_cfg) here is unusual compared to the other demos which import and call classes directly. This pattern:
- Obscures the dependency — readers won't immediately see what's being constructed.
- Bypasses static analysis / IDE navigation.
- Differs from the approach in every other demo file in this PR.
Is there a specific reason InteractiveScene cannot be imported directly here (e.g., circular import when Newton backend is active)? If so, a brief comment explaining why would help future maintainers. If not, consider using the direct import for consistency:
from isaaclab.scene import InteractiveScene
scene = InteractiveScene(scene_cfg)There was a problem hiding this comment.
@ooctipus Could you please take a look here? I tried to avoid local imports. Not sure if there exists a better way to achieve.
There was a problem hiding this comment.
Thanks for raising this @YizeWang — happy to share my thoughts while you wait for @ooctipus.
Looking at the file, InteractiveScene is actually already directly imported at the top:
from isaaclab.scene import InteractiveScene, InteractiveSceneCfgSo unless there's a runtime reason the import needs to be deferred (e.g., the class identity changes depending on the active physics backend), you could simply use:
scene = InteractiveScene(scene_cfg)…which would be consistent with the existing import and easier to follow.
If there is a backend-aware dispatch happening (where "isaaclab.scene:InteractiveScene" might resolve to a different class at runtime depending on the physics context), then string_to_callable makes sense — but a short inline comment explaining why would really help future readers. Something like:
# Use string_to_callable to allow backend-specific scene class resolution at runtime.
scene = string_to_callable("isaaclab.scene:InteractiveScene")(scene_cfg)Deferring to @ooctipus on whether the multi-backend machinery requires this indirection here.
There was a problem hiding this comment.
Improved in the latest commit "Remove string_to_callable"
There was a problem hiding this comment.
Great, thanks for removing it! 👍
There was a problem hiding this comment.
Nice, using scene_cfg.class_type(scene_cfg) is even cleaner than my suggestion — it keeps the construction tied to the config definition. Thanks for addressing this! 👍
| self.get_setting("/isaaclab/video/auto_start_kit") | ||
| ) | ||
|
|
||
| def is_headless_or_exist_active_visualizer(self) -> bool: |
There was a problem hiding this comment.
🟡 Medium: Method naming and semantics
The method name is_headless_or_exist_active_visualizer is a bit ambiguous — it reads as a query about the state but is actually used as a loop continuation predicate ("should we keep stepping?").
Consider:
should_continue_stepping()— clearer intent for the loop usage pattern- Or at minimum, update the docstring to clarify: "Returns True when the simulation loop should continue (either no visualizers are attached, or at least one visualizer window is still open)."
Also: the condition not self._visualizers returns True when _visualizers is an empty list. If a visualizer is removed from the list mid-simulation (rather than being marked closed), this would still return True and the loop would run indefinitely. Is that the intended behavior?
There was a problem hiding this comment.
If the visualizer is closed in the mid way, the second condition will be False.
There was a problem hiding this comment.
Ah, that makes sense — thanks for clarifying! So the logic is:
not self._visualizers→ no visualizers attached, headless mode, keep steppingany(viz.is_running() and not viz.is_closed for viz in self._visualizers)→ at least one visualizer is still alive
If the user closes the visualizer window mid-run, is_closed becomes True (or is_running() returns False), the any(...) evaluates to False, and the loop exits. That's a clean shutdown path 👍
The naming concern is minor — the current name does reflect what's checked. If you feel it's clear enough in context, happy to leave it as-is.
There was a problem hiding this comment.
Thanks for clarifying! That makes sense — so the intended behavior is:
- No visualizers attached (
not self._visualizers) → keep stepping (headless mode) - Visualizer(s) attached but all closed → stop the loop (the
any()returnsFalse) - At least one visualizer still open → keep stepping
This is reasonable semantics for a user-facing loop guard. My earlier concern about "running indefinitely" was misplaced since you do handle the closed-visualizer case correctly.
The naming suggestion (should_continue_stepping or similar) is still a mild preference for clarity, but I understand if you want to keep the current name — it's not blocking.
| physics_cfg.solver_cfg.nconmax = 70 | ||
| physics_cfg.solver_cfg.ls_iterations = 40 | ||
| physics_cfg.solver_cfg.cone = "elliptic" | ||
| physics_cfg.solver_cfg.impratio = 100 |
There was a problem hiding this comment.
🟠 Low: Duplicated solver tuning configuration
This identical MJWarp solver configuration block (njmax, nconmax, ls_iterations, cone, impratio, ls_parallel, integrator, num_substeps) is repeated verbatim across arms.py, bipeds.py, and hands.py.
Consider extracting a shared helper or preset:
# In a shared module, e.g. isaaclab_assets.newton_presets
ARTICULATION_MJWARP_PRESET = dict(
njmax=70, nconmax=70, ls_iterations=40,
cone="elliptic", impratio=100,
ls_parallel=False, integrator="implicitfast",
)This reduces the maintenance burden when solver defaults change and makes it obvious which demos share physics characteristics.
There was a problem hiding this comment.
No, we want to expose the way to tune parameters.
There was a problem hiding this comment.
That makes sense — for demo scripts, having the tuning parameters explicit and self-contained is more instructive for users learning how to configure the solver. Keeping each demo standalone avoids an extra indirection that could obscure the workflow.
No objection from me. Thanks for clarifying!
| def set_camera_view( | ||
| self, eye: tuple[float, float, float] | list[float], target: tuple[float, float, float] | list[float] | ||
| ) -> None: | ||
| """Set active viewer camera eye/target. |
There was a problem hiding this comment.
🟠 Low: Silent early return may surprise callers
set_camera_view() silently returns (with only a debug log) if the visualizer isn't initialized. Since this is called in main() before sim.reset(), the timing depends on when the Newton visualizer initializes.
If the visualizer initializes lazily (e.g., on first sim.step()), this camera pose will be lost entirely. Consider:
- Storing the requested pose and applying it once initialization completes (deferred apply pattern), or
- Raising a warning-level log so users notice the no-op during debugging.
The existing SimulationContext.set_camera_view() likely already handles this dispatch — is there a case where this method is called directly on the visualizer instance?
There was a problem hiding this comment.
set_camera_view is implemented in the same way as in kit_visualizer.py.
There was a problem hiding this comment.
This method was previously missing for the Newton visualizer.
There was a problem hiding this comment.
Thanks for the clarification! You're right — I can confirm the pattern matches kit_visualizer.py (early return with a debug log when not initialized). Keeping both implementations consistent makes sense.
The suggestion about a deferred-apply pattern was more of a general improvement idea that would apply to both visualizers equally, not something specific to this PR. No action needed here. 👍
There was a problem hiding this comment.
Makes sense — thanks for adding it! The implementation looks clean.
My comment was less about whether to add it and more about the early-return behavior: if set_camera_view() is called before the visualizer initializes (which can happen in main() before sim.reset()), the requested pose is silently dropped. That said, if the call site ordering guarantees initialization has already happened by then, this is fine as-is. Not a blocker.
| rigid_objects={ | ||
| f"Object_{label}_Layer{layer}": RigidObjectCfg( | ||
| prim_path=f"/World/envs/env_.*/Object_{label}_Layer{layer}", | ||
| prim_path=f"/World/envs/env_.*/Groceries/Object_{label}_Layer{layer}", |
There was a problem hiding this comment.
🟠 Low: Prim path hierarchy change
The prim path changed from /World/envs/env_.*/Object_{label}_Layer{layer} to /World/envs/env_.*/Groceries/Object_{label}_Layer{layer} (added Groceries/ intermediate Xform).
This is fine for a fresh run, but could break:
- Saved USD stages that reference the old paths
- Any downstream tooling or tests that pattern-match on prim paths
Is there a corresponding change that creates the /Groceries Xform prim? I don't see one in this diff — the InteractiveScene may handle it automatically, but it's worth confirming.
There was a problem hiding this comment.
The Newton visualizer needs this change. Otherwise, objects cannot be properly visualized.
There was a problem hiding this comment.
Thanks for the clarification! That makes sense — if Newton visualizer requires this hierarchy for proper object rendering, then this is the right approach. The InteractiveScene should handle creating the intermediate Xform automatically based on the prim path.
Good to go 👍
There was a problem hiding this comment.
Thanks for the clarification! That makes sense — the Newton visualizer likely needs the intermediate /Groceries Xform to correctly traverse and render the child prims in its scene graph.
Since this is a new demo script (not modifying an existing one), there are no pre-existing saved stages or path references to worry about. My concern about backward compatibility doesn't apply here. 👍
No further concerns on this change.
Greptile SummaryThis PR updates seven demo scripts to support a 2×2 matrix of physics backends (PhysX and Newton MJWarp) and visualizer frontends (Kit and Newton), while also adding
Confidence Score: 4/5Safe to merge; the changes are additive demo-script updates with one missing import and one redundant wrapper that don't affect runtime correctness. The core simulation-context and Newton-visualizer changes are clean and well-scoped. The demo scripts are correctly migrated to the new multi-backend launch pattern. The only substantive issues are in bin_packing.py: RigidObjectCollection was dropped from the import but is still used in type annotations (harmless at runtime due to PEP 563, but breaks static analysis), and string_to_callable is applied to a class that is already imported, making the workaround ineffective and confusing. The quadrupeds.py wrapping of an already-tensor return value in torch.tensor() is a minor code-quality concern. scripts/demos/bin_packing.py — missing RigidObjectCollection import and redundant string_to_callable usage. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Script entry point] --> B[parse args: --physics / --visualizer]
B --> C{launch_simulation context manager}
C --> D[PhysX backend]
C --> E[Newton MJWarp backend]
D --> F{Visualizer frontend}
E --> G{Tune MJWarp solver params?}
G -->|arms/bipeds/hands/bin_packing| H[Set njmax, nconmax, ls_iterations, etc.]
G -->|quadcopter/quadrupeds/arl_robot_1| I[Use defaults]
H --> F
I --> F
F --> J[Kit visualizer]
F --> K[Newton visualizer]
J --> L[SimulationContext created]
K --> L
L --> M[sim.set_camera_view - pending replayed after init]
M --> N[scene / robots spawned via cfg.class_type]
N --> O[sim.reset - visualizers initialized]
O --> P{sim.is_headless_or_exist_active_visualizer}
P -->|True| Q[step simulation]
Q --> P
P -->|False| R[exit loop / context cleanup]
|
|
Update (f8d7e25): Reviewed incremental changes (1 commit, 3 files). Changes observed:
Assessment: Purely stylistic fix to maintain consistent import ordering with the |
| ./isaaclab.sh -p scripts/demos/quadcopter.py --visualizer newton | ||
|
|
||
| # Usage with Newton (MJWarp) physics and default kit visualizer. | ||
| ./isaaclab.sh -p scripts/demos/quadcopter.py --physics newton_mjwarp |
There was a problem hiding this comment.
The quadcopter will fall with KitViz + Newton. No issues in other combinations. Still investigating.
There was a problem hiding this comment.
Issue has been filed in #5961. The fix is beyond this PR.
| ./isaaclab.sh -p scripts/demos/hands.py --visualizer newton | ||
|
|
||
| # Usage with Newton (MJWarp) physics and default kit visualizer. | ||
| ./isaaclab.sh -p scripts/demos/hands.py --physics newton_mjwarp |
There was a problem hiding this comment.
The shadow hand does not behave properly with the Newton backend. I tried tuning the MJWarp parameters but had no luck yet. Still investigating.
There was a problem hiding this comment.
Same tendon issue in #5437. This issue has been fixed in my latest commit: "Fix Shadow Hand Tendons".
| if TYPE_CHECKING: | ||
| from isaaclab.assets import Articulation | ||
|
|
||
| _SHADOW_HAND_NEWTON_MJWARP_CFG = ShadowHandRobotCfg().newton_mjwarp |
There was a problem hiding this comment.
The default configuration for the shadow hand does not work in the Newton backend. The analysis is in #5437. These lines are mimicking the fix in the quoted PR.
I think we should create a newton config for shadow hand as a new assest instead of hardcoding the actuations in the user scripts, such as https://github.com/isaac-sim/IsaacLab/pull/5437/changes#diff-1e58eac15480c1da1cba788a3a40401333d0fd9919923b9777a4fa94b6f39d95 and here.
There was a problem hiding this comment.
Were you able to test if #5522 asset was enough and if the additional changes are still needed?
There was a problem hiding this comment.
I have confirmed that #5522 fixes the tendon issue and the shadow hand works without overriding.
444f582 to
656fd2b
Compare
| ./isaaclab.sh -p scripts/demos/quadcopter.py --visualizer newton | ||
|
|
||
| # Usage with Newton (MJWarp) physics and default kit visualizer. | ||
| ./isaaclab.sh -p scripts/demos/quadcopter.py --physics newton_mjwarp |
| if TYPE_CHECKING: | ||
| from isaaclab.assets import Articulation | ||
|
|
||
| _SHADOW_HAND_NEWTON_MJWARP_CFG = ShadowHandRobotCfg().newton_mjwarp |
There was a problem hiding this comment.
I have confirmed that #5522 fixes the tendon issue and the shadow hand works without overriding.
| # Design scene | ||
| scene_cfg = MultiObjectSceneCfg(num_envs=args_cli.num_envs, env_spacing=1.0, replicate_physics=True) | ||
| with Timer("[INFO] Time to create scene: "): | ||
| scene = string_to_callable("isaaclab.scene:InteractiveScene")(scene_cfg) |
There was a problem hiding this comment.
@ooctipus Could you please take a look here? This is how I tried to avoid local imports. Not sure if there exists a better way to achieve.
There was a problem hiding this comment.
we can class_type in Cfg. and used cfg.class_type(cfg) pattern. This allow maximum extensibility, flexibility while protect us from bad import chain
8527930 to
4090883
Compare
|
@YizeWang really nice work! |
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
d96bf14 to
b0847bc
Compare
Description
This PR updates the demo scripts to support running across the default KitViz/PhysX path and NewtonViz/Newton-MJWarp backend combinations.
The affected demos now use consistent CLI parsing, import ordering, usage comments, default Kit visualizer behavior, and visualizer-aware simulation loops. It also tunes selected Newton MJWarp solver parameters for demos that need more stable articulation/contact behavior, avoids resolving
InteractiveScenebefore simulation launch inbin_packing.py, and adds Newton visualizer support forSimulationContext.set_camera_view().Dependencies
Type of change
Validation
Validated the demo matrix for:
scripts/demos/arl_robot_1.pyscripts/demos/arms.pyscripts/demos/bin_packing.pyscripts/demos/bipeds.pyscripts/demos/hands.pyscripts/demos/quadcopter.pyscripts/demos/quadrupeds.pywith:
Screenshots
Checklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists there