Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
175
crates/ruvector-robotics/src/perception/config.rs
Normal file
175
crates/ruvector-robotics/src/perception/config.rs
Normal file
@@ -0,0 +1,175 @@
|
||||
//! Configuration types for the perception pipeline.
|
||||
//!
|
||||
//! Provides tuning knobs for scene-graph construction, obstacle detection,
|
||||
//! and the top-level perception configuration that bundles them together.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Scene-graph configuration
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Tuning parameters for scene-graph construction from point clouds.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SceneGraphConfig {
|
||||
/// Maximum distance between two points to be considered part of the same
|
||||
/// cluster (metres).
|
||||
pub cluster_radius: f64,
|
||||
/// Minimum number of points required to form a valid cluster / object.
|
||||
pub min_cluster_size: usize,
|
||||
/// Hard cap on the number of objects the builder will emit.
|
||||
pub max_objects: usize,
|
||||
/// Maximum centre-to-centre distance for two objects to be connected by an
|
||||
/// edge in the scene graph (metres).
|
||||
pub edge_distance_threshold: f64,
|
||||
}
|
||||
|
||||
impl Default for SceneGraphConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cluster_radius: 0.5,
|
||||
min_cluster_size: 3,
|
||||
max_objects: 256,
|
||||
edge_distance_threshold: 5.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Obstacle configuration
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Tuning parameters for the obstacle detector.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ObstacleConfig {
|
||||
/// Minimum number of points that must fall inside a cluster to be
|
||||
/// considered an obstacle.
|
||||
pub min_obstacle_size: usize,
|
||||
/// Maximum range from the robot within which obstacles are detected
|
||||
/// (metres).
|
||||
pub max_detection_range: f64,
|
||||
/// Extra padding added around every detected obstacle (metres).
|
||||
pub safety_margin: f64,
|
||||
}
|
||||
|
||||
impl Default for ObstacleConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
min_obstacle_size: 3,
|
||||
max_detection_range: 20.0,
|
||||
safety_margin: 0.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Top-level perception configuration
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Aggregated configuration for the full perception pipeline.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PerceptionConfig {
|
||||
pub scene_graph: SceneGraphConfig,
|
||||
pub obstacle: ObstacleConfig,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_scene_graph_config_defaults() {
|
||||
let cfg = SceneGraphConfig::default();
|
||||
assert!((cfg.cluster_radius - 0.5).abs() < f64::EPSILON);
|
||||
assert_eq!(cfg.min_cluster_size, 3);
|
||||
assert_eq!(cfg.max_objects, 256);
|
||||
assert!((cfg.edge_distance_threshold - 5.0).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_obstacle_config_defaults() {
|
||||
let cfg = ObstacleConfig::default();
|
||||
assert_eq!(cfg.min_obstacle_size, 3);
|
||||
assert!((cfg.max_detection_range - 20.0).abs() < f64::EPSILON);
|
||||
assert!((cfg.safety_margin - 0.2).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_perception_config_defaults() {
|
||||
let cfg = PerceptionConfig::default();
|
||||
assert_eq!(cfg.scene_graph, SceneGraphConfig::default());
|
||||
assert_eq!(cfg.obstacle, ObstacleConfig::default());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scene_graph_config_serde_roundtrip() {
|
||||
let cfg = SceneGraphConfig {
|
||||
cluster_radius: 1.0,
|
||||
min_cluster_size: 5,
|
||||
max_objects: 128,
|
||||
edge_distance_threshold: 3.0,
|
||||
};
|
||||
let json = serde_json::to_string(&cfg).unwrap();
|
||||
let restored: SceneGraphConfig = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(cfg, restored);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_obstacle_config_serde_roundtrip() {
|
||||
let cfg = ObstacleConfig {
|
||||
min_obstacle_size: 10,
|
||||
max_detection_range: 50.0,
|
||||
safety_margin: 0.5,
|
||||
};
|
||||
let json = serde_json::to_string(&cfg).unwrap();
|
||||
let restored: ObstacleConfig = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(cfg, restored);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_perception_config_serde_roundtrip() {
|
||||
let cfg = PerceptionConfig::default();
|
||||
let json = serde_json::to_string_pretty(&cfg).unwrap();
|
||||
let restored: PerceptionConfig = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(cfg, restored);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_clone_equality() {
|
||||
let a = PerceptionConfig::default();
|
||||
let b = a.clone();
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_debug_format() {
|
||||
let cfg = PerceptionConfig::default();
|
||||
let dbg = format!("{:?}", cfg);
|
||||
assert!(dbg.contains("PerceptionConfig"));
|
||||
assert!(dbg.contains("SceneGraphConfig"));
|
||||
assert!(dbg.contains("ObstacleConfig"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_custom_perception_config() {
|
||||
let cfg = PerceptionConfig {
|
||||
scene_graph: SceneGraphConfig {
|
||||
cluster_radius: 2.0,
|
||||
min_cluster_size: 10,
|
||||
max_objects: 64,
|
||||
edge_distance_threshold: 10.0,
|
||||
},
|
||||
obstacle: ObstacleConfig {
|
||||
min_obstacle_size: 5,
|
||||
max_detection_range: 100.0,
|
||||
safety_margin: 1.0,
|
||||
},
|
||||
};
|
||||
assert!((cfg.scene_graph.cluster_radius - 2.0).abs() < f64::EPSILON);
|
||||
assert_eq!(cfg.obstacle.min_obstacle_size, 5);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user