Skip to content

Commit 7f31343

Browse files
committed
Doc adjustments: timestep-independance -> stability
1 parent 0b398a7 commit 7f31343

File tree

5 files changed

+22
-22
lines changed

5 files changed

+22
-22
lines changed

crates/avian2d/examples/joint_motors_2d.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ fn setup(mut commands: Commands) {
120120

121121
// Revolute joint with position-controlled motor (servo behavior)
122122
//
123-
// Using spring parameters (frequency, damping_ratio) for timestep-independent behavior.
124-
// This provides predictable spring-damper dynamics regardless of substep count.
123+
// Using spring parameters (frequency, damping_ratio) for stable behavior.
124+
// This provides predictable spring-damper dynamics across different configurations.
125125
// - frequency: 5 Hz = fairly stiff spring
126126
// - damping_ratio: 1.0 = critically damped (fastest approach without overshoot)
127127
commands.spawn((

src/dynamics/joints/motor.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@ use bevy::prelude::*;
33

44
/// Determines how the joint motor force/torque is computed.
55
///
6-
/// Different models offer trade-offs between ease of tuning, physical accuracy,
7-
/// and timestep-independence. The default is a [`SpringDamper`](MotorModel::SpringDamper)
8-
/// model that provides stable, predictable behavior regardless of the timestep.
6+
/// Different models offer trade-offs between ease of tuning and physical accuracy.
7+
/// The default is a [`SpringDamper`](MotorModel::SpringDamper) model that provides
8+
/// stable, predictable behavior across different configurations.
99
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
1010
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1111
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
1212
#[reflect(Debug, PartialEq)]
1313
pub enum MotorModel {
14-
/// A spring-damper model using implicit Euler integration for timestep-independent behavior.
14+
/// A spring-damper model using implicit Euler integration.
1515
///
16-
/// While not truly timestep-independent, this model provides stable and predictable
17-
/// spring-damper behavior regardless of the physics substep count or mass configuration.
18-
/// This makes it easier to achieve the desired behavior without extensive tuning.
16+
/// Unlike the other models, this is unconditionally stable: the implicit formulation
17+
/// naturally limits the response as frequency increases, preventing overshoot and
18+
/// oscillation even with aggressive parameters. This makes it easier to tune than
19+
/// the other models, which can become unstable with high stiffness values.
1920
///
2021
/// This is the recommended model for most use cases.
2122
///
@@ -44,9 +45,8 @@ pub enum MotorModel {
4445
///
4546
/// This produces physically accurate forces/torques, but requires careful tuning of the
4647
/// stiffness and damping parameters based on the masses of the connected bodies.
47-
/// As a result, it can be more difficult to achieve the desired behavior compared to
48-
/// the [`AccelerationBased`](MotorModel::AccelerationBased) model or the
49-
/// [`SpringDamper`](MotorModel::SpringDamper) model.
48+
/// High stiffness values can cause instability (overshoot, oscillation, or divergence),
49+
/// so parameters must be chosen appropriately for your timestep and mass configuration.
5050
///
5151
/// # Parameters
5252
///
@@ -72,8 +72,8 @@ pub enum MotorModel {
7272
/// It is therefore easier to tune compared to the [`ForceBased`](MotorModel::ForceBased) model,
7373
/// which requires manual adjustment of stiffness and damping based on mass.
7474
///
75-
/// For more timestep-independent spring-damper behavior, consider using
76-
/// the [`SpringDamper`](MotorModel::SpringDamper) model instead.
75+
/// Note that high stiffness values can still cause instability. For unconditionally
76+
/// stable behavior, use the [`SpringDamper`](MotorModel::SpringDamper) model instead.
7777
///
7878
/// # Parameters
7979
///
@@ -205,11 +205,11 @@ impl AngularMotor {
205205
/// Motors are configured as part of a joint, applying force to drive
206206
/// the joint towards a target velocity and/or position.
207207
///
208-
/// # Timestep-Independent Spring-Damper
208+
/// # Spring-Damper Model
209209
///
210-
/// For position control that behaves consistently regardless of substep count, use
211-
/// [`MotorModel::SpringDamper`]. This uses an implicit Euler integration that provides
212-
/// stable, predictable spring-damper behavior.
210+
/// For stable position control that behaves consistently across different configurations,
211+
/// use [`MotorModel::SpringDamper`]. This uses implicit Euler integration for
212+
/// unconditional stability.
213213
///
214214
/// ```ignore
215215
/// PrismaticJoint::new(entity1, entity2)

src/dynamics/joints/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ fn revolute_motor_force_based() {
637637

638638
/// Tests that the default `SpringDamper` motor model works.
639639
///
640-
/// `SpringDamper` is timestep-independent and uses `frequency`/`damping_ratio`.
640+
/// `SpringDamper` is unconditionally stable and uses `frequency`/`damping_ratio`.
641641
#[test]
642642
fn revolute_motor_spring_damper() {
643643
let mut app = create_app();

src/dynamics/solver/xpbd/joints/prismatic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl PrismaticJoint {
303303
frequency,
304304
damping_ratio,
305305
} => {
306-
// Implicit Euler formulation for timestep-independent spring-damper behavior.
306+
// Implicit Euler formulation for stable spring-damper behavior.
307307
let omega = TAU * frequency;
308308
let omega_sq = omega * omega;
309309
let two_zeta_omega = 2.0 * damping_ratio * omega;

src/dynamics/solver/xpbd/joints/revolute.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ impl RevoluteJoint {
241241

242242
/// Applies motor forces to drive the joint towards the target velocity and/or position.
243243
///
244-
/// Uses a PD controller approach with optional implicit Euler integration for timestep independence.
244+
/// Uses a PD controller approach with optional implicit Euler integration improved stability.
245245
fn apply_motor(
246246
&self,
247247
body1: &mut SolverBody,
@@ -347,7 +347,7 @@ impl RevoluteJoint {
347347
frequency,
348348
damping_ratio,
349349
} => {
350-
// Implicit Euler formulation for timestep-independent spring-damper behavior.
350+
// Implicit Euler formulation for stable spring-damper behavior.
351351
let omega = TAU * frequency;
352352
let omega_sq = omega * omega;
353353
let two_zeta_omega = 2.0 * damping_ratio * omega;

0 commit comments

Comments
 (0)