Skip to main content

locus_core/
error.rs

1//! Error types for the detection pipeline.
2
3use thiserror::Error;
4
5/// Errors that can occur during detector configuration validation.
6#[derive(Debug, Clone, Error)]
7pub enum ConfigError {
8    /// Threshold tile size must be >= 2.
9    #[error("threshold_tile_size must be >= 2, got {0}")]
10    TileSizeTooSmall(usize),
11    /// Decimation factor must be >= 1.
12    #[error("decimation factor must be >= 1, got {0}")]
13    InvalidDecimation(usize),
14    /// Upscale factor must be >= 1.
15    #[error("upscale_factor must be >= 1, got {0}")]
16    InvalidUpscaleFactor(usize),
17    /// Minimum fill ratio must be in [0.0, 1.0].
18    #[error("fill ratio range invalid: min={min}, max={max} (must be 0.0..=1.0, min < max)")]
19    InvalidFillRatio {
20        /// The minimum fill ratio that was set.
21        min: f32,
22        /// The maximum fill ratio that was set.
23        max: f32,
24    },
25    /// Minimum edge length must be positive.
26    #[error("quad_min_edge_length must be positive, got {0}")]
27    InvalidEdgeLength(f64),
28    /// Structure tensor radius must stay within the supported kernel bound.
29    #[error("structure_tensor_radius must be <= 8, got {0}")]
30    InvalidStructureTensorRadius(u8),
31    /// EdLines is geometrically incompatible with Erf corner refinement.
32    ///
33    /// Erf performs an independent 1-D search per corner which destroys the
34    /// planarity constraint established by the joint Gauss-Newton solver in
35    /// the EdLines pipeline, degrading corner RMSE from ~0.17 px to ~0.59 px.
36    #[error(
37        "EdLines + Erf refinement are incompatible: use CornerRefinementMode::None or \
38         CornerRefinementMode::Gwlf with EdLines"
39    )]
40    EdLinesIncompatibleWithErf,
41    /// EdLines is statistically incompatible with Soft (LLR) decoding.
42    ///
43    /// EdLines produces a large number of background line-segment candidates.
44    /// Soft decoding forces deep probabilistic evaluation of all of them,
45    /// causing a 10–22% precision collapse compared to Hard decoding.
46    #[error("EdLines + Soft decoding are incompatible: use DecodeMode::Hard with EdLines")]
47    EdLinesIncompatibleWithSoftDecode,
48    /// EdLines is geometrically incompatible with distorted cameras.
49    ///
50    /// EdLines' Huber IRLS line fit, micro-ray parabola, and GN refinement all
51    /// assume Euclidean pixel geometry. A Brown-Conrady or Kannala-Brandt
52    /// intrinsic bends marker edges into curves, invalidating that assumption.
53    /// Use `QuadExtractionMode::ContourRdp` when passing distortion coefficients.
54    #[error(
55        "EdLines is geometrically incompatible with distorted cameras (BrownConrady / \
56         KannalaBrandt): use QuadExtractionMode::ContourRdp"
57    )]
58    EdLinesUnsupportedWithDistortion,
59    /// Profile JSON failed to parse (malformed syntax or unknown fields).
60    ///
61    /// `serde_json::Error` is not `Clone`, so its `Display` form is captured
62    /// at construction time. The wrapping `ConfigError` stays `Clone`.
63    #[error("profile JSON parse error: {0}")]
64    ProfileParse(String),
65}
66
67/// Errors that can occur during tag detection.
68#[derive(Debug, Clone, Error)]
69pub enum DetectorError {
70    /// Image preprocessing (decimation or upscaling) failed.
71    #[error("preprocessing failed: {0}")]
72    Preprocessing(String),
73    /// Image view construction failed (invalid dimensions/stride).
74    #[error("invalid image: {0}")]
75    InvalidImage(String),
76    /// Configuration validation failed.
77    #[error("config error: {0}")]
78    Config(#[from] ConfigError),
79}