Skip to main content

locus_core/
lib.rs

1//! High-performance AprilTag and ArUco detection engine.
2//!
3//! Locus is a research-oriented, memory-safe fiducial marker detector targeting low
4//! latency. It provides a performance-focused pipeline for robotics and computer vision,
5//! with strict zero-heap allocation in the detection hot-path.
6
7/// Batched state container for Structure of Arrays (SoA) layout.
8pub mod batch;
9/// Configuration types for the detector pipeline.
10pub mod config;
11/// Tag decoding traits and implementations.
12pub mod decoder;
13/// The primary public API for the detector.
14pub mod detector;
15/// Tag family dictionaries (AprilTag, ArUco).
16pub mod dictionaries;
17/// Error types for the detection pipeline.
18pub mod error;
19/// Edge-preserving filtering for small tag detection.
20pub mod filter;
21/// Gradient computation for edge refinement.
22pub mod gradient;
23/// Image buffer abstractions.
24pub mod image;
25/// 3D Pose Estimation (PnP).
26pub mod pose;
27/// Weighted pose estimation logic.
28pub mod pose_weighted;
29/// Quad extraction and geometric primitives.
30pub mod quad;
31/// Connected components labeling using Union-Find.
32pub mod segmentation;
33/// SIMD optimized mathematical kernels.
34pub mod simd;
35/// Decoding strategies (Hard vs Soft).
36pub mod strategy;
37/// Utilities for testing and synthetic data generation.
38pub mod test_utils;
39/// Adaptive thresholding implementation.
40pub mod threshold;
41
42// Re-exports for the public API
43pub use crate::config::{
44    CornerRefinementMode, DecodeMode, DetectOptions, DetectorConfig, PoseEstimationMode, TagFamily,
45};
46pub use crate::detector::{Detector, DetectorBuilder};
47pub use crate::error::{ConfigError, DetectorError};
48pub use crate::image::ImageView;
49pub use crate::pose::CameraIntrinsics;
50
51#[cfg(feature = "bench-internals")]
52pub mod bench_api {
53    //! Internal API exposed exclusively for benchmarking and integration testing.
54    pub use crate::batch::*;
55    pub use crate::decoder::*;
56    pub use crate::dictionaries::*;
57    pub use crate::filter::*;
58    pub use crate::pose::*;
59    pub use crate::quad::*;
60    pub use crate::segmentation::*;
61    pub use crate::test_utils::*;
62    pub use crate::threshold::*;
63}
64
65/// A single tag detection result.
66#[derive(Clone, Debug, Default)]
67pub struct Detection {
68    /// The decoded ID of the tag.
69    pub id: u32,
70    /// The center coordinates of the tag in image pixels (x, y).
71    pub center: [f64; 2],
72    /// The 4 corners of the tag in image pixels.
73    pub corners: [[f64; 2]; 4],
74    /// The number of hamming errors corrected during decoding.
75    pub hamming: u32,
76    /// The rotation of the tag relative to its canonical orientation (0-3).
77    pub rotation: u8,
78    /// The decision margin of the decoding (higher is more confident).
79    pub decision_margin: f64,
80    /// The extracted bits from the tag.
81    pub bits: u64,
82    /// The 3D pose of the tag relative to the camera (if requested).
83    pub pose: Option<crate::pose::Pose>,
84    /// The covariance of the estimated 3D pose (6x6 matrix), if computed.
85    pub pose_covariance: Option<[[f64; 6]; 6]>,
86}
87
88impl Detection {
89    /// Compute the axis-aligned bounding box (AABB) of the detection.
90    ///
91    /// Returns (min_x, min_y, max_x, max_y) in integer pixel coordinates.
92    #[must_use]
93    #[allow(clippy::cast_sign_loss)]
94    pub fn aabb(&self) -> (usize, usize, usize, usize) {
95        let mut min_x = f64::INFINITY;
96        let mut min_y = f64::INFINITY;
97        let max_x = self
98            .corners
99            .iter()
100            .fold(f64::NEG_INFINITY, |acc, p| acc.max(p[0]));
101        let max_y = self
102            .corners
103            .iter()
104            .fold(f64::NEG_INFINITY, |acc, p| acc.max(p[1]));
105        for p in &self.corners {
106            min_x = min_x.min(p[0]);
107            min_y = min_y.min(p[1]);
108        }
109
110        (
111            min_x.floor().max(0.0) as usize,
112            min_y.floor().max(0.0) as usize,
113            max_x.ceil().max(0.0) as usize,
114            max_y.ceil().max(0.0) as usize,
115        )
116    }
117}
118
119/// A 2D point with f64 precision.
120#[derive(Clone, Copy, Debug, Default)]
121pub struct Point {
122    /// X coordinate.
123    pub x: f64,
124    /// Y coordinate.
125    pub y: f64,
126}
127
128/// A 3D pose (rotation + translation).
129pub use crate::pose::Pose;
130
131/// Returns version and build information for the core library.
132#[must_use]
133pub fn core_info() -> String {
134    "Locus Core v0.1.0 Engine (Encapsulated)".to_string()
135}