use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObjectDetectorConfig {
#[serde(default = "default_model_path")]
pub model_path: String,
#[serde(default = "default_model_name")]
pub model_name: String,
#[serde(default = "default_input_size")]
pub input_size: u32,
#[serde(default = "default_confidence_threshold")]
pub confidence_threshold: f32,
#[serde(default = "default_iou_threshold")]
pub iou_threshold: f32,
#[serde(default = "default_max_detections")]
pub max_detections: usize,
#[serde(default = "default_frame_skip")]
pub frame_skip: u32,
#[serde(default = "default_enabled")]
pub default_enabled: bool,
#[serde(default = "default_use_int8")]
pub use_int8: bool,
#[serde(default = "default_max_async_frames")]
pub max_async_frames: usize,
#[serde(default)]
pub topics: Topics,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Topics {
#[serde(default)]
pub publishes: Vec<HashMap<String, String>>,
#[serde(default)]
pub subscribes: Vec<HashMap<String, String>>,
}
impl Default for Topics {
fn default() -> Self {
let mut publishes = Vec::new();
let mut subscribes = Vec::new();
let mut pub_map = HashMap::new();
pub_map.insert("output".to_string(), "/vision/object/detections".to_string());
publishes.push(pub_map);
let mut input_map = HashMap::new();
input_map.insert("input".to_string(), "/camera/rgb".to_string());
subscribes.push(input_map);
let mut control_map = HashMap::new();
control_map.insert("control".to_string(), "/vision/object/control".to_string());
subscribes.push(control_map);
Self { publishes, subscribes }
}
}
impl ObjectDetectorConfig {
pub fn input_topic(&self) -> String {
self.topics
.subscribes
.iter()
.find_map(|t| t.get("input"))
.cloned()
.unwrap_or_else(|| "/camera/rgb".to_string())
}
pub fn output_topic(&self) -> String {
self.topics
.publishes
.iter()
.find_map(|t| t.get("output"))
.cloned()
.unwrap_or_else(|| "/vision/object/detections".to_string())
}
pub fn control_topic(&self) -> String {
self.topics
.subscribes
.iter()
.find_map(|t| t.get("control"))
.cloned()
.unwrap_or_else(|| "/vision/object/control".to_string())
}
}
fn default_model_path() -> String {
"models/yolov8n/model.onnx".to_string()
}
fn default_model_name() -> String {
"yolov8n".to_string()
}
fn default_input_size() -> u32 {
640
}
fn default_confidence_threshold() -> f32 {
0.5
}
fn default_iou_threshold() -> f32 {
0.45
}
fn default_max_detections() -> usize {
100
}
fn default_frame_skip() -> u32 {
1
}
fn default_enabled() -> bool {
false
}
fn default_use_int8() -> bool {
false
}
fn default_max_async_frames() -> usize {
1
}
impl Default for ObjectDetectorConfig {
fn default() -> Self {
Self {
model_path: default_model_path(),
model_name: default_model_name(),
input_size: default_input_size(),
confidence_threshold: default_confidence_threshold(),
iou_threshold: default_iou_threshold(),
max_detections: default_max_detections(),
frame_skip: default_frame_skip(),
default_enabled: default_enabled(),
use_int8: default_use_int8(),
max_async_frames: default_max_async_frames(),
topics: Topics::default(),
}
}
}