agent_tk/simulation/
tst.rs1use futures::future::FutureExt;
4use geo::{Area, Centroid};
5
6use crate::definitions::agent as definitions_agent;
7use crate::definitions::tst as definitions_tst;
8use crate::definitions::tst::SpeedCompute;
9use crate::execution::tst as execution_tst;
10use crate::execution::tst::TreeExecutorTrait;
11use crate::{Error, Result};
12
13mod utils;
14
15#[derive(Default, Clone, serde::Serialize, serde::Deserialize)]
23pub struct SimulationResult
24{
25 estimated_cost: f32,
26 final_states: crate::states::States,
27}
28
29impl SimulationResult
30{
31 pub fn get_estimated_cost(&self) -> f32
33 {
34 self.estimated_cost
35 }
36 pub fn get_final_states(&self) -> &crate::states::States
38 {
39 &self.final_states
40 }
41}
42
43pub async fn simulate_execution(
51 initial_states: crate::states::States,
52 capabilities: definitions_agent::capabilities::Capabilities,
53 tst_node: definitions_tst::Node,
54) -> Result<SimulationResult>
55{
56 let agent = Agent {
57 capabilities,
58 ..Default::default()
59 };
60 agent.simulation_result.lock().unwrap().final_states = initial_states;
61 let executor =
62 execution_tst::DefaultTreeExecutor::<MoveToExecutor, SearchAreaExecutor>::from_agent(&agent);
63 let r = executor.execute(tst_node);
64 let res = r.await;
65 if let Err(e) = res
66 {
67 Err(e)
68 }
69 else
70 {
71 Ok(agent.simulation_result.lock().unwrap().clone())
72 }
73}
74
75#[derive(Clone, Default)]
80struct Agent
81{
82 capabilities: definitions_agent::capabilities::Capabilities,
83 simulation_result: std::sync::Arc<std::sync::Mutex<SimulationResult>>,
84}
85
86impl execution_tst::Agent for Agent {}
87
88struct MoveToExecutor
89{
90 agent: Agent,
91}
92
93impl execution_tst::CreatableFromAgent<Agent, MoveToExecutor> for MoveToExecutor
94{
95 fn from_agent(agent: &Agent) -> MoveToExecutor
96 {
97 MoveToExecutor {
98 agent: agent.clone(),
99 }
100 }
101}
102
103impl execution_tst::Executor<definitions_tst::MoveTo> for MoveToExecutor
104{
105 fn execute<'b>(
106 &self,
107 _executors: &'b impl execution_tst::Executors,
108 t: definitions_tst::MoveTo,
109 ) -> execution_tst::ExecutionResult<'b>
110 {
111 let simulation_result = self.agent.simulation_result.clone();
112 let capabilities = self.agent.capabilities.clone();
113 async move {
114 let mut simulation_result = simulation_result.lock().unwrap();
115 let current_position = simulation_result.final_states.get_position()?;
116
117 let move_to_capability = capabilities
118 .get_move()
119 .map_err(|e| crate::Error::ExecutionFailed(Box::new(e)))?;
120 let vel = t
121 .params
122 .speed
123 .compute_velocity(move_to_capability.get_max_velocity());
124 simulation_result.estimated_cost += utils::haversine_distance(
125 current_position.longitude,
126 current_position.latitude,
127 t.params.waypoint.longitude,
128 t.params.waypoint.latitude,
129 ) as f32
130 * vel;
131
132 simulation_result
133 .final_states
134 .update_state(crate::states::Position {
135 latitude: t.params.waypoint.latitude,
136 longitude: t.params.waypoint.longitude,
137 })?;
138 Ok::<(), Error>(())
139 }
140 .boxed()
141 }
142}
143
144struct SearchAreaExecutor
145{
146 agent: Agent,
147}
148
149impl execution_tst::CreatableFromAgent<Agent, SearchAreaExecutor> for SearchAreaExecutor
150{
151 fn from_agent(agent: &Agent) -> SearchAreaExecutor
152 {
153 SearchAreaExecutor {
154 agent: agent.clone(),
155 }
156 }
157}
158
159impl execution_tst::Executor<definitions_tst::SearchArea> for SearchAreaExecutor
160{
161 fn execute<'b>(
162 &self,
163 _executors: &'b impl execution_tst::Executors,
164 t: definitions_tst::SearchArea,
165 ) -> execution_tst::ExecutionResult<'b>
166 {
167 let simulation_result = self.agent.simulation_result.clone();
168 let capabilities = self.agent.capabilities.clone();
169
170 async move {
171 let mut simulation_result = simulation_result.lock().unwrap();
172 let current_position = simulation_result.final_states.get_position()?;
173
174 let move_to_capability = capabilities
175 .get_move()
176 .map_err(|e| crate::Error::ExecutionFailed(Box::new(e)))?;
177
178 let mut polygon_points = Vec::<(f64, f64)>::new();
180
181 for pt in t.params.area
182 {
183 polygon_points.push((pt.longitude, pt.latitude));
184 }
185
186 polygon_points.push(polygon_points[0]);
187
188 let polygon = geo::Polygon::new(geo::LineString::from(polygon_points), vec![]);
189
190 let center = polygon.centroid().unwrap();
191 simulation_result.estimated_cost += utils::haversine_distance(
192 current_position.longitude,
193 current_position.latitude,
194 center.x(),
195 center.y(),
196 ) as f32;
197 simulation_result.estimated_cost +=
198 polygon.unsigned_area() as f32 * move_to_capability.get_max_velocity();
199
200 simulation_result
201 .final_states
202 .update_state(crate::states::Position {
203 longitude: center.x(),
204 latitude: center.y(),
205 })?;
206 Ok::<(), Error>(())
207 }
208 .boxed()
209 }
210}