mecha10_behavior_runtime/actions/
navigation.rs1use crate::{BehaviorNode, Context, NodeStatus};
4use async_trait::async_trait;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8macro_rules! stub_tick_success {
9 ($msg:literal) => {{
10 tracing::debug!($msg);
11 Ok(NodeStatus::Success)
12 }};
13}
14
15#[derive(Debug)]
16pub struct PlanPathNode {
17 #[allow(dead_code)]
18 target_position: Vec<f64>,
19 #[allow(dead_code)]
20 algorithm: String,
21}
22
23#[derive(Debug, Serialize, Deserialize)]
24struct PlanPathConfig {
25 target_position: Vec<f64>,
26 #[serde(default = "default_algorithm")]
27 path_planning_algorithm: String,
28}
29
30fn default_algorithm() -> String {
31 "a_star".to_string()
32}
33
34impl PlanPathNode {
35 pub fn from_json(config: Value) -> anyhow::Result<Self> {
37 let cfg: PlanPathConfig = serde_json::from_value(config)?;
38 Ok(Self {
39 target_position: cfg.target_position,
40 algorithm: cfg.path_planning_algorithm,
41 })
42 }
43}
44
45#[async_trait]
46impl BehaviorNode for PlanPathNode {
47 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
48 tracing::debug!("PlanPathNode: planning path to {:?} (stub)", self.target_position);
49 Ok(NodeStatus::Success)
50 }
51
52 fn name(&self) -> &str {
53 "PlanPathNode"
54 }
55}
56
57#[derive(Debug)]
58pub struct FollowPathNode {
59 #[allow(dead_code)]
60 topic: String,
61 #[allow(dead_code)]
62 max_speed: f64,
63 #[allow(dead_code)]
64 turn_rate: f64,
65}
66
67#[derive(Debug, Serialize, Deserialize)]
68struct FollowPathConfig {
69 #[serde(default = "default_motor_topic")]
70 topic: String,
71 #[serde(default = "default_max_speed")]
72 max_speed: f64,
73 #[serde(default = "default_turn_rate")]
74 turn_rate: f64,
75}
76
77fn default_motor_topic() -> String {
78 "/motor/cmd_vel".to_string()
79}
80
81fn default_max_speed() -> f64 {
82 1.0
83}
84
85fn default_turn_rate() -> f64 {
86 0.5
87}
88
89impl FollowPathNode {
90 pub fn from_json(config: Value) -> anyhow::Result<Self> {
92 let cfg: FollowPathConfig = serde_json::from_value(config)?;
93 Ok(Self {
94 topic: cfg.topic,
95 max_speed: cfg.max_speed,
96 turn_rate: cfg.turn_rate,
97 })
98 }
99}
100
101#[async_trait]
102impl BehaviorNode for FollowPathNode {
103 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
104 stub_tick_success!("FollowPathNode: following path (stub)")
105 }
106
107 fn name(&self) -> &str {
108 "FollowPathNode"
109 }
110}
111
112#[derive(Debug)]
113pub struct CheckArrivalNode {
114 #[allow(dead_code)]
115 position_tolerance: f64,
116 #[allow(dead_code)]
117 angular_tolerance: f64,
118}
119
120#[derive(Debug, Serialize, Deserialize)]
121struct CheckArrivalConfig {
122 position_tolerance: f64,
123 angular_tolerance: f64,
124}
125
126impl CheckArrivalNode {
127 pub fn from_json(config: Value) -> anyhow::Result<Self> {
129 let cfg: CheckArrivalConfig = serde_json::from_value(config)?;
130 Ok(Self {
131 position_tolerance: cfg.position_tolerance,
132 angular_tolerance: cfg.angular_tolerance,
133 })
134 }
135}
136
137#[async_trait]
138impl BehaviorNode for CheckArrivalNode {
139 async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
140 stub_tick_success!("CheckArrivalNode: checking arrival (stub)")
141 }
142
143 fn name(&self) -> &str {
144 "CheckArrivalNode"
145 }
146}