Skip to content

Commit 20cc4f0

Browse files
shanecelisJondolf
andauthored
Remove rest_length field from DistanceJoint. (#517)
# Objective Remove `rest_length` from `DistanceJoint` which is ignored if `length_limits` is present. # Problem I was using distance joints as muscles, changing their rest length to exert them. However, when I set the `length_limits`, nothing worked anymore. I looked into the code and saw my error: `rest_length` is ignored when `length_limits` is set, which seems like a foot gun to me. A TODO in the code said "Remove rest_length" and after surveying the code, I agreed. ## Solution I removed `rest_length` and `with_rest_length()` from `DistanceJoint`. I changed the name and arguments of `with_limits()` to `with_length_limits()`. I think this makes it clearer that it's associated with the `length_limits` field. And I altered the arguments to accept `Into<DistanceLimit>`, so that it can be set with a `Scalar`, a pair of `Scalar`s, or a `DistanceLimit`. My hope was that `with_length_limits()` could serve in place of both `with_limits()` and `with_rest_length()`. Edit by Jondolf: The changes to `with_limits` were reverted for now, see [this message](#517 (review)). ## Auxillary Changes Some doc tests weren't passing. I added the necessary ampersands (&) to make them pass. --- ## Changelog - Added: `From<Scalar>` and `From<[Scalar; 2]>` for `DistanceLimit` and `AngleLimit`. - Added: `From<Scalar>` and `From<(Scalar, Scalar)>` for `DistanceLimit` and `AngleLimit`. - Changed: Removed `rest_length` field from `DistanceJoint`. - Changed: Removed `with_rest_length()` method from `DistanceJoint`. ## Migration Guide - Replace `DistanceJoint::with_rest_length(1.0)` with `DistanceJoint::with_limits(1.0, 1.0)`. - Replace `joint.rest_length = 1.0` with `joint.length_limits = 1.0.into()`. --------- Co-authored-by: Joona Aalto <[email protected]>
1 parent c56eb51 commit 20cc4f0

File tree

4 files changed

+58
-28
lines changed

4 files changed

+58
-28
lines changed

crates/avian2d/examples/distance_joint_2d.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn setup(mut commands: Commands) {
4242
DistanceJoint::new(anchor, object)
4343
.with_local_anchor_1(Vector::ZERO)
4444
.with_local_anchor_2(Vector::ZERO)
45-
.with_rest_length(100.0)
45+
.with_limits(100.0, 100.0)
4646
.with_linear_velocity_damping(0.1)
4747
.with_angular_velocity_damping(1.0)
4848
.with_compliance(0.00000001),

crates/avian3d/examples/distance_joint_3d.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn setup(
4545
commands.spawn(
4646
DistanceJoint::new(static_cube, dynamic_cube)
4747
.with_local_anchor_2(0.5 * Vector::ONE)
48-
.with_rest_length(1.5)
48+
.with_limits(1.5, 1.5)
4949
.with_compliance(1.0 / 400.0),
5050
);
5151

src/dynamics/solver/joints/distance.rs

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@ pub struct DistanceJoint {
3131
pub local_anchor1: Vector,
3232
/// Attachment point on the second body.
3333
pub local_anchor2: Vector,
34-
/// The distance the attached bodies will be kept relative to each other.
35-
pub rest_length: Scalar,
3634
/// The extents of the allowed relative translation between the attached bodies.
37-
pub length_limits: Option<DistanceLimit>,
35+
pub length_limits: DistanceLimit,
3836
/// Linear damping applied by the joint.
3937
pub damping_linear: Scalar,
4038
/// Angular damping applied by the joint.
@@ -110,15 +108,9 @@ impl XpbdConstraint<2> for DistanceJoint {
110108
+ (world_r2 - world_r1)
111109
+ self.pre_step.center_difference;
112110

113-
// If min and max limits aren't specified, use rest length
114-
// TODO: Remove rest length, just use min/max limits.
115-
let limits = self
116-
.length_limits
117-
.unwrap_or(DistanceLimit::new(self.rest_length, self.rest_length));
118-
119111
// Compute the direction and magnitude of the positional correction required
120112
// to keep the bodies within a certain distance from each other.
121-
let (dir, distance) = limits.compute_correction(separation);
113+
let (dir, distance) = self.length_limits.compute_correction(separation);
122114

123115
if distance <= Scalar::EPSILON {
124116
// No separation, no need to apply a correction.
@@ -172,8 +164,7 @@ impl Joint for DistanceJoint {
172164
entity2,
173165
local_anchor1: Vector::ZERO,
174166
local_anchor2: Vector::ZERO,
175-
rest_length: 0.0,
176-
length_limits: None,
167+
length_limits: DistanceLimit::ZERO,
177168
damping_linear: 0.0,
178169
damping_angular: 0.0,
179170
relative_dominance: 0,
@@ -262,20 +253,11 @@ impl DistanceJoint {
262253
self.force
263254
}
264255

265-
/// Sets the minimum and maximum distances between the attached bodies.
266-
pub fn with_limits(self, min: Scalar, max: Scalar) -> Self {
267-
Self {
268-
length_limits: Some(DistanceLimit::new(min, max)),
269-
..self
270-
}
271-
}
272-
273-
/// Sets the joint's rest length, or distance the bodies will be kept at.
274-
pub fn with_rest_length(self, rest_length: Scalar) -> Self {
275-
Self {
276-
rest_length,
277-
..self
278-
}
256+
/// Sets the minimum and maximum distance between the anchor points of the bodies.
257+
#[inline]
258+
pub const fn with_limits(mut self, min: Scalar, max: Scalar) -> Self {
259+
self.length_limits = DistanceLimit { min, max };
260+
self
279261
}
280262
}
281263

src/dynamics/solver/joints/mod.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,30 @@ pub struct DistanceLimit {
153153
pub max: Scalar,
154154
}
155155

156+
impl From<Scalar> for DistanceLimit {
157+
/// Converts the given `limit` into a [`DistanceLimit`] where `min == max`.
158+
fn from(limit: Scalar) -> DistanceLimit {
159+
DistanceLimit {
160+
min: limit,
161+
max: limit,
162+
}
163+
}
164+
}
165+
166+
impl From<[Scalar; 2]> for DistanceLimit {
167+
/// Converts the given `[min, max]` array into a [`DistanceLimit`].
168+
fn from([min, max]: [Scalar; 2]) -> DistanceLimit {
169+
DistanceLimit { min, max }
170+
}
171+
}
172+
173+
impl From<(Scalar, Scalar)> for DistanceLimit {
174+
/// Converts the given `(min, max)` pair into a [`DistanceLimit`].
175+
fn from((min, max): (Scalar, Scalar)) -> DistanceLimit {
176+
DistanceLimit { min, max }
177+
}
178+
}
179+
156180
impl DistanceLimit {
157181
/// A `DistanceLimit` with `min` and `max` set to zero.
158182
pub const ZERO: Self = Self { min: 0.0, max: 0.0 };
@@ -215,6 +239,30 @@ pub struct AngleLimit {
215239
pub max: Scalar,
216240
}
217241

242+
impl From<Scalar> for AngleLimit {
243+
/// Converts the given `limit` into a [`AngleLimit`] where `min == max`.
244+
fn from(limit: Scalar) -> AngleLimit {
245+
AngleLimit {
246+
min: limit,
247+
max: limit,
248+
}
249+
}
250+
}
251+
252+
impl From<[Scalar; 2]> for AngleLimit {
253+
/// Converts the given `[min, max]` array into a [`AngleLimit`].
254+
fn from([min, max]: [Scalar; 2]) -> AngleLimit {
255+
AngleLimit { min, max }
256+
}
257+
}
258+
259+
impl From<(Scalar, Scalar)> for AngleLimit {
260+
/// Converts the given `(min, max)` pair into a [`AngleLimit`].
261+
fn from((min, max): (Scalar, Scalar)) -> AngleLimit {
262+
AngleLimit { min, max }
263+
}
264+
}
265+
218266
impl AngleLimit {
219267
/// An `AngleLimit` with `alpha` and `beta` set to zero.
220268
pub const ZERO: Self = Self { min: 0.0, max: 0.0 };

0 commit comments

Comments
 (0)