use nalgebra::Point2;
use projective_grid::Coord;
use projective_grid::LocalAxis as NextLocalAxis;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct AxisEstimate {
pub angle: f32,
pub sigma: f32,
}
impl Default for AxisEstimate {
fn default() -> Self {
Self {
angle: 0.0,
sigma: std::f32::consts::PI,
}
}
}
impl AxisEstimate {
pub fn from_angle(angle: f32) -> Self {
Self { angle, sigma: 0.0 }
}
}
#[inline]
pub fn axis_estimate_to_next(a: AxisEstimate) -> NextLocalAxis {
NextLocalAxis::new(a.angle, Some(a.sigma))
}
#[cfg(test)]
mod axis_tests {
use super::*;
#[test]
fn default_axis_is_no_information_sentinel() {
let axis = AxisEstimate::default();
assert_eq!(axis.angle, 0.0);
assert_eq!(axis.sigma, std::f32::consts::PI);
}
#[test]
fn from_angle_sets_zero_sigma() {
let axis = AxisEstimate::from_angle(1.25);
assert_eq!(axis.angle, 1.25);
assert_eq!(axis.sigma, 0.0);
}
#[test]
fn to_next_carries_angle_and_sigma() {
let axis = AxisEstimate {
angle: 0.75,
sigma: 0.02,
};
let next = axis_estimate_to_next(axis);
assert_eq!(next.angle_rad, 0.75);
assert_eq!(next.sigma_rad, Some(0.02));
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TargetKind {
Chessboard,
Charuco,
CheckerboardMarker,
PuzzleBoard,
}
#[non_exhaustive]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LabeledCorner {
pub position: Point2<f32>,
pub grid: Option<Coord>,
pub id: Option<u32>,
#[serde(default)]
pub target_position: Option<Point2<f32>>,
#[serde(alias = "confidence")]
pub score: f32,
}
impl LabeledCorner {
pub fn new(position: Point2<f32>, score: f32) -> Self {
Self {
position,
grid: None,
id: None,
target_position: None,
score,
}
}
#[must_use]
pub fn with_grid(mut self, grid: Coord) -> Self {
self.grid = Some(grid);
self
}
#[must_use]
pub fn with_id(mut self, id: u32) -> Self {
self.id = Some(id);
self
}
#[must_use]
pub fn with_target_position(mut self, target_position: Point2<f32>) -> Self {
self.target_position = Some(target_position);
self
}
}
#[non_exhaustive]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TargetDetection {
pub kind: TargetKind,
pub corners: Vec<LabeledCorner>,
}
impl TargetDetection {
pub fn new(kind: TargetKind, corners: Vec<LabeledCorner>) -> Self {
Self { kind, corners }
}
}