rapier3d/dynamics/joint/
prismatic_joint.rs

1use crate::dynamics::joint::{GenericJoint, GenericJointBuilder, JointAxesMask};
2use crate::dynamics::{JointAxis, MotorModel};
3use crate::math::{Point, Real, UnitVector};
4
5use super::{JointLimits, JointMotor};
6
7#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
8#[derive(Copy, Clone, Debug, PartialEq)]
9#[repr(transparent)]
10/// A sliding joint that allows movement along one axis only (like a piston or sliding door).
11///
12/// Prismatic joints lock all motion except sliding along a single axis. Use for:
13/// - Pistons and hydraulics
14/// - Sliding doors and drawers
15/// - Elevator platforms
16/// - Linear actuators
17/// - Telescoping mechanisms
18///
19/// You can optionally add:
20/// - **Limits**: Restrict sliding distance (min/max positions)
21/// - **Motor**: Powered sliding with target velocity or position
22///
23/// The axis is specified when creating the joint and is expressed in each body's local space.
24pub struct PrismaticJoint {
25    /// The underlying joint data.
26    pub data: GenericJoint,
27}
28
29impl PrismaticJoint {
30    /// Creates a new prismatic joint allowing only relative translations along the specified axis.
31    ///
32    /// This axis is expressed in the local-space of both rigid-bodies.
33    pub fn new(axis: UnitVector<Real>) -> Self {
34        let data = GenericJointBuilder::new(JointAxesMask::LOCKED_PRISMATIC_AXES)
35            .local_axis1(axis)
36            .local_axis2(axis)
37            .build();
38        Self { data }
39    }
40
41    /// The underlying generic joint.
42    pub fn data(&self) -> &GenericJoint {
43        &self.data
44    }
45
46    /// Are contacts between the attached rigid-bodies enabled?
47    pub fn contacts_enabled(&self) -> bool {
48        self.data.contacts_enabled
49    }
50
51    /// Sets whether contacts between the attached rigid-bodies are enabled.
52    pub fn set_contacts_enabled(&mut self, enabled: bool) -> &mut Self {
53        self.data.set_contacts_enabled(enabled);
54        self
55    }
56
57    /// The joint’s anchor, expressed in the local-space of the first rigid-body.
58    #[must_use]
59    pub fn local_anchor1(&self) -> Point<Real> {
60        self.data.local_anchor1()
61    }
62
63    /// Sets the joint’s anchor, expressed in the local-space of the first rigid-body.
64    pub fn set_local_anchor1(&mut self, anchor1: Point<Real>) -> &mut Self {
65        self.data.set_local_anchor1(anchor1);
66        self
67    }
68
69    /// The joint’s anchor, expressed in the local-space of the second rigid-body.
70    #[must_use]
71    pub fn local_anchor2(&self) -> Point<Real> {
72        self.data.local_anchor2()
73    }
74
75    /// Sets the joint’s anchor, expressed in the local-space of the second rigid-body.
76    pub fn set_local_anchor2(&mut self, anchor2: Point<Real>) -> &mut Self {
77        self.data.set_local_anchor2(anchor2);
78        self
79    }
80
81    /// The principal axis of the joint, expressed in the local-space of the first rigid-body.
82    #[must_use]
83    pub fn local_axis1(&self) -> UnitVector<Real> {
84        self.data.local_axis1()
85    }
86
87    /// Sets the principal axis of the joint, expressed in the local-space of the first rigid-body.
88    pub fn set_local_axis1(&mut self, axis1: UnitVector<Real>) -> &mut Self {
89        self.data.set_local_axis1(axis1);
90        self
91    }
92
93    /// The principal axis of the joint, expressed in the local-space of the second rigid-body.
94    #[must_use]
95    pub fn local_axis2(&self) -> UnitVector<Real> {
96        self.data.local_axis2()
97    }
98
99    /// Sets the principal axis of the joint, expressed in the local-space of the second rigid-body.
100    pub fn set_local_axis2(&mut self, axis2: UnitVector<Real>) -> &mut Self {
101        self.data.set_local_axis2(axis2);
102        self
103    }
104
105    /// The motor affecting the joint’s translational degree of freedom.
106    #[must_use]
107    pub fn motor(&self) -> Option<&JointMotor> {
108        self.data.motor(JointAxis::LinX)
109    }
110
111    /// Set the spring-like model used by the motor to reach the desired target velocity and position.
112    pub fn set_motor_model(&mut self, model: MotorModel) -> &mut Self {
113        self.data.set_motor_model(JointAxis::LinX, model);
114        self
115    }
116
117    /// Sets the motor's target sliding speed.
118    ///
119    /// Makes the joint slide at a desired velocity (like a powered piston or conveyor).
120    ///
121    /// # Parameters
122    /// * `target_vel` - Desired velocity in units/second
123    /// * `factor` - Motor strength
124    pub fn set_motor_velocity(&mut self, target_vel: Real, factor: Real) -> &mut Self {
125        self.data
126            .set_motor_velocity(JointAxis::LinX, target_vel, factor);
127        self
128    }
129
130    /// Sets the motor's target position along the sliding axis.
131    ///
132    /// Makes the joint slide toward a specific position using spring-like behavior.
133    ///
134    /// # Parameters
135    /// * `target_pos` - Desired position along the axis
136    /// * `stiffness` - Spring constant
137    /// * `damping` - Resistance to motion
138    pub fn set_motor_position(
139        &mut self,
140        target_pos: Real,
141        stiffness: Real,
142        damping: Real,
143    ) -> &mut Self {
144        self.data
145            .set_motor_position(JointAxis::LinX, target_pos, stiffness, damping);
146        self
147    }
148
149    /// Configures both target position and target velocity for the motor.
150    pub fn set_motor(
151        &mut self,
152        target_pos: Real,
153        target_vel: Real,
154        stiffness: Real,
155        damping: Real,
156    ) -> &mut Self {
157        self.data
158            .set_motor(JointAxis::LinX, target_pos, target_vel, stiffness, damping);
159        self
160    }
161
162    /// Sets the maximum force the motor can deliver.
163    pub fn set_motor_max_force(&mut self, max_force: Real) -> &mut Self {
164        self.data.set_motor_max_force(JointAxis::LinX, max_force);
165        self
166    }
167
168    /// The limit distance attached bodies can translate along the joint’s principal axis.
169    #[must_use]
170    pub fn limits(&self) -> Option<&JointLimits<Real>> {
171        self.data.limits(JointAxis::LinX)
172    }
173
174    /// Sets the `[min,max]` limit distances attached bodies can translate along the joint’s principal axis.
175    pub fn set_limits(&mut self, limits: [Real; 2]) -> &mut Self {
176        self.data.set_limits(JointAxis::LinX, limits);
177        self
178    }
179}
180
181impl From<PrismaticJoint> for GenericJoint {
182    fn from(val: PrismaticJoint) -> GenericJoint {
183        val.data
184    }
185}
186
187/// Create prismatic joints using the builder pattern.
188///
189/// A prismatic joint locks all relative motion except for translations along the joint’s principal axis.
190#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
191#[derive(Copy, Clone, Debug, PartialEq)]
192pub struct PrismaticJointBuilder(pub PrismaticJoint);
193
194impl PrismaticJointBuilder {
195    /// Creates a new builder for prismatic joints.
196    ///
197    /// This axis is expressed in the local-space of both rigid-bodies.
198    pub fn new(axis: UnitVector<Real>) -> Self {
199        Self(PrismaticJoint::new(axis))
200    }
201
202    /// Sets whether contacts between the attached rigid-bodies are enabled.
203    #[must_use]
204    pub fn contacts_enabled(mut self, enabled: bool) -> Self {
205        self.0.set_contacts_enabled(enabled);
206        self
207    }
208
209    /// Sets the joint’s anchor, expressed in the local-space of the first rigid-body.
210    #[must_use]
211    pub fn local_anchor1(mut self, anchor1: Point<Real>) -> Self {
212        self.0.set_local_anchor1(anchor1);
213        self
214    }
215
216    /// Sets the joint’s anchor, expressed in the local-space of the second rigid-body.
217    #[must_use]
218    pub fn local_anchor2(mut self, anchor2: Point<Real>) -> Self {
219        self.0.set_local_anchor2(anchor2);
220        self
221    }
222
223    /// Sets the principal axis of the joint, expressed in the local-space of the first rigid-body.
224    #[must_use]
225    pub fn local_axis1(mut self, axis1: UnitVector<Real>) -> Self {
226        self.0.set_local_axis1(axis1);
227        self
228    }
229
230    /// Sets the principal axis of the joint, expressed in the local-space of the second rigid-body.
231    #[must_use]
232    pub fn local_axis2(mut self, axis2: UnitVector<Real>) -> Self {
233        self.0.set_local_axis2(axis2);
234        self
235    }
236
237    /// Set the spring-like model used by the motor to reach the desired target velocity and position.
238    #[must_use]
239    pub fn motor_model(mut self, model: MotorModel) -> Self {
240        self.0.set_motor_model(model);
241        self
242    }
243
244    /// Sets the target velocity this motor needs to reach.
245    #[must_use]
246    pub fn motor_velocity(mut self, target_vel: Real, factor: Real) -> Self {
247        self.0.set_motor_velocity(target_vel, factor);
248        self
249    }
250
251    /// Sets the target angle this motor needs to reach.
252    #[must_use]
253    pub fn motor_position(mut self, target_pos: Real, stiffness: Real, damping: Real) -> Self {
254        self.0.set_motor_position(target_pos, stiffness, damping);
255        self
256    }
257
258    /// Configure both the target angle and target velocity of the motor.
259    #[must_use]
260    pub fn set_motor(
261        mut self,
262        target_pos: Real,
263        target_vel: Real,
264        stiffness: Real,
265        damping: Real,
266    ) -> Self {
267        self.0.set_motor(target_pos, target_vel, stiffness, damping);
268        self
269    }
270
271    /// Sets the maximum force the motor can deliver.
272    #[must_use]
273    pub fn motor_max_force(mut self, max_force: Real) -> Self {
274        self.0.set_motor_max_force(max_force);
275        self
276    }
277
278    /// Sets the `[min,max]` limit distances attached bodies can translate along the joint’s principal axis.
279    #[must_use]
280    pub fn limits(mut self, limits: [Real; 2]) -> Self {
281        self.0.set_limits(limits);
282        self
283    }
284
285    /// Builds the prismatic joint.
286    #[must_use]
287    pub fn build(self) -> PrismaticJoint {
288        self.0
289    }
290}
291
292impl From<PrismaticJointBuilder> for GenericJoint {
293    fn from(val: PrismaticJointBuilder) -> GenericJoint {
294        val.0.into()
295    }
296}