feat: update CAN integration and T2G seat firmware
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -9,27 +9,27 @@ class LocalIntentParserTests(unittest.TestCase):
|
||||
@staticmethod
|
||||
def context(level: int = 0) -> dict:
|
||||
return {
|
||||
"last_target": "driver" if level else None,
|
||||
"last_target": "passenger" if level else None,
|
||||
"devices": {
|
||||
"driver": {
|
||||
"ventilation": {"state": "on" if level else "off", "level": level},
|
||||
"ventilation": {"state": "off", "level": 0},
|
||||
"heating": {"state": "off", "level": 0},
|
||||
},
|
||||
"passenger": {
|
||||
"ventilation": {"state": "off", "level": 0},
|
||||
"ventilation": {"state": "on" if level else "off", "level": level},
|
||||
"heating": {"state": "off", "level": 0},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def test_parses_driver_ventilation_on(self) -> None:
|
||||
result = parse_local_intent("打开主驾座椅通风")
|
||||
def test_parses_passenger_ventilation_on(self) -> None:
|
||||
result = parse_local_intent("打开副驾座椅通风")
|
||||
|
||||
self.assertEqual(
|
||||
result["actions"],
|
||||
[
|
||||
{
|
||||
"target": "driver",
|
||||
"target": "passenger",
|
||||
"function": "ventilation",
|
||||
"state": "on",
|
||||
"requested_level": None,
|
||||
@@ -38,31 +38,65 @@ class LocalIntentParserTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(result["ambiguities"], [])
|
||||
|
||||
def test_expands_front_seats(self) -> None:
|
||||
def test_rejects_scope_that_includes_driver(self) -> None:
|
||||
result = parse_local_intent("主副驾座椅通风都打开")
|
||||
|
||||
self.assertEqual({item["target"] for item in result["actions"]}, {"driver", "passenger"})
|
||||
self.assertTrue(all(item["state"] == "on" for item in result["actions"]))
|
||||
|
||||
def test_keeps_requested_level_for_safety_validation(self) -> None:
|
||||
result = parse_local_intent("主驾座椅加热开到三档")
|
||||
|
||||
self.assertEqual(result["actions"][0]["requested_level"], 3)
|
||||
|
||||
def test_requires_target(self) -> None:
|
||||
result = parse_local_intent("打开座椅通风")
|
||||
|
||||
self.assertEqual(result["actions"], [])
|
||||
self.assertEqual(result["ambiguities"][0]["field"], "target")
|
||||
self.assertIn("仅控制副驾", result["ambiguities"][0]["question"])
|
||||
|
||||
def test_keeps_requested_level_for_safety_validation(self) -> None:
|
||||
result = parse_local_intent("副驾座椅加热开到三档")
|
||||
|
||||
self.assertEqual(result["actions"][0]["requested_level"], 3)
|
||||
|
||||
def test_defaults_missing_target_to_passenger(self) -> None:
|
||||
result = parse_local_intent("打开座椅通风")
|
||||
|
||||
self.assertEqual(result["actions"][0]["target"], "passenger")
|
||||
self.assertEqual(result["ambiguities"], [])
|
||||
|
||||
def test_parses_four_axis_zero_for_passenger(self) -> None:
|
||||
result = parse_local_intent("把水平、坐盆、靠背、腿托四轴归零")
|
||||
|
||||
self.assertEqual(result["ambiguities"], [])
|
||||
self.assertEqual(
|
||||
[(action["axis"], action["position_pct"]) for action in result["actions"]],
|
||||
[
|
||||
("longitudinal", 0),
|
||||
("cushion_tilt", 0),
|
||||
("backrest_recline", 0),
|
||||
("legrest_height", 0),
|
||||
],
|
||||
)
|
||||
self.assertTrue(
|
||||
all(action["target"] == "passenger" for action in result["actions"])
|
||||
)
|
||||
|
||||
def test_parses_explicit_motion_percentages(self) -> None:
|
||||
result = parse_local_intent("副驾水平移到63%,靠背调到54%")
|
||||
|
||||
self.assertEqual(result["ambiguities"], [])
|
||||
self.assertEqual(
|
||||
[(action["axis"], action["position_pct"]) for action in result["actions"]],
|
||||
[("longitudinal", 63), ("backrest_recline", 54)],
|
||||
)
|
||||
|
||||
def test_rejects_driver_four_axis_zero(self) -> None:
|
||||
result = parse_local_intent("把主驾座椅四轴归零")
|
||||
|
||||
self.assertEqual(result["actions"], [])
|
||||
self.assertEqual(result["ambiguities"][0]["field"], "target")
|
||||
self.assertIn("仅控制副驾", result["ambiguities"][0]["question"])
|
||||
|
||||
def test_maps_mild_hot_and_stuffy_feedback_to_level_one(self) -> None:
|
||||
result = parse_local_intent("主驾有点热,有点闷", self.context())
|
||||
result = parse_local_intent("副驾有点热,有点闷", self.context())
|
||||
|
||||
self.assertEqual(
|
||||
result["actions"],
|
||||
[
|
||||
{
|
||||
"target": "driver",
|
||||
"target": "passenger",
|
||||
"function": "ventilation",
|
||||
"state": "on",
|
||||
"requested_level": 1,
|
||||
@@ -75,7 +109,7 @@ class LocalIntentParserTests(unittest.TestCase):
|
||||
result = parse_local_intent("还有点闷", self.context(level=1))
|
||||
|
||||
self.assertEqual(result["actions"][0]["requested_level"], 2)
|
||||
self.assertEqual(result["actions"][0]["target"], "driver")
|
||||
self.assertEqual(result["actions"][0]["target"], "passenger")
|
||||
self.assertIn("提升到2档", "".join(result["decision_summary"]))
|
||||
|
||||
def test_cold_feedback_reduces_active_ventilation_before_heating(self) -> None:
|
||||
@@ -85,7 +119,7 @@ class LocalIntentParserTests(unittest.TestCase):
|
||||
result["actions"],
|
||||
[
|
||||
{
|
||||
"target": "driver",
|
||||
"target": "passenger",
|
||||
"function": "ventilation",
|
||||
"state": "off",
|
||||
"requested_level": None,
|
||||
@@ -114,7 +148,7 @@ class LocalIntentParserTests(unittest.TestCase):
|
||||
self.assertIn("致冷来源", "".join(result["decision_summary"]))
|
||||
|
||||
def test_cold_and_stuffy_are_independent_comfort_dimensions(self) -> None:
|
||||
result = parse_local_intent("主驾有点冷、有点闷", self.context())
|
||||
result = parse_local_intent("副驾有点冷、有点闷", self.context())
|
||||
|
||||
self.assertEqual(
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ class MatrixCompilerTests(unittest.TestCase):
|
||||
self.compiler = SeatCompiler(DOMAIN_ROOT / "can" / "signal-mapping.yaml")
|
||||
|
||||
def test_encodes_combined_control_bits(self) -> None:
|
||||
parsed = parse_local_intent("打开主驾座椅通风,同时关闭副驾座椅加热")
|
||||
parsed = parse_local_intent("打开副驾座椅通风,同时关闭副驾座椅加热")
|
||||
config = build_function_config(parsed, "req-test-001", "local_rules")
|
||||
plan = self.compiler.compile(config)
|
||||
command = plan["spec"]["commands"][0]
|
||||
@@ -32,7 +32,7 @@ class MatrixCompilerTests(unittest.TestCase):
|
||||
frame = self.matrix.encode(command["message"], command["signals"])
|
||||
|
||||
self.assertEqual(frame["frame_id"], "0x42A")
|
||||
self.assertEqual(frame["data_hex"], "01 80")
|
||||
self.assertEqual(frame["data_hex"], "00 90")
|
||||
|
||||
def test_compilation_is_deterministic(self) -> None:
|
||||
parsed = parse_local_intent("关闭副驾座椅通风")
|
||||
@@ -46,20 +46,20 @@ class MatrixCompilerTests(unittest.TestCase):
|
||||
"actions": [
|
||||
{
|
||||
"action_type": "position",
|
||||
"target": "driver",
|
||||
"target": "passenger",
|
||||
"axis": "longitudinal",
|
||||
"position_pct": 35,
|
||||
},
|
||||
{
|
||||
"action_type": "position",
|
||||
"target": "driver",
|
||||
"target": "passenger",
|
||||
"axis": "backrest_recline",
|
||||
"position_pct": 60,
|
||||
},
|
||||
],
|
||||
"deferred_requests": [],
|
||||
"ambiguities": [],
|
||||
"decision_summary": ["Move two driver-seat axes."],
|
||||
"decision_summary": ["Move two front-passenger-seat axes."],
|
||||
"confidence": 1.0,
|
||||
}
|
||||
config = build_function_config(parsed, "req-motion-001", "test")
|
||||
@@ -68,15 +68,15 @@ class MatrixCompilerTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(len(plan["spec"]["commands"]), 2)
|
||||
first, second = plan["spec"]["commands"]
|
||||
self.assertEqual(first["message"], "Driver_Seat_Motion_Command_550")
|
||||
self.assertEqual(first["message"], "Passenger_Seat_Motion_Command_551")
|
||||
self.assertEqual(first["signals"]["Longitudinal_Target_Pct"], 35)
|
||||
self.assertEqual(first["signals"]["Motion_Enable_Mask"], 1)
|
||||
self.assertEqual(first["completion"]["message"], "Driver_Seat_Motion_Status_558")
|
||||
self.assertEqual(first["completion"]["message"], "Passenger_Seat_Motion_Status_559")
|
||||
self.assertEqual(first["completion"]["signal"], "Longitudinal_Actual_Pct")
|
||||
self.assertEqual(second["signals"]["Backrest_Recline_Target_Pct"], 60)
|
||||
self.assertEqual(second["signals"]["Motion_Enable_Mask"], 4)
|
||||
frame = self.combined_matrix.encode(first["message"], first["signals"])
|
||||
self.assertEqual(frame["frame_id"], "0x550")
|
||||
self.assertEqual(frame["frame_id"], "0x551")
|
||||
self.assertEqual(frame["payload_size"], 8)
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user