mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-07 13:03:42 +08:00
a82935f326
Integrate onroad views, configurable widgets, local settings, steering-profile contracts, Bluetooth and Android Auto with their device and runtime services. Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> Co-authored-by: Daniel Koepping <elkoled@gmail.com> Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com> Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com> Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: Shane Smiskol <shane@smiskol.com> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com> Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Co-authored-by: stef <19478336+stefpi@users.noreply.github.com> Co-authored-by: whoisdomi <dcantu83@gmail.com> Co-authored-by: Intelli <contact@intelli.software> Co-authored-by: pharmacomaniac <blittle65@gmail.com> Co-authored-by: prabhaavp <prabhaav@msu.edu>
101 lines
6.0 KiB
Python
101 lines
6.0 KiB
Python
from dataclasses import replace
|
|
from typing import Any
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
|
|
from openpilot.cereal import log, messaging
|
|
|
|
from openpilot.starpilot.conditional_mode.host import HostProposal
|
|
from openpilot.starpilot.conditional_mode.projection import ProjectedScene
|
|
from openpilot.starpilot.conditional_mode.policy import Authority, Decision, ModeChoice, Reason
|
|
from openpilot.starpilot.conditional_mode.status import StatusPublisher
|
|
from openpilot.starpilot.conditional_mode.runtime_settings import SettingsSnapshot, DocumentState, SafeModeState
|
|
from openpilot.starpilot.ui.conditional_status import ConditionalPerceptionProjector
|
|
from openpilot.starpilot.ui.onroad_conditional import reason, stop_active
|
|
from openpilot.starpilot.ui.onroad_state import OnroadState, SpeedLimitObservation
|
|
|
|
|
|
def changed_arguments(arguments: dict[str, Any], changes: dict[str, Any]) -> dict[str, Any]:
|
|
return arguments | changes
|
|
|
|
|
|
def test_aol_perception_is_not_longitudinal_authority():
|
|
now = 100_000_000_000
|
|
authority = Authority(True, True, False, False, False, True)
|
|
decision = Decision(True, False, True, True, Reason.CEM_STOP, 8)
|
|
settings = SettingsSnapshot("test", 1, now, now, DocumentState.ABSENT, SafeModeState.ABSENT_FALSE, None, None, None)
|
|
proposal = HostProposal(ModeChoice.CEM, Mock(spec=ProjectedScene, authority=authority), decision, None,
|
|
'inactive_axis', settings.revision)
|
|
publisher = StatusPublisher()
|
|
event = publisher.attach(None, proposal, settings, now_ns=now, drive_id=now - 1_000_000_000,
|
|
model_ns=now, car_state_ns=now)
|
|
assert not event.slcState.conditionalMode.hasOverride
|
|
projector = ConditionalPerceptionProjector()
|
|
args: dict[str, Any] = {'now_ns': now + 20_000_000, 'event_ns': now, 'drive_id': now - 1_000_000_000, 'choice': ModeChoice.CEM,
|
|
'lateral_active': True, 'selfdrive_enabled': False, 'car_valid': True, 'system_long': True}
|
|
value = projector.project(event.slcState, **args)
|
|
assert value is not None and value.reason == 'cem_stop' and not value.effective_experimental
|
|
state = OnroadState(False, True, 0.0, 0.0, SpeedLimitObservation(), conditional_perception=value)
|
|
assert reason(state) == 'cem_stop'
|
|
assert not stop_active(state)
|
|
for changed in ({'now_ns': now + 200_000_001}, {'drive_id': now + 1}, {'car_valid': False},
|
|
{'lateral_active': False}, {'choice': ModeChoice.STOCK}):
|
|
assert projector.project(event.slcState, **changed_arguments(args, changed)) is None
|
|
state = replace(state, conditional_effective=replace(value, effective_experimental=True))
|
|
assert not stop_active(state)
|
|
state = replace(state, longitudinal_active=True)
|
|
assert stop_active(state)
|
|
|
|
|
|
@pytest.mark.parametrize('sample_delay_ns', [1_315_523, 10_509_607])
|
|
def test_independently_stamped_scene_survives_transport_without_control_authority(sample_delay_ns):
|
|
envelope_ns = 100_000_000_000
|
|
scene_ns = envelope_ns + sample_delay_ns
|
|
drive_id = envelope_ns - 1_000_000_000
|
|
settings = SettingsSnapshot("test", 1, scene_ns, scene_ns, DocumentState.ABSENT, SafeModeState.ABSENT_FALSE, None, None, None)
|
|
decision = Decision(True, False, True, True, Reason.CEM_STOP, 8)
|
|
authority = Authority(True, True, False, False, False, True)
|
|
proposal = HostProposal(ModeChoice.CEM, Mock(spec=ProjectedScene, authority=authority), decision, None,
|
|
'inactive_axis', settings.revision)
|
|
event = messaging.new_message('slcState')
|
|
event.valid = True
|
|
event.logMonoTime = envelope_ns
|
|
publisher = StatusPublisher()
|
|
publisher.attach(event, proposal, settings, now_ns=scene_ns, drive_id=drive_id,
|
|
model_ns=envelope_ns, car_state_ns=envelope_ns)
|
|
with log.Event.from_bytes(event.to_bytes()) as received:
|
|
assert received.logMonoTime == envelope_ns
|
|
assert received.slcState.conditionalMode.observedMonoTime == scene_ns
|
|
projector = ConditionalPerceptionProjector()
|
|
args: dict[str, Any] = {'now_ns': scene_ns + 20_000_000, 'event_ns': int(received.logMonoTime), 'drive_id': drive_id,
|
|
'choice': ModeChoice.CEM, 'lateral_active': True, 'selfdrive_enabled': False, 'car_valid': True, 'system_long': True}
|
|
value = projector.project(received.slcState, **args)
|
|
assert value is not None and value.reason == 'cem_stop'
|
|
assert not value.effective_experimental
|
|
assert not received.slcState.conditionalMode.hasOverride
|
|
ui = OnroadState(False, True, 0.0, 0.0, SpeedLimitObservation(), conditional_perception=value)
|
|
assert reason(ui) == 'cem_stop' and not stop_active(ui)
|
|
# The display may outlast the control proposal, but neither timestamp is unbounded.
|
|
assert projector.project(received.slcState, **changed_arguments(args, {'now_ns': envelope_ns + 200_000_000})) is not None
|
|
assert projector.project(received.slcState, **changed_arguments(args, {'now_ns': scene_ns - 1})) is None
|
|
assert projector.project(received.slcState, **changed_arguments(args, {'now_ns': envelope_ns + 200_000_001})) is None
|
|
assert projector.project(received.slcState, **changed_arguments(args, {'event_ns': scene_ns + 20_000_001})) is None
|
|
assert projector.project(received.slcState, **changed_arguments(args, {'drive_id': drive_id + 1})) is None
|
|
|
|
# A fresh envelope must not revive a stale or malformed nested scene.
|
|
for altered in ({'observedMonoTime': envelope_ns - 200_000_001},
|
|
{'modelMonoTime': scene_ns + 1}, {'carStateMonoTime': drive_id - 1},
|
|
{'validUntilMonoTime': scene_ns + 150_000_001}):
|
|
changed = event.as_reader().as_builder()
|
|
for key, value in altered.items():
|
|
setattr(changed.slcState.conditionalMode, key, value)
|
|
assert ConditionalPerceptionProjector().project(changed.slcState, **args) is None
|
|
|
|
first = event.as_reader().as_builder()
|
|
publisher.attach(event, proposal, settings, now_ns=scene_ns + 10_000_000, drive_id=drive_id,
|
|
model_ns=scene_ns, car_state_ns=scene_ns)
|
|
projector = ConditionalPerceptionProjector()
|
|
assert projector.project(event.slcState, **args) is not None
|
|
assert projector.project(first.slcState, **args) is None
|