backend
This commit is contained in:
@@ -65,7 +65,9 @@ spec:
|
||||
description: >-
|
||||
Set one front seat's fore-aft rail position. position_pct is an absolute target: 0 is the
|
||||
rearmost mechanical limit and 100 is the forwardmost limit. Resolve relative requests such
|
||||
as "move back a little" against the current position supplied in runtime state.
|
||||
as "move back a little" against the current position supplied in runtime state. For a
|
||||
vehicle-specific physical relative request, distance_mm may be supplied and the runtime
|
||||
converts it to an absolute position_pct before CAN compilation.
|
||||
target_devices:
|
||||
- seat_longitudinal_motor
|
||||
target_scopes:
|
||||
@@ -75,10 +77,17 @@ spec:
|
||||
- name: position_pct
|
||||
type: integer
|
||||
unit: percent
|
||||
required: true
|
||||
required: false
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
description: Absolute normalized fore-aft target.
|
||||
- name: distance_mm
|
||||
type: number
|
||||
unit: mm
|
||||
required: false
|
||||
minimum: 0
|
||||
maximum: 215
|
||||
description: Relative physical fore-aft movement resolved against current position and vehicle calibration.
|
||||
risk_level: high
|
||||
confirmation_policy: on_ambiguity
|
||||
- name: seat.set_cushion_tilt
|
||||
@@ -105,7 +114,9 @@ spec:
|
||||
Set the backrest recline of one front seat. Use either position_pct or angle_deg.
|
||||
position_pct is absolute: 0 is the most upright limit and 100 is the most reclined limit.
|
||||
angle_deg is the included angle between the seat-cushion surface and backrest centreline,
|
||||
from 95 to 140 degrees. "Backrest backward" means a larger value.
|
||||
from 95 to 163 degrees for the selected Denza N7 profile. "Backrest backward" means a
|
||||
larger value. For relative physical angle requests, angle_delta_deg may be supplied and the
|
||||
runtime converts it to an absolute position_pct before CAN compilation.
|
||||
target_devices:
|
||||
- seat_backrest_motor
|
||||
target_scopes:
|
||||
@@ -124,16 +135,25 @@ spec:
|
||||
unit: degree
|
||||
required: false
|
||||
minimum: 95
|
||||
maximum: 140
|
||||
maximum: 163
|
||||
description: Exact included angle between the cushion surface and backrest centreline.
|
||||
- name: angle_delta_deg
|
||||
type: number
|
||||
unit: degree
|
||||
required: false
|
||||
minimum: 0
|
||||
maximum: 68
|
||||
description: Relative backrest angle movement resolved against current posture and vehicle calibration.
|
||||
risk_level: high
|
||||
confirmation_policy: on_ambiguity
|
||||
- name: seat.set_legrest_height
|
||||
description: >-
|
||||
Raise or lower one front seat's powered leg rest. Use either position_pct or angle_deg.
|
||||
position_pct is absolute: 0 is fully lowered and 100 is fully raised. angle_deg is the
|
||||
included angle between the cushion surface and leg-rest surface, from 95 to 160 degrees.
|
||||
This axis does not change leg-rest extension.
|
||||
included angle between the cushion surface and leg-rest surface, from 95 to 173 degrees for
|
||||
the selected Denza N7 profile. For relative physical angle requests, angle_delta_deg may be
|
||||
supplied and the runtime converts it to an absolute position_pct before CAN compilation. This
|
||||
axis does not change leg-rest extension.
|
||||
target_devices:
|
||||
- seat_legrest_lift_motor
|
||||
target_scopes:
|
||||
@@ -152,8 +172,15 @@ spec:
|
||||
unit: degree
|
||||
required: false
|
||||
minimum: 95
|
||||
maximum: 160
|
||||
maximum: 173
|
||||
description: Exact included angle between the cushion surface and leg-rest surface.
|
||||
- name: angle_delta_deg
|
||||
type: number
|
||||
unit: degree
|
||||
required: false
|
||||
minimum: 0
|
||||
maximum: 78
|
||||
description: Relative leg-rest lift angle movement resolved against current posture and vehicle calibration.
|
||||
risk_level: high
|
||||
confirmation_policy: on_ambiguity
|
||||
- name: seat.set_legrest_extension
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"required": ["position_pct"],
|
||||
"properties": {
|
||||
"position_pct": {"type": "integer", "minimum": 0, "maximum": 100},
|
||||
"angle_deg": {"type": "number", "minimum": 95, "maximum": 160}
|
||||
"angle_deg": {"type": "number", "minimum": 95, "maximum": 173}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ SUPPORTED_MOTION_AXES = {
|
||||
"legrest_extension",
|
||||
}
|
||||
ANGLE_RANGES = {
|
||||
"backrest_recline": (95, 140),
|
||||
"legrest_height": (95, 160),
|
||||
"backrest_recline": (95, 163),
|
||||
"legrest_height": (95, 173),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -376,6 +376,105 @@ class SeatServiceIntegrationTests(unittest.TestCase):
|
||||
40,
|
||||
)
|
||||
|
||||
def test_model_relative_physical_motion_uses_vehicle_profile(self) -> None:
|
||||
model_output = {
|
||||
"detected_domains": ["seat"],
|
||||
"requests": [
|
||||
{
|
||||
"domain": "seat",
|
||||
"capability": "seat.set_longitudinal_position",
|
||||
"target_scope": "driver",
|
||||
"operation": "increase",
|
||||
"parameters": [{"name": "distance_mm", "value": 50}],
|
||||
"reason": "Move forward by a physical distance.",
|
||||
},
|
||||
{
|
||||
"domain": "seat",
|
||||
"capability": "seat.set_backrest_recline",
|
||||
"target_scope": "driver",
|
||||
"operation": "increase",
|
||||
"parameters": [{"name": "angle_delta_deg", "value": 10}],
|
||||
"reason": "Recline by a relative physical angle.",
|
||||
},
|
||||
],
|
||||
"ambiguities": [],
|
||||
"decision_summary": ["使用车型量程把相对物理量换算为绝对百分比。"],
|
||||
"confidence": 0.94,
|
||||
}
|
||||
self.service.openai.api_key = "test-key"
|
||||
|
||||
with patch.object(self.service.openai, "interpret", return_value=model_output) as interpret:
|
||||
result = self.service.process(
|
||||
"主驾水平向前移动50毫米,靠背往后10度",
|
||||
"openai",
|
||||
"conv-vehicle-profile-relative",
|
||||
vehicle_id="denza_n7",
|
||||
)
|
||||
|
||||
self.assertEqual(result["status"], "succeeded")
|
||||
self.assertEqual(result["vehicle"]["id"], "denza_n7")
|
||||
operations = result["function_config"]["spec"]["operations"]
|
||||
self.assertEqual(operations[0]["parameters"], {"position_pct": 73})
|
||||
self.assertEqual(
|
||||
operations[1]["parameters"],
|
||||
{"position_pct": 38, "angle_deg": 116},
|
||||
)
|
||||
backrest_motion = operations[1]["motion"]
|
||||
self.assertEqual(backrest_motion["mode"], "relative")
|
||||
self.assertEqual(backrest_motion["direction"], "increase")
|
||||
self.assertEqual(backrest_motion["start_position_pct"], 20)
|
||||
self.assertEqual(backrest_motion["delta_position_pct"], 18)
|
||||
self.assertEqual(backrest_motion["start_angle_deg"], 106.0)
|
||||
self.assertEqual(backrest_motion["delta_angle_deg"], 10)
|
||||
context_sent_to_model = interpret.call_args.args[1]
|
||||
self.assertEqual(context_sent_to_model["vehicle"]["id"], "denza_n7")
|
||||
self.assertEqual(
|
||||
context_sent_to_model["devices"]["driver"]["position"][
|
||||
"backrest_recline"
|
||||
]["angle_deg"],
|
||||
106.0,
|
||||
)
|
||||
|
||||
def test_vehicle_profile_angle_limits_are_accepted(self) -> None:
|
||||
model_output = {
|
||||
"detected_domains": ["seat"],
|
||||
"requests": [
|
||||
{
|
||||
"domain": "seat",
|
||||
"capability": "seat.set_backrest_recline",
|
||||
"target_scope": "passenger",
|
||||
"operation": "set",
|
||||
"parameters": [{"name": "angle_deg", "value": 163}],
|
||||
"reason": "Use the vehicle-specific maximum backrest angle.",
|
||||
},
|
||||
{
|
||||
"domain": "seat",
|
||||
"capability": "seat.set_legrest_height",
|
||||
"target_scope": "passenger",
|
||||
"operation": "set",
|
||||
"parameters": [{"name": "angle_deg", "value": 173}],
|
||||
"reason": "Use the vehicle-specific maximum legrest angle.",
|
||||
},
|
||||
],
|
||||
"ambiguities": [],
|
||||
"decision_summary": ["车型角度边界按腾势 N7 配置执行。"],
|
||||
"confidence": 0.95,
|
||||
}
|
||||
self.service.openai.api_key = "test-key"
|
||||
|
||||
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
||||
result = self.service.process(
|
||||
"副驾靠背到163度,腿托到173度",
|
||||
"openai",
|
||||
"conv-vehicle-angle-limits",
|
||||
vehicle_id="denza_n7",
|
||||
)
|
||||
|
||||
self.assertEqual(result["status"], "succeeded")
|
||||
operations = result["function_config"]["spec"]["operations"]
|
||||
self.assertEqual(operations[0]["parameters"], {"position_pct": 100, "angle_deg": 163})
|
||||
self.assertEqual(operations[1]["parameters"], {"position_pct": 100, "angle_deg": 173})
|
||||
|
||||
def test_motion_adapter_does_not_resolve_missing_absolute_target(self) -> None:
|
||||
model_output = {
|
||||
"detected_domains": ["seat"],
|
||||
@@ -527,11 +626,11 @@ class SeatServiceIntegrationTests(unittest.TestCase):
|
||||
first_operations = first["function_config"]["spec"]["operations"]
|
||||
self.assertEqual(
|
||||
first_operations[0]["parameters"],
|
||||
{"position_pct": 73, "angle_deg": 128},
|
||||
{"position_pct": 49, "angle_deg": 128},
|
||||
)
|
||||
self.assertEqual(
|
||||
first_operations[1]["parameters"],
|
||||
{"position_pct": 58, "angle_deg": 133},
|
||||
{"position_pct": 49, "angle_deg": 133},
|
||||
)
|
||||
self.assertEqual(
|
||||
first["actuator_state"]["passenger"]["position"]["backrest_recline"][
|
||||
@@ -541,7 +640,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
|
||||
)
|
||||
first_telemetry = first["execution_report"]["spec"]["results"][0]["telemetry"]
|
||||
self.assertEqual(first_telemetry["requested_angle_deg"], 128)
|
||||
self.assertEqual(first_telemetry["effective_position_pct"], 73)
|
||||
self.assertEqual(first_telemetry["effective_position_pct"], 49)
|
||||
|
||||
self.assertEqual(
|
||||
second["actuator_state"]["passenger"]["position"]["backrest_recline"][
|
||||
@@ -554,8 +653,8 @@ class SeatServiceIntegrationTests(unittest.TestCase):
|
||||
]
|
||||
self.assertEqual(relative_motion["mode"], "relative")
|
||||
self.assertEqual(relative_motion["direction"], "increase")
|
||||
self.assertEqual(relative_motion["start_position_pct"], 73)
|
||||
self.assertEqual(relative_motion["delta_position_pct"], 11)
|
||||
self.assertEqual(relative_motion["start_position_pct"], 49)
|
||||
self.assertEqual(relative_motion["delta_position_pct"], 7)
|
||||
self.assertEqual(relative_motion["delta_angle_deg"], 5)
|
||||
second_context = interpret.call_args_list[1].args[1]
|
||||
self.assertEqual(
|
||||
|
||||
@@ -598,6 +598,11 @@ class T2GHardwareTests(unittest.TestCase):
|
||||
"COGNITIVE_AGENT_HARDWARE_EXECUTION_ENABLED": "true",
|
||||
"COGNITIVE_AGENT_HARDWARE_APPROVAL_TOKEN": "bench-secret",
|
||||
"COGNITIVE_AGENT_SEAT_FIRMWARE_PROFILES": "combined",
|
||||
"COGNITIVE_AGENT_SEAT_CAN_BACKEND": "python-can",
|
||||
"COGNITIVE_AGENT_SEAT_CAN_BITRATE": "500000",
|
||||
"COGNITIVE_AGENT_SEAT_CAN_INTERFACE": "socketcan",
|
||||
"COGNITIVE_AGENT_SEAT_CAN_CHANNEL": "0",
|
||||
"COGNITIVE_AGENT_SEAT_AUTO_FLASH_ENABLED": "false",
|
||||
"COGNITIVE_AGENT_ENABLE_UNVERIFIED_LONGITUDINAL": "false",
|
||||
}
|
||||
with patch.dict(os.environ, environment, clear=False):
|
||||
|
||||
Reference in New Issue
Block a user