aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics/integration_parameters.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynamics/integration_parameters.rs')
-rw-r--r--src/dynamics/integration_parameters.rs55
1 files changed, 52 insertions, 3 deletions
diff --git a/src/dynamics/integration_parameters.rs b/src/dynamics/integration_parameters.rs
index d07527f..bcb823b 100644
--- a/src/dynamics/integration_parameters.rs
+++ b/src/dynamics/integration_parameters.rs
@@ -44,10 +44,12 @@ pub struct IntegrationParameters {
pub max_penetration_correction: Real,
/// The maximal distance separating two objects that will generate predictive contacts (default: `0.002`).
pub prediction_distance: Real,
- /// Number of iterations performed to solve friction constraints at solver iteration (default: `2`).
- pub num_friction_iteration_per_solver_iteration: usize,
/// The number of solver iterations run by the constraints solver for calculating forces (default: `4`).
pub num_solver_iterations: NonZeroUsize,
+ /// Number of addition friction resolution iteration run during the last solver sub-step (default: `4`).
+ pub num_additional_friction_iterations: usize,
+ /// Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
+ pub num_internal_pgs_iterations: usize,
/// Minimum number of dynamic bodies in each active island (default: `128`).
pub min_island_size: usize,
/// Maximum number of substeps performed by the solver (default: `1`).
@@ -55,6 +57,52 @@ pub struct IntegrationParameters {
}
impl IntegrationParameters {
+ /// Configures the integration parameters to match the old PGS solver
+ /// from Rapier version <= 0.17.
+ ///
+ /// This solver was slightly faster than the new one but resulted
+ /// in less stable joints and worse convergence rates.
+ ///
+ /// This should only be used for comparison purpose or if you are
+ /// experiencing problems with the new solver.
+ ///
+ /// NOTE: this does not affect any [`RigidBody::additional_solver_iterations`] that will
+ /// still create solver iterations based on the new "small-steps" PGS solver.
+ /// NOTE: this resets [`Self::erp`], [`Self::damping_ratio`], [`Self::joint_erp`],
+ /// [`Self::joint_damping_ratio`] to their former default values.
+ pub fn switch_to_standard_pgs_solver(&mut self) {
+ self.num_internal_pgs_iterations =
+ self.num_solver_iterations.get() * self.num_internal_pgs_iterations;
+ self.num_solver_iterations = NonZeroUsize::new(1).unwrap();
+ self.erp = 0.8;
+ self.damping_ratio = 0.25;
+ self.joint_erp = 1.0;
+ self.joint_damping_ratio = 1.0;
+ }
+
+ /// Configures the integration parameters to match the new "small-steps" PGS solver
+ /// from Rapier version >= 0.18.
+ ///
+ /// The "small-steps" PGS solver is the default one given by [`Self::default()`] so
+ /// calling this function is generally not needed unless
+ /// [`Self::switch_to_standard_pgs_solver()`] was called.
+ ///
+ /// This solver results in more stable joints and significantly better convergence
+ /// rates but is slightly slower in its default settings.
+ ///
+ /// NOTE: this resets [`Self::erp`], [`Self::damping_ratio`], [`Self::joint_erp`],
+ /// [`Self::joint_damping_ratio`] to their default values.
+ pub fn switch_to_small_steps_pgs_solver(&mut self) {
+ self.num_solver_iterations = NonZeroUsize::new(self.num_internal_pgs_iterations).unwrap();
+ self.num_internal_pgs_iterations = 1;
+
+ let default = Self::default();
+ self.erp = default.erp;
+ self.damping_ratio = default.damping_ratio;
+ self.joint_erp = default.joint_erp;
+ self.joint_damping_ratio = default.joint_damping_ratio;
+ }
+
/// The inverse of the time-stepping length, i.e. the steps per seconds (Hz).
///
/// This is zero if `self.dt` is zero.
@@ -154,7 +202,8 @@ impl Default for IntegrationParameters {
allowed_linear_error: 0.001,
max_penetration_correction: Real::MAX,
prediction_distance: 0.002,
- num_friction_iteration_per_solver_iteration: 2,
+ num_internal_pgs_iterations: 1,
+ num_additional_friction_iterations: 4,
num_solver_iterations: NonZeroUsize::new(4).unwrap(),
// TODO: what is the optimal value for min_island_size?
// It should not be too big so that we don't end up with