@@ -27,7 +27,7 @@ class ObservationKeys:
2727 JOINT_OBS = STATE_OBS + ".joints"
2828 CARTESIAN_OBS = STATE_OBS + ".cartesian"
2929 TARGET_OBS = STATE_OBS + ".target"
30- SENSOR_OBS = STATE_OBS + ".sensors "
30+ SENSOR_OBS = STATE_OBS + ".sensor "
3131
3232 IMAGE_OBS = "observation.images"
3333
@@ -172,22 +172,32 @@ def from_yaml(cls, yaml_path: Path, **overrides) -> "ManipulatorEnvConfig": # n
172172 Returns:
173173 ManipulatorEnvConfig: Configured environment instance
174174 """
175- # TODO: @danielsanjosepro Better validation of YAML contents
176175 with open (yaml_path , "r" ) as f :
177- data = yaml .safe_load (f ) or {}
176+ original_data = yaml .safe_load (f ) or {}
178177
179- # Apply overrides
180- data .update (overrides )
178+ original_data .update (overrides )
181179
182- # Handle nested configs that need special treatment
183- if "robot_config" in data and isinstance (data ["robot_config" ], dict ):
184- # Use make_robot_config to handle different robot types
185- data ["robot_config" ] = make_robot_config (** data ["robot_config" ])
180+ data = dict (original_data ) # Make a shallow copy to modify
186181
187- if "gripper_config" in data and isinstance (data ["gripper_config" ], dict ):
182+ if "robot_config" in data :
183+ if not isinstance (data ["robot_config" ], dict ):
184+ raise ValueError ("robot_config must be a dictionary in the YAML file." )
185+
186+ if "from_yaml" in data ["robot_config" ]:
187+ robot_yaml_path = find_config (data ["robot_config" ]["from_yaml" ])
188+ if robot_yaml_path is None :
189+ raise FileNotFoundError (
190+ f"Robot config file '{ data ['robot_config' ]['from_yaml' ]} ' not found in any CRISP config paths"
191+ )
192+ data ["robot_config" ] = RobotConfig .from_yaml (yaml_path = robot_yaml_path .resolve ())
193+ else :
194+ data ["robot_config" ] = make_robot_config (** data ["robot_config" ])
195+
196+ if "gripper_config" in data :
188197 gripper_cfg = data ["gripper_config" ]
198+ if not isinstance (gripper_cfg , dict ):
199+ raise ValueError ("gripper_config must be a dictionary in the YAML file." )
189200 if "from_yaml" in gripper_cfg :
190- # Load from external YAML file
191201 gripper_yaml_path = find_config (gripper_cfg ["from_yaml" ])
192202 if gripper_yaml_path is None :
193203 raise FileNotFoundError (
@@ -198,16 +208,38 @@ def from_yaml(cls, yaml_path: Path, **overrides) -> "ManipulatorEnvConfig": # n
198208 data ["gripper_config" ] = GripperConfig (** gripper_cfg )
199209
200210 if "camera_configs" in data and isinstance (data ["camera_configs" ], list ):
201- data ["camera_configs" ] = [
202- CameraConfig (** cam_cfg ) if isinstance (cam_cfg , dict ) else cam_cfg
203- for cam_cfg in data ["camera_configs" ]
204- ]
211+ data ["camera_configs" ] = [] # Reset to fill in properly
212+ for camera_cfg in original_data ["camera_configs" ]:
213+ if "from_yaml" in camera_cfg :
214+ camera_yaml_path = find_config (camera_cfg ["from_yaml" ])
215+ if camera_yaml_path is None :
216+ raise FileNotFoundError (
217+ f"Camera config file '{ camera_cfg ['from_yaml' ]} ' not found in any CRISP config paths"
218+ )
219+ cam_config = CameraConfig .from_yaml (yaml_path = camera_yaml_path .resolve ())
220+ data ["camera_configs" ].append (cam_config )
221+ else :
222+ data ["camera_configs" ].append (
223+ CameraConfig (** camera_cfg ) if isinstance (camera_cfg , dict ) else camera_cfg
224+ )
205225
206226 if "sensor_configs" in data and isinstance (data ["sensor_configs" ], list ):
207- data ["sensor_configs" ] = [
208- SensorConfig (** sensor_cfg ) if isinstance (sensor_cfg , dict ) else sensor_cfg
209- for sensor_cfg in data ["sensor_configs" ]
210- ]
227+ data ["sensor_configs" ] = []
228+ for sensor_config in original_data ["sensor_configs" ]:
229+ if "from_yaml" in sensor_config :
230+ sensor_yaml_path = find_config (sensor_config ["from_yaml" ])
231+ if sensor_yaml_path is None :
232+ raise FileNotFoundError (
233+ f"Sensor config file '{ sensor_config ['from_yaml' ]} ' not found in any CRISP config paths"
234+ )
235+ sensor_cfg = SensorConfig .from_yaml (yaml_path = sensor_yaml_path .resolve ())
236+ data ["sensor_configs" ].append (sensor_cfg )
237+ else :
238+ data ["sensor_configs" ].append (
239+ SensorConfig (** sensor_config )
240+ if isinstance (sensor_config , dict )
241+ else sensor_config
242+ )
211243
212244 return cls (** data )
213245
0 commit comments