use std::path::PathBuf;
use emath;
use serde::{Deserialize, Serialize};
use crate::error::{Error, Result};
use crate::os_helpers::resolve_symlink;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct MapPose {
pub translation: Translation,
pub rotation: Rotation,
#[serde(default)]
pub root_frame: String,
#[serde(default)]
pub map_frame: String,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Rotation {
#[serde(default)]
pub roll: f32,
#[serde(default)]
pub pitch: f32,
pub yaw: f32,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Translation {
pub x: f32,
pub y: f32,
#[serde(default)]
pub z: f32,
}
impl MapPose {
pub fn new(root_frame: String, map_frame: String) -> MapPose {
MapPose {
root_frame,
map_frame,
translation: Translation::default(),
rotation: Rotation::default(),
}
}
pub fn invert(&mut self) {
let inverted_translation = self.rot2().inverse() * (-self.vec2());
self.translation.x = inverted_translation.x;
self.translation.y = inverted_translation.y;
self.rotation.yaw = -self.rotation.yaw;
}
pub fn negate(&mut self) {
self.translation.x = -self.translation.x;
self.translation.y = -self.translation.y;
self.rotation.yaw = -self.rotation.yaw;
}
pub fn with_vec2(&mut self, vec: emath::Vec2) -> &mut Self {
self.translation.x = vec.x;
self.translation.y = vec.y;
self
}
pub fn with_rot2(&mut self, rot: emath::Rot2) -> &mut Self {
self.rotation.yaw = rot.angle();
self
}
pub fn rot2(&self) -> emath::Rot2 {
emath::Rot2::from_angle(self.rotation.yaw).normalized()
}
pub fn vec2(&self) -> emath::Vec2 {
emath::vec2(self.translation.x, self.translation.y)
}
fn normalized(mut self) -> MapPose {
self.rotation.yaw = emath::normalized_angle(self.rotation.yaw);
self
}
pub fn from_yaml_file(yaml_path: &PathBuf) -> Result<MapPose> {
let file = std::fs::File::open(resolve_symlink(yaml_path))
.map_err(|e| Error::io(format!("Cannot open map pose file {yaml_path:?}"), e))?;
let map_pose = serde_yaml_ng::from_reader::<std::fs::File, MapPose>(file)
.map_err(|e| Error::yaml(format!("Cannot parse map pose from {yaml_path:?}"), e))?
.normalized();
Ok(map_pose)
}
pub fn from_bytes(bytes: &[u8]) -> Result<MapPose> {
let map_pose = serde_yaml_ng::from_slice::<MapPose>(bytes)
.map_err(|e| Error::yaml("Cannot parse map pose from bytes", e))?
.normalized();
Ok(map_pose)
}
pub fn to_yaml(&self) -> Result<String> {
serde_yaml_ng::to_string(self)
.map_err(|e| Error::yaml("Cannot serialize map pose to YAML", e))
}
pub fn to_yaml_file(&self, yaml_path: &PathBuf) -> Result<()> {
let yaml_content = self.to_yaml()?;
std::fs::write(yaml_path, yaml_content)
.map_err(|e| Error::io(format!("Cannot write map pose to {yaml_path:?}"), e))
}
pub fn to_bytes(&self) -> Result<Vec<u8>> {
let yaml = self.to_yaml()?;
Ok(yaml.into_bytes())
}
}