mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-06 20:43:46 +08:00
Fixes
This commit is contained in:
@@ -335,8 +335,8 @@ def test_actual_card_active_observation_requires_fresh_selfdrive_state(monkeypat
|
||||
host.observe_ioniq6_long_authority = lambda *args: None
|
||||
host.update_vehicle_state_context = lambda *args: None
|
||||
|
||||
def update_cruise_speed(_state, _pending, *, approved=None):
|
||||
assert approved is None
|
||||
def update_cruise_speed(_state, _pending, *, wheel_context=None):
|
||||
assert wheel_context is None
|
||||
host.update_cruise_speed = update_cruise_speed
|
||||
host.v_cruise_helper = SimpleNamespace(slc_consumed_button=None, toyota=None)
|
||||
host.startup_panda_configured = lambda: True
|
||||
|
||||
@@ -870,7 +870,7 @@ class TestIoniq6PrepublicationHandoff(unittest.TestCase):
|
||||
card_owner.is_metric = True
|
||||
card_owner.experimental_mode = False
|
||||
card_owner.initial_cruise_speed = 40
|
||||
card_owner.v_cruise_helper = SimpleNamespace(update_v_cruise=lambda *_, slc_enabled=False, slc_approved=None: None,
|
||||
card_owner.v_cruise_helper = SimpleNamespace(update_v_cruise=lambda *_, slc_enabled=False, wheel_context=None: None,
|
||||
initialize_v_cruise=lambda *_, **kwargs: None, slc_consumed_button=None, toyota=None,
|
||||
slc_cruise_change=None, v_cruise_kph=60.0, v_cruise_cluster_kph=60.0)
|
||||
card_owner.RI = SimpleNamespace(update=lambda _: None)
|
||||
|
||||
@@ -333,7 +333,7 @@ struct SlcState @0xa1680744031fdb2d {
|
||||
hasPendingAdjustedLimit @45 :Bool;
|
||||
presentationAdjustedLimit @46 :Float32;
|
||||
hasPresentationAdjustedLimit @47 :Bool;
|
||||
overrideBasis @48 :Text; # none/pedal/persistent; qualified contribution only
|
||||
overrideBasis @48 :Text; # none/pedal/persistent/wheel; qualified contribution only
|
||||
retainedOverride @49 :Bool;
|
||||
commandActionSequenceId @50 :UInt64; # UI sequence that issued this command
|
||||
automaticAdoptionPending @51 :Bool;
|
||||
@@ -347,6 +347,7 @@ struct SlcState @0xa1680744031fdb2d {
|
||||
upcomingSpeedLimit @57 :Float32;
|
||||
upcomingBoundaryId @58 :Text;
|
||||
acceptedIsPreview @59 :Bool; # a temporary ceiling, ineligible for initializing SET
|
||||
wheelOverrideSince @60 :UInt64; # nonzero while a wheel tap may cross the current adjusted limit
|
||||
struct SourceReading {
|
||||
source @0 :Text;
|
||||
enabled @1 :Bool;
|
||||
@@ -515,6 +516,7 @@ struct SlcCruiseEvent @0xcd96dafb67a082d0 {
|
||||
trafficMode @13 :TrafficModeGesture;
|
||||
wheelAction @14 :SlcAction.ControllerCruiseAction;
|
||||
teslaStockCruise @15 :TeslaStockCruise;
|
||||
wheelOverrideSince @16 :UInt64; # SLC eligibility captured by a physical + tap; zero for ordinary SET changes
|
||||
|
||||
struct TeslaStockCruise {
|
||||
version @0 :UInt16;
|
||||
|
||||
@@ -3741,17 +3741,17 @@ const ::capnp::_::RawSchema s_da96579883444c35 = {
|
||||
0, 5, i_da96579883444c35, nullptr, nullptr, { &s_da96579883444c35, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<1030> b_a1680744031fdb2d = {
|
||||
static const ::capnp::_::AlignedData<1047> b_a1680744031fdb2d = {
|
||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||
45, 219, 31, 3, 68, 7, 104, 161,
|
||||
13, 0, 0, 0, 1, 0, 18, 0,
|
||||
13, 0, 0, 0, 1, 0, 19, 0,
|
||||
89, 10, 85, 29, 102, 186, 38, 181,
|
||||
22, 0, 7, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
21, 0, 0, 0, 178, 0, 0, 0,
|
||||
29, 0, 0, 0, 87, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
117, 0, 0, 0, 39, 13, 0, 0,
|
||||
117, 0, 0, 0, 95, 13, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
99, 117, 115, 116, 111, 109, 46, 99,
|
||||
@@ -3781,427 +3781,434 @@ static const ::capnp::_::AlignedData<1030> b_a1680744031fdb2d = {
|
||||
67, 111, 110, 100, 105, 116, 105, 111,
|
||||
110, 97, 108, 77, 111, 100, 101, 83,
|
||||
116, 97, 116, 101, 0, 0, 0, 0,
|
||||
240, 0, 0, 0, 3, 0, 4, 0,
|
||||
244, 0, 0, 0, 3, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
129, 6, 0, 0, 58, 0, 0, 0,
|
||||
157, 6, 0, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
124, 6, 0, 0, 3, 0, 1, 0,
|
||||
136, 6, 0, 0, 2, 0, 1, 0,
|
||||
152, 6, 0, 0, 3, 0, 1, 0,
|
||||
164, 6, 0, 0, 2, 0, 1, 0,
|
||||
1, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
133, 6, 0, 0, 74, 0, 0, 0,
|
||||
161, 6, 0, 0, 74, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
132, 6, 0, 0, 3, 0, 1, 0,
|
||||
144, 6, 0, 0, 2, 0, 1, 0,
|
||||
160, 6, 0, 0, 3, 0, 1, 0,
|
||||
172, 6, 0, 0, 2, 0, 1, 0,
|
||||
2, 0, 0, 0, 2, 0, 0, 0,
|
||||
0, 0, 1, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
141, 6, 0, 0, 66, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
136, 6, 0, 0, 3, 0, 1, 0,
|
||||
148, 6, 0, 0, 2, 0, 1, 0,
|
||||
3, 0, 0, 0, 3, 0, 0, 0,
|
||||
0, 0, 1, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
145, 6, 0, 0, 106, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
144, 6, 0, 0, 3, 0, 1, 0,
|
||||
156, 6, 0, 0, 2, 0, 1, 0,
|
||||
4, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 1, 0, 4, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
153, 6, 0, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
148, 6, 0, 0, 3, 0, 1, 0,
|
||||
160, 6, 0, 0, 2, 0, 1, 0,
|
||||
5, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 5, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
157, 6, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
156, 6, 0, 0, 3, 0, 1, 0,
|
||||
168, 6, 0, 0, 2, 0, 1, 0,
|
||||
6, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
165, 6, 0, 0, 82, 0, 0, 0,
|
||||
169, 6, 0, 0, 66, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
164, 6, 0, 0, 3, 0, 1, 0,
|
||||
176, 6, 0, 0, 2, 0, 1, 0,
|
||||
7, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 7, 0, 0, 0,
|
||||
3, 0, 0, 0, 3, 0, 0, 0,
|
||||
0, 0, 1, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
173, 6, 0, 0, 114, 0, 0, 0,
|
||||
173, 6, 0, 0, 106, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
172, 6, 0, 0, 3, 0, 1, 0,
|
||||
184, 6, 0, 0, 2, 0, 1, 0,
|
||||
8, 0, 0, 0, 128, 0, 0, 0,
|
||||
0, 0, 1, 0, 8, 0, 0, 0,
|
||||
4, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 1, 0, 4, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
181, 6, 0, 0, 66, 0, 0, 0,
|
||||
181, 6, 0, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
176, 6, 0, 0, 3, 0, 1, 0,
|
||||
188, 6, 0, 0, 2, 0, 1, 0,
|
||||
9, 0, 0, 0, 129, 0, 0, 0,
|
||||
0, 0, 1, 0, 9, 0, 0, 0,
|
||||
5, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 5, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
185, 6, 0, 0, 98, 0, 0, 0,
|
||||
185, 6, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
184, 6, 0, 0, 3, 0, 1, 0,
|
||||
196, 6, 0, 0, 2, 0, 1, 0,
|
||||
10, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 1, 0, 10, 0, 0, 0,
|
||||
6, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
193, 6, 0, 0, 130, 0, 0, 0,
|
||||
193, 6, 0, 0, 82, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
192, 6, 0, 0, 3, 0, 1, 0,
|
||||
204, 6, 0, 0, 2, 0, 1, 0,
|
||||
11, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 1, 0, 11, 0, 0, 0,
|
||||
7, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
201, 6, 0, 0, 58, 0, 0, 0,
|
||||
201, 6, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
196, 6, 0, 0, 3, 0, 1, 0,
|
||||
208, 6, 0, 0, 2, 0, 1, 0,
|
||||
12, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 12, 0, 0, 0,
|
||||
200, 6, 0, 0, 3, 0, 1, 0,
|
||||
212, 6, 0, 0, 2, 0, 1, 0,
|
||||
8, 0, 0, 0, 128, 0, 0, 0,
|
||||
0, 0, 1, 0, 8, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
205, 6, 0, 0, 90, 0, 0, 0,
|
||||
209, 6, 0, 0, 66, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
204, 6, 0, 0, 3, 0, 1, 0,
|
||||
216, 6, 0, 0, 2, 0, 1, 0,
|
||||
13, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 1, 0, 13, 0, 0, 0,
|
||||
9, 0, 0, 0, 129, 0, 0, 0,
|
||||
0, 0, 1, 0, 9, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
213, 6, 0, 0, 154, 0, 0, 0,
|
||||
213, 6, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
216, 6, 0, 0, 3, 0, 1, 0,
|
||||
228, 6, 0, 0, 2, 0, 1, 0,
|
||||
14, 0, 0, 0, 130, 0, 0, 0,
|
||||
0, 0, 1, 0, 14, 0, 0, 0,
|
||||
212, 6, 0, 0, 3, 0, 1, 0,
|
||||
224, 6, 0, 0, 2, 0, 1, 0,
|
||||
10, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 1, 0, 10, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
225, 6, 0, 0, 98, 0, 0, 0,
|
||||
221, 6, 0, 0, 130, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
220, 6, 0, 0, 3, 0, 1, 0,
|
||||
232, 6, 0, 0, 2, 0, 1, 0,
|
||||
11, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 1, 0, 11, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
229, 6, 0, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
224, 6, 0, 0, 3, 0, 1, 0,
|
||||
236, 6, 0, 0, 2, 0, 1, 0,
|
||||
15, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 1, 0, 15, 0, 0, 0,
|
||||
12, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 12, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
233, 6, 0, 0, 58, 0, 0, 0,
|
||||
233, 6, 0, 0, 90, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
228, 6, 0, 0, 3, 0, 1, 0,
|
||||
240, 6, 0, 0, 2, 0, 1, 0,
|
||||
16, 0, 0, 0, 8, 0, 0, 0,
|
||||
0, 0, 1, 0, 16, 0, 0, 0,
|
||||
232, 6, 0, 0, 3, 0, 1, 0,
|
||||
244, 6, 0, 0, 2, 0, 1, 0,
|
||||
13, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 1, 0, 13, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
237, 6, 0, 0, 106, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
236, 6, 0, 0, 3, 0, 1, 0,
|
||||
248, 6, 0, 0, 2, 0, 1, 0,
|
||||
17, 0, 0, 0, 131, 0, 0, 0,
|
||||
0, 0, 1, 0, 17, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
245, 6, 0, 0, 90, 0, 0, 0,
|
||||
241, 6, 0, 0, 154, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
244, 6, 0, 0, 3, 0, 1, 0,
|
||||
0, 7, 0, 0, 2, 0, 1, 0,
|
||||
18, 0, 0, 0, 9, 0, 0, 0,
|
||||
0, 0, 1, 0, 18, 0, 0, 0,
|
||||
14, 0, 0, 0, 130, 0, 0, 0,
|
||||
0, 0, 1, 0, 14, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
253, 6, 0, 0, 146, 0, 0, 0,
|
||||
253, 6, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
252, 6, 0, 0, 3, 0, 1, 0,
|
||||
8, 7, 0, 0, 2, 0, 1, 0,
|
||||
15, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 1, 0, 15, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
5, 7, 0, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 7, 0, 0, 3, 0, 1, 0,
|
||||
12, 7, 0, 0, 2, 0, 1, 0,
|
||||
19, 0, 0, 0, 132, 0, 0, 0,
|
||||
0, 0, 1, 0, 19, 0, 0, 0,
|
||||
16, 0, 0, 0, 8, 0, 0, 0,
|
||||
0, 0, 1, 0, 16, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 7, 0, 0, 90, 0, 0, 0,
|
||||
9, 7, 0, 0, 106, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 7, 0, 0, 3, 0, 1, 0,
|
||||
20, 7, 0, 0, 2, 0, 1, 0,
|
||||
20, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 20, 0, 0, 0,
|
||||
17, 0, 0, 0, 131, 0, 0, 0,
|
||||
0, 0, 1, 0, 17, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
17, 7, 0, 0, 90, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16, 7, 0, 0, 3, 0, 1, 0,
|
||||
28, 7, 0, 0, 2, 0, 1, 0,
|
||||
21, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 1, 0, 21, 0, 0, 0,
|
||||
18, 0, 0, 0, 9, 0, 0, 0,
|
||||
0, 0, 1, 0, 18, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
25, 7, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
24, 7, 0, 0, 3, 0, 1, 0,
|
||||
36, 7, 0, 0, 2, 0, 1, 0,
|
||||
22, 0, 0, 0, 8, 0, 0, 0,
|
||||
0, 0, 1, 0, 22, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
33, 7, 0, 0, 58, 0, 0, 0,
|
||||
25, 7, 0, 0, 146, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
28, 7, 0, 0, 3, 0, 1, 0,
|
||||
40, 7, 0, 0, 2, 0, 1, 0,
|
||||
19, 0, 0, 0, 132, 0, 0, 0,
|
||||
0, 0, 1, 0, 19, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
37, 7, 0, 0, 90, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
36, 7, 0, 0, 3, 0, 1, 0,
|
||||
48, 7, 0, 0, 2, 0, 1, 0,
|
||||
20, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 20, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
45, 7, 0, 0, 90, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
44, 7, 0, 0, 3, 0, 1, 0,
|
||||
56, 7, 0, 0, 2, 0, 1, 0,
|
||||
21, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 1, 0, 21, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
53, 7, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
52, 7, 0, 0, 3, 0, 1, 0,
|
||||
64, 7, 0, 0, 2, 0, 1, 0,
|
||||
22, 0, 0, 0, 8, 0, 0, 0,
|
||||
0, 0, 1, 0, 22, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
61, 7, 0, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
56, 7, 0, 0, 3, 0, 1, 0,
|
||||
68, 7, 0, 0, 2, 0, 1, 0,
|
||||
23, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 1, 0, 23, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
37, 7, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
40, 7, 0, 0, 3, 0, 1, 0,
|
||||
52, 7, 0, 0, 2, 0, 1, 0,
|
||||
24, 0, 0, 0, 9, 0, 0, 0,
|
||||
0, 0, 1, 0, 24, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
49, 7, 0, 0, 106, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
48, 7, 0, 0, 3, 0, 1, 0,
|
||||
60, 7, 0, 0, 2, 0, 1, 0,
|
||||
25, 0, 0, 0, 10, 0, 0, 0,
|
||||
0, 0, 1, 0, 25, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
57, 7, 0, 0, 194, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
60, 7, 0, 0, 3, 0, 1, 0,
|
||||
72, 7, 0, 0, 2, 0, 1, 0,
|
||||
26, 0, 0, 0, 16, 0, 0, 0,
|
||||
0, 0, 1, 0, 26, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
69, 7, 0, 0, 114, 0, 0, 0,
|
||||
65, 7, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
68, 7, 0, 0, 3, 0, 1, 0,
|
||||
80, 7, 0, 0, 2, 0, 1, 0,
|
||||
27, 0, 0, 0, 9, 0, 0, 0,
|
||||
0, 0, 1, 0, 27, 0, 0, 0,
|
||||
24, 0, 0, 0, 9, 0, 0, 0,
|
||||
0, 0, 1, 0, 24, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
77, 7, 0, 0, 186, 0, 0, 0,
|
||||
77, 7, 0, 0, 106, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
80, 7, 0, 0, 3, 0, 1, 0,
|
||||
92, 7, 0, 0, 2, 0, 1, 0,
|
||||
28, 0, 0, 0, 10, 0, 0, 0,
|
||||
0, 0, 1, 0, 28, 0, 0, 0,
|
||||
76, 7, 0, 0, 3, 0, 1, 0,
|
||||
88, 7, 0, 0, 2, 0, 1, 0,
|
||||
25, 0, 0, 0, 10, 0, 0, 0,
|
||||
0, 0, 1, 0, 25, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
89, 7, 0, 0, 202, 0, 0, 0,
|
||||
85, 7, 0, 0, 194, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
88, 7, 0, 0, 3, 0, 1, 0,
|
||||
100, 7, 0, 0, 2, 0, 1, 0,
|
||||
26, 0, 0, 0, 16, 0, 0, 0,
|
||||
0, 0, 1, 0, 26, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
97, 7, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
96, 7, 0, 0, 3, 0, 1, 0,
|
||||
108, 7, 0, 0, 2, 0, 1, 0,
|
||||
29, 0, 0, 0, 11, 0, 0, 0,
|
||||
0, 0, 1, 0, 29, 0, 0, 0,
|
||||
27, 0, 0, 0, 9, 0, 0, 0,
|
||||
0, 0, 1, 0, 27, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
105, 7, 0, 0, 82, 0, 0, 0,
|
||||
105, 7, 0, 0, 186, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
104, 7, 0, 0, 3, 0, 1, 0,
|
||||
116, 7, 0, 0, 2, 0, 1, 0,
|
||||
30, 0, 0, 0, 11, 0, 0, 0,
|
||||
0, 0, 1, 0, 30, 0, 0, 0,
|
||||
108, 7, 0, 0, 3, 0, 1, 0,
|
||||
120, 7, 0, 0, 2, 0, 1, 0,
|
||||
28, 0, 0, 0, 10, 0, 0, 0,
|
||||
0, 0, 1, 0, 28, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
113, 7, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
112, 7, 0, 0, 3, 0, 1, 0,
|
||||
124, 7, 0, 0, 2, 0, 1, 0,
|
||||
31, 0, 0, 0, 12, 0, 0, 0,
|
||||
0, 0, 1, 0, 31, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
121, 7, 0, 0, 50, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
116, 7, 0, 0, 3, 0, 1, 0,
|
||||
128, 7, 0, 0, 2, 0, 1, 0,
|
||||
32, 0, 0, 0, 13, 0, 0, 0,
|
||||
0, 0, 1, 0, 32, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
125, 7, 0, 0, 130, 0, 0, 0,
|
||||
117, 7, 0, 0, 202, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
124, 7, 0, 0, 3, 0, 1, 0,
|
||||
136, 7, 0, 0, 2, 0, 1, 0,
|
||||
33, 0, 0, 0, 14, 0, 0, 0,
|
||||
0, 0, 1, 0, 33, 0, 0, 0,
|
||||
29, 0, 0, 0, 11, 0, 0, 0,
|
||||
0, 0, 1, 0, 29, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
133, 7, 0, 0, 98, 0, 0, 0,
|
||||
133, 7, 0, 0, 82, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
132, 7, 0, 0, 3, 0, 1, 0,
|
||||
144, 7, 0, 0, 2, 0, 1, 0,
|
||||
34, 0, 0, 0, 15, 0, 0, 0,
|
||||
0, 0, 1, 0, 34, 0, 0, 0,
|
||||
30, 0, 0, 0, 11, 0, 0, 0,
|
||||
0, 0, 1, 0, 30, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
141, 7, 0, 0, 122, 0, 0, 0,
|
||||
141, 7, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
140, 7, 0, 0, 3, 0, 1, 0,
|
||||
152, 7, 0, 0, 2, 0, 1, 0,
|
||||
35, 0, 0, 0, 16, 0, 0, 0,
|
||||
0, 0, 1, 0, 35, 0, 0, 0,
|
||||
31, 0, 0, 0, 12, 0, 0, 0,
|
||||
0, 0, 1, 0, 31, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
149, 7, 0, 0, 122, 0, 0, 0,
|
||||
149, 7, 0, 0, 50, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
148, 7, 0, 0, 3, 0, 1, 0,
|
||||
160, 7, 0, 0, 2, 0, 1, 0,
|
||||
36, 0, 0, 0, 17, 0, 0, 0,
|
||||
0, 0, 1, 0, 36, 0, 0, 0,
|
||||
144, 7, 0, 0, 3, 0, 1, 0,
|
||||
156, 7, 0, 0, 2, 0, 1, 0,
|
||||
32, 0, 0, 0, 13, 0, 0, 0,
|
||||
0, 0, 1, 0, 32, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
157, 7, 0, 0, 114, 0, 0, 0,
|
||||
153, 7, 0, 0, 130, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
156, 7, 0, 0, 3, 0, 1, 0,
|
||||
168, 7, 0, 0, 2, 0, 1, 0,
|
||||
37, 0, 0, 0, 17, 0, 0, 0,
|
||||
0, 0, 1, 0, 37, 0, 0, 0,
|
||||
152, 7, 0, 0, 3, 0, 1, 0,
|
||||
164, 7, 0, 0, 2, 0, 1, 0,
|
||||
33, 0, 0, 0, 14, 0, 0, 0,
|
||||
0, 0, 1, 0, 33, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
165, 7, 0, 0, 186, 0, 0, 0,
|
||||
161, 7, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
160, 7, 0, 0, 3, 0, 1, 0,
|
||||
172, 7, 0, 0, 2, 0, 1, 0,
|
||||
34, 0, 0, 0, 15, 0, 0, 0,
|
||||
0, 0, 1, 0, 34, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
169, 7, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
168, 7, 0, 0, 3, 0, 1, 0,
|
||||
180, 7, 0, 0, 2, 0, 1, 0,
|
||||
38, 0, 0, 0, 133, 0, 0, 0,
|
||||
0, 0, 1, 0, 38, 0, 0, 0,
|
||||
35, 0, 0, 0, 16, 0, 0, 0,
|
||||
0, 0, 1, 0, 35, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
177, 7, 0, 0, 210, 0, 0, 0,
|
||||
177, 7, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
176, 7, 0, 0, 3, 0, 1, 0,
|
||||
188, 7, 0, 0, 2, 0, 1, 0,
|
||||
36, 0, 0, 0, 17, 0, 0, 0,
|
||||
0, 0, 1, 0, 36, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
185, 7, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
184, 7, 0, 0, 3, 0, 1, 0,
|
||||
196, 7, 0, 0, 2, 0, 1, 0,
|
||||
39, 0, 0, 0, 134, 0, 0, 0,
|
||||
0, 0, 1, 0, 39, 0, 0, 0,
|
||||
37, 0, 0, 0, 17, 0, 0, 0,
|
||||
0, 0, 1, 0, 37, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
193, 7, 0, 0, 138, 0, 0, 0,
|
||||
193, 7, 0, 0, 186, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
196, 7, 0, 0, 3, 0, 1, 0,
|
||||
208, 7, 0, 0, 2, 0, 1, 0,
|
||||
38, 0, 0, 0, 133, 0, 0, 0,
|
||||
0, 0, 1, 0, 38, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
205, 7, 0, 0, 210, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
212, 7, 0, 0, 3, 0, 1, 0,
|
||||
224, 7, 0, 0, 2, 0, 1, 0,
|
||||
39, 0, 0, 0, 134, 0, 0, 0,
|
||||
0, 0, 1, 0, 39, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
221, 7, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
224, 7, 0, 0, 3, 0, 1, 0,
|
||||
236, 7, 0, 0, 2, 0, 1, 0,
|
||||
40, 0, 0, 0, 135, 0, 0, 0,
|
||||
0, 0, 1, 0, 40, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
205, 7, 0, 0, 170, 0, 0, 0,
|
||||
233, 7, 0, 0, 170, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
208, 7, 0, 0, 3, 0, 1, 0,
|
||||
220, 7, 0, 0, 2, 0, 1, 0,
|
||||
236, 7, 0, 0, 3, 0, 1, 0,
|
||||
248, 7, 0, 0, 2, 0, 1, 0,
|
||||
41, 0, 0, 0, 18, 0, 0, 0,
|
||||
0, 0, 1, 0, 41, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
217, 7, 0, 0, 122, 0, 0, 0,
|
||||
245, 7, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
216, 7, 0, 0, 3, 0, 1, 0,
|
||||
244, 7, 0, 0, 2, 0, 1, 0,
|
||||
244, 7, 0, 0, 3, 0, 1, 0,
|
||||
16, 8, 0, 0, 2, 0, 1, 0,
|
||||
42, 0, 0, 0, 24, 0, 0, 0,
|
||||
0, 0, 1, 0, 42, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
241, 7, 0, 0, 178, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
244, 7, 0, 0, 3, 0, 1, 0,
|
||||
0, 8, 0, 0, 2, 0, 1, 0,
|
||||
43, 0, 0, 0, 136, 0, 0, 0,
|
||||
0, 0, 1, 0, 43, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
253, 7, 0, 0, 202, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 8, 0, 0, 3, 0, 1, 0,
|
||||
16, 8, 0, 0, 2, 0, 1, 0,
|
||||
44, 0, 0, 0, 25, 0, 0, 0,
|
||||
0, 0, 1, 0, 44, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
13, 8, 0, 0, 170, 0, 0, 0,
|
||||
13, 8, 0, 0, 178, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16, 8, 0, 0, 3, 0, 1, 0,
|
||||
28, 8, 0, 0, 2, 0, 1, 0,
|
||||
45, 0, 0, 0, 137, 0, 0, 0,
|
||||
0, 0, 1, 0, 45, 0, 0, 0,
|
||||
43, 0, 0, 0, 136, 0, 0, 0,
|
||||
0, 0, 1, 0, 43, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
25, 8, 0, 0, 194, 0, 0, 0,
|
||||
25, 8, 0, 0, 202, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
28, 8, 0, 0, 3, 0, 1, 0,
|
||||
40, 8, 0, 0, 2, 0, 1, 0,
|
||||
46, 0, 0, 0, 26, 0, 0, 0,
|
||||
0, 0, 1, 0, 46, 0, 0, 0,
|
||||
32, 8, 0, 0, 3, 0, 1, 0,
|
||||
44, 8, 0, 0, 2, 0, 1, 0,
|
||||
44, 0, 0, 0, 25, 0, 0, 0,
|
||||
0, 0, 1, 0, 44, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
37, 8, 0, 0, 210, 0, 0, 0,
|
||||
41, 8, 0, 0, 170, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
44, 8, 0, 0, 3, 0, 1, 0,
|
||||
56, 8, 0, 0, 2, 0, 1, 0,
|
||||
45, 0, 0, 0, 137, 0, 0, 0,
|
||||
0, 0, 1, 0, 45, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
53, 8, 0, 0, 194, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
56, 8, 0, 0, 3, 0, 1, 0,
|
||||
68, 8, 0, 0, 2, 0, 1, 0,
|
||||
46, 0, 0, 0, 26, 0, 0, 0,
|
||||
0, 0, 1, 0, 46, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
65, 8, 0, 0, 210, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
72, 8, 0, 0, 3, 0, 1, 0,
|
||||
84, 8, 0, 0, 2, 0, 1, 0,
|
||||
47, 0, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 1, 0, 47, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
53, 8, 0, 0, 234, 0, 0, 0,
|
||||
81, 8, 0, 0, 234, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
60, 8, 0, 0, 3, 0, 1, 0,
|
||||
72, 8, 0, 0, 2, 0, 1, 0,
|
||||
88, 8, 0, 0, 3, 0, 1, 0,
|
||||
100, 8, 0, 0, 2, 0, 1, 0,
|
||||
48, 0, 0, 0, 19, 0, 0, 0,
|
||||
0, 0, 1, 0, 48, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
69, 8, 0, 0, 114, 0, 0, 0,
|
||||
97, 8, 0, 0, 114, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
68, 8, 0, 0, 3, 0, 1, 0,
|
||||
80, 8, 0, 0, 2, 0, 1, 0,
|
||||
96, 8, 0, 0, 3, 0, 1, 0,
|
||||
108, 8, 0, 0, 2, 0, 1, 0,
|
||||
49, 0, 0, 0, 139, 0, 0, 0,
|
||||
0, 0, 1, 0, 49, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
77, 8, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
80, 8, 0, 0, 3, 0, 1, 0,
|
||||
92, 8, 0, 0, 2, 0, 1, 0,
|
||||
50, 0, 0, 0, 14, 0, 0, 0,
|
||||
0, 0, 1, 0, 50, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
89, 8, 0, 0, 194, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
92, 8, 0, 0, 3, 0, 1, 0,
|
||||
104, 8, 0, 0, 2, 0, 1, 0,
|
||||
51, 0, 0, 0, 140, 0, 0, 0,
|
||||
0, 0, 1, 0, 51, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
101, 8, 0, 0, 202, 0, 0, 0,
|
||||
105, 8, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
108, 8, 0, 0, 3, 0, 1, 0,
|
||||
120, 8, 0, 0, 2, 0, 1, 0,
|
||||
52, 0, 0, 0, 15, 0, 0, 0,
|
||||
0, 0, 1, 0, 52, 0, 0, 0,
|
||||
50, 0, 0, 0, 14, 0, 0, 0,
|
||||
0, 0, 1, 0, 50, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
117, 8, 0, 0, 170, 0, 0, 0,
|
||||
117, 8, 0, 0, 194, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
120, 8, 0, 0, 3, 0, 1, 0,
|
||||
132, 8, 0, 0, 2, 0, 1, 0,
|
||||
51, 0, 0, 0, 140, 0, 0, 0,
|
||||
0, 0, 1, 0, 51, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
129, 8, 0, 0, 202, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
136, 8, 0, 0, 3, 0, 1, 0,
|
||||
148, 8, 0, 0, 2, 0, 1, 0,
|
||||
52, 0, 0, 0, 15, 0, 0, 0,
|
||||
0, 0, 1, 0, 52, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
145, 8, 0, 0, 170, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
148, 8, 0, 0, 3, 0, 1, 0,
|
||||
160, 8, 0, 0, 2, 0, 1, 0,
|
||||
53, 0, 0, 0, 27, 0, 0, 0,
|
||||
0, 0, 1, 0, 53, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
129, 8, 0, 0, 186, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
132, 8, 0, 0, 3, 0, 1, 0,
|
||||
144, 8, 0, 0, 2, 0, 1, 0,
|
||||
54, 0, 0, 0, 20, 0, 0, 0,
|
||||
0, 0, 1, 0, 54, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
141, 8, 0, 0, 154, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
144, 8, 0, 0, 3, 0, 1, 0,
|
||||
156, 8, 0, 0, 2, 0, 1, 0,
|
||||
55, 0, 0, 0, 32, 0, 0, 0,
|
||||
0, 0, 1, 0, 55, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
153, 8, 0, 0, 210, 0, 0, 0,
|
||||
157, 8, 0, 0, 186, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
160, 8, 0, 0, 3, 0, 1, 0,
|
||||
172, 8, 0, 0, 2, 0, 1, 0,
|
||||
56, 0, 0, 0, 17, 0, 0, 0,
|
||||
0, 0, 1, 0, 56, 0, 0, 0,
|
||||
54, 0, 0, 0, 20, 0, 0, 0,
|
||||
0, 0, 1, 0, 54, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
169, 8, 0, 0, 138, 0, 0, 0,
|
||||
169, 8, 0, 0, 154, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
172, 8, 0, 0, 3, 0, 1, 0,
|
||||
184, 8, 0, 0, 2, 0, 1, 0,
|
||||
55, 0, 0, 0, 32, 0, 0, 0,
|
||||
0, 0, 1, 0, 55, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
181, 8, 0, 0, 210, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
188, 8, 0, 0, 3, 0, 1, 0,
|
||||
200, 8, 0, 0, 2, 0, 1, 0,
|
||||
56, 0, 0, 0, 17, 0, 0, 0,
|
||||
0, 0, 1, 0, 56, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
197, 8, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
200, 8, 0, 0, 3, 0, 1, 0,
|
||||
212, 8, 0, 0, 2, 0, 1, 0,
|
||||
57, 0, 0, 0, 33, 0, 0, 0,
|
||||
0, 0, 1, 0, 57, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
181, 8, 0, 0, 154, 0, 0, 0,
|
||||
209, 8, 0, 0, 154, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
184, 8, 0, 0, 3, 0, 1, 0,
|
||||
196, 8, 0, 0, 2, 0, 1, 0,
|
||||
212, 8, 0, 0, 3, 0, 1, 0,
|
||||
224, 8, 0, 0, 2, 0, 1, 0,
|
||||
58, 0, 0, 0, 21, 0, 0, 0,
|
||||
0, 0, 1, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
193, 8, 0, 0, 154, 0, 0, 0,
|
||||
221, 8, 0, 0, 154, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
196, 8, 0, 0, 3, 0, 1, 0,
|
||||
208, 8, 0, 0, 2, 0, 1, 0,
|
||||
224, 8, 0, 0, 3, 0, 1, 0,
|
||||
236, 8, 0, 0, 2, 0, 1, 0,
|
||||
59, 0, 0, 0, 141, 0, 0, 0,
|
||||
0, 0, 1, 0, 59, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
205, 8, 0, 0, 146, 0, 0, 0,
|
||||
233, 8, 0, 0, 146, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
208, 8, 0, 0, 3, 0, 1, 0,
|
||||
220, 8, 0, 0, 2, 0, 1, 0,
|
||||
236, 8, 0, 0, 3, 0, 1, 0,
|
||||
248, 8, 0, 0, 2, 0, 1, 0,
|
||||
60, 0, 0, 0, 18, 0, 0, 0,
|
||||
0, 0, 1, 0, 60, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
245, 8, 0, 0, 154, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
248, 8, 0, 0, 3, 0, 1, 0,
|
||||
4, 9, 0, 0, 2, 0, 1, 0,
|
||||
115, 108, 111, 116, 73, 100, 0, 0,
|
||||
12, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -4771,6 +4778,16 @@ static const ::capnp::_::AlignedData<1030> b_a1680744031fdb2d = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
119, 104, 101, 101, 108, 79, 118, 101,
|
||||
114, 114, 105, 100, 101, 83, 105, 110,
|
||||
99, 101, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, }
|
||||
};
|
||||
::capnp::word const* const bp_a1680744031fdb2d = b_a1680744031fdb2d.words;
|
||||
@@ -4782,11 +4799,11 @@ static const ::capnp::_::RawSchema* const d_a1680744031fdb2d[] = {
|
||||
&s_f58695a93b568caf,
|
||||
&s_fb41e1a738d832cb,
|
||||
};
|
||||
static const uint16_t m_a1680744031fdb2d[] = {42, 59, 56, 35, 13, 23, 24, 51, 50, 29, 30, 32, 31, 20, 9, 40, 16, 37, 8, 7, 14, 43, 17, 38, 19, 45, 47, 39, 55, 54, 53, 10, 15, 48, 44, 52, 36, 18, 46, 21, 4, 49, 6, 0, 1, 11, 26, 27, 25, 41, 28, 12, 22, 34, 33, 58, 57, 2, 3, 5};
|
||||
static const uint16_t i_a1680744031fdb2d[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59};
|
||||
static const uint16_t m_a1680744031fdb2d[] = {42, 59, 56, 35, 13, 23, 24, 51, 50, 29, 30, 32, 31, 20, 9, 40, 16, 37, 8, 7, 14, 43, 17, 38, 19, 45, 47, 39, 55, 54, 53, 10, 15, 48, 44, 52, 36, 18, 46, 21, 4, 49, 6, 0, 1, 11, 26, 27, 25, 41, 28, 12, 22, 34, 33, 58, 57, 2, 3, 5, 60};
|
||||
static const uint16_t i_a1680744031fdb2d[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60};
|
||||
const ::capnp::_::RawSchema s_a1680744031fdb2d = {
|
||||
0xa1680744031fdb2d, b_a1680744031fdb2d.words, 1030, d_a1680744031fdb2d, m_a1680744031fdb2d,
|
||||
5, 60, i_a1680744031fdb2d, nullptr, nullptr, { &s_a1680744031fdb2d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
0xa1680744031fdb2d, b_a1680744031fdb2d.words, 1047, d_a1680744031fdb2d, m_a1680744031fdb2d,
|
||||
5, 61, i_a1680744031fdb2d, nullptr, nullptr, { &s_a1680744031fdb2d, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<81> b_a7940385bedd1d4c = {
|
||||
@@ -6891,17 +6908,17 @@ const ::capnp::_::RawSchema s_b8cbd9e666181b95 = {
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
CAPNP_DEFINE_ENUM(Kind_b8cbd9e666181b95, b8cbd9e666181b95);
|
||||
static const ::capnp::_::AlignedData<295> b_cd96dafb67a082d0 = {
|
||||
static const ::capnp::_::AlignedData<312> b_cd96dafb67a082d0 = {
|
||||
{ 0, 0, 0, 0, 5, 0, 6, 0,
|
||||
208, 130, 160, 103, 251, 218, 150, 205,
|
||||
13, 0, 0, 0, 1, 0, 7, 0,
|
||||
13, 0, 0, 0, 1, 0, 8, 0,
|
||||
89, 10, 85, 29, 102, 186, 38, 181,
|
||||
6, 0, 7, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
21, 0, 0, 0, 226, 0, 0, 0,
|
||||
33, 0, 0, 0, 87, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
113, 0, 0, 0, 135, 3, 0, 0,
|
||||
113, 0, 0, 0, 191, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
99, 117, 115, 116, 111, 109, 46, 99,
|
||||
@@ -6930,119 +6947,126 @@ static const ::capnp::_::AlignedData<295> b_cd96dafb67a082d0 = {
|
||||
77, 97, 110, 117, 97, 108, 77, 111,
|
||||
100, 101, 71, 101, 115, 116, 117, 114,
|
||||
101, 0, 0, 0, 0, 0, 0, 0,
|
||||
64, 0, 0, 0, 3, 0, 4, 0,
|
||||
68, 0, 0, 0, 3, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
177, 1, 0, 0, 66, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
172, 1, 0, 0, 3, 0, 1, 0,
|
||||
184, 1, 0, 0, 2, 0, 1, 0,
|
||||
1, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
181, 1, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
184, 1, 0, 0, 3, 0, 1, 0,
|
||||
196, 1, 0, 0, 2, 0, 1, 0,
|
||||
2, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 1, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
193, 1, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
192, 1, 0, 0, 3, 0, 1, 0,
|
||||
204, 1, 0, 0, 2, 0, 1, 0,
|
||||
3, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
201, 1, 0, 0, 98, 0, 0, 0,
|
||||
205, 1, 0, 0, 66, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
200, 1, 0, 0, 3, 0, 1, 0,
|
||||
212, 1, 0, 0, 2, 0, 1, 0,
|
||||
4, 0, 0, 0, 12, 0, 0, 0,
|
||||
0, 0, 1, 0, 4, 0, 0, 0,
|
||||
1, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
209, 1, 0, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
204, 1, 0, 0, 3, 0, 1, 0,
|
||||
216, 1, 0, 0, 2, 0, 1, 0,
|
||||
5, 0, 0, 0, 208, 0, 0, 0,
|
||||
0, 0, 1, 0, 5, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
213, 1, 0, 0, 82, 0, 0, 0,
|
||||
209, 1, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
212, 1, 0, 0, 3, 0, 1, 0,
|
||||
224, 1, 0, 0, 2, 0, 1, 0,
|
||||
6, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 6, 0, 0, 0,
|
||||
2, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 1, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
221, 1, 0, 0, 146, 0, 0, 0,
|
||||
221, 1, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
224, 1, 0, 0, 3, 0, 1, 0,
|
||||
236, 1, 0, 0, 2, 0, 1, 0,
|
||||
7, 0, 0, 0, 14, 0, 0, 0,
|
||||
0, 0, 1, 0, 7, 0, 0, 0,
|
||||
220, 1, 0, 0, 3, 0, 1, 0,
|
||||
232, 1, 0, 0, 2, 0, 1, 0,
|
||||
3, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 3, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
233, 1, 0, 0, 42, 0, 0, 0,
|
||||
229, 1, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
228, 1, 0, 0, 3, 0, 1, 0,
|
||||
240, 1, 0, 0, 2, 0, 1, 0,
|
||||
8, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 8, 0, 0, 0,
|
||||
4, 0, 0, 0, 12, 0, 0, 0,
|
||||
0, 0, 1, 0, 4, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
237, 1, 0, 0, 82, 0, 0, 0,
|
||||
237, 1, 0, 0, 58, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
236, 1, 0, 0, 3, 0, 1, 0,
|
||||
248, 1, 0, 0, 2, 0, 1, 0,
|
||||
9, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 1, 0, 9, 0, 0, 0,
|
||||
232, 1, 0, 0, 3, 0, 1, 0,
|
||||
244, 1, 0, 0, 2, 0, 1, 0,
|
||||
5, 0, 0, 0, 208, 0, 0, 0,
|
||||
0, 0, 1, 0, 5, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
245, 1, 0, 0, 90, 0, 0, 0,
|
||||
241, 1, 0, 0, 82, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
244, 1, 0, 0, 3, 0, 1, 0,
|
||||
0, 2, 0, 0, 2, 0, 1, 0,
|
||||
10, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 10, 0, 0, 0,
|
||||
240, 1, 0, 0, 3, 0, 1, 0,
|
||||
252, 1, 0, 0, 2, 0, 1, 0,
|
||||
6, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
253, 1, 0, 0, 122, 0, 0, 0,
|
||||
249, 1, 0, 0, 146, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
252, 1, 0, 0, 3, 0, 1, 0,
|
||||
8, 2, 0, 0, 2, 0, 1, 0,
|
||||
7, 0, 0, 0, 14, 0, 0, 0,
|
||||
0, 0, 1, 0, 7, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
5, 2, 0, 0, 42, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 2, 0, 0, 3, 0, 1, 0,
|
||||
12, 2, 0, 0, 2, 0, 1, 0,
|
||||
8, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 8, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 2, 0, 0, 82, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 2, 0, 0, 3, 0, 1, 0,
|
||||
20, 2, 0, 0, 2, 0, 1, 0,
|
||||
9, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 1, 0, 9, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
17, 2, 0, 0, 90, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16, 2, 0, 0, 3, 0, 1, 0,
|
||||
28, 2, 0, 0, 2, 0, 1, 0,
|
||||
10, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 10, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
25, 2, 0, 0, 122, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
24, 2, 0, 0, 3, 0, 1, 0,
|
||||
36, 2, 0, 0, 2, 0, 1, 0,
|
||||
11, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 1, 0, 11, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
5, 2, 0, 0, 82, 0, 0, 0,
|
||||
33, 2, 0, 0, 82, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 2, 0, 0, 3, 0, 1, 0,
|
||||
16, 2, 0, 0, 2, 0, 1, 0,
|
||||
32, 2, 0, 0, 3, 0, 1, 0,
|
||||
44, 2, 0, 0, 2, 0, 1, 0,
|
||||
12, 0, 0, 0, 2, 0, 0, 0,
|
||||
0, 0, 1, 0, 12, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
13, 2, 0, 0, 90, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
12, 2, 0, 0, 3, 0, 1, 0,
|
||||
24, 2, 0, 0, 2, 0, 1, 0,
|
||||
13, 0, 0, 0, 3, 0, 0, 0,
|
||||
0, 0, 1, 0, 13, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
21, 2, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
20, 2, 0, 0, 3, 0, 1, 0,
|
||||
32, 2, 0, 0, 2, 0, 1, 0,
|
||||
14, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 1, 0, 14, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
29, 2, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
28, 2, 0, 0, 3, 0, 1, 0,
|
||||
40, 2, 0, 0, 2, 0, 1, 0,
|
||||
15, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 15, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
37, 2, 0, 0, 138, 0, 0, 0,
|
||||
41, 2, 0, 0, 90, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
40, 2, 0, 0, 3, 0, 1, 0,
|
||||
52, 2, 0, 0, 2, 0, 1, 0,
|
||||
13, 0, 0, 0, 3, 0, 0, 0,
|
||||
0, 0, 1, 0, 13, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
49, 2, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
48, 2, 0, 0, 3, 0, 1, 0,
|
||||
60, 2, 0, 0, 2, 0, 1, 0,
|
||||
14, 0, 0, 0, 4, 0, 0, 0,
|
||||
0, 0, 1, 0, 14, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
57, 2, 0, 0, 98, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
56, 2, 0, 0, 3, 0, 1, 0,
|
||||
68, 2, 0, 0, 2, 0, 1, 0,
|
||||
15, 0, 0, 0, 5, 0, 0, 0,
|
||||
0, 0, 1, 0, 15, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
65, 2, 0, 0, 138, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
68, 2, 0, 0, 3, 0, 1, 0,
|
||||
80, 2, 0, 0, 2, 0, 1, 0,
|
||||
16, 0, 0, 0, 7, 0, 0, 0,
|
||||
0, 0, 1, 0, 16, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
77, 2, 0, 0, 154, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
80, 2, 0, 0, 3, 0, 1, 0,
|
||||
92, 2, 0, 0, 2, 0, 1, 0,
|
||||
101, 118, 101, 110, 116, 73, 100, 0,
|
||||
9, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -7185,6 +7209,16 @@ static const ::capnp::_::AlignedData<295> b_cd96dafb67a082d0 = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
119, 104, 101, 101, 108, 79, 118, 101,
|
||||
114, 114, 105, 100, 101, 83, 105, 110,
|
||||
99, 101, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, }
|
||||
};
|
||||
@@ -7198,11 +7232,11 @@ static const ::capnp::_::RawSchema* const d_cd96dafb67a082d0[] = {
|
||||
&s_efc922094a634c9f,
|
||||
&s_fd07e0b91e3573c2,
|
||||
};
|
||||
static const uint16_t m_cd96dafb67a082d0[] = {4, 11, 9, 0, 7, 5, 12, 1, 10, 2, 6, 3, 8, 15, 13, 14};
|
||||
static const uint16_t i_cd96dafb67a082d0[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
|
||||
static const uint16_t m_cd96dafb67a082d0[] = {4, 11, 9, 0, 7, 5, 12, 1, 10, 2, 6, 3, 8, 15, 13, 14, 16};
|
||||
static const uint16_t i_cd96dafb67a082d0[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
const ::capnp::_::RawSchema s_cd96dafb67a082d0 = {
|
||||
0xcd96dafb67a082d0, b_cd96dafb67a082d0.words, 295, d_cd96dafb67a082d0, m_cd96dafb67a082d0,
|
||||
6, 16, i_cd96dafb67a082d0, nullptr, nullptr, { &s_cd96dafb67a082d0, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
0xcd96dafb67a082d0, b_cd96dafb67a082d0.words, 312, d_cd96dafb67a082d0, m_cd96dafb67a082d0,
|
||||
6, 17, i_cd96dafb67a082d0, nullptr, nullptr, { &s_cd96dafb67a082d0, nullptr, nullptr, 0, 0, nullptr }, false
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
static const ::capnp::_::AlignedData<99> b_cc2db5640fb6dc61 = {
|
||||
|
||||
@@ -730,7 +730,7 @@ struct SlcState {
|
||||
struct ConditionalModeState;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(a1680744031fdb2d, 18, 22)
|
||||
CAPNP_DECLARE_STRUCT_HEADER(a1680744031fdb2d, 19, 22)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
@@ -878,7 +878,7 @@ struct SlcCruiseEvent {
|
||||
struct ManualModeGesture;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(cd96dafb67a082d0, 7, 6)
|
||||
CAPNP_DECLARE_STRUCT_HEADER(cd96dafb67a082d0, 8, 6)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
@@ -4368,6 +4368,8 @@ public:
|
||||
|
||||
inline bool getAcceptedIsPreview() const;
|
||||
|
||||
inline ::uint64_t getWheelOverrideSince() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
@@ -4664,6 +4666,9 @@ public:
|
||||
inline bool getAcceptedIsPreview();
|
||||
inline void setAcceptedIsPreview(bool value);
|
||||
|
||||
inline ::uint64_t getWheelOverrideSince();
|
||||
inline void setWheelOverrideSince( ::uint64_t value);
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
@@ -5975,6 +5980,8 @@ public:
|
||||
inline bool hasTeslaStockCruise() const;
|
||||
inline ::cereal::SlcCruiseEvent::TeslaStockCruise::Reader getTeslaStockCruise() const;
|
||||
|
||||
inline ::uint64_t getWheelOverrideSince() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
@@ -6075,6 +6082,9 @@ public:
|
||||
inline void adoptTeslaStockCruise(::capnp::Orphan< ::cereal::SlcCruiseEvent::TeslaStockCruise>&& value);
|
||||
inline ::capnp::Orphan< ::cereal::SlcCruiseEvent::TeslaStockCruise> disownTeslaStockCruise();
|
||||
|
||||
inline ::uint64_t getWheelOverrideSince();
|
||||
inline void setWheelOverrideSince( ::uint64_t value);
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
@@ -19732,6 +19742,20 @@ inline void SlcState::Builder::setAcceptedIsPreview(bool value) {
|
||||
::capnp::bounded<141>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline ::uint64_t SlcState::Reader::getWheelOverrideSince() const {
|
||||
return _reader.getDataField< ::uint64_t>(
|
||||
::capnp::bounded<18>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::uint64_t SlcState::Builder::getWheelOverrideSince() {
|
||||
return _builder.getDataField< ::uint64_t>(
|
||||
::capnp::bounded<18>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void SlcState::Builder::setWheelOverrideSince( ::uint64_t value) {
|
||||
_builder.setDataField< ::uint64_t>(
|
||||
::capnp::bounded<18>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool SlcState::SourceReading::Reader::hasSource() const {
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
@@ -22107,6 +22131,20 @@ inline ::capnp::Orphan< ::cereal::SlcCruiseEvent::TeslaStockCruise> SlcCruiseEve
|
||||
::capnp::bounded<5>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline ::uint64_t SlcCruiseEvent::Reader::getWheelOverrideSince() const {
|
||||
return _reader.getDataField< ::uint64_t>(
|
||||
::capnp::bounded<7>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::uint64_t SlcCruiseEvent::Builder::getWheelOverrideSince() {
|
||||
return _builder.getDataField< ::uint64_t>(
|
||||
::capnp::bounded<7>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void SlcCruiseEvent::Builder::setWheelOverrideSince( ::uint64_t value) {
|
||||
_builder.setDataField< ::uint64_t>(
|
||||
::capnp::bounded<7>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline ::uint16_t SlcCruiseEvent::TeslaStockCruise::Reader::getVersion() const {
|
||||
return _reader.getDataField< ::uint16_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -332,6 +332,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||
{"SLCAdvanceHigherSeconds", {PERSISTENT, INT, "0"}},
|
||||
{"SLCAdvanceLowerSeconds", {PERSISTENT, INT, "0"}},
|
||||
{"SLCOverrideMode", {PERSISTENT, INT, "1"}},
|
||||
{"SLCWheelOverride", {PERSISTENT, BOOL, "0"}},
|
||||
{"SLCQualifiedHistory", {PERSISTENT, JSON}},
|
||||
{"ConditionalModeConfig", {PERSISTENT | DONT_LOG, JSON}},
|
||||
{"ConditionalManualState", {PERSISTENT | DONT_LOG, JSON}},
|
||||
|
||||
@@ -31,7 +31,7 @@ from opendbc.car.hyundai.ioniq6_media import Ioniq6MediaButtons
|
||||
from opendbc.car.hyundai.values import CAR as HYUNDAI_CAR
|
||||
from opendbc.car.interfaces import CarInterfaceBase, RadarInterfaceBase
|
||||
from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp
|
||||
from openpilot.selfdrive.car.cruise import VCruiseHelper
|
||||
from openpilot.selfdrive.car.cruise import SlcWheelContext, VCruiseHelper
|
||||
from openpilot.starpilot.speed_limits import physical_actions as slc_physical
|
||||
from openpilot.starpilot.aol.intent import AolProcessFaultContext, independent_axis_requested, read_settings
|
||||
from openpilot.starpilot.aol.transport_pause import TransportPauseFeedback, cp_identity
|
||||
@@ -573,7 +573,15 @@ class Car:
|
||||
if self.slc_replay:
|
||||
pending = slc_physical.pending_confirmation(
|
||||
self.sm, now_ns, long_active=slc_long_active, after_ns=floor_ns)
|
||||
self.update_cruise_speed(CS, pending)
|
||||
wheel_context = None
|
||||
slc_settings = getattr(self, 'slc_configuration', (False, None))[1]
|
||||
cruise_helper = self.v_cruise_helper
|
||||
if (self.slc_replay and getattr(slc_settings, 'wheel_override', False) and host_long_active and can_rcv_valid and
|
||||
not self.CP.pcmCruise and pending is None and (cruise_helper.slc_wheel_press is not None or len(CS.buttonEvents) > 0) and
|
||||
not (CS.brakePressed or CS.gasPressed or CS.standstill or CS.cruiseState.standstill)):
|
||||
wheel_context = slc_physical.wheel_override_context(self.sm, now_ns, after_ns=floor_ns,
|
||||
selected_kph=cruise_helper.v_cruise_kph, is_metric=self.is_metric)
|
||||
self.update_cruise_speed(CS, pending, wheel_context=wheel_context)
|
||||
if self.controller_cruise_sock is not None:
|
||||
for _ in range(8):
|
||||
request = messaging.recv_one_or_none(self.controller_cruise_sock)
|
||||
@@ -788,9 +796,10 @@ class Car:
|
||||
|
||||
return CS, RD
|
||||
|
||||
def update_cruise_speed(self, CS, pending=None):
|
||||
def update_cruise_speed(self, CS, pending=None, *, wheel_context: SlcWheelContext | None = None):
|
||||
self.v_cruise_helper.update_v_cruise(CS, self.sm['carControl'].enabled, self.is_metric, pending,
|
||||
slc_enabled=getattr(self, 'slc_control_enabled', getattr(self, 'slc_replay', False)))
|
||||
slc_enabled=getattr(self, 'slc_control_enabled', getattr(self, 'slc_replay', False)),
|
||||
wheel_context=wheel_context)
|
||||
if self.sm['carControl'].enabled and not self.CC_prev.enabled:
|
||||
target, initial = None, None
|
||||
now_ns = int(self.can_log_mono_time) if REPLAY and hasattr(self, 'can_log_mono_time') else time.monotonic_ns()
|
||||
@@ -1123,6 +1132,8 @@ class Car:
|
||||
if kind == 'driverChange':
|
||||
assert isinstance(detail, tuple) and len(detail) == 4
|
||||
record.button, record.longPress = detail[2], detail[3]
|
||||
if self.v_cruise_helper.slc_wheel_tap is not None:
|
||||
record.sessionId, record.wheelOverrideSince = self.v_cruise_helper.slc_wheel_tap
|
||||
elif kind in ('confirmationAccept', 'confirmationReject'):
|
||||
record.button = detail.button
|
||||
record.sessionId = detail.pending.session_id
|
||||
|
||||
@@ -43,6 +43,9 @@ class SlcConsumedButton:
|
||||
button: str
|
||||
|
||||
|
||||
SlcWheelContext = tuple[str, int]
|
||||
|
||||
|
||||
def validated_initial_cruise_speed(value: object) -> int:
|
||||
if type(value) is int and V_CRUISE_INITIAL <= value <= V_CRUISE_MAX:
|
||||
return value
|
||||
@@ -70,18 +73,22 @@ class VCruiseHelper:
|
||||
self.slc_consumed_button: SlcConsumedButton | None = None
|
||||
self.slc_suppressed_buttons: set[ButtonType] = set()
|
||||
self.slc_released_suppressed = False
|
||||
self.slc_wheel_press: SlcWheelContext | None = None
|
||||
self.slc_wheel_tap: SlcWheelContext | None = None
|
||||
|
||||
@property
|
||||
def v_cruise_initialized(self):
|
||||
return self.v_cruise_kph != V_CRUISE_UNSET
|
||||
|
||||
def update_v_cruise(self, CS, enabled, is_metric, slc_pending: SlcPendingConfirmation | None = None, *, slc_enabled: bool = False):
|
||||
def update_v_cruise(self, CS, enabled, is_metric, slc_pending: SlcPendingConfirmation | None = None, *,
|
||||
slc_enabled: bool = False, wheel_context: SlcWheelContext | None = None):
|
||||
from opendbc.car.subaru.software_cruise import selected as subaru_software_selected
|
||||
subaru_software = subaru_software_selected(self.CP)
|
||||
software_cruise = not self.CP.pcmCruise or subaru_software
|
||||
self.slc_cruise_change = None
|
||||
self.slc_consumed_button = None
|
||||
self.slc_released_suppressed = False
|
||||
self.slc_wheel_tap = None
|
||||
self.v_cruise_kph_last = self.v_cruise_kph
|
||||
now_ns = monotonic_ns()
|
||||
if not CS.cruiseState.available or now_ns - self.pending_resume_ns > 500_000_000:
|
||||
@@ -97,6 +104,16 @@ class VCruiseHelper:
|
||||
if software_cruise or slc_enabled and self.CP.openpilotLongitudinalControl or self.slc_suppressed_buttons:
|
||||
self._update_slc_button_latches(CS, enabled, slc_pending)
|
||||
|
||||
if (not slc_enabled or not enabled or self.CP.pcmCruise or slc_pending is not None or
|
||||
not CS.cruiseState.available or ButtonType.accelCruise in self.slc_suppressed_buttons):
|
||||
wheel_context = None
|
||||
if wheel_context != self.slc_wheel_press:
|
||||
self.slc_wheel_press = None
|
||||
if wheel_context is not None and self.button_timers[ButtonType.accelCruise] == 0:
|
||||
pressed = {b.type.raw for b in CS.buttonEvents if b.pressed}
|
||||
if ButtonType.accelCruise in pressed and ButtonType.resumeCruise not in pressed:
|
||||
self.slc_wheel_press = wheel_context
|
||||
|
||||
if CS.cruiseState.available:
|
||||
if software_cruise:
|
||||
if subaru_software and (not enabled or not self.v_cruise_initialized):
|
||||
@@ -122,6 +139,8 @@ class VCruiseHelper:
|
||||
self.pcm_slc_button = ButtonType.unknown
|
||||
if software_cruise:
|
||||
self.update_button_timers(CS, enabled)
|
||||
if self.button_timers[ButtonType.accelCruise] == 0:
|
||||
self.slc_wheel_press = None
|
||||
|
||||
def _update_toyota_pcm_slc_change(self, CS, enabled: bool, now_ns: int) -> None:
|
||||
"""Observe a physical PCM speed change without writing stock selected speed."""
|
||||
@@ -211,7 +230,9 @@ class VCruiseHelper:
|
||||
if not self.button_change_states[button_type]["enabled"]:
|
||||
return
|
||||
|
||||
self.adjust_v_cruise(button_type, CS, is_metric, long_press=long_press)
|
||||
changed = self.adjust_v_cruise(button_type, CS, is_metric, long_press=long_press)
|
||||
if changed and button_type == ButtonType.accelCruise and not long_press and self.button_timers[button_type] > 0:
|
||||
self.slc_wheel_tap = self.slc_wheel_press
|
||||
|
||||
def adjust_v_cruise(self, button_type, CS, is_metric: bool, *, long_press: bool = False) -> bool:
|
||||
"""Apply the normal software cruise step without synthesizing button events."""
|
||||
|
||||
@@ -124,6 +124,12 @@ def confirm_curve_frame(host: CurveHost | None, planner: LongitudinalPlanner, no
|
||||
host.runtime.confirm_applied(now_ns, applied=bool(planner.last_curve_ceiling_applied))
|
||||
|
||||
|
||||
def wheel_override_blocked(force_stop: ForceStopRuntime | None, curve_host: CurveHost | None, *, curve_backlog: bool = False) -> bool:
|
||||
# Force Stop can consume RES on the tick it commits, before a forcing plan is published.
|
||||
return ((force_stop is not None and (force_stop.policy.can_commit_next_frame or force_stop.plan.speed_ceiling_mps is not None)) or
|
||||
(curve_host is not None and (curve_backlog or curve_host.runtime.was_controlling)))
|
||||
|
||||
|
||||
def conditional_handoff_for_frame(host: ConditionalPlannerHost | None, sm, CP, now_ns: int,
|
||||
drive_id: int) -> ConditionalHandoff | None:
|
||||
if host is None or not CP.openpilotLongitudinalControl or CP.passive or CP.dashcamOnly:
|
||||
@@ -444,7 +450,10 @@ def starpilot_main():
|
||||
else:
|
||||
wheel_coast.receive(event, params, CP, sm, now_ns=now_ns)
|
||||
pending_wheel = waiting_wheel
|
||||
slc_output = slc_lifecycle.step(sm, now_ns, pending_slc_actions, pending_slc_cruise, drive_changed=drive_changed)
|
||||
# Curve observes the press before SLC sees the release. A queued Curve press can still own the tap.
|
||||
curve_event = current_cruise_event(pending_curve_events, now_ns)
|
||||
slc_output = slc_lifecycle.step(sm, now_ns, pending_slc_actions, pending_slc_cruise, drive_changed=drive_changed,
|
||||
wheel_override_blocked=wheel_override_blocked(force_stop_owner, curve_host, curve_backlog=bool(pending_curve_events)))
|
||||
cruise_ceiling = slc_output.result.ceiling if slc_output is not None else None
|
||||
if slc_output is not None:
|
||||
planner_status = slc_output.message
|
||||
@@ -507,7 +516,6 @@ def starpilot_main():
|
||||
lead_approach_key = lead_approach_for_frame(approach_preferences, sm, CP, now_ns)
|
||||
if curve_preferences is not None and curve_host is not None:
|
||||
curve_preferences.refresh(curve_host, now_ns)
|
||||
curve_event = current_cruise_event(pending_curve_events, now_ns)
|
||||
conditional_handoff = (conditional_handoff_for_frame(conditional_host, sm, CP, clock_pair[0], current_start_ns)
|
||||
if clock_pair is not None else None)
|
||||
wheel_coast.conditional_stop = bool(conditional_handoff is not None and conditional_host is not None and
|
||||
@@ -586,6 +594,8 @@ def starpilot_main():
|
||||
mode_owner.sample('switchback', sm, CP, now_ns=now_ns), session=mode_session,
|
||||
sequence=mode_sequence, now_ns=now_ns, source_car_control_ns=int(sm.logMonoTime['carControl']))
|
||||
if planner_status is not None:
|
||||
if planner_status.slcState.wheelOverrideSince and wheel_override_blocked(force_stop_owner, curve_host):
|
||||
planner_status.slcState.wheelOverrideSince = 0
|
||||
pm.send('slcState', planner_status)
|
||||
if current_start_ns > 0:
|
||||
drive_start_ns = current_start_ns
|
||||
|
||||
@@ -63,7 +63,9 @@ DESCRIPTIONS = {
|
||||
'curve_reset': 'Deletes saved cornering learning so Curve Speed Controller can learn your preferences again.',
|
||||
'SpeedLimitController': 'Follows accepted limits plus offsets up to SET speed. Missing data uses the previous accepted limit.',
|
||||
'SLCOnEngage': 'Starts software cruise SET at the SLC limit plus offset, including a saved limit when live data is missing. RES restores the previous SET.',
|
||||
'SLCOverrideMode': 'Chooses whether pressing the gas past the adjusted speed limit holds the speed you reach, uses SET, or leaves the limit in control.',
|
||||
'SLCOverrideMode': ('Cruise uses this target when you lift off the accelerator. ' +
|
||||
'Holding your speed uses the highest speed you reached, up to SET.'),
|
||||
'SLCWheelOverride': 'Press + to raise SET past the adjusted limit and use your new SET speed.',
|
||||
'ShowSpeedLimits': 'Shows recognized speed-limit signs on the driving screen.',
|
||||
'SLCConfirmation': ('Off adopts new limits automatically. Both, Higher only, and Lower only prompt relative to the last accepted limit. ' +
|
||||
'+ accepts and − declines within 30 seconds.'),
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
"SLCPriority1",
|
||||
"SLCPriority2",
|
||||
"SLCPriority3",
|
||||
"SLCWheelOverride",
|
||||
"ScreenBrightness",
|
||||
"ScreenBrightnessOnroad",
|
||||
"ScreenTimeout",
|
||||
|
||||
@@ -7,6 +7,8 @@ from openpilot.common.realtime import DT_MDL
|
||||
|
||||
STANDSTILL_HOLD_NS = 2_000_000_000
|
||||
STANDSTILL_CLEAR_NS = 750_000_000
|
||||
STOP_COMMIT_TIME_S = .5
|
||||
SIGN_CONFIRM_STEP_S = 2 * DT_MDL
|
||||
SIGN_MAX_SPEED_MPS = 17.88
|
||||
SIGN_MODEL_AGREE_M = 50.0
|
||||
SIGN_SEED_M = 27.0
|
||||
@@ -102,6 +104,10 @@ class ForceStop:
|
||||
self.standstill_clear_ns = 0
|
||||
self.standstill_reason = None
|
||||
|
||||
@property
|
||||
def can_commit_next_frame(self) -> bool:
|
||||
return self.timer + SIGN_CONFIRM_STEP_S >= STOP_COMMIT_TIME_S
|
||||
|
||||
def step(self, frame: StopFrame, tune: StopTune, offset_ft: int = 0) -> StopPlan:
|
||||
now = frame.model_ns
|
||||
if (type(now) is not int or now <= 0 or now <= self.last_model_ns or
|
||||
@@ -177,16 +183,16 @@ class ForceStop:
|
||||
if not available and not self.forcing:
|
||||
self.timer = 0
|
||||
elif active and not frame.standstill:
|
||||
self.timer = min(2.0, self.timer + DT_MDL * (2 if frame.sign else 1))
|
||||
self.timer = min(2.0, self.timer + (SIGN_CONFIRM_STEP_S if frame.sign else DT_MDL))
|
||||
elif turn and not self.forcing and not frame.standstill:
|
||||
self.timer = 0
|
||||
elif held:
|
||||
self.timer = max(self.timer, .5)
|
||||
self.timer = max(self.timer, STOP_COMMIT_TIME_S)
|
||||
elif self.forcing and frame.standstill and not frame.sign and not frame.light and not frame.raw_model_stopped:
|
||||
self.timer = 0
|
||||
else:
|
||||
self.timer = max(0, self.timer - DT_MDL * .25)
|
||||
force = self.timer >= .5 or self.forcing and not frame.standstill or held
|
||||
force = self.timer >= STOP_COMMIT_TIME_S or self.forcing and not frame.standstill or held
|
||||
light_cleared = (not held and self.forcing and self.from_light and not frame.standstill and
|
||||
available and not frame.light and not frame.sign and go_scene)
|
||||
low_speed_hold = (light_cleared and tune.low_speed_hold_mps is not None and self.entry_speed is not None and
|
||||
|
||||
@@ -7,11 +7,12 @@ from opendbc.car.honda.interface import CarInterface
|
||||
from opendbc.car.honda.values import CAR
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlanner
|
||||
from openpilot.selfdrive.controls.plannerd import update_curve_frame
|
||||
from openpilot.selfdrive.controls.plannerd import update_curve_frame, wheel_override_blocked
|
||||
from openpilot.starpilot.curve_speed.host import CurveHost
|
||||
from openpilot.starpilot.longitudinal.force_stop import StopPlan
|
||||
from openpilot.starpilot.longitudinal.force_stop import StopPlan, vehicle_tune
|
||||
from openpilot.starpilot.longitudinal.force_stop_runtime import ForceStopRuntime, dashboard_stop_sign
|
||||
from openpilot.starpilot.longitudinal.tests.test_cruise_ceiling import messages, snapshot
|
||||
from openpilot.starpilot.longitudinal.tests.test_force_stop import frame as stop_frame
|
||||
from openpilot.starpilot.longitudinal.tests.test_stop_resume import event as button_event
|
||||
|
||||
BASE = 100_000_000_000
|
||||
@@ -61,6 +62,31 @@ class ForceStopRuntimeTests(unittest.TestCase):
|
||||
self.assertTrue(output.forcing)
|
||||
return output
|
||||
|
||||
def test_wheel_priority_requires_a_stop_cap_or_possible_commit_next_frame(self):
|
||||
tune = vehicle_tune(str(self.cp.carFingerprint))
|
||||
sign = {'light': False, 'sign': True, 'horizon_m': 40.}
|
||||
self.owner.plan = self.owner.policy.step(stop_frame(0, **sign), tune)
|
||||
self.assertIsNone(self.owner.plan.speed_ceiling_mps)
|
||||
self.assertFalse(wheel_override_blocked(self.owner, None))
|
||||
self.owner.plan = self.owner.policy.step(stop_frame(1, light=False, resume_requested=True), tune)
|
||||
self.assertGreater(self.owner.policy.timer, 0.)
|
||||
self.assertEqual(self.owner.policy.override_until_ns, 0)
|
||||
self.assertFalse(wheel_override_blocked(self.owner, None))
|
||||
|
||||
self.owner.reset()
|
||||
for tick in range(4):
|
||||
self.owner.plan = self.owner.policy.step(stop_frame(tick, **sign), tune)
|
||||
self.assertIsNone(self.owner.plan.speed_ceiling_mps)
|
||||
self.assertTrue(wheel_override_blocked(self.owner, None))
|
||||
self.owner.policy.step(stop_frame(4, resume_requested=True, **sign), tune)
|
||||
self.assertGreater(self.owner.policy.override_until_ns, 0)
|
||||
|
||||
self.owner.reset()
|
||||
self.owner.plan = self.owner.policy.step(stop_frame(0), tune)
|
||||
self.assertFalse(self.owner.policy.can_commit_next_frame)
|
||||
self.assertIsNotNone(self.owner.plan.speed_ceiling_mps)
|
||||
self.assertTrue(wheel_override_blocked(self.owner, None))
|
||||
|
||||
def test_committed_stop_survives_valid_mode_settings_and_traffic_changes(self):
|
||||
import json
|
||||
from openpilot.starpilot.conditional_mode.policy import ModeChoice
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
# Driver inputs
|
||||
|
||||
Ordinary cruise +/- changes the driver's SET ceiling. It does not bypass SLC, create
|
||||
a persistent override, or cross out the sign. The causal ledger still distinguishes
|
||||
driver actions and consumed confirmations. SLC has no separate override reducer.
|
||||
|
||||
Normal accelerator handling belongs to the vehicle controls. SLC never raises or
|
||||
latches its target from pedal speed. Confirmation remains available while the
|
||||
driver is engaged, including when the native controls temporarily yield to the pedal.
|
||||
Ordinary cruise +/- changes the driver's SET ceiling. With **Override speed limit
|
||||
with +** enabled, a qualifying physical tap past the adjusted limit also lets cruise
|
||||
use SET. The accelerator override has its own policy. See [SET speed and accelerator](README.md#set-speed-and-accelerator).
|
||||
|
||||
Source loss uses the previous accepted limit plus the current offset, up to SET.
|
||||
That remembered limit survives re-engagement and restarts; applying it still needs
|
||||
|
||||
@@ -176,9 +176,8 @@ cap while renewing pending actions. Disabling SLC still clears that constraint.
|
||||
|
||||
## SET speed and accelerator
|
||||
|
||||
Ordinary cruise +/- changes the driver's maximum; it does not bypass SLC or cross
|
||||
out the sign. Confirmation presses remain consumed through hold and release and
|
||||
do not also apply a software cruise step. Native PCM button effects remain native;
|
||||
Cruise + and − change SET. Confirmation presses remain consumed through hold and
|
||||
release and do not also apply a software cruise step. Native PCM button effects remain native;
|
||||
StarPilot does not pretend it can suppress the vehicle's own SET adjustment.
|
||||
Native standstill RES takes precedence over confirmation.
|
||||
|
||||
@@ -188,16 +187,23 @@ Subaru software-cruise mode remains independent of SLC.
|
||||
The Volt conventional-cruise controller uses the fresh SLC cap beneath SET for its
|
||||
cruise-button speed boundary, with its existing physical-source and timing checks.
|
||||
|
||||
**Gas pedal override** defaults to **Hold Reached Speed**. Pressing the gas
|
||||
above the accepted limit plus offset lets cruise hold the fastest speed you reach,
|
||||
up to SET. **Use Set Speed** uses SET as the override target. **Off** returns
|
||||
to the accepted limit on release. The override clears when cruise disengages,
|
||||
**After an accelerator override** defaults to **Hold the speed you reached**. Pressing
|
||||
the gas above the accepted limit plus offset lets cruise hold the fastest speed you
|
||||
reach, up to SET. **Use your SET speed** targets SET. **Resume the adjusted limit**
|
||||
returns to the accepted limit plus offset on release. The override clears when cruise disengages,
|
||||
the adjusted limit catches up, or the driver explicitly accepts or adopts a limit.
|
||||
After an explicit choice, the current accelerator press cannot start another
|
||||
override. Releasing and pressing again can start one.
|
||||
SET and the accepted limit are separate from the override. Lead, curve and
|
||||
stopping constraints still apply.
|
||||
|
||||
**Override speed limit with +** defaults to Off and is available when StarPilot
|
||||
owns SET. A tap must move the displayed SET from at or below the adjusted limit
|
||||
to above it. Cruise then uses SET until it returns to the adjusted limit, a different
|
||||
limit is accepted, or engagement ends. A display-unit change or a stop while
|
||||
cruise stays engaged preserves an active override. Confirmation, Curve Speed and
|
||||
Force Stop take priority over this gesture.
|
||||
|
||||
The configured wheel action can explicitly adopt the displayed current limit. It
|
||||
updates SLC acceptance, not SET. The onroad screen adds no new control.
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ class Frame:
|
||||
pedal_override: PedalOverride = PedalOverride.OFF
|
||||
preview_reverted: bool = False
|
||||
confirmation_grace_ns: int = 0
|
||||
wheel_override_enabled: bool = False
|
||||
wheel_override_blocked: bool = False
|
||||
wheel_override_since_ns: int = 0
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -53,6 +56,8 @@ class State:
|
||||
reset_required: bool = False
|
||||
pedal_target_mps: float = 0.
|
||||
pedal_blocked_until_release: bool = False
|
||||
wheel_override_metric: bool | None = None
|
||||
wheel_override_since_ns: int = 0
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -86,7 +91,9 @@ def _state_valid(state: object) -> bool:
|
||||
return False
|
||||
return (type(state.session_id) is str and bool(state.session_id) and state.acceptance.session_id == state.session_id and
|
||||
_number(state.pedal_target_mps) and (state.last_now_ns is None or _integer(state.last_now_ns)) and
|
||||
type(state.reset_required) is bool and type(state.pedal_blocked_until_release) is bool)
|
||||
type(state.reset_required) is bool and type(state.pedal_blocked_until_release) is bool and
|
||||
(state.wheel_override_metric is None or type(state.wheel_override_metric) is bool) and
|
||||
_integer(state.wheel_override_since_ns))
|
||||
|
||||
|
||||
def _host_valid(host: object) -> bool:
|
||||
@@ -119,9 +126,11 @@ def step(state: State, frame: Frame) -> Result:
|
||||
not _host_valid(frame.host) or not acc.authority_is_valid(frame.authority) or
|
||||
not isinstance(frame.acceptance_policy, acc.Policy) or
|
||||
not isinstance(frame.pedal_override, PedalOverride) or
|
||||
not _integer(frame.wheel_override_since_ns) or
|
||||
any(type(value) is not bool for value in (frame.acceptance_policy.confirm_lower,
|
||||
frame.acceptance_policy.confirm_higher,
|
||||
frame.acceptance_policy.display_only)) or
|
||||
frame.acceptance_policy.display_only,
|
||||
frame.wheel_override_enabled, frame.wheel_override_blocked)) or
|
||||
not isinstance(frame.selected_kind, sd.DomainStatus) or not isinstance(frame.ego_pair, sd.SpeedPair) or
|
||||
(frame.is_metric is not None and type(frame.is_metric) is not bool)):
|
||||
return Result(replace(state, reset_required=True), status="invalid_frame", errors=("invalid frame or clock",))
|
||||
@@ -136,7 +145,7 @@ def step(state: State, frame: Frame) -> Result:
|
||||
engaged_path = (frame.authority.can_control and (host_long or frame.authority.accelerator_override) and
|
||||
selected_initialized and not frame.acceptance_policy.display_only)
|
||||
active_path = engaged_path and not host.force_decel
|
||||
base = replace(state, last_now_ns=frame.now_ns, pedal_target_mps=0.)
|
||||
base = replace(state, last_now_ns=frame.now_ns, pedal_target_mps=0., wheel_override_metric=None, wheel_override_since_ns=0)
|
||||
|
||||
if frame.classified_cruise is not None:
|
||||
classified = frame.classified_cruise
|
||||
@@ -185,6 +194,8 @@ def step(state: State, frame: Frame) -> Result:
|
||||
return Result(replace(base, reset_required=True), selected, acceptance, domain,
|
||||
status="invalid_domain", errors=(domain.reason,))
|
||||
clear_override = frame.preview_reverted or acceptance.basis in ('driver_accept', 'driver_adopt')
|
||||
clear_wheel = clear_override or state.acceptance.accepted != acceptance.state.accepted
|
||||
wheel_metric = state.wheel_override_metric if frame.wheel_override_enabled and not clear_wheel else None
|
||||
previous = 0. if clear_override else state.pedal_target_mps
|
||||
pedal_blocked = (state.pedal_blocked_until_release or clear_override) and (
|
||||
frame.pedal_pressed is not False or ego.status is not sd.DomainStatus.VALID)
|
||||
@@ -193,17 +204,39 @@ def step(state: State, frame: Frame) -> Result:
|
||||
# Longitudinal output can resume one frame after the driver releases the pedal.
|
||||
if (system_mode and host.selfdrive_enabled and not engaged_path and selected_initialized and
|
||||
not (host.force_decel or frame.acceptance_policy.display_only) and
|
||||
frame.pedal_override is not PedalOverride.OFF and ego.status is sd.DomainStatus.VALID and pair.status is sd.DomainStatus.VALID):
|
||||
base = replace(base, pedal_target_mps=previous)
|
||||
ego.status is sd.DomainStatus.VALID and pair.status is sd.DomainStatus.VALID):
|
||||
base = replace(base, pedal_target_mps=previous if frame.pedal_override is not PedalOverride.OFF else 0.,
|
||||
wheel_override_metric=wheel_metric)
|
||||
return Result(base, selected, acceptance, domain, status='inactive_or_unavailable')
|
||||
context = domain.context
|
||||
assert context is not None
|
||||
selected_cluster = context.selected_raw_mps + context.selected_delta_mps
|
||||
if frame.wheel_override_enabled and frame.is_metric is not None:
|
||||
since = 0 if clear_wheel else state.wheel_override_since_ns
|
||||
pending = acceptance.state.pending
|
||||
ready = (host_long and not frame.pedal_pressed and not frame.wheel_override_blocked and
|
||||
(pending is None or pending.automatic))
|
||||
adjusted_limit = context.effective_cluster_mps
|
||||
change = frame.classified_cruise.change if frame.classified_cruise is not None else None
|
||||
# A tap belongs to the eligibility interval at button-down, even if SET changes later.
|
||||
if (wheel_metric is None and ready and since > 0 and frame.wheel_override_since_ns == since and change is not None and
|
||||
change.disposition is arb.Disposition.DRIVER_INTENT and change.previous_mps is not None and
|
||||
not sd.set_above_limit(change.previous_mps, adjusted_limit, frame.is_metric)):
|
||||
wheel_metric = frame.is_metric
|
||||
# A display-unit edit can round two different speeds to the same number.
|
||||
if wheel_metric is not None and not sd.set_above_limit(selected_cluster, adjusted_limit, wheel_metric):
|
||||
wheel_metric = None
|
||||
base = replace(base, wheel_override_metric=wheel_metric,
|
||||
wheel_override_since_ns=(since or frame.now_ns) if ready else 0)
|
||||
if wheel_metric is not None:
|
||||
coordinate = sd.PlannerCoordinate(None, 'wheel', selected_cluster, context.ego_delta_mps)
|
||||
return Result(base, selected, acceptance, domain, coordinate, status=acceptance.basis)
|
||||
|
||||
pedal_target = 0.
|
||||
if frame.pedal_override is not PedalOverride.OFF:
|
||||
ego_cluster = context.ego_raw_mps + context.ego_delta_mps
|
||||
gas_above_limit = not pedal_blocked and frame.authority.accelerator_override and ego_cluster > context.effective_cluster_mps
|
||||
if gas_above_limit or previous > context.effective_cluster_mps:
|
||||
selected_cluster = context.selected_raw_mps + context.selected_delta_mps
|
||||
pedal_target = (selected_cluster if frame.pedal_override is PedalOverride.SET_SPEED else
|
||||
min(selected_cluster, max(previous, ego_cluster if gas_above_limit else 0.)))
|
||||
if pedal_target <= context.effective_cluster_mps:
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
import math
|
||||
|
||||
from openpilot.cereal.services import SERVICE_LIST
|
||||
from openpilot.selfdrive.car.cruise import SlcPendingConfirmation, V_CRUISE_MIN, V_CRUISE_MAX
|
||||
from openpilot.selfdrive.car.cruise import SlcPendingConfirmation, SlcWheelContext, V_CRUISE_MIN, V_CRUISE_MAX
|
||||
from openpilot.starpilot.speed_limits.acceptance import CONFIRMATION_NS
|
||||
from openpilot.starpilot.speed_limits.selection import Source
|
||||
from openpilot.starpilot.speed_limits.speed_domain import set_above_limit
|
||||
|
||||
|
||||
STATE_MAX_AGE_NS = int(2e9 / SERVICE_LIST['slcState'].frequency)
|
||||
@@ -67,6 +68,17 @@ def active_ceiling(sm, now_ns: int, *, after_ns: int = 0) -> float | None:
|
||||
return cap if finite_speed(cap) and cap <= V_CRUISE_MAX / 3.6 + 1e-5 else None
|
||||
|
||||
|
||||
def wheel_override_context(sm, now_ns: int, *, selected_kph: float, is_metric: bool,
|
||||
after_ns: int = 0) -> SlcWheelContext | None:
|
||||
state = _state(sm, now_ns)
|
||||
if (state is None or int(state.frameMonoTime) <= after_ns or not state.hasAcceptedAdjustedLimit or
|
||||
not finite_speed(state.acceptedAdjustedLimit) or not V_CRUISE_MIN <= selected_kph <= V_CRUISE_MAX or
|
||||
set_above_limit(selected_kph / 3.6, float(state.acceptedAdjustedLimit), is_metric)):
|
||||
return None
|
||||
since = int(state.wheelOverrideSince)
|
||||
return (str(state.sessionId), since) if 0 < since <= int(state.frameMonoTime) else None
|
||||
|
||||
|
||||
def engagement_state(sm, observation, producer_session: str, now_ns: int, *, after_ns: int = 0):
|
||||
state = _current_state(sm, now_ns)
|
||||
if (state is None or int(state.frameMonoTime) <= after_ns or int(state.presentationId) <= 0 or
|
||||
|
||||
@@ -69,6 +69,8 @@ class SavedSlcLifecycle:
|
||||
if (settings.advance_higher_seconds != self.runtime.settings.advance_higher_seconds or
|
||||
settings.advance_lower_seconds != self.runtime.settings.advance_lower_seconds):
|
||||
self.runtime.update_advance(settings.advance_higher_seconds, settings.advance_lower_seconds)
|
||||
if settings.wheel_override != self.runtime.settings.wheel_override:
|
||||
self.runtime.state = replace(self.runtime.state, wheel_override_metric=None, wheel_override_since_ns=0)
|
||||
self.runtime.settings = settings
|
||||
self.runtime.vision_enabled = vision
|
||||
self.runtime.vision_control_qualified = vision and configuration[3]
|
||||
@@ -90,7 +92,7 @@ class SavedSlcLifecycle:
|
||||
pending_cruise.clear()
|
||||
return self.runtime, True
|
||||
|
||||
def step(self, sm, now_ns, pending_actions, pending_cruise, *, drive_changed):
|
||||
def step(self, sm, now_ns, pending_actions, pending_cruise, *, drive_changed, wheel_override_blocked=False):
|
||||
runtime = self.runtime
|
||||
if runtime is None:
|
||||
return None
|
||||
@@ -105,7 +107,7 @@ class SavedSlcLifecycle:
|
||||
pending_actions[0][0] <= now_ns else None)
|
||||
previous_accepted = runtime.history_limit
|
||||
output = runtime.step(sm, self.cp, now_ns=now_ns, request=request, cruise_event=cruise_event,
|
||||
confirmation_grace_ns=ACTION_MAX_AGE_NS)
|
||||
confirmation_grace_ns=ACTION_MAX_AGE_NS, wheel_override_blocked=wheel_override_blocked)
|
||||
accepted = runtime.history_limit
|
||||
if accepted != previous_accepted:
|
||||
self.params.put("SLCQualifiedHistory", json.loads(history.encode(accepted, time.time_ns())) if accepted is not None else {})
|
||||
@@ -125,7 +127,7 @@ def cruise_event_from_message(event):
|
||||
return CruiseEvent(int(cruise.eventId), int(cruise.observedMonoTime), float(cruise.previousMps),
|
||||
float(cruise.selectedMps), str(cruise.button), str(cruise.producerSessionId),
|
||||
int(event.logMonoTime), str(cruise.kind), str(cruise.sessionId), int(cruise.decisionId),
|
||||
int(cruise.presentationId), int(cruise.commandId))
|
||||
int(cruise.presentationId), int(cruise.commandId), int(cruise.wheelOverrideSince), bool(cruise.longPress))
|
||||
|
||||
|
||||
def action_from_message(event):
|
||||
|
||||
@@ -6,6 +6,7 @@ from dataclasses import dataclass, replace
|
||||
|
||||
import openpilot.cereal.messaging as messaging
|
||||
from openpilot.cereal.services import SERVICE_LIST
|
||||
from openpilot.selfdrive.car.cruise import V_CRUISE_MIN, V_CRUISE_MAX
|
||||
from openpilot.starpilot.aol.runtime import current_axis
|
||||
from openpilot.starpilot.speed_limits import acceptance as acc
|
||||
from openpilot.starpilot.speed_limits import action_arbitration as arb
|
||||
@@ -100,6 +101,8 @@ class CruiseEvent:
|
||||
decision_id: int = 0
|
||||
presentation_id: int = 0
|
||||
command_id: int = 0
|
||||
wheel_override_since_ns: int = 0
|
||||
long_press: bool = False
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -175,7 +178,7 @@ class Runtime:
|
||||
acceptance = replace(self.state.acceptance, observation=acc.Observation(acc.ObservationKind.UNKNOWN),
|
||||
pending=None, presentation=None, timer_running=False)
|
||||
self.current_presentation = None
|
||||
self.state = replace(self.state, acceptance=acceptance)
|
||||
self.state = replace(self.state, acceptance=acceptance, wheel_override_since_ns=0)
|
||||
self._ui_receipt = None
|
||||
|
||||
def update_advance(self, higher_seconds: int, lower_seconds: int) -> None:
|
||||
@@ -327,7 +330,7 @@ class Runtime:
|
||||
return values
|
||||
|
||||
def _frame(self, sm, CP, now_ns: int, now_boot_ns: int | None, action: acc.DriverAction | None, adopt: acc.AdoptRequest | None,
|
||||
classified: arb.Result | None) -> comp.Frame:
|
||||
classified: arb.Result | None, *, wheel_override_blocked: bool) -> comp.Frame:
|
||||
car_fresh = _fresh(sm, "carState", now_ns) and not sm["carState"].canTimeout
|
||||
controls_fresh = _fresh(sm, "controlsState", now_ns)
|
||||
selfdrive_fresh = _fresh(sm, "selfdriveState", now_ns)
|
||||
@@ -353,11 +356,16 @@ class Runtime:
|
||||
host = comp.HostState(bool(CP.openpilotLongitudinalControl), host_long, bool(selfdrive.enabled and selfdrive_fresh),
|
||||
bool(controls.forceDecel) if controls_fresh else True, selected, selected_cluster)
|
||||
observations = self._observations(sm, CP, now_ns, now_boot_ns)
|
||||
wheel_enabled = (self.settings.wheel_override and not CP.pcmCruise and car_fresh and car_state.canValid and
|
||||
V_CRUISE_MIN <= selected <= V_CRUISE_MAX and selected_cluster == selected and
|
||||
not car_state.brakePressed)
|
||||
wheel_blocked = wheel_override_blocked or car_state.standstill or car_state.cruiseState.standstill
|
||||
frame = comp.Frame(now_ns, observations, self.settings.selection, authority,
|
||||
self.settings.acceptance, self.settings.offsets,
|
||||
sd.DomainStatus.VALID if car_fresh and selected_cluster is not None else sd.DomainStatus.STALE,
|
||||
ego, bool(car_state.gasPressed) if car_fresh else False, host, action=action, adopt=adopt,
|
||||
classified_cruise=classified, is_metric=self.is_metric, pedal_override=self.settings.pedal_override)
|
||||
classified_cruise=classified, is_metric=self.is_metric, pedal_override=self.settings.pedal_override,
|
||||
wheel_override_enabled=wheel_enabled, wheel_override_blocked=wheel_blocked)
|
||||
maps_selected = self._maps_selected
|
||||
encounter = self.advance.encounter
|
||||
if not maps_selected and encounter is None:
|
||||
@@ -432,7 +440,7 @@ class Runtime:
|
||||
return acc.DriverAction(self.session_id, action_id, request.decision_id, kind, request.observed_ns), None, action_id
|
||||
|
||||
def step(self, sm, CP, *, now_ns: int, now_boot_ns: int | None = None, request: Action | None = None,
|
||||
cruise_event: CruiseEvent | None = None, confirmation_grace_ns: int = 0) -> Output:
|
||||
cruise_event: CruiseEvent | None = None, confirmation_grace_ns: int = 0, wheel_override_blocked: bool = False) -> Output:
|
||||
classified = self._cruise(cruise_event, sm, now_ns) if request is None else None
|
||||
action, adopt, action_id = self._action(request, now_ns)
|
||||
if cruise_event is not None and request is None:
|
||||
@@ -444,8 +452,16 @@ class Runtime:
|
||||
adopt = replace(adopt, candidate=shown.candidate)
|
||||
self.state = replace(self.state, acceptance=replace(self.state.acceptance, presentation=shown, pending=None, timer_running=False,
|
||||
observation=acc.Observation(acc.ObservationKind.VALID, shown.candidate)))
|
||||
frame = replace(self._frame(sm, CP, now_ns, now_boot_ns, action, adopt, classified),
|
||||
confirmation_grace_ns=confirmation_grace_ns)
|
||||
wheel_since = 0
|
||||
if (classified is not None and cruise_event is not None and cruise_event.button == 'accel' and
|
||||
not cruise_event.long_press and cruise_event.selected_mps > cruise_event.previous_mps and
|
||||
abs(float(sm['carState'].vCruise) / 3.6 - cruise_event.selected_mps) <= 0.0001 and
|
||||
0 < cruise_event.wheel_override_since_ns <= cruise_event.observed_ns and cruise_event.session_id == self.session_id and
|
||||
_fresh(sm, 'slcDashboardObservation', now_ns) and
|
||||
cruise_event.producer_session == str(sm['slcDashboardObservation'].producerSessionId)):
|
||||
wheel_since = cruise_event.wheel_override_since_ns
|
||||
frame = self._frame(sm, CP, now_ns, now_boot_ns, action, adopt, classified, wheel_override_blocked=wheel_override_blocked)
|
||||
frame = replace(frame, confirmation_grace_ns=confirmation_grace_ns, wheel_override_since_ns=wheel_since)
|
||||
result = comp.step(self.state, frame)
|
||||
self.state = result.state
|
||||
self.advance.observe(result)
|
||||
@@ -541,8 +557,11 @@ class Runtime:
|
||||
state.decisionId = pending.decision_id
|
||||
state.automaticAdoptionPending = pending.automatic
|
||||
state.pendingSinceMonoTime = now_ns - pending.active_elapsed_ns
|
||||
state.driverOverrideActive = result.ceiling is not None and result.state.pedal_target_mps > 0.
|
||||
state.overrideBasis = ('pedal' if frame.pedal_pressed else 'persistent') if state.driverOverrideActive else 'none'
|
||||
wheel_active = result.coordinate is not None and result.coordinate.basis == 'wheel'
|
||||
state.wheelOverrideSince = result.state.wheel_override_since_ns if not result.errors else 0
|
||||
state.driverOverrideActive = wheel_active or result.ceiling is not None and result.state.pedal_target_mps > 0.
|
||||
state.overrideBasis = 'wheel' if wheel_active else (
|
||||
('pedal' if frame.pedal_pressed else 'persistent') if state.driverOverrideActive else 'none')
|
||||
shown = result.state.acceptance.presentation
|
||||
ego = frame.ego_pair
|
||||
ego_delta = (max(0.0, ego.cluster_mps - ego.raw_mps)
|
||||
|
||||
@@ -22,8 +22,9 @@ ADVANCE_SECONDS = range(11)
|
||||
ADVANCE_BYTES = tuple(str(seconds).encode() for seconds in ADVANCE_SECONDS)
|
||||
|
||||
PEDAL_OVERRIDE_KEY = 'SLCOverrideMode'
|
||||
PEDAL_OVERRIDE_CHOICES = ('Off', 'Hold Reached Speed', 'Use Set Speed')
|
||||
PEDAL_OVERRIDE_CHOICES = ('Resume the adjusted limit', 'Hold the speed you reached', 'Use your SET speed')
|
||||
PEDAL_OVERRIDE_BYTES = (b'0', b'1', b'2')
|
||||
WHEEL_OVERRIDE_KEY = 'SLCWheelOverride'
|
||||
|
||||
|
||||
class PedalOverride(IntEnum):
|
||||
@@ -45,6 +46,7 @@ class Settings:
|
||||
advance_higher_seconds: int = 0
|
||||
advance_lower_seconds: int = 0
|
||||
pedal_override: PedalOverride = PedalOverride.OFF
|
||||
wheel_override: bool = False
|
||||
|
||||
|
||||
def _bool(values: Mapping[str, object], key: str, default: bool = False) -> bool:
|
||||
@@ -95,7 +97,7 @@ def parse(values: Mapping[str, object]) -> Settings:
|
||||
pedal_override = PedalOverride.OFF.value
|
||||
return Settings(control, display, sel.SelectionPolicy(mode, slots, False), policy, offsets,
|
||||
requested=control, advance_higher_seconds=higher, advance_lower_seconds=lower,
|
||||
pedal_override=PedalOverride(pedal_override))
|
||||
pedal_override=PedalOverride(pedal_override), wheel_override=values.get(WHEEL_OVERRIDE_KEY) is True)
|
||||
except (ValueError, OverflowError) as error:
|
||||
return _disabled(str(error))
|
||||
|
||||
@@ -105,7 +107,7 @@ SAVED_KEYS = ("SpeedLimitController", "ShowSpeedLimits", "IsMetric", *SOURCE_PRI
|
||||
|
||||
|
||||
def read_params(params) -> Settings:
|
||||
values = {}
|
||||
values = {WHEEL_OVERRIDE_KEY: read_saved(params, WHEEL_OVERRIDE_KEY, 1) == (b'1', True)}
|
||||
raw_override, readable_override = read_saved(params, PEDAL_OVERRIDE_KEY, 1)
|
||||
if raw_override is not None or not readable_override:
|
||||
values[PEDAL_OVERRIDE_KEY] = int(raw_override) if readable_override and raw_override in PEDAL_OVERRIDE_BYTES else 0
|
||||
|
||||
@@ -5,6 +5,7 @@ import struct
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
|
||||
from openpilot.common.constants import CV
|
||||
from openpilot.selfdrive.car.cruise import V_CRUISE_MIN, V_CRUISE_MAX, slc_target_kph
|
||||
from openpilot.starpilot.speed_limits import acceptance as acc
|
||||
|
||||
@@ -165,6 +166,15 @@ def set_speed_matches(target_mps: float, raw_kph: float, cluster_kph: float | No
|
||||
math.isclose(target_kph, cluster_kph, rel_tol=0, abs_tol=0.001))
|
||||
|
||||
|
||||
def set_above_limit(selected_mps: float, adjusted_limit_mps: float, is_metric: bool) -> bool:
|
||||
# Use the sign's wire precision and restore software SET's 0.1 km/h after transport.
|
||||
limit_mps = struct.unpack('f', struct.pack('f', adjusted_limit_mps))[0]
|
||||
selected_kph = round(selected_mps * CV.MS_TO_KPH, 1)
|
||||
if is_metric:
|
||||
return round(selected_kph) > round(limit_mps * CV.MS_TO_KPH)
|
||||
return round(selected_kph * CV.KPH_TO_MPH) > round(limit_mps * CV.MS_TO_MPH)
|
||||
|
||||
|
||||
def resolve(decision: acc.Decision, schedule: OffsetSchedule, selected: SpeedPair, ego: SpeedPair) -> DomainResolution:
|
||||
"""Bind an explicit offset and contemporaneous speed pairs to an acceptance output."""
|
||||
if (not isinstance(decision, acc.Decision) or not isinstance(decision.state, acc.State) or decision.errors or
|
||||
|
||||
@@ -71,6 +71,147 @@ def test_cruise_adjustments_change_only_the_driver_ceiling(drive, selected):
|
||||
assert sm['carState'].vCruise == selected
|
||||
|
||||
|
||||
def wheel_crossing(drive, *, metric=True, enabled=True, previous_kph=90., selected_kph=91., offset=0.):
|
||||
sm, cp = drive
|
||||
cp.pcmCruise = False
|
||||
car_state = sm['carState']
|
||||
car_state.canValid = True
|
||||
car_state.vCruise = car_state.vCruiseCluster = previous_kph
|
||||
settings = replace(controller(offset).settings, wheel_override=enabled)
|
||||
runtime = Runtime(settings, is_metric=metric)
|
||||
first = tick(runtime, sm, cp, 0).message.slcState
|
||||
car_state.vCruise = car_state.vCruiseCluster = selected_kph
|
||||
event = CruiseEvent(1, START + 50_000_000, previous_kph / 3.6, selected_kph / 3.6, 'accel',
|
||||
'card-producer', START + 50_000_000, session_id=runtime.session_id,
|
||||
wheel_override_since_ns=first.wheelOverrideSince)
|
||||
return runtime, event
|
||||
|
||||
|
||||
@pytest.mark.parametrize('metric,previous_kph,selected_kph,limit,offset', [
|
||||
(True, 90., 91., 25., 0.),
|
||||
(True, 54.5, 55.5, 54. / 3.6, 0.),
|
||||
(False, 89., 90.6, 55. * CV.MPH_TO_MS, 0.),
|
||||
(False, 86.9, 88.5, 55. * CV.MPH_TO_MS, -.5 * CV.MPH_TO_MS),
|
||||
])
|
||||
def test_wheel_tap_crosses_displayed_limit_and_uses_native_set(drive, metric, previous_kph, selected_kph, limit, offset):
|
||||
from struct import pack, unpack
|
||||
sm, cp = drive
|
||||
sm['slcDashboardObservation'].speedMps = limit
|
||||
sm['carState'].vEgoCluster += 1.0
|
||||
runtime, event = wheel_crossing(drive, metric=metric, previous_kph=previous_kph, selected_kph=selected_kph, offset=offset)
|
||||
event = replace(event, previous_mps=unpack('f', pack('f', event.previous_mps))[0])
|
||||
assert event.wheel_override_since_ns == START
|
||||
# Card publishes carState before the event. The new SET can be sampled first.
|
||||
assert tick(runtime, sm, cp, 1).result.ceiling is not None
|
||||
crossed = tick(runtime, sm, cp, 2, cruise_event=event)
|
||||
status = crossed.message.slcState
|
||||
assert crossed.result.ceiling is None and status.driverOverrideActive and status.overrideBasis == 'wheel'
|
||||
assert status.effectiveClusterTarget == pytest.approx(selected_kph / 3.6)
|
||||
assert not status.isLimitingMaxSet
|
||||
planner = LongitudinalPlanner(cp)
|
||||
planner.update(sm, cruise_ceiling=crossed.result.ceiling)
|
||||
assert planner.last_cruise_ceiling_status == 'absent'
|
||||
|
||||
sm['carState'].vCruise = sm['carState'].vCruiseCluster = previous_kph
|
||||
lowered = tick(runtime, sm, cp, 3)
|
||||
assert lowered.result.ceiling is not None and not lowered.message.slcState.driverOverrideActive
|
||||
sm['carState'].vCruise = sm['carState'].vCruiseCluster = selected_kph
|
||||
assert not tick(runtime, sm, cp, 4, cruise_event=event).message.slcState.driverOverrideActive
|
||||
|
||||
|
||||
@pytest.mark.parametrize('scenario', ['off', 'already above', 'controller', 'hold', 'foreign producer', 'foreign session',
|
||||
'different SET', 'stop or curve', 'confirmation', 'new limit', 'disengaged', 'pcm',
|
||||
'standstill', 'units changed'])
|
||||
def test_wheel_override_requires_current_unconsumed_physical_crossing(drive, scenario):
|
||||
sm, cp = drive
|
||||
prior, selected = (100., 101.) if scenario == 'already above' else (90., 91.)
|
||||
runtime, event = wheel_crossing(drive, enabled=scenario != 'off', previous_kph=prior, selected_kph=selected)
|
||||
changes = {
|
||||
'controller': {'wheel_override_since_ns': 0},
|
||||
'hold': {'long_press': True},
|
||||
'foreign producer': {'producer_session': 'old-card'},
|
||||
'foreign session': {'session_id': 'old-slc'},
|
||||
'different SET': {'selected_mps': event.selected_mps - .05},
|
||||
}
|
||||
event = replace(event, **changes.get(scenario, {}))
|
||||
if scenario in ('confirmation', 'new limit'):
|
||||
sm['slcDashboardObservation'].speedMps = 23.
|
||||
if scenario == 'confirmation':
|
||||
runtime.settings = replace(runtime.settings, acceptance=acc.Policy(confirm_lower=True))
|
||||
if scenario == 'disengaged':
|
||||
sm['carControl'].enabled = sm['carControl'].longActive = sm['selfdriveState'].enabled = False
|
||||
if scenario == 'pcm':
|
||||
cp.pcmCruise = True
|
||||
if scenario == 'standstill':
|
||||
sm['carState'].standstill = True
|
||||
if scenario == 'units changed':
|
||||
runtime.update_offsets(runtime.settings.offsets, is_metric=False)
|
||||
output = tick(runtime, sm, cp, 1, cruise_event=event, wheel_override_blocked=scenario == 'stop or curve')
|
||||
assert not output.message.slcState.driverOverrideActive
|
||||
if scenario in ('stop or curve', 'standstill'):
|
||||
assert output.message.slcState.wheelOverrideSince == 0
|
||||
sm['carState'].standstill = False
|
||||
assert not tick(runtime, sm, cp, 2, cruise_event=replace(event, event_id=2)).message.slcState.driverOverrideActive
|
||||
|
||||
|
||||
@pytest.mark.parametrize('limit_kph', [51., 90.])
|
||||
def test_wheel_override_survives_units_change_until_set_returns_to_limit(drive, limit_kph):
|
||||
sm, cp = drive
|
||||
sm['slcDashboardObservation'].speedMps = limit_kph / 3.6
|
||||
runtime, event = wheel_crossing(drive, previous_kph=limit_kph, selected_kph=limit_kph + 1.)
|
||||
assert tick(runtime, sm, cp, 1, cruise_event=event).message.slcState.overrideBasis == 'wheel'
|
||||
|
||||
# At 51 km/h both speeds round to 32 mph, even though SET remains higher.
|
||||
runtime.update_offsets(runtime.settings.offsets, is_metric=False)
|
||||
changed = tick(runtime, sm, cp, 2)
|
||||
assert changed.result.ceiling is None
|
||||
assert changed.message.slcState.overrideBasis == 'wheel'
|
||||
assert changed.message.slcState.wheelOverrideSince != event.wheel_override_since_ns
|
||||
|
||||
sm['carState'].vCruise = sm['carState'].vCruiseCluster = limit_kph
|
||||
returned = tick(runtime, sm, cp, 3)
|
||||
assert returned.result.ceiling.speed_mps == pytest.approx(limit_kph / 3.6)
|
||||
assert not returned.message.slcState.driverOverrideActive
|
||||
|
||||
|
||||
@pytest.mark.parametrize('cruise_standstill', [False, True])
|
||||
def test_wheel_override_survives_engaged_stop(drive, cruise_standstill):
|
||||
sm, cp = drive
|
||||
runtime, event = wheel_crossing(drive)
|
||||
assert tick(runtime, sm, cp, 1, cruise_event=event).message.slcState.overrideBasis == 'wheel'
|
||||
|
||||
stopped = sm['carState'].cruiseState if cruise_standstill else sm['carState']
|
||||
stopped.standstill = True
|
||||
sm['carState'].vEgo = sm['carState'].vEgoCluster = 0.
|
||||
sm['controlsState'].longControlState = 'stopping'
|
||||
held = tick(runtime, sm, cp, 2)
|
||||
assert held.message.slcState.overrideBasis == 'wheel'
|
||||
assert held.message.slcState.wheelOverrideSince == 0
|
||||
|
||||
stopped.standstill = False
|
||||
sm['controlsState'].longControlState = 'pid'
|
||||
assert tick(runtime, sm, cp, 3).message.slcState.overrideBasis == 'wheel'
|
||||
|
||||
|
||||
def test_wheel_override_survives_gas_handoff_without_latching_pedal_speed(drive):
|
||||
sm, cp = drive
|
||||
runtime, event = wheel_crossing(drive)
|
||||
assert tick(runtime, sm, cp, 1, cruise_event=event).message.slcState.overrideBasis == 'wheel'
|
||||
sm['carState'].vEgo = sm['carState'].vEgoCluster = 91. / 3.6
|
||||
sm['carState'].gasPressed = True
|
||||
sm['carControl'].longActive = False
|
||||
sm['controlsState'].longControlState = 'off'
|
||||
assert tick(runtime, sm, cp, 2).result.state.pedal_target_mps == 0.
|
||||
sm['carState'].gasPressed = False
|
||||
assert tick(runtime, sm, cp, 3).result.state.wheel_override_metric is True
|
||||
sm['carControl'].longActive = True
|
||||
sm['controlsState'].longControlState = 'pid'
|
||||
assert tick(runtime, sm, cp, 4).message.slcState.overrideBasis == 'wheel'
|
||||
sm['slcDashboardObservation'].speedMps = 23.
|
||||
accepted = tick(runtime, sm, cp, 5)
|
||||
assert accepted.result.ceiling.speed_mps == 23. and not accepted.message.slcState.driverOverrideActive
|
||||
|
||||
|
||||
@pytest.mark.parametrize('missing', ['absent', 'unknown', 'stale'])
|
||||
def test_source_gap_uses_the_previous_limit_and_current_offset(drive, missing):
|
||||
sm, cp = drive
|
||||
|
||||
@@ -524,6 +524,68 @@ class RuntimeReplayTests(unittest.TestCase):
|
||||
self.assertEqual(result.message.slcState.actionStatus, outcome)
|
||||
|
||||
|
||||
def test_physical_wheel_override_receipt_through_card_and_planner_queue(self):
|
||||
from openpilot.cereal import messaging
|
||||
from openpilot.selfdrive.car import card
|
||||
from openpilot.selfdrive.controls.plannerd import current_cruise_event, queue_cruise_event, wheel_override_blocked
|
||||
from openpilot.starpilot.curve_speed.host import CurveHost
|
||||
|
||||
self.cp.pcmCruise = False
|
||||
self.sm['carState'].canValid = True
|
||||
self.sm['carState'].vCruise = self.sm['carState'].vCruiseCluster = 90.
|
||||
settings = parse({'SpeedLimitController': True, 'SLCPriority1': 'Dashboard', 'SLCWheelOverride': True})
|
||||
for curve_claims, curve_backlog in ((False, False), (True, False), (False, True)):
|
||||
with self.subTest(curve_claims=curve_claims, curve_backlog=curve_backlog):
|
||||
start = 2_000_000_000
|
||||
self.sm.advance(start)
|
||||
self.sm['carState'].vCruise = self.sm['carState'].vCruiseCluster = 90.
|
||||
runtime = Runtime(settings, is_metric=True)
|
||||
state = runtime.step(self.sm, self.cp, now_ns=start).message.slcState
|
||||
fake, current_cs = self._card_with_slc_state(state, None, start)
|
||||
fake.slc_configuration = fake.slc_requested_configuration = (True, settings)
|
||||
fake.v_cruise_helper.v_cruise_kph = fake.v_cruise_helper.v_cruise_cluster_kph = 90.
|
||||
fake.is_metric = True
|
||||
fake.curve_replay = True
|
||||
fake.car_params_published = True
|
||||
fake.sm.frame = 1
|
||||
fake.sm.all_checks = lambda services: True
|
||||
fake.last_actuators_output = car.CarControl.Actuators()
|
||||
fake.slc_cruise_event_id = 0
|
||||
fake.radar_publish = mock.Mock()
|
||||
fake.rk = SimpleNamespace(remaining=0.0)
|
||||
fake.aol_replay = False
|
||||
clock = [start + 10_000_000]
|
||||
|
||||
def can_batch(*args, clock=clock, **kwargs):
|
||||
return [messaging.new_message('can', size=0, logMonoTime=clock[0]).to_bytes()]
|
||||
|
||||
with (mock.patch.object(card, 'REPLAY', True),
|
||||
mock.patch.object(card.messaging, 'drain_sock_raw', side_effect=can_batch)):
|
||||
for pressed in (True, False):
|
||||
current_cs[0] = car.CarState(canValid=True, cruiseState={'available': True},
|
||||
buttonEvents=[car.CarState.ButtonEvent(type='accelCruise', pressed=pressed)])
|
||||
cs, radar = fake.state_update()
|
||||
fake.state_publish(cs, radar)
|
||||
clock[0] += 10_000_000
|
||||
fake.sm.logMonoTime['carControl'] = clock[0]
|
||||
slc_events, curve_events = deque(), deque()
|
||||
for call in fake.pm.send.call_args_list:
|
||||
name, message = call.args
|
||||
if name == 'slcCruiseEvent':
|
||||
queue_cruise_event(messaging.log_from_bytes(message.to_bytes()), slc_events, curve_events)
|
||||
self.assertEqual(len(curve_events), 1)
|
||||
self.assertEqual(len(slc_events), 1)
|
||||
self.assertEqual(cs.vCruise, 91.)
|
||||
self.sm['carState'].vCruise = self.sm['carState'].vCruiseCluster = cs.vCruise
|
||||
self.sm.advance(clock[0])
|
||||
event = current_cruise_event(slc_events, clock[0])
|
||||
self.assertEqual(event.wheel_override_since_ns, start)
|
||||
curve = CurveHost()
|
||||
curve.runtime.was_controlling = curve_claims
|
||||
output = runtime.step(self.sm, self.cp, now_ns=clock[0], cruise_event=event,
|
||||
wheel_override_blocked=wheel_override_blocked(None, curve, curve_backlog=curve_backlog))
|
||||
self.assertEqual(output.message.slcState.driverOverrideActive, not (curve_claims or curve_backlog))
|
||||
|
||||
def test_malformed_saved_priorities_disable_runtime_without_crashing(self):
|
||||
for key in ('SLCPriority1', 'SLCPriority2'):
|
||||
for malformed in ([], {}, 1, None):
|
||||
|
||||
@@ -151,6 +151,19 @@ class RuntimeSettingsTests(unittest.TestCase):
|
||||
self.assertFalse(settings.enabled)
|
||||
self.assertTrue(settings.errors)
|
||||
|
||||
def test_wheel_override_is_opt_in_and_bad_bytes_keep_slc_enabled(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
params = Params(directory)
|
||||
params.put_bool('SpeedLimitController', True, block=True)
|
||||
self.assertFalse(params.get_default_value('SLCWheelOverride'))
|
||||
self.assertFalse(read_params(params).wheel_override)
|
||||
params.put_bool('SLCWheelOverride', True, block=True)
|
||||
self.assertTrue(read_params(params).wheel_override)
|
||||
Path(params.get_param_path('SLCWheelOverride')).write_bytes(b'bad')
|
||||
settings = read_params(params)
|
||||
self.assertTrue(settings.enabled)
|
||||
self.assertFalse(settings.wheel_override)
|
||||
|
||||
def test_retired_offsets_are_unregistered_and_ignored_with_zero_defaults(self):
|
||||
for metric in (False, True):
|
||||
with self.subTest(metric=metric), tempfile.TemporaryDirectory() as directory:
|
||||
|
||||
@@ -39,7 +39,7 @@ from openpilot.starpilot.ui.feature_settings_state import (
|
||||
from openpilot.starpilot.speed_limits.offset_document import MPH_TO_MPS
|
||||
from openpilot.starpilot.speed_limits.runtime_settings import (
|
||||
ADVANCE_BYTES, ADVANCE_KEYS, CONFIRMATION_CHOICES,
|
||||
PEDAL_OVERRIDE_BYTES, PEDAL_OVERRIDE_CHOICES, PEDAL_OVERRIDE_KEY, SOURCE_PRIORITY_KEYS,
|
||||
PEDAL_OVERRIDE_BYTES, PEDAL_OVERRIDE_CHOICES, PEDAL_OVERRIDE_KEY, SOURCE_PRIORITY_KEYS, WHEEL_OVERRIDE_KEY, PedalOverride,
|
||||
)
|
||||
from openpilot.starpilot.aol.vehicle import policy_for as aol_policy_for
|
||||
from openpilot.starpilot.feature_capabilities import longitudinal_supported as feature_longitudinal_supported
|
||||
@@ -92,6 +92,7 @@ BOOL_DEFAULTS = {
|
||||
"RemapCancelToDistance": False, "LongPitch": True, "DisableOpenpilotLongitudinal": False,
|
||||
"SpeedLimitController": False, "ShowSpeedLimits": True,
|
||||
"SLCOnEngage": False,
|
||||
WHEEL_OVERRIDE_KEY: False,
|
||||
"PauseLateralOnSignal": False,
|
||||
"LaneCentering": True, "LaneCenteringPauseOnSignal": True,
|
||||
"CustomPersonalities": False, PLANNER_SELECTION_KEY: True,
|
||||
@@ -1129,6 +1130,9 @@ class FeatureSettingsOwner:
|
||||
rows.append(self._bool_row("ShowSpeedLimits", "Show speed limit signs", self.authority("preferences"),
|
||||
reason="Display signs independently of Speed Limit Controller; does not change cruise speed"))
|
||||
rows.extend(policy_rows(self._value, self._readable, allowed=allowed))
|
||||
if cp is not None and not cp.pcmCruise:
|
||||
rows.append(self._bool_row(WHEEL_OVERRIDE_KEY, "Override speed limit with +", allowed and control == "1",
|
||||
reason="Press + to raise SET past the adjusted limit and use your new SET speed."))
|
||||
source_capability = self._source_capability()
|
||||
vision_dev, maps_available = source_capability
|
||||
source_allowed = configurable and self.authority("preferences")
|
||||
@@ -1633,7 +1637,7 @@ class FeatureSettingsOwner:
|
||||
encoded = str(SLC_ADVANCE_CHOICES.index(request.value))
|
||||
elif key == PEDAL_OVERRIDE_KEY:
|
||||
if request.value not in PEDAL_OVERRIDE_CHOICES or (
|
||||
request.value != 'Off' and request.expected not in (None, *PEDAL_OVERRIDE_BYTES)):
|
||||
request.value != PEDAL_OVERRIDE_CHOICES[PedalOverride.OFF] and request.expected not in (None, *PEDAL_OVERRIDE_BYTES)):
|
||||
return False
|
||||
encoded = PEDAL_OVERRIDE_CHOICES.index(request.value)
|
||||
elif key in BOOL_DEFAULTS:
|
||||
@@ -1642,7 +1646,7 @@ class FeatureSettingsOwner:
|
||||
return False
|
||||
if key == "SpeedLimitController" and request.value == "On" and not self.slc_offsets.ready_to_enable():
|
||||
return False
|
||||
if key == "SLCOnEngage":
|
||||
if key in ("SLCOnEngage", WHEEL_OVERRIDE_KEY):
|
||||
cp = self.vehicle_params()
|
||||
if cp is None or cp.pcmCruise or not self.longitudinal_available() or (
|
||||
request.value == "On" and self._raw("SpeedLimitController") != b"1"):
|
||||
|
||||
@@ -26,12 +26,13 @@ def policy_rows(read_value, readable, *, allowed):
|
||||
reason=f'Offer or adopt {direction} mapped limits this many seconds early at the current speed'
|
||||
if valid_advance else 'Invalid saved advance time; restore Off'))
|
||||
_, raw_override, readable_override = read_value(PEDAL_OVERRIDE_KEY)
|
||||
resume_limit = PEDAL_OVERRIDE_CHOICES[PedalOverride.OFF]
|
||||
default_override = PEDAL_OVERRIDE_CHOICES[PedalOverride.SPEED_REACHED]
|
||||
valid_override = readable_override and (raw_override is None or raw_override in PEDAL_OVERRIDE_BYTES)
|
||||
rows.append(FeatureRow(PEDAL_OVERRIDE_KEY, 'Gas pedal override',
|
||||
rows.append(FeatureRow(PEDAL_OVERRIDE_KEY, 'After an accelerator override',
|
||||
default_override if raw_override is None else PEDAL_OVERRIDE_CHOICES[int(raw_override)] if valid_override else 'Invalid',
|
||||
raw_override, PEDAL_OVERRIDE_CHOICES if valid_override else ('Off',),
|
||||
raw_override, PEDAL_OVERRIDE_CHOICES if valid_override else (resume_limit,),
|
||||
available=allowed and readable(PEDAL_OVERRIDE_KEY), default_value=default_override,
|
||||
repair_value='' if valid_override else 'Off',
|
||||
reason='Choose what cruise holds after you press the gas past the adjusted speed limit'))
|
||||
repair_value='' if valid_override else resume_limit,
|
||||
reason='Cruise uses this target when you lift off the accelerator. Held speed stays at or below SET.'))
|
||||
return rows
|
||||
|
||||
@@ -586,15 +586,41 @@ class FeatureSettingsOwnerTests(unittest.TestCase):
|
||||
|
||||
def test_gas_pedal_override_uses_the_shared_slc_settings_owner(self):
|
||||
row = self._row('slc', 'SLCOverrideMode')
|
||||
self.assertEqual(row.value, 'Hold Reached Speed')
|
||||
self.assertEqual(row.choices, ('Off', 'Hold Reached Speed', 'Use Set Speed'))
|
||||
request = required_change(row)
|
||||
choices = ('Resume the adjusted limit', 'Hold the speed you reached', 'Use your SET speed')
|
||||
self.assertEqual((row.label, row.value), ('After an accelerator override', choices[1]))
|
||||
self.assertEqual(row.choices, choices)
|
||||
self.allowed = False
|
||||
self.assertFalse(self.owner.apply(request))
|
||||
self.assertFalse(self.owner.apply(required_change(row)))
|
||||
self.allowed = True
|
||||
for mode in (2, 0, 1):
|
||||
self.assertTrue(self.owner.apply(required_change(row)))
|
||||
self.assertEqual(self.params.get('SLCOverrideMode'), mode)
|
||||
row = self._row('slc', 'SLCOverrideMode')
|
||||
self.assertEqual(row.value, choices[mode])
|
||||
|
||||
Path(self.params.get_param_path('SLCOverrideMode')).write_bytes(b'9')
|
||||
repair = required_change(self._row('slc', 'SLCOverrideMode'))
|
||||
self.assertEqual(repair.value, choices[0])
|
||||
self.assertFalse(self.owner.apply(replace(repair, value=choices[2])))
|
||||
self.assertTrue(self.owner.apply(repair))
|
||||
self.assertEqual(self.params.get('SLCOverrideMode'), 0)
|
||||
|
||||
def test_wheel_override_is_off_and_only_configurable_for_software_set(self):
|
||||
from opendbc.car.structs import car
|
||||
cp = car.CarParams(carFingerprint=self.fingerprint, openpilotLongitudinalControl=True, pcmCruise=False)
|
||||
self.owner.vehicle_params = lambda: cp
|
||||
self.params.put_bool('SpeedLimitController', True, block=True)
|
||||
row = self._row('slc', 'SLCWheelOverride')
|
||||
self.assertEqual((row.label, row.value, row.default_value), ('Override speed limit with +', 'Off', 'Off'))
|
||||
request = required_change(row)
|
||||
cp.pcmCruise = True
|
||||
self.assertFalse(self.owner.apply(request))
|
||||
cp.pcmCruise = False
|
||||
self.params.put_bool('SpeedLimitController', False, block=True)
|
||||
self.assertFalse(self.owner.apply(request))
|
||||
self.params.put_bool('SpeedLimitController', True, block=True)
|
||||
self.assertTrue(self.owner.apply(request))
|
||||
self.assertEqual(self.params.get('SLCOverrideMode'), 2)
|
||||
self.assertEqual(self._row('slc', 'SLCOverrideMode').value, 'Use Set Speed')
|
||||
self.assertTrue(self.params.get_bool('SLCWheelOverride'))
|
||||
|
||||
def test_limit_sign_preference_needs_parked_authority_not_long_control_or_vehicle(self):
|
||||
self.fingerprint = None
|
||||
|
||||
Reference in New Issue
Block a user