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//! # Cargo features
8//!
9//! - `non_rectified` — enables [`BrownConradyModel`] and [`KannalaBrandtModel`] alongside
10//! the corresponding [`pose::DistortionCoeffs`] variants. Off by default; opt in for
11//! cameras with significant lens distortion (OpenCV Brown-Conrady or Kannala-Brandt
12//! equidistant fisheye). See `README.md` for the full feature matrix.
13
14/// Batched state container for Structure of Arrays (SoA) layout.
15pub(crate) mod batch;
16/// Board-level configuration and layout utilities.
17pub mod board;
18/// Zero-cost camera distortion model trait and implementations.
19pub mod camera;
20/// ChAruco board saddle-point extraction and pose estimation.
21pub mod charuco;
22/// Configuration types for the detector pipeline.
23pub mod config;
24/// Tag decoding traits and implementations.
25pub(crate) mod decoder;
26/// The primary public API for the detector.
27pub mod detector;
28/// Tag family dictionaries (AprilTag, ArUco).
29pub(crate) mod dictionaries;
30/// Unified ERF-based sub-pixel edge refinement shared by quad and decoder stages.
31pub(crate) mod edge_refinement;
32/// EDLines localized quad extraction.
33pub(crate) mod edlines;
34/// Error types for the detection pipeline.
35pub mod error;
36/// Edge-preserving filtering for small tag detection.
37pub(crate) mod filter;
38/// Fast-path decoding funnel.
39pub(crate) mod funnel;
40/// Gradient computation for edge refinement.
41pub(crate) mod gradient;
42/// Gradient-Weighted Line Fitting (GWLF).
43pub(crate) mod gwlf;
44/// Image buffer abstractions.
45pub mod image;
46/// 3D Pose Estimation (PnP).
47pub mod pose;
48/// Weighted pose estimation logic.
49pub(crate) mod pose_weighted;
50/// Quad extraction and geometric primitives.
51pub(crate) mod quad;
52/// Connected components labeling using Union-Find.
53pub(crate) mod segmentation;
54/// SIMD optimized mathematical kernels.
55pub(crate) mod simd;
56/// SIMD-Accelerated Connected Components Labeling (CCL).
57pub(crate) mod simd_ccl_fusion;
58/// Decoding strategies (Hard vs Soft).
59pub(crate) mod strategy;
60/// Utilities for testing and synthetic data generation.
61#[cfg(any(test, feature = "bench-internals"))]
62pub(crate) mod test_utils;
63/// Adaptive thresholding implementation.
64pub(crate) mod threshold;
65/// Thread-local workspace arena for per-candidate allocations.
66pub(crate) mod workspace;
67
68// Re-exports for the public API
69pub use crate::batch::TelemetryPayload;
70pub use crate::board::{AprilGridTopology, BoardConfigError, CharucoTopology};
71#[cfg(feature = "non_rectified")]
72pub use crate::camera::{BrownConradyModel, KannalaBrandtModel};
73pub use crate::camera::{CameraModel, PinholeModel};
74pub use crate::config::{
75 CornerRefinementMode, DecodeMode, DetectOptions, DetectorConfig, PoseEstimationMode,
76 QuadExtractionMode, TagFamily,
77};
78pub use crate::detector::{Detector, DetectorBuilder, FrameContext, LocusEngine};
79pub use crate::error::{ConfigError, DetectorError};
80pub use crate::image::ImageView;
81pub use crate::pose::{CameraIntrinsics, DistortionCoeffs};
82
83#[cfg(feature = "bench-internals")]
84pub mod bench_api {
85 //! Internal API exposed exclusively for benchmarking and integration testing.
86 pub use crate::batch::*;
87 pub use crate::camera::*;
88 pub use crate::decoder::*;
89 pub use crate::dictionaries::*;
90 pub use crate::edge_refinement::*;
91 pub use crate::filter::*;
92 pub use crate::funnel::*;
93 pub use crate::gwlf::*;
94 pub use crate::pose::*;
95 pub use crate::pose_weighted::bench_compute_corner_covariance;
96 pub use crate::quad::*;
97 pub use crate::segmentation::*;
98 pub use crate::simd::sampler::*;
99 pub use crate::simd_ccl_fusion::*;
100 pub use crate::strategy::*;
101 pub use crate::test_utils::*;
102 pub use crate::threshold::*;
103}
104
105/// A single tag detection result.
106#[derive(Clone, Debug, Default)]
107pub struct Detection {
108 /// The decoded ID of the tag.
109 pub id: u32,
110 /// The center coordinates of the tag in image pixels (x, y).
111 pub center: [f64; 2],
112 /// The 4 corners of the tag in image pixels.
113 pub corners: [[f64; 2]; 4],
114 /// The number of hamming errors corrected during decoding.
115 pub hamming: u32,
116 /// The rotation of the tag relative to its canonical orientation (0-3).
117 pub rotation: u8,
118 /// The decision margin of the decoding (higher is more confident).
119 pub decision_margin: f64,
120 /// The extracted bits from the tag.
121 pub bits: u64,
122 /// The 3D pose of the tag relative to the camera (if requested).
123 pub pose: Option<crate::pose::Pose>,
124 /// The covariance of the estimated 3D pose (6x6 matrix), if computed.
125 pub pose_covariance: Option<[[f64; 6]; 6]>,
126}
127
128impl Detection {
129 /// Compute the axis-aligned bounding box (AABB) of the detection.
130 ///
131 /// Returns (min_x, min_y, max_x, max_y) in integer pixel coordinates.
132 #[must_use]
133 #[allow(clippy::cast_sign_loss)]
134 pub fn aabb(&self) -> (usize, usize, usize, usize) {
135 let mut min_x = f64::INFINITY;
136 let mut min_y = f64::INFINITY;
137 let max_x = self
138 .corners
139 .iter()
140 .fold(f64::NEG_INFINITY, |acc, p| acc.max(p[0]));
141 let max_y = self
142 .corners
143 .iter()
144 .fold(f64::NEG_INFINITY, |acc, p| acc.max(p[1]));
145 for p in &self.corners {
146 min_x = min_x.min(p[0]);
147 min_y = min_y.min(p[1]);
148 }
149
150 (
151 min_x.floor().max(0.0) as usize,
152 min_y.floor().max(0.0) as usize,
153 max_x.ceil().max(0.0) as usize,
154 max_y.ceil().max(0.0) as usize,
155 )
156 }
157}
158
159/// A 2D point with f64 precision.
160#[derive(Clone, Copy, Debug, Default)]
161pub struct Point {
162 /// X coordinate.
163 pub x: f64,
164 /// Y coordinate.
165 pub y: f64,
166}
167
168/// A 3D pose (rotation + translation).
169pub use crate::pose::Pose;
170
171/// Returns version and build information for the core library.
172#[must_use]
173pub fn core_info() -> String {
174 "Locus Core v0.1.0 Engine (Encapsulated)".to_string()
175}