feat: synchronize CH1 vehicle control and feedback
This commit is contained in:
@@ -6,6 +6,7 @@ from copy import deepcopy
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
from cognitive_agent.application.native_can_intent import resolve_ch1_default_target
|
||||
from cognitive_agent.application.seat_calibration import (
|
||||
ANGLE_CALIBRATIONS,
|
||||
angle_to_position_pct,
|
||||
@@ -35,6 +36,20 @@ NATIVE_CAN_ONLY_CAPABILITIES = {
|
||||
"climate.set_control_mode",
|
||||
"roof.set_shade_motion",
|
||||
}
|
||||
DEFAULT_DRIVER_NATIVE_SEAT_CAPABILITIES = {
|
||||
"seat.set_ventilation": "seat.set_driver_ventilation_native",
|
||||
"seat.set_heating": "seat.set_driver_heating_native",
|
||||
}
|
||||
EXPLICIT_DRIVER_SEAT_PATTERN = re.compile(
|
||||
r"主驾|驾驶位|司机位|左前(?:的)?(?:座椅|座位)|"
|
||||
r"seat\s+(?:driver|front-left)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
EXPLICIT_NON_DRIVER_SEAT_PATTERN = re.compile(
|
||||
r"副驾|乘客|右前|后排|前排|所有座椅|全部座椅|"
|
||||
r"seat\s+(?:passenger|front-right)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
class ModelPlanAdapter:
|
||||
@@ -55,6 +70,7 @@ class ModelPlanAdapter:
|
||||
plan: dict[str, Any],
|
||||
context: dict[str, Any] | None = None,
|
||||
vehicle_profile: VehicleProfile | None = None,
|
||||
utterance: str = "",
|
||||
) -> dict[str, Any]:
|
||||
actions: list[dict[str, Any]] = []
|
||||
domain_actions: list[dict[str, Any]] = []
|
||||
@@ -64,7 +80,8 @@ class ModelPlanAdapter:
|
||||
ambiguities = list(plan.get("ambiguities", []))
|
||||
context = context or {}
|
||||
|
||||
for index, request in enumerate(plan.get("requests", [])):
|
||||
for index, raw_request in enumerate(plan.get("requests", [])):
|
||||
request = self._apply_ch1_default_target(raw_request, utterance)
|
||||
capability_name = str(request.get("capability"))
|
||||
registered = self.capabilities.get(capability_name)
|
||||
if registered is None or registered[0] != request.get("domain"):
|
||||
@@ -246,6 +263,36 @@ class ModelPlanAdapter:
|
||||
"model_requests": deepcopy(plan.get("requests", [])),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _apply_ch1_default_target(
|
||||
raw_request: dict[str, Any], utterance: str
|
||||
) -> dict[str, Any]:
|
||||
"""Normalize omitted model targets to driver-console CH1 defaults."""
|
||||
|
||||
request = deepcopy(raw_request)
|
||||
capability = str(request.get("capability", ""))
|
||||
native_seat_capability = DEFAULT_DRIVER_NATIVE_SEAT_CAPABILITIES.get(
|
||||
capability
|
||||
)
|
||||
if native_seat_capability is not None:
|
||||
explicit_non_driver = bool(
|
||||
EXPLICIT_NON_DRIVER_SEAT_PATTERN.search(utterance)
|
||||
)
|
||||
explicit_driver = bool(EXPLICIT_DRIVER_SEAT_PATTERN.search(utterance))
|
||||
implicit_driver = (
|
||||
resolve_ch1_default_target(native_seat_capability, utterance)
|
||||
== "driver"
|
||||
)
|
||||
if not explicit_non_driver and (explicit_driver or implicit_driver):
|
||||
request["capability"] = native_seat_capability
|
||||
request["target_scope"] = "driver"
|
||||
capability = native_seat_capability
|
||||
|
||||
default_target = resolve_ch1_default_target(capability, utterance)
|
||||
if default_target is not None:
|
||||
request["target_scope"] = default_target
|
||||
return request
|
||||
|
||||
@staticmethod
|
||||
def _generic_action(
|
||||
index: int,
|
||||
|
||||
Reference in New Issue
Block a user