aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics/joint/spring_model.rs
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2021-02-22 17:40:29 +0100
committerGitHub <noreply@github.com>2021-02-22 17:40:29 +0100
commitd31a327b45118a77bd9676f350f110683a235acf (patch)
treeac972a97204f3b7d375a6c877336730312b76041 /src/dynamics/joint/spring_model.rs
parentc650bb1feff8763b309e0705fe6427ce94ed2b2e (diff)
parente5c4c2e8ffccf81aa5436c166b426a01b8b8831e (diff)
downloadrapier-d31a327b45118a77bd9676f350f110683a235acf.tar.gz
rapier-d31a327b45118a77bd9676f350f110683a235acf.tar.bz2
rapier-d31a327b45118a77bd9676f350f110683a235acf.zip
Merge pull request #119 from dimforge/joint_drive
Add joint motors
Diffstat (limited to 'src/dynamics/joint/spring_model.rs')
-rw-r--r--src/dynamics/joint/spring_model.rs65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/dynamics/joint/spring_model.rs b/src/dynamics/joint/spring_model.rs
new file mode 100644
index 0000000..c2c9ebd
--- /dev/null
+++ b/src/dynamics/joint/spring_model.rs
@@ -0,0 +1,65 @@
+use crate::math::Real;
+
+/// The spring-like model used for constraints resolution.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+pub enum SpringModel {
+ /// No equation is solved.
+ Disabled,
+ /// The solved spring-like equation is:
+ /// `delta_velocity(t + dt) = stiffness / dt * (target_pos - pos(t)) + damping * (target_vel - vel(t))`
+ ///
+ /// Here the `stiffness` is the ratio of position error to be solved at each timestep (like
+ /// a velocity-based ERP), and the `damping` is the ratio of velocity error to be solved at
+ /// each timestep.
+ VelocityBased,
+ /// The solved spring-like equation is:
+ /// `acceleration(t + dt) = stiffness * (target_pos - pos(t)) + damping * (target_vel - vel(t))`
+ AccelerationBased,
+ /// The solved spring-like equation is:
+ /// `force(t + dt) = stiffness * (target_pos - pos(t + dt)) + damping * (target_vel - vel(t + dt))`
+ ForceBased,
+}
+
+impl Default for SpringModel {
+ fn default() -> Self {
+ SpringModel::VelocityBased
+ }
+}
+
+impl SpringModel {
+ /// Combines the coefficients used for solving the spring equation.
+ ///
+ /// Returns the new coefficients (stiffness, damping, inv_lhs_scale, keep_inv_lhs)
+ /// coefficients for the equivalent impulse-based equation. These new
+ /// coefficients must be used in the following way:
+ /// - `rhs = (stiffness * pos_err + damping * vel_err) / gamma`.
+ /// - `new_inv_lhs = gamma * if keep_inv_lhs { inv_lhs } else { 1.0 }`.
+ /// Note that the returned `gamma` will be zero if both `stiffness` and `damping` are zero.
+ pub fn combine_coefficients(
+ self,
+ dt: Real,
+ stiffness: Real,
+ damping: Real,
+ ) -> (Real, Real, Real, bool) {
+ match self {
+ SpringModel::VelocityBased => (stiffness * crate::utils::inv(dt), damping, 1.0, true),
+ SpringModel::AccelerationBased => {
+ let effective_stiffness = stiffness * dt;
+ let effective_damping = damping * dt;
+ // TODO: Using gamma behaves very badly for some reasons.
+ // Maybe I got the formulation wrong, so let's keep it to 1.0 for now,
+ // and get back to this later.
+ // let gamma = effective_stiffness * dt + effective_damping;
+ (effective_stiffness, effective_damping, 1.0, true)
+ }
+ SpringModel::ForceBased => {
+ let effective_stiffness = stiffness * dt;
+ let effective_damping = damping * dt;
+ let gamma = effective_stiffness * dt + effective_damping;
+ (effective_stiffness, effective_damping, gamma, false)
+ }
+ SpringModel::Disabled => return (0.0, 0.0, 0.0, false),
+ }
+ }
+}