Files
Cognitive_Agent/src/cognitive_agent/application/n7_seat_preset.py
T

70 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Translate the N7 passenger-seat preset contract into local seat operations."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any
from cognitive_agent.application.vehicle_profile import VehicleProfile
# N7 targets_pulse uses the ECU's M0, M1, M2, M3 ordering.
N7_SEAT_PRESET_AXES = (
"longitudinal", "cushion_tilt", "backrest_recline", "legrest_height",
)
N7_SEAT_PRESET_CAPABILITIES = (
"seat.set_longitudinal_position", "seat.set_cushion_tilt",
"seat.set_backrest_recline", "seat.set_legrest_height",
)
def expand_n7_seat_preset(
action: Mapping[str, Any], vehicle: VehicleProfile,
) -> list[dict[str, Any]] | None:
"""Expand an immediate preset; retain unrelated/timed actions for N7 routing.
The existing seat contract accepts whole percentages. Retain the source
pulses in the stored card, and round only at this execution boundary.
Never round a nonzero pulse target into the ECU's explicit homing command.
"""
if action.get("capability") != "local_scene.seat_preset":
return None
if (
vehicle.id != "denza_n7"
or action.get("domain") != "local_vehicle"
or action.get("target_scope") not in {"vehicle", "passenger", "front_right"}
or action.get("operation") != "set"
):
raise ValueError("车端座椅预设仅支持腾势 N7 副驾的绝对位置设置。")
parameters = action.get("parameters")
if not isinstance(parameters, Mapping) or set(parameters) != {"targets_pulse"}:
raise ValueError("车端座椅预设必须且只能包含 targets_pulse 参数。")
targets = parameters["targets_pulse"]
if not isinstance(targets, list) or len(targets) != 4:
raise ValueError("车端座椅预设需要按 M0–M3 顺序提供四个脉冲目标。")
operations = []
for axis, capability, pulse in zip(
N7_SEAT_PRESET_AXES, N7_SEAT_PRESET_CAPABILITIES, targets, strict=True
):
motor = vehicle.seat_motors.get(axis)
maximum = motor.hall_total_pulses if motor is not None else 0
if maximum <= 0:
raise ValueError(f"车端座椅预设缺少 {axis} 的有效霍尔标定。")
if isinstance(pulse, bool) or not isinstance(pulse, int) or not 0 <= pulse <= maximum:
raise ValueError(f"车端座椅预设 {axis} 脉冲目标必须为 0–{maximum} 的整数。")
position_pct = round(pulse * 100 / maximum)
if 0 < pulse < maximum:
position_pct = max(1, min(99, position_pct))
operations.append({
"domain": "seat",
"capability": capability,
"target_scope": "passenger",
"operation": "set",
"parameters": {"position_pct": position_pct},
"reason": f"车端副驾预设 {axis}:{pulse}/{maximum} 脉冲转换为 {position_pct}%。",
})
# A delayed vehicle-owned action must not become an immediate PC movement.
if action.get("at_ms", 0) != 0:
return None
return operations