rapier3d/dynamics/joint/
motor_model.rs

1use crate::math::Real;
2
3/// How motor stiffness/damping values are interpreted (mass-dependent vs mass-independent).
4///
5/// This affects how motors behave when attached to bodies of different masses.
6///
7/// ## Acceleration-Based (default, recommended)
8///
9/// Spring constants are automatically scaled by mass, so:
10/// - Heavy and light objects respond similarly to same spring values
11/// - Easier to tune - values work across different mass ranges
12/// - **Formula**: `acceleration = stiffness × error + damping × velocity_error`
13///
14/// ## Force-Based
15///
16/// Spring constants produce absolute forces, so:
17/// - Same spring values → different behavior for different masses
18/// - More physically accurate representation
19/// - Requires re-tuning if masses change
20/// - **Formula**: `force = stiffness × error + damping × velocity_error`
21///
22/// **Most users should use AccelerationBased (the default).**
23#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
24#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
25pub enum MotorModel {
26    /// Spring constants auto-scale with mass (easier to tune, recommended).
27    #[default]
28    AccelerationBased,
29    /// Spring constants produce absolute forces (mass-dependent).
30    ForceBased,
31}
32
33impl MotorModel {
34    /// Combines the coefficients used for solving the spring equation.
35    ///
36    /// Returns the coefficients (erp_inv_dt, cfm_coeff, cfm_gain).
37    pub fn combine_coefficients(
38        self,
39        dt: Real,
40        stiffness: Real,
41        damping: Real,
42    ) -> (Real, Real, Real) {
43        match self {
44            MotorModel::AccelerationBased => {
45                let erp_inv_dt = stiffness * crate::utils::inv(dt * stiffness + damping);
46                let cfm_coeff = crate::utils::inv(dt * dt * stiffness + dt * damping);
47                (erp_inv_dt, cfm_coeff, 0.0)
48            }
49            MotorModel::ForceBased => {
50                let erp_inv_dt = stiffness * crate::utils::inv(dt * stiffness + damping);
51                let cfm_gain = crate::utils::inv(dt * dt * stiffness + dt * damping);
52                (erp_inv_dt, 0.0, cfm_gain)
53            }
54        }
55    }
56}