mecha10_sim/services/
simulation.rs1#![allow(dead_code)]
2
3use crate::paths;
9use crate::sim::{EnvironmentSelector, RobotGenerator, RobotProfile};
10use anyhow::Result;
11use std::path::{Path, PathBuf};
12
13pub struct SimulationService {
35 base_path: PathBuf,
37}
38
39impl SimulationService {
40 pub fn new() -> Self {
42 Self {
43 base_path: PathBuf::from(paths::project::SIMULATION_OUTPUT_DIR),
44 }
45 }
46
47 pub fn with_base_path(base_path: impl Into<PathBuf>) -> Self {
53 Self {
54 base_path: base_path.into(),
55 }
56 }
57
58 pub fn generate(
67 &self,
68 config_path: &Path,
69 output_path: &Path,
70 max_envs: usize,
71 min_score: i32,
72 ) -> Result<GenerationResult> {
73 let profile = RobotProfile::from_config_file(config_path)?;
74
75 let robot_output = output_path.join("robot.tscn");
76 let robot_generator = RobotGenerator::from_config_file(config_path)?;
77 robot_generator.generate(&robot_output)?;
78
79 let selector = EnvironmentSelector::new()?;
80 let matches = selector.select_environments(&profile, max_envs)?;
81
82 let filtered_matches: Vec<_> = matches.into_iter().filter(|m| m.score >= min_score).collect();
83
84 if filtered_matches.is_empty() {
85 return Err(anyhow::anyhow!(
86 "No matching environments found (min score: {})",
87 min_score
88 ));
89 }
90
91 let _catalog_path = PathBuf::from(paths::framework::ROBOT_TASKS_CATALOG);
92 let base_path = PathBuf::from(paths::framework::ROBOT_TASKS_DIR);
93 let mut available_count = 0;
94
95 for env_match in &filtered_matches {
96 let env_path = base_path.join(&env_match.environment.path);
97 if env_path.exists() {
98 available_count += 1;
99 }
100 }
101
102 Ok(GenerationResult {
103 robot_scene: robot_output,
104 environments: filtered_matches.iter().map(|m| m.environment.id.clone()).collect(),
105 available_count,
106 })
107 }
108
109 pub fn generate_robot(&self, config_path: &Path, output_path: &Path) -> Result<()> {
116 let robot_generator = RobotGenerator::from_config_file(config_path)?;
117 robot_generator.generate(output_path)
118 }
119
120 pub fn list_environments(&self, config_path: &Path, verbose: bool) -> Result<Vec<EnvironmentInfo>> {
127 let profile = RobotProfile::from_config_file(config_path)?;
128 let selector = EnvironmentSelector::new()?;
129 let matches = selector.select_environments(&profile, 100)?;
130
131 let base_path = PathBuf::from(paths::framework::ROBOT_TASKS_DIR);
132 let mut environments = Vec::new();
133
134 for env_match in matches {
135 let env_path = base_path.join(&env_match.environment.path);
136 let available = env_path.exists();
137
138 if verbose || available {
139 environments.push(EnvironmentInfo {
140 id: env_match.environment.id.clone(),
141 name: env_match.environment.name.clone(),
142 description: env_match.environment.description.clone(),
143 score: env_match.score,
144 available,
145 });
146 }
147 }
148
149 Ok(environments)
150 }
151
152 pub fn validate_config(&self, config_path: &Path) -> Result<ValidationResult> {
158 let profile = RobotProfile::from_config_file(config_path)?;
159
160 let mut errors = Vec::new();
161 let mut warnings = Vec::new();
162
163 if profile.platform.is_empty() {
164 errors.push("Platform not specified".to_string());
165 }
166
167 if profile.sensors.is_empty() {
168 warnings.push("No sensors configured".to_string());
169 }
170
171 if profile.task_nodes.is_empty() {
172 warnings.push("No task nodes configured".to_string());
173 }
174
175 let is_valid = errors.is_empty();
176
177 Ok(ValidationResult {
178 is_valid,
179 errors,
180 warnings,
181 platform: profile.platform,
182 sensor_count: profile.sensors.len(),
183 node_count: profile.task_nodes.len(),
184 })
185 }
186
187 pub fn is_setup(&self) -> bool {
189 self.base_path.exists() && self.base_path.join("robot.tscn").exists()
190 }
191
192 pub fn base_path(&self) -> &Path {
194 &self.base_path
195 }
196}
197
198impl Default for SimulationService {
199 fn default() -> Self {
200 Self::new()
201 }
202}
203
204#[derive(Debug)]
206pub struct GenerationResult {
207 pub robot_scene: PathBuf,
208 pub environments: Vec<String>,
209 pub available_count: usize,
210}
211
212#[derive(Debug, Clone)]
214pub struct EnvironmentInfo {
215 pub id: String,
216 pub name: String,
217 pub description: String,
218 pub score: i32,
219 pub available: bool,
220}
221
222#[derive(Debug)]
224pub struct ValidationResult {
225 pub is_valid: bool,
226 pub errors: Vec<String>,
227 pub warnings: Vec<String>,
228 pub platform: String,
229 pub sensor_count: usize,
230 pub node_count: usize,
231}