优化前端,优化前端指令,优化自定义控制
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
@@ -109,6 +111,8 @@ class DriverSeatNativeCanTests(unittest.TestCase):
|
||||
"seat.set_driver_heating_native",
|
||||
"seat.set_driver_massage_native",
|
||||
"seat.set_driver_axis_native",
|
||||
"seat.set_driver_position_native",
|
||||
"seat.recall_driver_memory_native",
|
||||
},
|
||||
)
|
||||
for capability in capabilities.values():
|
||||
@@ -151,6 +155,16 @@ class DriverSeatNativeCanTests(unittest.TestCase):
|
||||
{"axis": "height", "direction": "stop", "duration_ms": 500},
|
||||
"driver",
|
||||
),
|
||||
"seat driver position 3": (
|
||||
"seat.set_driver_position_native",
|
||||
{"slot": 3},
|
||||
"driver",
|
||||
),
|
||||
"seat driver memory recall 2": (
|
||||
"seat.recall_driver_memory_native",
|
||||
{"slot": 2},
|
||||
"driver",
|
||||
),
|
||||
}
|
||||
for utterance, expected in cases.items():
|
||||
with self.subTest(utterance=utterance):
|
||||
@@ -196,6 +210,10 @@ class DriverSeatNativeCanTests(unittest.TestCase):
|
||||
"seat.set_driver_axis_native",
|
||||
{"axis": "height", "direction": "up", "duration_ms": 500},
|
||||
),
|
||||
"主驾座椅调整到记忆位置3": (
|
||||
"seat.recall_driver_memory_native",
|
||||
{"slot": 3},
|
||||
),
|
||||
}
|
||||
for utterance, expected in cases.items():
|
||||
with self.subTest(utterance=utterance):
|
||||
@@ -356,6 +374,142 @@ class DriverSeatNativeCanTests(unittest.TestCase):
|
||||
self.assertEqual(command["repeat"], {"count": 3, "period_ms": 100})
|
||||
self.assertNotIn("special_handler", command["signals"])
|
||||
|
||||
def test_memory_aliases_compile_the_same_learned_twenty_frame_sequence(self) -> None:
|
||||
commands = []
|
||||
for capability in (
|
||||
"seat.set_driver_position_native",
|
||||
"seat.recall_driver_memory_native",
|
||||
):
|
||||
with self.subTest(capability=capability):
|
||||
_, plan = self._compile(capability, {"slot": 3})
|
||||
command = plan["spec"]["commands"][0]
|
||||
commands.append(command)
|
||||
self.assertEqual(command["signals"]["frame_id"], "0x4C1")
|
||||
self.assertEqual(
|
||||
command["signals"]["special_handler"],
|
||||
"driver_seat_memory_recall",
|
||||
)
|
||||
special = json.loads(command["signals"]["special_parameters"])
|
||||
self.assertEqual(len(special["frame_sequence"]), 20)
|
||||
self.assertEqual(
|
||||
special["frame_sequence"][0::2],
|
||||
["16 9A 66 3C 76 04 06 00"] * 10,
|
||||
)
|
||||
self.assertEqual(
|
||||
special["frame_sequence"][1::2],
|
||||
["15 02 C6 3E 2A C8 FF FF"] * 10,
|
||||
)
|
||||
self.assertEqual(special["period_ms"], 50)
|
||||
public = self.runtime.command_frame_public(command)
|
||||
self.assertEqual(public["sequence"]["frame_count"], 20)
|
||||
self.assertTrue(
|
||||
public["sequence"]["requires_fresh_initialized_0x494"]
|
||||
)
|
||||
self.assertEqual(
|
||||
commands[0]["signals"]["special_parameters"],
|
||||
commands[1]["signals"]["special_parameters"],
|
||||
)
|
||||
|
||||
def test_memory_executor_requires_initialized_status_and_alternates_frames(self) -> None:
|
||||
config, plan = self._compile(
|
||||
"seat.recall_driver_memory_native", {"slot": 2}
|
||||
)
|
||||
initialized = CanFrame(
|
||||
0x494,
|
||||
bytes((0, 0, 0, 0, 0, 0, 0, 0x3C)),
|
||||
channel=1,
|
||||
is_fd=True,
|
||||
bitrate_switch=True,
|
||||
)
|
||||
bus = _FakeBus([initialized, initialized])
|
||||
with patch("cognitive_agent.application.native_can_runtime.time.sleep"):
|
||||
report = NativeCanExecutor(
|
||||
lambda: bus, feedback_timeout_ms=1, feedback_required=False
|
||||
).execute(self.runtime, plan, config)
|
||||
self.assertEqual(report["spec"]["status"], "succeeded")
|
||||
self.assertEqual(len(bus.sent), 20)
|
||||
self.assertTrue(all(frame.is_fd and frame.bitrate_switch for frame in bus.sent))
|
||||
self.assertEqual(
|
||||
[frame.data[0] for frame in bus.sent], [0x16, 0x15] * 10
|
||||
)
|
||||
self.assertEqual(
|
||||
[frame.data for frame in bus.sent[0::2]],
|
||||
[bytes.fromhex("16 9A 66 3C 76 04 06 00")] * 10,
|
||||
)
|
||||
self.assertEqual(
|
||||
[frame.data for frame in bus.sent[1::2]],
|
||||
[bytes.fromhex("15 02 A6 AE 00 C8 FF FF")] * 10,
|
||||
)
|
||||
telemetry = report["spec"]["results"][0]["telemetry"]
|
||||
self.assertFalse(telemetry["physical_effect_confirmed"])
|
||||
self.assertEqual(len(telemetry["sent_frames"]), 20)
|
||||
|
||||
uninitialized_bus = _FakeBus(
|
||||
[CanFrame(0x494, bytes(8), channel=1, is_fd=True)]
|
||||
)
|
||||
rejected = NativeCanExecutor(
|
||||
lambda: uninitialized_bus,
|
||||
feedback_timeout_ms=1,
|
||||
feedback_required=False,
|
||||
).execute(self.runtime, plan, config)
|
||||
self.assertEqual(rejected["spec"]["status"], "failed")
|
||||
self.assertFalse(uninitialized_bus.sent)
|
||||
|
||||
def test_memory_sequence_stops_immediately_on_send_failure(self) -> None:
|
||||
config, plan = self._compile(
|
||||
"seat.set_driver_position_native", {"slot": 1}
|
||||
)
|
||||
initialized = CanFrame(
|
||||
0x494, bytes((0, 0, 0, 0, 0, 0, 0, 0x3C)), channel=1
|
||||
)
|
||||
bus = _FakeBus([initialized], fail_on_calls={4})
|
||||
with patch("cognitive_agent.application.native_can_runtime.time.sleep"):
|
||||
report = NativeCanExecutor(
|
||||
lambda: bus, feedback_timeout_ms=1, feedback_required=False
|
||||
).execute(self.runtime, plan, config)
|
||||
self.assertEqual(report["spec"]["status"], "failed")
|
||||
self.assertEqual(bus.send_calls, 4)
|
||||
self.assertEqual(len(bus.sent), 3)
|
||||
|
||||
def test_memory_compile_rejects_missing_or_malformed_learned_slots(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "driver_memory.json"
|
||||
path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"version": 1,
|
||||
"positions": {
|
||||
"1": {
|
||||
"payload_15": "15 00",
|
||||
"payload_16": "16 00 00 00 00 00 00 00",
|
||||
}
|
||||
},
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{"COGNITIVE_AGENT_DRIVER_SEAT_MEMORY_PATH": str(path)},
|
||||
):
|
||||
config = self.runtime.build_function_config(
|
||||
"seat",
|
||||
[_native_action("seat.recall_driver_memory_native", {"slot": 1})],
|
||||
"req-bad-memory",
|
||||
"local_rules",
|
||||
)
|
||||
with self.assertRaisesRegex(NativeCanCompileError, "8-byte"):
|
||||
self.runtime.compile(config)
|
||||
|
||||
missing = self.runtime.build_function_config(
|
||||
"seat",
|
||||
[_native_action("seat.recall_driver_memory_native", {"slot": 2})],
|
||||
"req-missing-memory",
|
||||
"local_rules",
|
||||
)
|
||||
with self.assertRaisesRegex(NativeCanCompileError, "has not been learned"):
|
||||
self.runtime.compile(missing)
|
||||
|
||||
def test_compiler_fails_closed_for_wrong_seat_or_invalid_parameters(self) -> None:
|
||||
for target in ("passenger", "front_right"):
|
||||
action = _native_action(
|
||||
|
||||
Reference in New Issue
Block a user