use crate::types::Position3D;
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MotionSnapshot {
pub position: Position3D,
pub velocity: Position3D,
pub acceleration: Position3D,
pub timestamp: f64,
}
#[derive(Debug, Clone)]
pub struct MotionPredictor {
prediction_horizon: f32,
min_samples: usize,
max_history_size: usize,
}
impl MotionPredictor {
pub fn new() -> Self {
Self {
prediction_horizon: 0.1, min_samples: 3,
max_history_size: 50,
}
}
pub fn predict_position(
&self,
history: &VecDeque<MotionSnapshot>,
prediction_time: Duration,
) -> Option<Position3D> {
if history.len() < self.min_samples {
return None;
}
let latest = history.back()?;
let dt = prediction_time.as_secs_f32();
Some(Position3D::new(
latest.position.x + latest.velocity.x * dt + 0.5 * latest.acceleration.x * dt * dt,
latest.position.y + latest.velocity.y * dt + 0.5 * latest.acceleration.y * dt * dt,
latest.position.z + latest.velocity.z * dt + 0.5 * latest.acceleration.z * dt * dt,
))
}
pub fn set_prediction_horizon(&mut self, horizon: f32) {
self.prediction_horizon = horizon;
}
pub fn prediction_horizon(&self) -> f32 {
self.prediction_horizon
}
}
impl Default for MotionPredictor {
fn default() -> Self {
Self::new()
}
}