openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

109 lines
3.8 KiB

import pyray as rl
from enum import IntEnum
import cereal.messaging as messaging
from openpilot.system.ui.lib.application import gui_app
from openpilot.selfdrive.ui.layouts.sidebar import Sidebar, SIDEBAR_WIDTH
from openpilot.selfdrive.ui.layouts.home import HomeLayout
from openpilot.selfdrive.ui.layouts.settings.settings import SettingsLayout, PanelType
from openpilot.selfdrive.ui.onroad.augmented_road_view import AugmentedRoadView
from openpilot.selfdrive.ui.ui_state import device, ui_state
from openpilot.system.ui.widgets import Widget
ONROAD_FPS = 20
OFFROAD_FPS = 60
class MainState(IntEnum):
HOME = 0
SETTINGS = 1
ONROAD = 2
class MainLayout(Widget):
def __init__(self):
super().__init__()
self._pm = messaging.PubMaster(['bookmarkButton'])
self._sidebar = Sidebar()
self._current_mode = MainState.HOME
self._prev_onroad = False
gui_app.set_target_fps(OFFROAD_FPS)
# Initialize layouts
self._layouts = {MainState.HOME: HomeLayout(), MainState.SETTINGS: SettingsLayout(), MainState.ONROAD: AugmentedRoadView()}
self._sidebar_rect = rl.Rectangle(0, 0, 0, 0)
self._content_rect = rl.Rectangle(0, 0, 0, 0)
# Set callbacks
self._setup_callbacks()
def _render(self, _):
self._handle_onroad_transition()
self._render_main_content()
def _setup_callbacks(self):
self._sidebar.set_callbacks(on_settings=self._on_settings_clicked,
on_flag=self._on_bookmark_clicked)
self._layouts[MainState.HOME]._setup_widget.set_open_settings_callback(lambda: self.open_settings(PanelType.FIREHOSE))
self._layouts[MainState.SETTINGS].set_callbacks(on_close=self._set_mode_for_state)
self._layouts[MainState.ONROAD].set_click_callback(self._on_onroad_clicked)
device.add_interactive_timeout_callback(self._set_mode_for_state)
def _update_layout_rects(self):
self._sidebar_rect = rl.Rectangle(self._rect.x, self._rect.y, SIDEBAR_WIDTH, self._rect.height)
x_offset = SIDEBAR_WIDTH if self._sidebar.is_visible else 0
self._content_rect = rl.Rectangle(self._rect.y + x_offset, self._rect.y, self._rect.width - x_offset, self._rect.height)
def _handle_onroad_transition(self):
if ui_state.started != self._prev_onroad:
self._prev_onroad = ui_state.started
self._set_mode_for_state()
def _set_mode_for_state(self):
if ui_state.started:
# Don't hide sidebar from interactive timeout
if self._current_mode != MainState.ONROAD:
self._sidebar.set_visible(False)
self._set_current_layout(MainState.ONROAD)
else:
self._set_current_layout(MainState.HOME)
self._sidebar.set_visible(True)
def _set_current_layout(self, layout: MainState):
if layout != self._current_mode:
self._layouts[self._current_mode].hide_event()
self._current_mode = layout
self._layouts[self._current_mode].show_event()
# No need to draw onroad faster than source (model at 20Hz) and prevents screen tearing
gui_app.set_target_fps(ONROAD_FPS if self._current_mode == MainState.ONROAD else OFFROAD_FPS)
def open_settings(self, panel_type: PanelType):
self._layouts[MainState.SETTINGS].set_current_panel(panel_type)
self._set_current_layout(MainState.SETTINGS)
self._sidebar.set_visible(False)
def _on_settings_clicked(self):
self.open_settings(PanelType.DEVICE)
def _on_bookmark_clicked(self):
user_bookmark = messaging.new_message('bookmarkButton')
user_bookmark.valid = True
self._pm.send('bookmarkButton', user_bookmark)
def _on_onroad_clicked(self):
self._sidebar.set_visible(not self._sidebar.is_visible)
def _render_main_content(self):
# Render sidebar
if self._sidebar.is_visible:
self._sidebar.render(self._sidebar_rect)
content_rect = self._content_rect if self._sidebar.is_visible else self._rect
self._layouts[self._current_mode].render(content_rect)