1use na::RealField;
23use crate::math::{Isometry, Point, Translation, Vector};
45/// A continuous rigid motion.
6///
7/// This is a function, assumed to be continuous, that, given a parameter `t` returns a direct isometry.
8/// Mathematically speaking this is a one-parameter curve on the space of direct isometries. This curve
9/// should have a continuity of at least `C0`.
10pub trait RigidMotion<N: RealField + Copy> {
11/// Get a position at the time `t`.
12fn position_at_time(&self, t: N) -> Isometry<N>;
13}
1415impl<N: RealField + Copy> RigidMotion<N> for Isometry<N> {
16fn position_at_time(&self, _: N) -> Isometry<N> {
17*self
18}
19}
2021/// Interpolation between two isometries using LERP for the translation part and SLERP for the rotation.
22pub struct InterpolatedRigidMotion<N: RealField + Copy> {
23/// The transformation at `t = 0.0`.
24pub start: Isometry<N>,
25/// The transformation at `t = 1.0`.
26pub end: Isometry<N>,
27}
2829impl<N: RealField + Copy> InterpolatedRigidMotion<N> {
30/// Initialize a lerp-slerp interpolation with the given start and end transformations.
31 ///
32 /// The `start` is the transformation at the time `t = 0.0` and `end` is the transformation at
33 /// the time `t = 1.0`.
34pub fn new(start: Isometry<N>, end: Isometry<N>) -> Self {
35 InterpolatedRigidMotion { start, end }
36 }
37}
3839impl<N: RealField + Copy> RigidMotion<N> for InterpolatedRigidMotion<N> {
40fn position_at_time(&self, t: N) -> Isometry<N> {
41self.start.lerp_slerp(&self.end, t)
42 }
43}
4445/// A linear motion from a starting isometry traveling at constant translational velocity.
46pub struct ConstantLinearVelocityRigidMotion<N: RealField + Copy> {
47/// The time at which this parametrization begins. Can be negative.
48pub t0: N,
49/// The starting isometry at `t = self.t0`.
50pub start: Isometry<N>,
51/// The translational velocity of this motion.
52pub velocity: Vector<N>,
53}
5455impl<N: RealField + Copy> ConstantLinearVelocityRigidMotion<N> {
56/// Initialize a linear motion from a starting isometry and a translational velocity.
57pub fn new(t0: N, start: Isometry<N>, velocity: Vector<N>) -> Self {
58 ConstantLinearVelocityRigidMotion {
59 t0,
60 start,
61 velocity,
62 }
63 }
64}
6566impl<N: RealField + Copy> RigidMotion<N> for ConstantLinearVelocityRigidMotion<N> {
67fn position_at_time(&self, t: N) -> Isometry<N> {
68 Isometry::from_parts(
69 (self.start.translation.vector + self.velocity * (t - self.t0)).into(),
70self.start.rotation,
71 )
72 }
73}
7475/// A linear motion from a starting isometry traveling at constant translational velocity.
76#[derive(Debug)]
77pub struct ConstantVelocityRigidMotion<N: RealField + Copy> {
78/// The time at which this parametrization begins. Can be negative.
79pub t0: N,
80/// The starting isometry at `t = self.t0`.
81pub start: Isometry<N>,
82/// The local-space point at which the rotational part of this motion is applied.
83pub local_center: Point<N>,
84/// The translational velocity of this motion.
85pub linvel: Vector<N>,
86/// The angular velocity of this motion.
87#[cfg(feature = "dim2")]
88pub angvel: N,
89/// The angular velocity of this motion.
90#[cfg(feature = "dim3")]
91pub angvel: Vector<N>,
92}
9394impl<N: RealField + Copy> ConstantVelocityRigidMotion<N> {
95/// Initialize a motion from a starting isometry and linear and angular velocities.
96#[cfg(feature = "dim2")]
97pub fn new(
98 t0: N,
99 start: Isometry<N>,
100 local_center: Point<N>,
101 linvel: Vector<N>,
102 angvel: N,
103 ) -> Self {
104 ConstantVelocityRigidMotion {
105 t0,
106 start,
107 local_center,
108 linvel,
109 angvel,
110 }
111 }
112113/// Initialize a motion from a starting isometry and linear and angular velocities.
114#[cfg(feature = "dim3")]
115pub fn new(
116 t0: N,
117 start: Isometry<N>,
118 local_center: Point<N>,
119 linvel: Vector<N>,
120 angvel: Vector<N>,
121 ) -> Self {
122 ConstantVelocityRigidMotion {
123 t0,
124 start,
125 local_center,
126 linvel,
127 angvel,
128 }
129 }
130}
131132impl<N: RealField + Copy> RigidMotion<N> for ConstantVelocityRigidMotion<N> {
133fn position_at_time(&self, t: N) -> Isometry<N> {
134let scaled_linvel = self.linvel * (t - self.t0);
135let scaled_angvel = self.angvel * (t - self.t0);
136137let center = self.start.rotation * self.local_center.coords;
138let lhs = self.start.translation * Translation::from(center);
139let rhs = Translation::from(-center) * self.start.rotation;
140141 lhs * Isometry::new(scaled_linvel, scaled_angvel) * rhs
142 }
143}
144145/*
146 * For composition.
147 */
148149/// Trait for composing some rigid motions.
150pub trait RigidMotionComposition<N: RealField + Copy>: RigidMotion<N> {
151/// Prepend a translation to the rigid motion `self`.
152fn prepend_translation(&self, translation: Vector<N>) -> PrependTranslation<N, Self> {
153 PrependTranslation {
154 motion: self,
155 translation,
156 }
157 }
158159/// Prepend a transformation to the rigid motion `self`.
160fn prepend_transformation(
161&self,
162 transformation: Isometry<N>,
163 ) -> PrependTransformation<N, Self> {
164 PrependTransformation {
165 motion: self,
166 transformation,
167 }
168 }
169}
170171impl<N: RealField + Copy, M: ?Sized + RigidMotion<N>> RigidMotionComposition<N> for M {}
172173/// The result of prepending a translation to a rigid motion.
174pub struct PrependTranslation<'a, N: RealField + Copy, M: ?Sized> {
175 motion: &'a M,
176 translation: Vector<N>,
177}
178179impl<'a, N: RealField + Copy, M: ?Sized + RigidMotion<N>> RigidMotion<N>
180for PrependTranslation<'a, N, M>
181{
182fn position_at_time(&self, t: N) -> Isometry<N> {
183let m = self.motion.position_at_time(t);
184 m * Translation::from(self.translation)
185 }
186}
187188/// The result of prepending an isometric transformation to a rigid motion.
189pub struct PrependTransformation<'a, N: RealField + Copy, M: ?Sized> {
190 motion: &'a M,
191 transformation: Isometry<N>,
192}
193194impl<'a, N: RealField + Copy, M: ?Sized + RigidMotion<N>> RigidMotion<N>
195for PrependTransformation<'a, N, M>
196{
197fn position_at_time(&self, t: N) -> Isometry<N> {
198let m = self.motion.position_at_time(t);
199 m * self.transformation
200 }
201}