use std::{any::Any, ops::Deref};
use crate::base::state::{CompoundState, RealVectorState, SO2State, State};
#[derive(Clone, Debug)]
pub struct SE2State(pub CompoundState);
impl State for SE2State {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl SE2State {
pub fn new(x: f64, y: f64, yaw: f64) -> Self {
SE2State(CompoundState {
components: vec![
Box::new(RealVectorState::new(vec![x, y])),
Box::new(SO2State::new(yaw)),
],
})
}
pub fn get_translation(&self) -> &RealVectorState {
(self.0.components[0].deref() as &dyn Any)
.downcast_ref::<RealVectorState>()
.expect("Issue found in retreiving the translation vector.")
}
pub fn get_rotation(&self) -> &SO2State {
(self.0.components[1].deref() as &dyn Any)
.downcast_ref::<SO2State>()
.expect("Issue found in retreiving the rotation.")
}
pub fn get_x(&self) -> f64 {
(self.0.components[0].deref() as &dyn Any)
.downcast_ref::<RealVectorState>()
.expect("Issue found in retreiving the translation vector.")
.values[0]
}
pub fn get_y(&self) -> f64 {
(self.0.components[0].deref() as &dyn Any)
.downcast_ref::<RealVectorState>()
.expect("Issue found in retreiving the translation vector.")
.values[1]
}
pub fn get_yaw(&self) -> f64 {
(self.0.components[1].deref() as &dyn Any)
.downcast_ref::<SO2State>()
.expect("Issue found in retreiving the rotation.")
.value
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::base::state::{RealVectorState, SO2State};
use std::f64::consts::PI;
#[test]
fn test_se2_state_creation_and_getters() {
let state = SE2State::new(1.5, -2.5, PI / 2.0);
assert_eq!(state.get_x(), 1.5);
assert_eq!(state.get_y(), -2.5);
assert_eq!(state.get_yaw(), PI / 2.0);
assert_eq!(
state.get_translation(),
&RealVectorState::new(vec![1.5, -2.5])
);
assert_eq!(state.get_rotation(), &SO2State::new(PI / 2.0));
}
#[test]
fn test_se2_state_yaw_normalization() {
let state1 = SE2State::new(1.0, 2.0, 3.0 * PI / 2.0);
assert!((state1.get_yaw() - (-PI / 2.0)).abs() < 1e-9);
let state2 = SE2State::new(1.0, 2.0, 5.0 * PI);
assert!((state2.get_yaw() + PI).abs() < 1e-9);
let state3 = SE2State::new(1.0, 2.0, -7.0 * PI / 2.0);
assert!((state3.get_yaw() - (PI / 2.0)).abs() < 1e-9);
}
#[test]
fn test_se2_state_clone() {
let state1 = SE2State::new(10.0, 20.0, PI / 4.0);
let state2 = state1.clone();
assert_eq!(state1.get_x(), state2.get_x());
assert_eq!(state1.get_y(), state2.get_y());
assert_eq!(state1.get_yaw(), state2.get_yaw());
assert_eq!(state1.get_translation(), state2.get_translation());
assert_eq!(state1.get_rotation(), state2.get_rotation());
}
}