|
|
@@ -27,8 +27,14 @@ class DeviceConfig(BaseModel):
|
|
|
return v
|
|
|
|
|
|
class MagazineConfig(BaseModel):
|
|
|
- pos : Tuple[float, float]
|
|
|
+ x_pos: float = Field(default=0.0, ge=0, le=700)
|
|
|
+ rot_deg: float = Field(default=0.0, ge=-180.0, le=180.0)
|
|
|
capacity: int = Field(default=10, ge=0)
|
|
|
+
|
|
|
+class DefeederMagazineConfig(MagazineConfig):
|
|
|
+ health_threshold: float = Field(ge=0.0, le=1.0)
|
|
|
+ name: str
|
|
|
+
|
|
|
class FeederConfig(BaseModel):
|
|
|
robot_pos: Tuple[float, float, float]
|
|
|
mag_pos : Tuple[float, float]
|
|
|
@@ -40,7 +46,7 @@ class DefeederConfig(BaseModel):
|
|
|
robot_pos: Tuple[float, float, float]
|
|
|
mag_pos : Tuple[float, float]
|
|
|
max_capacity: int = Field(default=10, ge=0)
|
|
|
- magazines: List[MagazineConfig] = Field(default_factory=list)
|
|
|
+ magazines: List[DefeederMagazineConfig] = Field(default_factory=list)
|
|
|
|
|
|
class MagDistributorConfig(BaseModel):
|
|
|
max_speed: float = Field(default=100.0, ge=0.0)
|
|
|
@@ -51,7 +57,7 @@ class DropoffGradeConfig(BaseModel):
|
|
|
id: str
|
|
|
x_pos: float = Field(default=0.0, ge=0, le=700)
|
|
|
rot_deg: float = Field(default=0.0, ge=-180.0, le=180.0)
|
|
|
- capacity_threshold: float = Field(ge=0.0, le=1.0)
|
|
|
+ health_threshold: float = Field(ge=0.0, le=1.0)
|
|
|
|
|
|
class MQTTConfig(BaseModel):
|
|
|
broker: str = "localhost"
|
|
|
@@ -138,8 +144,9 @@ class RobotConfig(BaseModel):
|
|
|
measurement_devices: List[DeviceConfig]
|
|
|
feeder: FeederConfig
|
|
|
defeeder: DefeederConfig
|
|
|
+ feeder_magazines: List[MagazineConfig] = Field(default_factory=list)
|
|
|
+ defeeder_magazines: List[DefeederMagazineConfig] = Field(default_factory=list)
|
|
|
mag_distributor: MagDistributorConfig
|
|
|
- dropoff_grades: List[DropoffGradeConfig]
|
|
|
mqtt: MQTTConfig
|
|
|
grbl: GRBLConfig
|
|
|
vision: VisionConfig
|
|
|
@@ -150,18 +157,19 @@ class RobotConfig(BaseModel):
|
|
|
logging: LoggingConfig
|
|
|
|
|
|
@model_validator(mode='after')
|
|
|
- def validate_dropoff_grades(self) -> 'RobotConfig':
|
|
|
+ def validate_defeeder_magazines(self) -> 'RobotConfig':
|
|
|
# Sort grades by threshold in descending order for consistent behavior
|
|
|
- sorted_grades = sorted(self.dropoff_grades, key=lambda x: x.capacity_threshold, reverse=True)
|
|
|
- for i in range(1, len(sorted_grades)):
|
|
|
- if sorted_grades[i-1].capacity_threshold <= sorted_grades[i].capacity_threshold:
|
|
|
+
|
|
|
+ sorted_defeeding_mags = sorted(self.defeeder_magazines, key=lambda x: x.health_threshold, reverse=True)
|
|
|
+ for i in range(1, len(sorted_defeeding_mags)):
|
|
|
+ if sorted_defeeding_mags[i-1].health_threshold <= sorted_defeeding_mags[i].health_threshold:
|
|
|
raise ValueError(
|
|
|
f"Dropoff grade thresholds must be in strictly descending order. Found: "
|
|
|
- f"Grade {sorted_grades[i-1].id} ({sorted_grades[i-1].capacity_threshold}) <= "
|
|
|
- f"Grade {sorted_grades[i].id} ({sorted_grades[i].capacity_threshold})"
|
|
|
+ f"Grade {sorted_defeeding_mags[i-1].name} ({sorted_defeeding_mags[i-1].health_threshold}) <= "
|
|
|
+ f"Grade {sorted_defeeding_mags[i].name} ({sorted_defeeding_mags[i].health_threshold})"
|
|
|
)
|
|
|
# Store sorted grades to ensure consistent behavior
|
|
|
- self.dropoff_grades = sorted_grades
|
|
|
+ self.defeeder_magazines = sorted_defeeding_mags
|
|
|
return self
|
|
|
|
|
|
class ConfigParser:
|
|
|
@@ -181,7 +189,11 @@ class ConfigParser:
|
|
|
device_id = device['id']
|
|
|
for slot in device['slots']:
|
|
|
slot['device_id'] = device_id
|
|
|
-
|
|
|
+
|
|
|
+ # Set default values for feeder and defeeder magazines
|
|
|
+ config_dict['feeder_magazines'] = config_dict.get('feeder_magazines', [])
|
|
|
+ config_dict['defeeder_magazines'] = config_dict.get('defeeder_magazines', [])
|
|
|
+
|
|
|
return RobotConfig(**config_dict)
|
|
|
|
|
|
@property
|