52 lines
1.3 KiB
Python
Executable File
52 lines
1.3 KiB
Python
Executable File
"""Virtual seat posture calibration shared by planning and state handling."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AngleCalibration:
|
|
axis: str
|
|
minimum_deg: float
|
|
maximum_deg: float
|
|
|
|
|
|
ANGLE_CALIBRATIONS = {
|
|
"seat.set_backrest_recline": AngleCalibration(
|
|
axis="backrest_recline",
|
|
minimum_deg=95,
|
|
maximum_deg=163,
|
|
),
|
|
"seat.set_legrest_height": AngleCalibration(
|
|
axis="legrest_height",
|
|
minimum_deg=95,
|
|
maximum_deg=167,
|
|
),
|
|
}
|
|
AXIS_ANGLE_CALIBRATIONS = {
|
|
calibration.axis: calibration for calibration in ANGLE_CALIBRATIONS.values()
|
|
}
|
|
|
|
|
|
def angle_to_position_pct(capability: str, angle_deg: float) -> int:
|
|
calibration = ANGLE_CALIBRATIONS[capability]
|
|
normalized = (
|
|
(float(angle_deg) - calibration.minimum_deg)
|
|
/ (calibration.maximum_deg - calibration.minimum_deg)
|
|
)
|
|
return round(normalized * 100)
|
|
|
|
|
|
def position_pct_to_angle(axis: str, position_pct: float) -> float | None:
|
|
calibration = AXIS_ANGLE_CALIBRATIONS.get(axis)
|
|
if calibration is None:
|
|
return None
|
|
return round(
|
|
calibration.minimum_deg
|
|
+ (calibration.maximum_deg - calibration.minimum_deg)
|
|
* float(position_pct)
|
|
/ 100,
|
|
1,
|
|
)
|