aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCrozet Sébastien <developer@crozet.re>2021-02-01 17:19:27 +0100
committerCrozet Sébastien <developer@crozet.re>2021-02-01 17:19:27 +0100
commit16ba01be16fbf86cf51dab4eea30ae49b7cbea0d (patch)
treea38cb52b725cbe92500cd20977ebdead8965867b /src
parent3805943067713ce881ec479bfce2b7af5d334414 (diff)
downloadrapier-16ba01be16fbf86cf51dab4eea30ae49b7cbea0d.tar.gz
rapier-16ba01be16fbf86cf51dab4eea30ae49b7cbea0d.tar.bz2
rapier-16ba01be16fbf86cf51dab4eea30ae49b7cbea0d.zip
More experiments with velocity-based error correction.
Diffstat (limited to 'src')
-rw-r--r--src/dynamics/integration_parameters.rs12
-rw-r--r--src/dynamics/solver/constraint_regularization.rs34
-rw-r--r--src/dynamics/solver/island_solver.rs2
-rw-r--r--src/dynamics/solver/mod.rs2
-rw-r--r--src/dynamics/solver/position_constraint.rs2
-rw-r--r--src/dynamics/solver/position_constraint_wide.rs2
-rw-r--r--src/dynamics/solver/position_ground_constraint.rs2
-rw-r--r--src/dynamics/solver/position_ground_constraint_wide.rs2
-rw-r--r--src/dynamics/solver/solver_constraints.rs8
-rw-r--r--src/dynamics/solver/velocity_constraint_wide.rs6
-rw-r--r--src/dynamics/solver/velocity_constraint_wide_with_manifold_friction.rs23
-rw-r--r--src/dynamics/solver/velocity_constraint_with_manifold_friction.rs18
-rw-r--r--src/dynamics/solver/velocity_ground_constraint.rs6
-rw-r--r--src/dynamics/solver/velocity_ground_constraint_wide.rs6
-rw-r--r--src/dynamics/solver/velocity_ground_constraint_wide_with_manifold_friction.rs20
-rw-r--r--src/dynamics/solver/velocity_ground_constraint_with_manifold_friction.rs17
16 files changed, 120 insertions, 42 deletions
diff --git a/src/dynamics/integration_parameters.rs b/src/dynamics/integration_parameters.rs
index 4840ec0..8c773ff 100644
--- a/src/dynamics/integration_parameters.rs
+++ b/src/dynamics/integration_parameters.rs
@@ -20,10 +20,10 @@ pub struct IntegrationParameters {
pub return_after_ccd_substep: bool,
/// The Error Reduction Parameter in `[0, 1]` is the proportion of
/// the positional error to be corrected at the position level each time step (default: `0.0`).
- pub positionErp: Real,
+ pub position_erp: Real,
/// The Error Reduction Parameter in `[0, 1]` is the proportion of
/// the positional error to be corrected at the velocity level at each time step (default: `0.005`).
- pub velocityErp: Real,
+ pub velocity_erp: Real,
/// The Error Reduction Parameter for joints in `[0, 1]` is the proportion of
/// the positional error to be corrected at each time step (default: `0.2`).
pub joint_erp: Real,
@@ -116,7 +116,7 @@ impl IntegrationParameters {
IntegrationParameters {
dt,
// multithreading_enabled,
- positionErp: erp,
+ position_erp: erp,
joint_erp,
warmstart_coeff,
restitution_velocity_threshold,
@@ -139,7 +139,7 @@ impl IntegrationParameters {
return_after_ccd_substep,
multiple_ccd_substep_sensor_events_enabled,
ccd_on_penetration_enabled,
- velocityErp: 0.005,
+ velocity_erp: 0.005,
}
}
@@ -189,8 +189,8 @@ impl Default for IntegrationParameters {
dt: 1.0 / 60.0,
// multithreading_enabled: true,
return_after_ccd_substep: false,
- positionErp: 0.0,
- velocityErp: 0.005,
+ position_erp: 0.0,
+ velocity_erp: 0.005,
joint_erp: 0.2,
warmstart_coeff: 1.0,
restitution_velocity_threshold: 1.0,
diff --git a/src/dynamics/solver/constraint_regularization.rs b/src/dynamics/solver/constraint_regularization.rs
new file mode 100644
index 0000000..4c67145
--- /dev/null
+++ b/src/dynamics/solver/constraint_regularization.rs
@@ -0,0 +1,34 @@
+use crate::math::Real;
+use na::RealField;
+
+pub struct SpringRegularization {
+ pub angular_frequency: Real,
+ pub damping: Real,
+}
+
+impl Default for SpringRegularization {
+ fn default() -> Self {
+ SpringRegularization {
+ angular_frequency: 30.0 * Real::two_pi(),
+ damping: 1.0,
+ }
+ }
+}
+
+impl SpringRegularization {
+ pub fn erp_cfm_impulse_scale(&self, dt: Real) -> (Real, Real, Real) {
+ let freq_dt = self.angular_frequency * dt;
+ let erp = self.angular_frequency / (freq_dt + self.damping * 2.0);
+ let extra = 1.0 / (freq_dt * (freq_dt + self.damping * 2.0));
+ let cfm = 1.0 / (1.0 + extra);
+ let impulse_scale = extra * cfm;
+
+ let kd = 1.0;
+ let kp = 10.0;
+ let erp = 0.2 / dt; // kp / (dt * kp + kd);
+ let cfm = 1.0e-5 / dt; // 1.0 / (dt * kp + kd);
+ let impulse_scale = 0.9;
+
+ (erp, cfm, impulse_scale)
+ }
+}
diff --git a/src/dynamics/solver/island_solver.rs b/src/dynamics/solver/island_solver.rs
index 68074e1..8b7e587 100644
--- a/src/dynamics/solver/island_solver.rs
+++ b/src/dynamics/solver/island_solver.rs
@@ -60,7 +60,7 @@ impl IslandSolver {
bodies.foreach_active_island_body_mut_internal(island_id, |_, rb| rb.integrate(params.dt));
counters.solver.velocity_update_time.pause();
- if params.positionErp != 0.0 {
+ if params.position_erp != 0.0 {
if manifold_indices.len() != 0 || joint_indices.len() != 0 {
counters.solver.position_resolution_time.resume();
self.position_solver.solve(
diff --git a/src/dynamics/solver/mod.rs b/src/dynamics/solver/mod.rs
index 2291615..5a0d0c7 100644
--- a/src/dynamics/solver/mod.rs
+++ b/src/dynamics/solver/mod.rs
@@ -14,6 +14,7 @@ pub(self) use self::position_solver::PositionSolver;
pub(self) use self::solver_constraints::SolverConstraints;
#[cfg(not(feature = "parallel"))]
pub(self) use self::velocity_solver::VelocitySolver;
+pub(self) use constraint_regularization::*;
pub(self) use delta_vel::DeltaVel;
pub(self) use interaction_groups::*;
pub(self) use joint_constraint::*;
@@ -37,6 +38,7 @@ pub(self) use velocity_ground_constraint_wide_with_manifold_friction::*;
pub(self) use velocity_ground_constraint_with_manifold_friction::*;
mod categorization;
+mod constraint_regularization;
mod delta_vel;
mod interaction_groups;
#[cfg(not(feature = "parallel"))]
diff --git a/src/dynamics/solver/position_constraint.rs b/src/dynamics/solver/position_constraint.rs
index dc5b218..ecf8286 100644
--- a/src/dynamics/solver/position_constraint.rs
+++ b/src/dynamics/solver/position_constraint.rs
@@ -93,7 +93,7 @@ impl PositionConstraint {
ii1: rb1.effective_world_inv_inertia_sqrt.squared(),
ii2: rb2.effective_world_inv_inertia_sqrt.squared(),
num_contacts: manifold_points.len() as u8,
- erp: params.positionErp,
+ erp: params.position_erp,
max_linear_correction: params.max_linear_correction,
};
diff --git a/src/dynamics/solver/position_constraint_wide.rs b/src/dynamics/solver/position_constraint_wide.rs
index 8701bfc..b7918c5 100644
--- a/src/dynamics/solver/position_constraint_wide.rs
+++ b/src/dynamics/solver/position_constraint_wide.rs
@@ -74,7 +74,7 @@ impl WPositionConstraint {
im2,
ii1: sqrt_ii1.squared(),
ii2: sqrt_ii2.squared(),
- erp: SimdReal::splat(params.positionErp),
+ erp: SimdReal::splat(params.position_erp),
max_linear_correction: SimdReal::splat(params.max_linear_correction),
num_contacts: num_points as u8,
};
diff --git a/src/dynamics/solver/position_ground_constraint.rs b/src/dynamics/solver/position_ground_constraint.rs
index e69d8ea..1e5a2ff 100644
--- a/src/dynamics/solver/position_ground_constraint.rs
+++ b/src/dynamics/solver/position_ground_constraint.rs
@@ -66,7 +66,7 @@ impl PositionGroundConstraint {
im2: rb2.effective_inv_mass,
ii2: rb2.effective_world_inv_inertia_sqrt.squared(),
num_contacts: manifold_contacts.len() as u8,
- erp: params.positionErp,
+ erp: params.position_erp,
max_linear_correction: params.max_linear_correction,
};
diff --git a/src/dynamics/solver/position_ground_constraint_wide.rs b/src/dynamics/solver/position_ground_constraint_wide.rs
index 99a469f..531eead 100644
--- a/src/dynamics/solver/position_ground_constraint_wide.rs
+++ b/src/dynamics/solver/position_ground_constraint_wide.rs
@@ -71,7 +71,7 @@ impl WPositionGroundConstraint {
dists: [SimdReal::zero(); MAX_MANIFOLD_POINTS],
im2,
ii2: sqrt_ii2.squared(),
- erp: SimdReal::splat(params.positionErp),
+ erp: SimdReal::splat(params.position_erp),
max_linear_correction: SimdReal::splat(params.max_linear_correction),
num_contacts: num_points as u8,
};
diff --git a/src/dynamics/solver/solver_constraints.rs b/src/dynamics/solver/solver_constraints.rs
index ab8c1e6..1f4cec5 100644
--- a/src/dynamics/solver/solver_constraints.rs
+++ b/src/dynamics/solver/solver_constraints.rs
@@ -135,7 +135,7 @@ impl SolverConstraints<AnyVelocityConstraint, AnyPositionConstraint> {
true,
);
- if params.positionErp != 0.0 {
+ if params.position_erp != 0.0 {
WPositionConstraint::generate(
params,
manifolds,
@@ -164,7 +164,7 @@ impl SolverConstraints<AnyVelocityConstraint, AnyPositionConstraint> {
true,
);
- if params.positionErp != 0.0 {
+ if params.position_erp != 0.0 {
PositionConstraint::generate(
params,
manifold,
@@ -199,7 +199,7 @@ impl SolverConstraints<AnyVelocityConstraint, AnyPositionConstraint> {
true,
);
- if params.positionErp != 0.0 {
+ if params.position_erp != 0.0 {
WPositionGroundConstraint::generate(
params,
manifolds,
@@ -228,7 +228,7 @@ impl SolverConstraints<AnyVelocityConstraint, AnyPositionConstraint> {
true,
);
- if params.positionErp != 0.0 {
+ if params.position_erp != 0.0 {
PositionGroundConstraint::generate(
params,
manifold,
diff --git a/src/dynamics/solver/velocity_constraint_wide.rs b/src/dynamics/solver/velocity_constraint_wide.rs
index a8384de..97aa0eb 100644
--- a/src/dynamics/solver/velocity_constraint_wide.rs
+++ b/src/dynamics/solver/velocity_constraint_wide.rs
@@ -152,7 +152,11 @@ impl WVelocityConstraint {
let use_restitution = rhs.simd_le(-restitution_velocity_threshold);
let rhs_with_restitution = rhs + rhs * restitution;
rhs = rhs_with_restitution.select(use_restitution, rhs);
- rhs += dist.simd_max(SimdReal::zero()) * inv_dt;
+
+ rhs += ((dist.simd_min(SimdReal::splat(0.0))
+ * SimdReal::splat(params.velocity_erp))
+ + dist.simd_max(SimdReal::splat(0.0)))
+ * inv_dt;
constraint.elements[k].normal_part = WVelocityConstraintElementPart {
gcross1,
diff --git a/src/dynamics/solver/velocity_constraint_wide_with_manifold_friction.rs b/src/dynamics/solver/velocity_constraint_wide_with_manifold_friction.rs
index d9d3e53..4a1ad82 100644
--- a/src/dynamics/solver/velocity_constraint_wide_with_manifold_friction.rs
+++ b/src/dynamics/solver/velocity_constraint_wide_with_manifold_friction.rs
@@ -1,4 +1,4 @@
-use super::{AnyVelocityConstraint, DeltaVel};
+use super::{AnyVelocityConstraint, DeltaVel, SpringRegularization};
use crate::dynamics::{IntegrationParameters, RigidBodySet};
use crate::geometry::{ContactManifold, ContactManifoldIndex};
use crate::math::{
@@ -44,6 +44,7 @@ pub(crate) struct WVelocityConstraintWithManifoldFriction {
mj_lambda2: [usize; SIMD_WIDTH],
manifold_id: [ContactManifoldIndex; SIMD_WIDTH],
manifold_contact_id: usize,
+ impulse_scale: SimdReal,
}
impl WVelocityConstraintWithManifoldFriction {
@@ -55,6 +56,9 @@ impl WVelocityConstraintWithManifoldFriction {
out_constraints: &mut Vec<AnyVelocityConstraint>,
push: bool,
) {
+ let (erp, cfm, impulse_scale) =
+ SpringRegularization::default().erp_cfm_impulse_scale(params.dt);
+
let inv_dt = SimdReal::splat(params.inv_dt());
let rbs1 = array![|ii| &bodies[manifolds[ii].data.body_pair.body1]; SIMD_WIDTH];
let rbs2 = array![|ii| &bodies[manifolds[ii].data.body_pair.body2]; SIMD_WIDTH];
@@ -111,6 +115,7 @@ impl WVelocityConstraintWithManifoldFriction {
manifold_id,
manifold_contact_id: l,
num_contacts: num_points as u8,
+ impulse_scale: SimdReal::splat(impulse_scale),
};
let mut manifold_center = Point::origin();
@@ -150,17 +155,18 @@ impl WVelocityConstraintWithManifoldFriction {
let gcross2 = ii2.transform_vector(dp2.gcross(-force_dir1));
let r = SimdReal::splat(1.0)
- / (im1 + im2 + gcross1.gdot(gcross1) + gcross2.gdot(gcross2));
+ / (SimdReal::splat(cfm)
+ + im1
+ + im2
+ + gcross1.gdot(gcross1)
+ + gcross2.gdot(gcross2));
let mut rhs = (vel1 - vel2).dot(&force_dir1);
let use_restitution = rhs.simd_le(-restitution_velocity_threshold);
let rhs_with_restitution = rhs + rhs * restitution;
rhs = rhs_with_restitution.select(use_restitution, rhs);
- rhs += ((dist.simd_min(SimdReal::splat(0.0))
- * SimdReal::splat(params.velocityErp))
- + dist.simd_max(SimdReal::splat(0.0)))
- * inv_dt;
- // rhs += dist.simd_max(SimdReal::splat(-0.01)) * inv_dt;
+ rhs += dist.simd_min(SimdReal::splat(0.0)) * SimdReal::splat(erp)
+ + dist.simd_max(SimdReal::splat(0.0)) * inv_dt;
constraint.normal_parts[k] = WVelocityConstraintPart {
gcross1,
@@ -340,7 +346,8 @@ impl WVelocityConstraintWithManifoldFriction {
- self.dir1.dot(&mj_lambda2.linear)
+ elt.gcross2.gdot(mj_lambda2.angular)
+ elt.rhs;
- let new_impulse = (elt.impulse - elt.r * dimpulse).simd_max(SimdReal::zero());
+ let new_impulse =
+ (elt.impulse * self.impulse_scale - elt.r * dimpulse).simd_max(SimdReal::zero());
let dlambda = new_impulse - elt.impulse;
elt.impulse = new_impulse;
diff --git a/src/dynamics/solver/velocity_constraint_with_manifold_friction.rs b/src/dynamics/solver/velocity_constraint_with_manifold_friction.rs
index 66269a4..de88f09 100644
--- a/src/dynamics/solver/velocity_constraint_with_manifold_friction.rs
+++ b/src/dynamics/solver/velocity_constraint_with_manifold_friction.rs
@@ -1,4 +1,4 @@
-use super::DeltaVel;
+use super::{DeltaVel, SpringRegularization};
use crate::dynamics::solver::{AnyVelocityConstraint, VelocityGroundConstraint};
use crate::dynamics::{IntegrationParameters, RigidBodySet};
use crate::geometry::{ContactManifold, ContactManifoldIndex};
@@ -43,6 +43,7 @@ pub(crate) struct VelocityConstraintWithManifoldFriction {
tangent_parts: [VelocityConstraintPart; DIM - 1],
twist_part: VelocityConstraintPart,
twist_weights: [Real; MAX_MANIFOLD_POINTS],
+ impulse_scale: Real,
}
impl VelocityConstraintWithManifoldFriction {
@@ -60,6 +61,9 @@ impl VelocityConstraintWithManifoldFriction {
out_constraints: &mut Vec<AnyVelocityConstraint>,
push: bool,
) {
+ let (erp, cfm, impulse_scale) =
+ SpringRegularization::default().erp_cfm_impulse_scale(params.dt);
+
let inv_dt = params.inv_dt();
let rb1 = &bodies[manifold.data.body_pair.body1];
let rb2 = &bodies[manifold.data.body_pair.body2];
@@ -89,6 +93,7 @@ impl VelocityConstraintWithManifoldFriction {
tangent_parts: [VelocityConstraintPart::zero(); DIM - 1],
twist_part: VelocityConstraintPart::zero(),
twist_weights: [0.0; MAX_MANIFOLD_POINTS],
+ impulse_scale,
};
let mut manifold_center = Point::origin();
@@ -115,7 +120,8 @@ impl VelocityConstraintWithManifoldFriction {
.transform_vector(dp2.gcross(-force_dir1));
let r = 1.0
- / (rb1.effective_inv_mass
+ / (cfm
+ + rb1.effective_inv_mass
+ rb2.effective_inv_mass
+ gcross1.gdot(gcross1)
+ gcross2.gdot(gcross2));
@@ -126,7 +132,11 @@ impl VelocityConstraintWithManifoldFriction {
rhs += manifold_point.restitution * rhs
}
- rhs += manifold_point.dist.max(0.0) * inv_dt;
+ if manifold_point.dist < 0.0 {
+ rhs += manifold_point.dist * erp;
+ } else {
+ rhs += manifold_point.dist * inv_dt;
+ }
let impulse = manifold_point.data.impulse * warmstart_coeff;
tangent_impulses[0] += manifold_point.data.tangent_impulse[0];
@@ -285,7 +295,7 @@ impl VelocityConstraintWithManifoldFriction {
- self.dir1.dot(&mj_lambda2.linear)
+ elt.gcross2.gdot(mj_lambda2.angular)
+ elt.rhs;
- let new_impulse = (elt.impulse - elt.r * dimpulse).max(0.0);
+ let new_impulse = (elt.impulse * self.impulse_scale - elt.r * dimpulse).max(0.0);
let dlambda = new_impulse - elt.impulse;
elt.impulse = new_impulse;
diff --git a/src/dynamics/solver/velocity_ground_constraint.rs b/src/dynamics/solver/velocity_ground_constraint.rs
index 20642ec..e773d5e 100644
--- a/src/dynamics/solver/velocity_ground_constraint.rs
+++ b/src/dynamics/solver/velocity_ground_constraint.rs
@@ -160,7 +160,11 @@ impl VelocityGroundConstraint {
rhs += manifold_point.restitution * rhs
}
- rhs += manifold_point.dist.max(0.0) * inv_dt;
+ if manifold_point.dist < 0.0 {
+ rhs += manifold_point.dist * params.velocity_erp * inv_dt;
+ } else {
+ rhs += manifold_point.dist * inv_dt;
+ }
let impulse = manifold_points[k].data.impulse * warmstart_coeff;
diff --git a/src/dynamics/solver/velocity_ground_constraint_wide.rs b/src/dynamics/solver/velocity_ground_constraint_wide.rs
index efb542f..d7221fc 100644
--- a/src/dynamics/solver/velocity_ground_constraint_wide.rs
+++ b/src/dynamics/solver/velocity_ground_constraint_wide.rs
@@ -144,7 +144,11 @@ impl WVelocityGroundConstraint {
let use_restitution = rhs.simd_le(-restitution_velocity_threshold);
let rhs_with_restitution = rhs + rhs * restitution;
rhs = rhs_with_restitution.select(use_restitution, rhs);
- rhs += dist.simd_max(SimdReal::zero()) * inv_dt;
+
+ rhs += ((dist.simd_min(SimdReal::splat(0.0))
+ * SimdReal::splat(params.velocity_erp))
+ + dist.simd_max(SimdReal::splat(0.0)))
+ * inv_dt;
constraint.elements[k].normal_part = WVelocityGroundConstraintElementPart {
gcross2,
diff --git a/src/dynamics/solver/velocity_ground_constraint_wide_with_manifold_friction.rs b/src/dynamics/solver/velocity_ground_constraint_wide_with_manifold_friction.rs
index bf7fecc..39f8d72 100644
--- a/src/dynamics/solver/velocity_ground_constraint_wide_with_manifold_friction.rs
+++ b/src/dynamics/solver/velocity_ground_constraint_wide_with_manifold_friction.rs
@@ -1,4 +1,4 @@
-use super::{AnyVelocityConstraint, DeltaVel};
+use super::{AnyVelocityConstraint, DeltaVel, SpringRegularization};
use crate::dynamics::{IntegrationParameters, RigidBodySet};
use crate::geometry::{ContactManifold, ContactManifoldIndex};
use crate::math::{
@@ -40,6 +40,7 @@ pub(crate) struct WVelocityGroundConstraintWithManifoldFriction {
mj_lambda2: [usize; SIMD_WIDTH],
manifold_id: [ContactManifoldIndex; SIMD_WIDTH],
manifold_contact_id: usize,
+ impulse_scale: SimdReal,
}
impl WVelocityGroundConstraintWithManifoldFriction {
@@ -51,6 +52,9 @@ impl WVelocityGroundConstraintWithManifoldFriction {
out_constraints: &mut Vec<AnyVelocityConstraint>,
push: bool,
) {
+ let (erp, cfm, impulse_scale) =
+ SpringRegularization::default().erp_cfm_impulse_scale(params.dt);
+
let inv_dt = SimdReal::splat(params.inv_dt());
let mut rbs1 = array![|ii| &bodies[manifolds[ii].data.body_pair.body1]; SIMD_WIDTH];
let mut rbs2 = array![|ii| &bodies[manifolds[ii].data.body_pair.body2]; SIMD_WIDTH];
@@ -109,6 +113,7 @@ impl WVelocityGroundConstraintWithManifoldFriction {
manifold_id,
manifold_contact_id: l,
num_contacts: num_points as u8,
+ impulse_scale: SimdReal::splat(impulse_scale),
};
let mut manifold_center = Point::origin();
@@ -146,17 +151,15 @@ impl WVelocityGroundConstraintWithManifoldFriction {
{
let gcross2 = ii2.transform_vector(dp2.gcross(-force_dir1));
- let r = SimdReal::splat(1.0) / (im2 + gcross2.gdot(gcross2));
+ let r =
+ SimdReal::splat(1.0) / (SimdReal::splat(cfm) + im2 + gcross2.gdot(gcross2));
let mut rhs = (vel1 - vel2).dot(&force_dir1);
let use_restitution = rhs.simd_le(-restitution_velocity_threshold);
let rhs_with_restitution = rhs + rhs * restitution;
rhs = rhs_with_restitution.select(use_restitution, rhs);
- rhs += ((dist.simd_min(SimdReal::splat(0.0))
- * SimdReal::splat(params.velocityErp))
- + dist.simd_max(SimdReal::splat(0.0)))
- * inv_dt;
- // rhs += dist.simd_max(SimdReal::splat(-0.1)) * inv_dt;
+ rhs += dist.simd_min(SimdReal::splat(0.0)) * SimdReal::splat(erp)
+ + dist.simd_max(SimdReal::splat(0.0)) * inv_dt;
constraint.normal_parts[k] = WVelocityConstraintPart {
gcross2,
@@ -295,7 +298,8 @@ impl WVelocityGroundConstraintWithManifoldFriction {
let elt = &mut self.normal_parts[i];
let dimpulse =
-self.dir1.dot(&mj_lambda2.linear) + elt.gcross2.gdot(mj_lambda2.angular) + elt.rhs;
- let new_impulse = (elt.impulse - elt.r * dimpulse).simd_max(SimdReal::zero());
+ let new_impulse =
+ (elt.impulse * self.impulse_scale - elt.r * dimpulse).simd_max(SimdReal::zero());
let dlambda = new_impulse - elt.impulse;
elt.impulse = new_impulse;
diff --git a/src/dynamics/solver/velocity_ground_constraint_with_manifold_friction.rs b/src/dynamics/solver/velocity_ground_constraint_with_manifold_friction.rs
index b6a45b1..30ad214 100644
--- a/src/dynamics/solver/velocity_ground_constraint_with_manifold_friction.rs
+++ b/src/dynamics/solver/velocity_ground_constraint_with_manifold_friction.rs
@@ -1,4 +1,4 @@
-use super::DeltaVel;
+use super::{DeltaVel, SpringRegularization};
use crate::dynamics::solver::{AnyVelocityConstraint, VelocityGroundConstraint};
use crate::dynamics::{IntegrationParameters, RigidBodySet};
use crate::geometry::{ContactManifold, ContactManifoldIndex};
@@ -39,6 +39,7 @@ pub(crate) struct VelocityGroundConstraintWithManifoldFriction {
tangent_parts: [VelocityConstraintElementPart; DIM - 1],
twist_part: VelocityConstraintElementPart,
twist_weights: [Real; MAX_MANIFOLD_POINTS],
+ impulse_scale: Real,
}
impl VelocityGroundConstraintWithManifoldFriction {
@@ -56,6 +57,9 @@ impl VelocityGroundConstraintWithManifoldFriction {
out_constraints: &mut Vec<AnyVelocityConstraint>,
push: bool,
) {
+ let (erp, cfm, impulse_scale) =
+ SpringRegularization::default().erp_cfm_impulse_scale(params.dt);
+
let inv_dt = params.inv_dt();
let mut rb1 = &bodies[manifold.data.body_pair.body1];
let mut rb2 = &bodies[manifold.data.body_pair.body2];
@@ -90,6 +94,7 @@ impl VelocityGroundConstraintWithManifoldFriction {
tangent_parts: [VelocityConstraintElementPart::zero(); DIM - 1],
twist_part: VelocityConstraintElementPart::zero(),
twist_weights: [0.0; MAX_MANIFOLD_POINTS],
+ impulse_scale,
};
let mut manifold_center = Point::origin();
@@ -112,7 +117,7 @@ impl VelocityGroundConstraintWithManifoldFriction {
.effective_world_inv_inertia_sqrt
.transform_vector(dp2.gcross(-force_dir1));
- let r = 1.0 / (rb2.effective_inv_mass + gcross2.gdot(gcross2));
+ let r = 1.0 / (cfm + rb2.effective_inv_mass + gcross2.gdot(gcross2));
let mut rhs = (vel1 - vel2).dot(&force_dir1);
@@ -120,7 +125,11 @@ impl VelocityGroundConstraintWithManifoldFriction {
rhs += manifold_point.restitution * rhs
}
- rhs += manifold_point.dist.max(0.0) * inv_dt;
+ if manifold_point.dist < 0.0 {
+ rhs += manifold_point.dist * erp;
+ } else {
+ rhs += manifold_point.dist * inv_dt;
+ }
let impulse = manifold_point.data.impulse * warmstart_coeff;
tangent_impulses[0] += manifold_point.data.tangent_impulse[0];
@@ -247,7 +256,7 @@ impl VelocityGroundConstraintWithManifoldFriction {
let elt = &mut self.normal_parts[i];
let dimpulse =
-self.dir1.dot(&mj_lambda2.linear) + elt.gcross2.gdot(mj_lambda2.angular) + elt.rhs;
- let new_impulse = (elt.impulse - elt.r * dimpulse).max(0.0);
+ let new_impulse = (elt.impulse * self.impulse_scale - elt.r * dimpulse).max(0.0);
let dlambda = new_impulse - elt.impulse;
elt.impulse = new_impulse;