Skip to main content

phoxal_model/robot/
motion.rs

1//! Canonical robot motion facts normalized from versioned source documents.
2
3use crate::ModelError;
4use crate::component::CapabilityRef;
5
6#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq)]
7#[serde(deny_unknown_fields)]
8pub struct MotionLimits {
9    pub max_linear_speed_mps: f64,
10    pub max_angular_speed_radps: f64,
11}
12
13impl MotionLimits {
14    pub fn validate(self) -> Result<Self, ModelError> {
15        if !(self.max_linear_speed_mps.is_finite()
16            && self.max_linear_speed_mps > 0.0
17            && self.max_linear_speed_mps <= f64::from(f32::MAX))
18        {
19            return Err(ModelError::Invalid(
20                "motion max_linear_speed_mps must be finite, positive, and fit in f32".into(),
21            ));
22        }
23        if !(self.max_angular_speed_radps.is_finite()
24            && self.max_angular_speed_radps > 0.0
25            && self.max_angular_speed_radps <= f64::from(f32::MAX))
26        {
27            return Err(ModelError::Invalid(
28                "motion max_angular_speed_radps must be finite, positive, and fit in f32".into(),
29            ));
30        }
31        Ok(self)
32    }
33}
34
35#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
36#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
37pub enum KinematicConfig {
38    Differential {
39        left_actuators: Vec<CapabilityRef>,
40        right_actuators: Vec<CapabilityRef>,
41        left_encoders: Vec<CapabilityRef>,
42        right_encoders: Vec<CapabilityRef>,
43        wheel_radius_m: f64,
44        wheel_base_m: f64,
45    },
46    Mecanum {
47        front_left_actuator: CapabilityRef,
48        front_right_actuator: CapabilityRef,
49        rear_left_actuator: CapabilityRef,
50        rear_right_actuator: CapabilityRef,
51        wheel_radius_m: f64,
52        wheel_base_m: f64,
53        track_m: f64,
54    },
55    Ackermann {
56        steering_actuator: CapabilityRef,
57        drive_actuator: CapabilityRef,
58        steering_encoder: Option<CapabilityRef>,
59        drive_encoder: Option<CapabilityRef>,
60        wheel_base_m: f64,
61        track_m: f64,
62        max_steering_angle_rad: f64,
63    },
64    Omnidirectional {
65        actuators: Vec<CapabilityRef>,
66        encoders: Vec<CapabilityRef>,
67    },
68}