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}