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}