-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Enable deterministic Newton physics #6930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
kellyguo11
merged 11 commits into
isaac-sim:develop
from
kellyguo11:kellyguo11/newton-gpu-determinism
Aug 9, 2026
Merged
Changes from 4 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
4c127c0
Enable deterministic Newton physics
kellyguo11 98022f8
Merge branch 'develop' into kellyguo11/newton-gpu-determinism
kellyguo11 0229f80
Merge remote-tracking branch 'upstream/develop' into kellyguo11/newto…
kellyguo11 bf1ea5e
Decouple Newton determinism from launcher
kellyguo11 4b69e3a
Test Newton environment determinism
kellyguo11 0e8ff8e
Use bounded Newton determinism task
kellyguo11 5527078
Bound Newton determinism test runtime
kellyguo11 1c77c4b
Handle deterministic MJWarp sensors
kellyguo11 d9e0d3a
Explain deterministic pipeline rebuild
kellyguo11 5e10d3c
Merge branch 'develop' into kellyguo11/newton-gpu-determinism
kellyguo11 fa54639
Clarify deterministic sort buffer rebuild
kellyguo11 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
source/isaaclab_newton/changelog.d/kellyguo11-newton-gpu-determinism.minor.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| Added | ||
| ^^^^^ | ||
|
|
||
| * Added :attr:`~isaaclab_newton.physics.NewtonCfg.deterministic_mode` to apply | ||
| one determinism setting to supported Newton solvers and collision handling. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -111,7 +111,10 @@ def _paused_gc(): | |
| from isaaclab_newton.physics.visualization_builder import build_visualization_builder_from_stage_envs | ||
| from isaaclab_newton.physics.visualization_deformables import populate_shadow_deformable_registry | ||
|
|
||
| from .newton_manager_cfg import NewtonCfg, NewtonShapeCfg | ||
| from .featherstone_manager_cfg import FeatherstoneSolverCfg | ||
| from .mjwarp_manager_cfg import MJWarpSolverCfg | ||
| from .newton_manager_cfg import NewtonCfg, NewtonShapeCfg, NewtonSolverCfg | ||
| from .xpbd_manager_cfg import XPBDSolverCfg | ||
|
|
||
| if TYPE_CHECKING: | ||
| from isaaclab_newton.actuators import NewtonActuatorAdapter | ||
|
|
@@ -369,6 +372,7 @@ def provides_implicit_damping(cls) -> bool: | |
| _num_substeps: int = 1 | ||
| _decimation: int = 1 | ||
| _collision_decimation: int = 0 | ||
| _deterministic_mode: wp.DeterministicMode = wp.DeterministicMode.NOT_GUARANTEED | ||
| _num_envs: int | None = None | ||
|
|
||
| # Newton model and state | ||
|
|
@@ -1051,6 +1055,7 @@ def clear(cls): | |
| NewtonManager._control = None | ||
| NewtonManager._contacts = None | ||
| NewtonManager._needs_collision_pipeline = False | ||
| NewtonManager._deterministic_mode = wp.DeterministicMode.NOT_GUARANTEED | ||
| NewtonManager._eval_fk = _eval_fk_unbound | ||
| NewtonManager._reset_solver_internals_delegate = _reset_solver_internals_unbound | ||
| NewtonManager._collision_pipeline = None | ||
|
|
@@ -1861,13 +1866,12 @@ def _initialize_contacts(cls) -> None: | |
| """ | ||
| if not cls._needs_collision_pipeline: | ||
| return | ||
| pipeline_args = {"broad_phase": "explicit"} | ||
| if cls._collision_cfg is not None: | ||
| pipeline_args = cls._collision_cfg.to_pipeline_args() | ||
| pipeline_args["deterministic"] = cls._deterministic_mode != wp.DeterministicMode.NOT_GUARANTEED | ||
| if cls._collision_pipeline is None: | ||
| if cls._collision_cfg is not None: | ||
| NewtonManager._collision_pipeline = CollisionPipeline( | ||
| cls._model, **cls._collision_cfg.to_pipeline_args() | ||
| ) | ||
| else: | ||
| NewtonManager._collision_pipeline = CollisionPipeline(cls._model, broad_phase="explicit") | ||
| NewtonManager._collision_pipeline = CollisionPipeline(cls._model, **pipeline_args) | ||
| if cls._contacts is None: | ||
| NewtonManager._contacts = cls._collision_pipeline.contacts() | ||
| # Grow the collision-pipeline contact buffer to the solver's max when the | ||
|
|
@@ -1880,12 +1884,17 @@ def _initialize_contacts(cls) -> None: | |
| if _solver is not None and hasattr(_solver, "get_max_contact_count"): | ||
| _need = _solver.get_max_contact_count() | ||
| if _need > NewtonManager._contacts.rigid_contact_max: | ||
| NewtonManager._contacts = Contacts( | ||
| rigid_contact_max=_need, | ||
| soft_contact_max=0, | ||
| device=PhysicsManager._device, | ||
| requested_attributes=cls._model.get_requested_contact_attributes(), | ||
| ) | ||
| if cls._deterministic_mode != wp.DeterministicMode.NOT_GUARANTEED: | ||
| pipeline_args["rigid_contact_max"] = _need | ||
| NewtonManager._collision_pipeline = CollisionPipeline(cls._model, **pipeline_args) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to brief about why collision pipeline rebuilt is needed. Seems collision pipeline uses _sort_key_array in deterministic mode which needs to match contacts but can only created at init. |
||
| NewtonManager._contacts = cls._collision_pipeline.contacts() | ||
| else: | ||
| NewtonManager._contacts = Contacts( | ||
| rigid_contact_max=_need, | ||
| soft_contact_max=0, | ||
| device=PhysicsManager._device, | ||
| requested_attributes=cls._model.get_requested_contact_attributes(), | ||
| ) | ||
|
|
||
| # ----- Solver construction (subclass contract) ------------------------ | ||
|
|
||
|
|
@@ -1937,7 +1946,38 @@ def _filter_solver_kwargs(solver_cls: type, solver_cfg) -> dict: | |
| are always excluded — ``model`` is passed positionally at construction. | ||
| """ | ||
| valid = set(inspect.signature(solver_cls.__init__).parameters) - {"self", "model"} | ||
| return {k: v for k, v in solver_cfg.to_dict().items() if k in valid} | ||
| kwargs = {k: v for k, v in solver_cfg.to_dict().items() if k in valid} | ||
| if "deterministic" in valid: | ||
| kwargs["deterministic"] = NewtonManager._deterministic_mode | ||
| return kwargs | ||
|
|
||
| @staticmethod | ||
| def _validate_deterministic_solver_cfg( | ||
| solver_cfg: NewtonSolverCfg, deterministic_mode: wp.DeterministicMode | ||
| ) -> None: | ||
| """Validate that a solver can provide the requested determinism guarantee.""" | ||
| if deterministic_mode == wp.DeterministicMode.NOT_GUARANTEED: | ||
| return | ||
| solver_cfg_type = type(solver_cfg).__name__ | ||
| if not isinstance(solver_cfg, (FeatherstoneSolverCfg, MJWarpSolverCfg, XPBDSolverCfg)): | ||
| raise ValueError( | ||
| f"Newton deterministic mode {deterministic_mode.name} is not supported by {solver_cfg_type}. " | ||
| "Use MJWarp on the GPU, XPBD, or Featherstone, or disable deterministic mode." | ||
| ) | ||
| if getattr(solver_cfg, "use_mujoco_cpu", False): | ||
| raise ValueError( | ||
| f"Newton deterministic mode {deterministic_mode.name} is not supported by the MuJoCo CPU backend. " | ||
| "Set MJWarpSolverCfg.use_mujoco_cpu=False or disable deterministic mode." | ||
| ) | ||
|
|
||
| @staticmethod | ||
| def _resolve_deterministic_mode(deterministic_mode: str) -> wp.DeterministicMode: | ||
| """Convert a Newton config value to Warp's deterministic-mode enum.""" | ||
| return { | ||
| "not_guaranteed": wp.DeterministicMode.NOT_GUARANTEED, | ||
| "run_to_run": wp.DeterministicMode.RUN_TO_RUN, | ||
| "gpu_to_gpu": wp.DeterministicMode.GPU_TO_GPU, | ||
| }[deterministic_mode] | ||
|
|
||
| @classmethod | ||
| def _step_solver( | ||
|
|
@@ -2010,6 +2050,9 @@ def initialize_solver(cls) -> None: | |
| with Timer(name="newton_initialize_solver", msg="Initialize solver took:", activity="Initializing solver"): | ||
| NewtonManager._num_substeps = cfg.num_substeps # type: ignore[union-attr] | ||
| NewtonManager._collision_decimation = cfg.collision_decimation # type: ignore[union-attr] | ||
| deterministic_mode = cls._resolve_deterministic_mode(cfg.deterministic_mode) # type: ignore[union-attr] | ||
| cls._validate_deterministic_solver_cfg(cfg.solver_cfg, deterministic_mode) # type: ignore[union-attr] | ||
| NewtonManager._deterministic_mode = deterministic_mode | ||
| NewtonManager._solver_dt = cls.get_physics_dt() / cls._num_substeps | ||
| NewtonManager._collision_cfg = cfg.collision_cfg # type: ignore[union-attr] | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use absolute imports here and elsewhere