mecha10-core 0.8.2

Mecha10 core runtime and foundational types
Documentation
use super::perception::Pose;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NavigationGoal {
    pub timestamp: u64,

    pub goal_id: String,

    pub target: Pose,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub max_linear_velocity: Option<f32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub max_angular_velocity: Option<f32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub position_tolerance: Option<f32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub orientation_tolerance: Option<f32>,
}

impl NavigationGoal {
    /// Create a simple 2D navigation goal
    pub fn new_2d(goal_id: String, x: f32, y: f32, yaw: f32) -> Self {
        Self {
            timestamp: crate::prelude::now_micros(),
            goal_id,
            target: Pose::new_2d(x, y, yaw),
            max_linear_velocity: None,
            max_angular_velocity: None,
            position_tolerance: None,
            orientation_tolerance: None,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Path {
    pub timestamp: u64,

    pub waypoints: Vec<Waypoint>,

    pub total_length: f32,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub estimated_time: Option<f32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub frame_id: Option<String>,
}

impl Path {
    /// Create an empty path
    pub fn empty() -> Self {
        Self {
            timestamp: crate::prelude::now_micros(),
            waypoints: Vec::new(),
            total_length: 0.0,
            estimated_time: None,
            frame_id: None,
        }
    }

    /// Check if path is empty
    pub fn is_empty(&self) -> bool {
        self.waypoints.is_empty()
    }

    /// Get the number of waypoints
    pub fn len(&self) -> usize {
        self.waypoints.len()
    }

    /// Calculate total path length from waypoints
    pub fn calculate_length(&mut self) {
        let mut length = 0.0;

        for i in 1..self.waypoints.len() {
            let prev = &self.waypoints[i - 1];
            let curr = &self.waypoints[i];

            let dx = curr.pose.position[0] - prev.pose.position[0];
            let dy = curr.pose.position[1] - prev.pose.position[1];
            let dz = curr.pose.position[2] - prev.pose.position[2];

            length += (dx * dx + dy * dy + dz * dz).sqrt();
        }

        self.total_length = length;
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Waypoint {
    pub pose: Pose,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub velocity: Option<f32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub distance_along_path: Option<f32>,
}

impl Waypoint {
    /// Create a simple waypoint from 2D coordinates
    pub fn new_2d(x: f32, y: f32, yaw: f32) -> Self {
        Self {
            pose: Pose::new_2d(x, y, yaw),
            velocity: None,
            distance_along_path: None,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NavigationStatus {
    pub timestamp: u64,

    pub goal_id: String,

    pub state: NavigationState,

    pub distance_remaining: f32,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub time_remaining: Option<f32>,

    pub progress: f32,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum NavigationState {
    Planning,

    Moving,

    Succeeded,

    Failed,

    Waiting,

    Recovering,
}