1#![macro_use]
2
3use na::{self, DVectorSliceMut, RealField, Unit};
4
5use crate::joint::{self, Joint, JointMotor, UnitJoint};
6use crate::math::{DIM, Isometry, JacobianSliceMut, Rotation, Translation, Vector, Velocity};
7use crate::object::{BodyPartHandle, Multibody, MultibodyLink};
8use crate::solver::{ConstraintSet, GenericNonlinearConstraint, IntegrationParameters};
9
10#[derive(Copy, Clone, Debug)]
12pub struct PrismaticJoint<N: RealField + Copy> {
13    axis: Unit<Vector<N>>,
14    jacobian: Velocity<N>,
15
16    offset: N,
17
18    min_offset: Option<N>,
19    max_offset: Option<N>,
20    motor: JointMotor<N, N>,
21}
22
23impl<N: RealField + Copy> PrismaticJoint<N> {
24    #[cfg(feature = "dim2")]
28    pub fn new(axis: Unit<Vector<N>>, offset: N) -> Self {
29        PrismaticJoint {
30            axis,
31            jacobian: Velocity::zero(),
32            offset,
33            min_offset: None,
34            max_offset: None,
35            motor: JointMotor::new(),
36        }
37    }
38
39    #[cfg(feature = "dim3")]
43    pub fn new(axis: Unit<Vector<N>>, offset: N) -> Self {
44        PrismaticJoint {
45            axis: axis,
46            jacobian: Velocity::zero(),
47            offset: offset,
48            min_offset: None,
49            max_offset: None,
50            motor: JointMotor::new(),
51        }
52    }
53
54    pub fn offset(&self) -> N {
56        self.offset
57    }
58
59    pub fn translation(&self) -> Translation<N> {
61        Translation::from(*self.axis * self.offset)
62    }
63
64    pub fn min_offset(&self) -> Option<N> {
66        self.min_offset
67    }
68
69    pub fn max_offset(&self) -> Option<N> {
71        self.max_offset
72    }
73
74    pub fn disable_min_offset(&mut self) {
76        self.min_offset = None;
77    }
78
79    pub fn disable_max_offset(&mut self) {
81        self.max_offset = None;
82    }
83
84    pub fn enable_min_offset(&mut self, limit: N) {
86        self.min_offset = Some(limit);
87        self.assert_limits();
88    }
89
90    pub fn enable_max_offset(&mut self, limit: N) {
92        self.max_offset = Some(limit);
93        self.assert_limits();
94    }
95
96    pub fn is_linear_motor_enabled(&self) -> bool {
98        self.motor.enabled
99    }
100
101    pub fn enable_linear_motor(&mut self) {
103        self.motor.enabled = true
104    }
105
106    pub fn disable_linear_motor(&mut self) {
108        self.motor.enabled = false;
109    }
110
111    pub fn desired_linear_motor_velocity(&self) -> N {
113        self.motor.desired_velocity
114    }
115
116    pub fn set_desired_linear_motor_velocity(&mut self, vel: N) {
118        self.motor.desired_velocity = vel;
119    }
120
121    pub fn max_linear_motor_velocity(&self) -> N {
123        self.motor.max_velocity
124    }
125
126    pub fn set_max_linear_motor_velocity(&mut self, max_vel: N) {
128        self.motor.max_velocity = max_vel;
129    }
130
131    pub fn max_linear_motor_force(&self) -> N {
133        self.motor.max_force
134    }
135
136    pub fn set_max_linear_motor_force(&mut self, force: N) {
138        self.motor.max_force = force;
139    }
140
141    fn assert_limits(&self) {
142        if let (Some(min_offset), Some(max_offset)) = (self.min_offset, self.max_offset) {
143            assert!(
144                min_offset <= max_offset,
145                "PrismaticJoint joint limits: the min offset must be larger than (or equal to) the max offset.");
146        }
147    }
148}
149
150impl<N: RealField + Copy> Joint<N> for PrismaticJoint<N> {
151    #[inline]
152    fn ndofs(&self) -> usize {
153        1
154    }
155
156    #[cfg(feature = "dim3")]
157    fn body_to_parent(&self, parent_shift: &Vector<N>, body_shift: &Vector<N>) -> Isometry<N> {
158        let trans = Translation::from(parent_shift - body_shift + self.axis.as_ref() * self.offset);
159        Isometry::from_parts(trans, Rotation::identity())
160    }
161
162    #[cfg(feature = "dim2")]
163    fn body_to_parent(&self, parent_shift: &Vector<N>, body_shift: &Vector<N>) -> Isometry<N> {
164        let trans = Translation::from(parent_shift - body_shift + self.axis.as_ref() * self.offset);
165        Isometry::from_parts(trans, Rotation::identity())
166    }
167
168    fn update_jacobians(&mut self, _: &Vector<N>, _: &[N]) {}
169
170    fn jacobian(&self, transform: &Isometry<N>, out: &mut JacobianSliceMut<N>) {
171        let transformed_axis = transform * self.axis;
172        out.fixed_rows_mut::<DIM>(0)
173            .copy_from(transformed_axis.as_ref())
174    }
175
176    fn jacobian_dot(&self, _: &Isometry<N>, _: &mut JacobianSliceMut<N>) {}
177
178    fn jacobian_dot_veldiff_mul_coordinates(
179        &self,
180        _: &Isometry<N>,
181        _: &[N],
182        _: &mut JacobianSliceMut<N>,
183    ) {
184    }
185
186    fn default_damping(&self, _: &mut DVectorSliceMut<N>) {}
187
188    fn integrate(&mut self, parameters: &IntegrationParameters<N>, vels: &[N]) {
189        self.offset += vels[0] * parameters.dt()
190    }
191
192    fn apply_displacement(&mut self, disp: &[N]) {
193        self.offset += disp[0]
194    }
195
196    fn jacobian_mul_coordinates(&self, acc: &[N]) -> Velocity<N> {
197        Velocity::new(self.axis.as_ref() * acc[0], na::zero())
198    }
199
200    fn jacobian_dot_mul_coordinates(&self, _: &[N]) -> Velocity<N> {
201        Velocity::zero()
202    }
203
204    #[inline]
205    fn clone(&self) -> Box<dyn Joint<N>> {
206        Box::new(*self)
207    }
208
209    fn num_velocity_constraints(&self) -> usize {
210        joint::unit_joint_num_velocity_constraints(self)
211    }
212
213    fn velocity_constraints(
214        &self,
215        parameters: &IntegrationParameters<N>,
216        multibody: &Multibody<N>,
217        link: &MultibodyLink<N>,
218        assembly_id: usize,
219        dof_id: usize,
220        ext_vels: &[N],
221        ground_j_id: &mut usize,
222        jacobians: &mut [N],
223        constraints: &mut ConstraintSet<N, (), (), usize>,
224    ) {
225        joint::unit_joint_velocity_constraints(
226            self,
227            parameters,
228            multibody,
229            link,
230            assembly_id,
231            dof_id,
232            ext_vels,
233            ground_j_id,
234            jacobians,
235            constraints,
236        );
237    }
238
239    fn num_position_constraints(&self) -> usize {
240        if self.min_offset.is_some() || self.max_offset.is_some() {
241            1
242        } else {
243            0
244        }
245    }
246
247    fn position_constraint(
248        &self,
249        _: usize,
250        multibody: &Multibody<N>,
251        link: &MultibodyLink<N>,
252        handle: BodyPartHandle<()>,
253        dof_id: usize,
254        jacobians: &mut [N],
255    ) -> Option<GenericNonlinearConstraint<N, ()>> {
256        joint::unit_joint_position_constraint(
257            self, multibody, link, handle, dof_id, false, jacobians,
258        )
259    }
260}
261
262impl<N: RealField + Copy> UnitJoint<N> for PrismaticJoint<N> {
263    fn position(&self) -> N {
264        self.offset
265    }
266
267    fn motor(&self) -> &JointMotor<N, N> {
268        &self.motor
269    }
270
271    fn min_position(&self) -> Option<N> {
272        self.min_offset
273    }
274
275    fn max_position(&self) -> Option<N> {
276        self.max_offset
277    }
278}
279
280#[cfg(feature = "dim3")]
281macro_rules! prismatic_motor_limit_methods (
282    ($ty: ident, $prism: ident) => {
283        _prismatic_motor_limit_methods!(
284            $ty,
285            $prism,
286            min_offset,
287            max_offset,
288            disable_min_offset,
289            disable_max_offset,
290            enable_min_offset,
291            enable_max_offset,
292            is_linear_motor_enabled,
293            enable_linear_motor,
294            disable_linear_motor,
295            desired_linear_motor_velocity,
296            set_desired_linear_motor_velocity,
297            max_linear_motor_force,
298            set_max_linear_motor_force);
299    }
300);
301
302#[cfg(feature = "dim3")]
303macro_rules! prismatic_motor_limit_methods_1 (
304    ($ty: ident, $prism: ident) => {
305        _prismatic_motor_limit_methods!(
306            $ty,
307            $prism,
308            min_offset_1,
309            max_offset_1,
310            disable_min_offset_1,
311            disable_max_offset_1,
312            enable_min_offset_1,
313            enable_max_offset_1,
314            is_linear_motor_enabled_1,
315            enable_linear_motor_1,
316            disable_linear_motor_1,
317            desired_linear_motor_velocity_1,
318            set_desired_linear_motor_velocity_1,
319            max_linear_motor_force_1,
320            set_max_linear_motor_force_1);
321    }
322);
323
324#[cfg(feature = "dim3")]
325macro_rules! prismatic_motor_limit_methods_2 (
326    ($ty: ident, $prism: ident) => {
327        _prismatic_motor_limit_methods!(
328            $ty,
329            $prism,
330            min_offset_2,
331            max_offset_2,
332            disable_min_offset_2,
333            disable_max_offset_2,
334            enable_min_offset_2,
335            enable_max_offset_2,
336            is_linear_motor_enabled_2,
337            enable_linear_motor_2,
338            disable_linear_motor_2,
339            desired_linear_motor_velocity_2,
340            set_desired_linear_motor_velocity_2,
341            max_linear_motor_force2,
342            set_max_linear_motor_force_2);
343    }
344);
345
346#[cfg(feature = "dim3")]
347macro_rules! _prismatic_motor_limit_methods (
348    ($ty: ident, $prism: ident,
349     $min_offset:         ident,
350     $max_offset:         ident,
351     $disable_min_offset: ident,
352     $disable_max_offset: ident,
353     $enable_min_offset:  ident,
354     $enable_max_offset:  ident,
355     $is_motor_enabled:  ident,
356     $enable_motor:      ident,
357     $disable_motor:     ident,
358     $desired_motor_velocity:     ident,
359     $set_desired_motor_velocity: ident,
360     $max_motor_force:           ident,
361     $set_max_motor_force:       ident
362     ) => {
363        impl<N: RealField + Copy> $ty<N> {
364            pub fn $min_offset(&self) -> Option<N> {
366                self.$prism.min_offset()
367            }
368
369            pub fn $max_offset(&self) -> Option<N> {
371                self.$prism.max_offset()
372            }
373
374            pub fn $disable_min_offset(&mut self) {
376                self.$prism.disable_max_offset();
377            }
378
379            pub fn $disable_max_offset(&mut self) {
381                self.$prism.disable_max_offset();
382            }
383
384            pub fn $enable_min_offset(&mut self, limit: N) {
386                self.$prism.enable_min_offset(limit);
387            }
388
389            pub fn $enable_max_offset(&mut self, limit: N) {
391                self.$prism.enable_max_offset(limit)
392            }
393
394            pub fn $is_motor_enabled(&self) -> bool {
396                self.$prism.is_linear_motor_enabled()
397            }
398
399            pub fn $enable_motor(&mut self) {
401                self.$prism.enable_linear_motor()
402            }
403
404            pub fn $disable_motor(&mut self) {
406                self.$prism.disable_linear_motor()
407            }
408
409            pub fn $desired_motor_velocity(&self) -> N {
411                self.$prism.desired_linear_motor_velocity()
412            }
413
414            pub fn $set_desired_motor_velocity(&mut self, vel: N) {
416                self.$prism.set_desired_linear_motor_velocity(vel)
417            }
418
419            pub fn $max_motor_force(&self) -> N {
421                self.$prism.max_linear_motor_force()
422            }
423
424            pub fn $set_max_motor_force(&mut self, force: N) {
426                self.$prism.set_max_linear_motor_force(force)
427            }
428        }
429    }
430);