Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## Unreleased

### Added

- Python: `NexusViewer.set_deterministic` / `deterministic` (applied to the state by `sync`),
and `NexusState.set_deterministic`, `deterministic` and `steps` for states stepped without a
viewer sync.

## v0.6.0 (4 October 2026)

### Breaking changes
Expand Down
19 changes: 19 additions & 0 deletions crates/nexus_python3d/src/nexus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,25 @@ impl NexusState {
self.0.set_rbd_implicit_coriolis(viewer.backend(), enabled);
}

/// Same-machine determinism: two runs of the same scene with the same
/// inputs give bit-identical results on the same machine and build. Off by
/// default. Can be called before or after `finalize`.
/// `NexusViewer.sync` overrides it with the viewer's own setting, so a state
/// synced through a viewer is configured with `NexusViewer.set_deterministic`.
fn set_deterministic(&mut self, viewer: PyRef<NexusViewer>, enabled: bool) {
self.0.set_deterministic(viewer.backend(), enabled);
}

/// Whether the simulation runs in deterministic mode (see `set_deterministic`).
fn deterministic(&self) -> bool {
self.0.deterministic()
}

/// Number of `NexusPipeline.simulate` calls since the scene was created.
fn steps(&self) -> u64 {
self.0.steps()
}

/// Multibody refresh cadence. `refresh` (default `True`) rebuilds the
/// robots' constraints, mass matrix and LU factors every substep; `False`
/// builds them once per step and later substeps only refresh the joint
Expand Down
11 changes: 11 additions & 0 deletions crates/nexus_python3d/src/viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,17 @@ impl NexusViewer {
self.inner_mut().set_vsync(enabled);
}

/// Same-machine determinism of the states this viewer syncs: `sync` applies
/// it to the state (see `NexusState.set_deterministic`). Off by default.
fn set_deterministic(&mut self, enabled: bool) {
self.inner_mut().ui.sim_settings.deterministic = enabled;
}

/// Whether `sync` puts the states it syncs in deterministic mode.
fn deterministic(&self) -> bool {
self.inner().ui.sim_settings.deterministic
}

// --- backend selection (fluent) --------------------------------------

fn with_cpu(mut slf: PyRefMut<Self>) -> PyRefMut<Self> {
Expand Down
Loading