Skip to main content

mecha10_sim/sim/
catalog.rs

1//! Environment catalog loading and management
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::path::Path;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct EnvironmentCatalog {
10    pub version: String,
11    pub environments: Vec<Environment>,
12    #[serde(default)]
13    pub tags: HashMap<String, String>,
14    #[serde(default)]
15    pub difficulty_levels: HashMap<String, String>,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct Environment {
20    pub id: String,
21    pub path: String,
22    pub name: String,
23    pub description: String,
24    pub tags: Vec<String>,
25    pub required_sensors: Vec<String>,
26    #[serde(default)]
27    pub optional_sensors: Vec<String>,
28    pub robot_platforms: Vec<String>,
29    #[serde(default)]
30    pub task_nodes: Vec<String>,
31    pub difficulty: String,
32    #[serde(default)]
33    pub dimensions: Vec<f32>,
34    #[serde(default)]
35    pub features: EnvironmentFeatures,
36    #[serde(default)]
37    pub curriculum_stage: i32,
38    #[serde(default)]
39    pub estimated_duration_s: i32,
40    #[serde(default)]
41    pub reward_config: HashMap<String, f32>,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, Default)]
45pub struct EnvironmentFeatures {
46    #[serde(default)]
47    pub floor: bool,
48    #[serde(default)]
49    pub walls: bool,
50    #[serde(default)]
51    pub obstacles: String,
52    #[serde(default)]
53    pub obstacle_count: i32,
54    #[serde(default)]
55    pub tables: i32,
56    #[serde(default)]
57    pub waypoints: i32,
58    #[serde(default)]
59    pub goal_zones: i32,
60    #[serde(default)]
61    pub npcs: bool,
62    #[serde(default)]
63    pub npc_count: i32,
64    #[serde(default)]
65    pub dynamic: bool,
66}
67
68impl EnvironmentCatalog {
69    /// Load the catalog from `<robot_tasks_dir>/catalog.json`, under a freshly-fetched
70    /// `mecha10-assets` extraction (`configs/simulation/environments/robot-tasks`). The caller
71    /// is responsible for fetching/extracting the assets tarball (see
72    /// `EnvironmentSelector::new`) - this no longer falls back to any bundled-in-the-monorepo
73    /// copy, since `mecha10-templates/templates/configs/simulation/...` was deleted when the
74    /// framework cut over to fetching published `mecha10-assets` content live.
75    pub fn load_default(robot_tasks_dir: &Path) -> Result<Self> {
76        Self::load(&robot_tasks_dir.join("catalog.json"))
77    }
78
79    /// Load catalog from specific path
80    pub fn load(path: &Path) -> Result<Self> {
81        super::load_json(path, "catalog file")
82    }
83}
84
85impl Environment {
86    /// Check if environment is compatible with robot (has all required sensors)
87    pub fn is_compatible_with_sensors(&self, sensors: &[String]) -> bool {
88        self.required_sensors.iter().all(|required| sensors.contains(required))
89    }
90
91    /// Check if environment is compatible with platform
92    pub fn is_compatible_with_platform(&self, platform: &str) -> bool {
93        self.robot_platforms.contains(&platform.to_string())
94    }
95}