mecha10_nodes_behavior_executor/
config.rs

1//! Configuration for BehaviorExecutor node
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6/// Configuration for the behavior executor node
7///
8/// This controls which behavior tree is loaded and executed.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct BehaviorExecutorConfig {
11    /// Name of the behavior to execute (e.g., "idle_wander")
12    ///
13    /// This should match a JSON file in the behaviors directory.
14    pub behavior_name: String,
15
16    /// Directory containing behavior tree templates
17    #[serde(default = "default_behaviors_dir")]
18    pub behaviors_dir: String,
19
20    /// Tick rate in Hz (how many times per second to tick the behavior tree)
21    #[serde(default = "default_tick_rate_hz")]
22    pub tick_rate_hz: f32,
23
24    /// Maximum number of ticks before stopping (None = run forever)
25    #[serde(default)]
26    pub max_ticks: Option<usize>,
27
28    /// Whether to log execution statistics
29    #[serde(default = "default_log_stats")]
30    pub log_stats: bool,
31
32    /// Topics configuration
33    #[serde(default)]
34    pub topics: Topics,
35}
36
37/// Topics configuration for behavior executor
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct Topics {
40    /// Topics this node publishes to
41    /// Format: [{ "status": "/behavior/status" }]
42    #[serde(default)]
43    pub publishes: Vec<HashMap<String, String>>,
44
45    /// Topics this node subscribes to
46    /// Format: [{ "control": "/behavior/control" }]
47    #[serde(default)]
48    pub subscribes: Vec<HashMap<String, String>>,
49}
50
51impl Default for Topics {
52    fn default() -> Self {
53        let mut publishes = Vec::new();
54        let mut subscribes = Vec::new();
55
56        // Default publish topic
57        let mut status_map = HashMap::new();
58        status_map.insert("status".to_string(), "/behavior/status".to_string());
59        publishes.push(status_map);
60
61        // Default subscribe topic
62        let mut control_map = HashMap::new();
63        control_map.insert("control".to_string(), "/behavior/control".to_string());
64        subscribes.push(control_map);
65
66        Self { publishes, subscribes }
67    }
68}
69
70impl BehaviorExecutorConfig {
71    /// Get control topic path from topics config
72    pub fn control_topic(&self) -> String {
73        self.topics
74            .subscribes
75            .iter()
76            .find_map(|t| t.get("control"))
77            .cloned()
78            .unwrap_or_else(|| "/behavior/control".to_string())
79    }
80
81    /// Get status topic path from topics config
82    pub fn status_topic(&self) -> String {
83        self.topics
84            .publishes
85            .iter()
86            .find_map(|t| t.get("status"))
87            .cloned()
88            .unwrap_or_else(|| "/behavior/status".to_string())
89    }
90}
91
92impl Default for BehaviorExecutorConfig {
93    fn default() -> Self {
94        Self {
95            behavior_name: "idle_wander".to_string(),
96            behaviors_dir: default_behaviors_dir(),
97            tick_rate_hz: default_tick_rate_hz(),
98            max_ticks: None,
99            log_stats: default_log_stats(),
100            topics: Topics::default(),
101        }
102    }
103}
104
105fn default_behaviors_dir() -> String {
106    "behaviors".to_string()
107}
108
109fn default_tick_rate_hz() -> f32 {
110    10.0
111}
112
113fn default_log_stats() -> bool {
114    true
115}