trajectory/
linear.rs
1use super::traits::*;
2use super::utils::*;
3use num_traits::Float;
4
5#[derive(Debug)]
6pub struct Linear<T>
7where
8 T: Float,
9{
10 times: Vec<T>,
11 points: Vec<Vec<T>>,
12}
13
14impl<T> Linear<T>
15where
16 T: Float,
17{
18 pub fn new(times: Vec<T>, points: Vec<Vec<T>>) -> Option<Self> {
19 if !is_inputs_valid(×, &points) {
20 return None;
21 }
22 Some(Self { times, points })
23 }
24}
25
26impl<T> Trajectory for Linear<T>
27where
28 T: Float,
29{
30 type Point = Vec<T>;
31 type Time = T;
32
33 fn position(&self, t: T) -> Option<Vec<T>> {
34 if t < self.times[0] {
35 return None;
36 }
37 for i in 0..(self.points.len() - 1) {
38 let t0 = self.times[i];
39 let t1 = self.times[i + 1];
40 if t >= t0 && t <= t1 {
41 let mut pt = self.points[i].clone();
42 let p0 = &self.points[i];
43 let p1 = &self.points[i + 1];
44 for j in 0..p0.len() {
45 pt[j] = p0[j] + (p1[j] - p0[j]) / (t1 - t0) * (t - t0);
46 }
47 return Some(pt);
48 }
49 }
50 None
51 }
52
53 fn velocity(&self, t: T) -> Option<Vec<T>> {
54 if t < self.times[0] {
55 return None;
56 }
57 let dim = self.points[0].len();
58
59 for i in 0..(self.points.len() - 1) {
60 let t0 = self.times[i];
61 let t1 = self.times[i + 1];
62 if t >= t0 && t <= t1 {
63 let mut pt = vec![T::zero(); dim];
64 let p0 = &self.points[i];
65 let p1 = &self.points[i + 1];
66 for j in 0..p0.len() {
67 pt[j] = (p1[j] - p0[j]) / (t1 - t0);
68 }
69 return Some(pt);
70 }
71 }
72 None
73 }
74
75 fn acceleration(&self, t: T) -> Option<Vec<T>> {
76 if t < self.times[0] {
77 return None;
78 }
79 let dim = self.points[0].len();
80 for tm in &self.times {
81 if t == *tm {
82 return None;
83 }
84 }
85 Some(vec![T::zero(); dim])
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use assert_approx_eq::assert_approx_eq;
93
94 #[test]
95 fn test_linear() {
96 let times = vec![0.0, 1.0, 3.0, 4.0];
97 let points = vec![
98 vec![0.0, -1.0],
99 vec![2.0, -3.0],
100 vec![3.0, 3.0],
101 vec![1.0, 5.0],
102 ];
103 let ip = Linear::new(times, points).unwrap();
104 let p0 = ip.position(-0.5);
105 assert!(p0.is_none());
106 let p1 = ip.position(0.5).unwrap();
107 assert_approx_eq!(p1[0], 1.0);
108 assert_approx_eq!(p1[1], -2.0);
109 let p2 = ip.position(1.0).unwrap();
110 assert_approx_eq!(p2[0], 2.0);
111 assert_approx_eq!(p2[1], -3.0);
112 let p3 = ip.position(3.0).unwrap();
113 assert_approx_eq!(p3[0], 3.0);
114 assert_approx_eq!(p3[1], 3.0);
115 let p4 = ip.position(3.5).unwrap();
116 assert_approx_eq!(p4[0], 2.0);
117 assert_approx_eq!(p4[1], 4.0);
118 }
119}