crazyflie_lib/subsystems/memory/
trajectory.rs1use crate::{Error, Result, subsystems::memory::{MemoryBackend, memory_types}};
9use memory_types::{FromMemoryBackend, MemoryType};
10
11fn encode_spatial(coordinate: f32) -> Result<i16> {
15 let scaled = coordinate * 1000.0;
16 if scaled < i16::MIN as f32 || scaled > i16::MAX as f32 {
17 return Err(Error::InvalidArgument(
18 format!("Spatial coordinate {:.3}m out of representable range ({:.3}m to {:.3}m)",
19 coordinate, i16::MIN as f32 / 1000.0, i16::MAX as f32 / 1000.0)
20 ));
21 }
22 Ok(scaled as i16)
23}
24
25fn encode_yaw(angle_rad: f32) -> Result<i16> {
29 let scaled = angle_rad.to_degrees() * 10.0;
30 if scaled < i16::MIN as f32 || scaled > i16::MAX as f32 {
31 return Err(Error::InvalidArgument(
32 format!("Yaw angle {:.3} rad out of representable range", angle_rad)
33 ));
34 }
35 Ok(scaled as i16)
36}
37
38#[derive(Debug, Clone)]
40pub struct Poly {
41 pub values: [f32; 8],
43}
44
45impl Default for Poly {
46 fn default() -> Self {
47 Self { values: [0.0; 8] }
48 }
49}
50
51impl Poly {
52 pub fn new(values: [f32; 8]) -> Self {
54 Self { values }
55 }
56
57 pub fn from_slice(values: &[f32]) -> Self {
62 let mut poly = Self::default();
63 let len = values.len().min(8);
64 poly.values[..len].copy_from_slice(&values[..len]);
65 poly
66 }
67}
68
69#[derive(Debug, Clone)]
74pub struct Poly4D {
75 pub duration: f32,
77 pub x: Poly,
79 pub y: Poly,
81 pub z: Poly,
83 pub yaw: Poly,
85}
86
87impl Poly4D {
88 pub fn new(duration: f32, x: Poly, y: Poly, z: Poly, yaw: Poly) -> Self {
90 Self { duration, x, y, z, yaw }
91 }
92
93 pub fn pack(&self) -> Vec<u8> {
95 let mut data = Vec::with_capacity(132); for &v in &self.x.values {
99 data.extend_from_slice(&v.to_le_bytes());
100 }
101 for &v in &self.y.values {
103 data.extend_from_slice(&v.to_le_bytes());
104 }
105 for &v in &self.z.values {
107 data.extend_from_slice(&v.to_le_bytes());
108 }
109 for &v in &self.yaw.values {
111 data.extend_from_slice(&v.to_le_bytes());
112 }
113 data.extend_from_slice(&self.duration.to_le_bytes());
115
116 data
117 }
118}
119
120#[derive(Debug, Clone)]
125pub struct CompressedStart {
126 pub x: f32,
128 pub y: f32,
130 pub z: f32,
132 pub yaw: f32,
134}
135
136impl CompressedStart {
137 pub fn new(x: f32, y: f32, z: f32, yaw: f32) -> Self {
139 Self { x, y, z, yaw }
140 }
141
142 pub fn pack(&self) -> Result<Vec<u8>> {
146 let mut data = Vec::with_capacity(8);
147
148 data.extend_from_slice(&encode_spatial(self.x)?.to_le_bytes());
149 data.extend_from_slice(&encode_spatial(self.y)?.to_le_bytes());
150 data.extend_from_slice(&encode_spatial(self.z)?.to_le_bytes());
151 data.extend_from_slice(&encode_yaw(self.yaw)?.to_le_bytes());
152
153 Ok(data)
154 }
155}
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159enum ElementType {
160 Constant = 0,
162 Linear = 1,
164 Quadratic = 2,
166 Full = 3,
168}
169
170impl ElementType {
171 fn from_len(len: usize) -> Option<Self> {
172 match len {
173 0 => Some(ElementType::Constant),
174 1 => Some(ElementType::Linear),
175 3 => Some(ElementType::Quadratic),
176 7 => Some(ElementType::Full),
177 _ => None,
178 }
179 }
180}
181
182#[derive(Debug, Clone)]
188pub struct CompressedSegment {
189 duration: f32,
190 x: Vec<f32>,
191 y: Vec<f32>,
192 z: Vec<f32>,
193 yaw: Vec<f32>,
194}
195
196impl CompressedSegment {
197 pub fn new(duration: f32, x: Vec<f32>, y: Vec<f32>, z: Vec<f32>, yaw: Vec<f32>) -> Result<Self> {
209 Self::validate(&x)?;
210 Self::validate(&y)?;
211 Self::validate(&z)?;
212 Self::validate(&yaw)?;
213
214 Ok(Self { duration, x, y, z, yaw })
215 }
216
217 fn validate(element: &[f32]) -> Result<()> {
218 let len = element.len();
219 if len != 0 && len != 1 && len != 3 && len != 7 {
220 return Err(Error::InvalidArgument(
221 "Element length must be 0, 1, 3, or 7".to_owned()
222 ));
223 }
224 Ok(())
225 }
226
227 fn encode_type(element: &[f32]) -> u8 {
228 ElementType::from_len(element.len()).unwrap() as u8
230 }
231
232 fn pack_spatial_element(element: &[f32]) -> Result<Vec<u8>> {
233 let mut data = Vec::new();
234 for &v in element {
235 data.extend_from_slice(&encode_spatial(v)?.to_le_bytes());
236 }
237 Ok(data)
238 }
239
240 fn pack_yaw_element(element: &[f32]) -> Result<Vec<u8>> {
241 let mut data = Vec::new();
242 for &v in element {
243 data.extend_from_slice(&encode_yaw(v)?.to_le_bytes());
244 }
245 Ok(data)
246 }
247
248 pub fn pack(&self) -> Result<Vec<u8>> {
252 let element_types = Self::encode_type(&self.x)
253 | (Self::encode_type(&self.y) << 2)
254 | (Self::encode_type(&self.z) << 4)
255 | (Self::encode_type(&self.yaw) << 6);
256 let duration_ms = (self.duration * 1000.0) as u16;
257
258 let mut data = Vec::new();
259
260 data.push(element_types);
261 data.extend_from_slice(&duration_ms.to_le_bytes());
262 data.extend(Self::pack_spatial_element(&self.x)?);
263 data.extend(Self::pack_spatial_element(&self.y)?);
264 data.extend(Self::pack_spatial_element(&self.z)?);
265 data.extend(Self::pack_yaw_element(&self.yaw)?);
266
267 Ok(data)
268 }
269}
270
271#[derive(Debug)]
278pub struct TrajectoryMemory {
279 memory: MemoryBackend,
280}
281
282impl FromMemoryBackend for TrajectoryMemory {
283 async fn from_memory_backend(memory: MemoryBackend) -> Result<Self> {
284 if memory.memory_type == MemoryType::Trajectory {
285 Ok(Self { memory })
286 } else {
287 Err(Error::MemoryError("Wrong type of memory!".to_owned()))
288 }
289 }
290
291 async fn initialize_memory_backend(memory: MemoryBackend) -> Result<Self> {
292 if memory.memory_type == MemoryType::Trajectory {
293 Ok(Self { memory })
294 } else {
295 Err(Error::MemoryError("Wrong type of memory!".to_owned()))
296 }
297 }
298
299 fn close_memory(self) -> MemoryBackend {
300 self.memory
301 }
302}
303
304impl TrajectoryMemory {
305 pub async fn write_uncompressed(
314 &self,
315 segments: &[Poly4D],
316 start_addr: usize,
317 ) -> Result<usize> {
318 let mut data = Vec::new();
319 for segment in segments {
320 data.extend(segment.pack());
321 }
322
323 self.memory.write::<fn(usize, usize)>(start_addr, &data, None).await?;
324 Ok(data.len())
325 }
326
327 pub async fn write_uncompressed_with_progress<F>(
337 &self,
338 segments: &[Poly4D],
339 start_addr: usize,
340 progress_callback: F,
341 ) -> Result<usize>
342 where
343 F: FnMut(usize, usize),
344 {
345 let mut data = Vec::new();
346 for segment in segments {
347 data.extend(segment.pack());
348 }
349
350 self.memory.write(start_addr, &data, Some(progress_callback)).await?;
351 Ok(data.len())
352 }
353
354 pub async fn write_compressed(
367 &self,
368 start: &CompressedStart,
369 segments: &[CompressedSegment],
370 start_addr: usize,
371 ) -> Result<usize> {
372 let mut data = start.pack()?;
373 for segment in segments {
374 data.extend(segment.pack()?);
375 }
376
377 self.memory.write::<fn(usize, usize)>(start_addr, &data, None).await?;
378 Ok(data.len())
379 }
380
381 pub async fn write_compressed_with_progress<F>(
392 &self,
393 start: &CompressedStart,
394 segments: &[CompressedSegment],
395 start_addr: usize,
396 progress_callback: F,
397 ) -> Result<usize>
398 where
399 F: FnMut(usize, usize),
400 {
401 let mut data = start.pack()?;
402 for segment in segments {
403 data.extend(segment.pack()?);
404 }
405
406 self.memory.write(start_addr, &data, Some(progress_callback)).await?;
407 Ok(data.len())
408 }
409
410}