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.
 
 
 
 
 
 

204 lines
6.0 KiB

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/resource.h>
#include <algorithm>
#include "common/util.h"
#include "common/utilpp.h"
#include "common/params.h"
#include "common/touch.h"
#include "common/swaglog.h"
#include "ui.hpp"
#include "paint.hpp"
#include "android/sl_sound.hpp"
volatile sig_atomic_t do_exit = 0;
static void set_do_exit(int sig) {
do_exit = 1;
}
static void ui_set_brightness(UIState *s, int brightness) {
static int last_brightness = -1;
if (last_brightness != brightness && (s->awake || brightness == 0)) {
if (set_brightness(brightness)) {
last_brightness = brightness;
}
}
}
int event_processing_enabled = -1;
static void enable_event_processing(bool yes) {
if (event_processing_enabled != 1 && yes) {
system("service call window 18 i32 1"); // enable event processing
event_processing_enabled = 1;
} else if (event_processing_enabled != 0 && !yes) {
system("service call window 18 i32 0"); // disable event processing
event_processing_enabled = 0;
}
}
// TODO: implement double tap to wake and actually turn display off
static void handle_display_state(UIState *s, bool user_input) {
static int display_mode = HWC_POWER_MODE_OFF;
static int display_timeout = 0;
// determine desired state
int desired_mode = display_mode;
if (user_input || s->ignition || s->started) {
desired_mode = HWC_POWER_MODE_NORMAL;
display_timeout = 30*UI_FREQ;
} else {
display_timeout = std::max(display_timeout-1, 0);
if (display_timeout == 0) {
desired_mode = HWC_POWER_MODE_DOZE;
}
}
// handle state transition
if (display_mode != desired_mode) {
LOGW("setting display mode %d", desired_mode);
display_mode = desired_mode;
s->awake = display_mode == HWC_POWER_MODE_NORMAL;
framebuffer_set_power(s->fb, display_mode);
enable_event_processing(s->awake);
if (!s->awake) {
ui_set_brightness(s, 0);
}
}
}
static void handle_vision_touch(UIState *s, int touch_x, int touch_y) {
if (s->started && (touch_x >= s->scene.viz_rect.x - bdr_s)
&& (s->active_app != cereal::UiLayoutState::App::SETTINGS)) {
if (!s->scene.frontview) {
s->scene.uilayout_sidebarcollapsed = !s->scene.uilayout_sidebarcollapsed;
} else {
Params().write_db_value("IsDriverViewEnabled", "0", 1);
}
}
}
static void handle_sidebar_touch(UIState *s, int touch_x, int touch_y) {
if (!s->scene.uilayout_sidebarcollapsed && touch_x <= sbr_w) {
if (settings_btn.ptInRect(touch_x, touch_y)) {
s->active_app = cereal::UiLayoutState::App::SETTINGS;
} else if (home_btn.ptInRect(touch_x, touch_y)) {
if (s->started) {
s->active_app = cereal::UiLayoutState::App::NONE;
s->scene.uilayout_sidebarcollapsed = true;
} else {
s->active_app = cereal::UiLayoutState::App::HOME;
}
}
}
}
static void update_offroad_layout_state(UIState *s, PubMaster *pm) {
static int timeout = 0;
static bool prev_collapsed = false;
static cereal::UiLayoutState::App prev_app = cereal::UiLayoutState::App::NONE;
if (timeout > 0) {
timeout--;
}
if (prev_collapsed != s->scene.uilayout_sidebarcollapsed || prev_app != s->active_app || timeout == 0) {
MessageBuilder msg;
auto layout = msg.initEvent().initUiLayoutState();
layout.setActiveApp(s->active_app);
layout.setSidebarCollapsed(s->scene.uilayout_sidebarcollapsed);
pm->send("offroadLayout", msg);
LOGD("setting active app to %d with sidebar %d", (int)s->active_app, s->scene.uilayout_sidebarcollapsed);
prev_collapsed = s->scene.uilayout_sidebarcollapsed;
prev_app = s->active_app;
timeout = 2 * UI_FREQ;
}
}
int main(int argc, char* argv[]) {
setpriority(PRIO_PROCESS, 0, -14);
signal(SIGINT, (sighandler_t)set_do_exit);
SLSound sound;
UIState uistate = {};
UIState *s = &uistate;
ui_init(s);
s->sound = &sound;
handle_display_state(s, true);
enable_event_processing(true);
PubMaster *pm = new PubMaster({"offroadLayout"});
TouchState touch = {0};
touch_init(&touch);
// light sensor scaling and volume params
const bool LEON = util::read_file("/proc/cmdline").find("letv") != std::string::npos;
float brightness_b = 0, brightness_m = 0;
int result = read_param(&brightness_b, "BRIGHTNESS_B", true);
result += read_param(&brightness_m, "BRIGHTNESS_M", true);
if(result != 0) {
brightness_b = LEON ? 10.0 : 5.0;
brightness_m = LEON ? 2.6 : 1.3;
write_param_float(brightness_b, "BRIGHTNESS_B", true);
write_param_float(brightness_m, "BRIGHTNESS_M", true);
}
float smooth_brightness = brightness_b;
const int MIN_VOLUME = LEON ? 12 : 9;
const int MAX_VOLUME = LEON ? 15 : 12;
s->sound->setVolume(MIN_VOLUME);
while (!do_exit) {
if (!s->started || !s->vision_connected) {
// Delay a while to avoid 9% cpu usage while car is not started and user is keeping touching on the screen.
usleep(30 * 1000);
}
double u1 = millis_since_boot();
ui_update(s);
// poll for touch events
int touch_x = -1, touch_y = -1;
int touched = touch_poll(&touch, &touch_x, &touch_y, 0);
if (touched == 1) {
handle_sidebar_touch(s, touch_x, touch_y);
handle_vision_touch(s, touch_x, touch_y);
}
// Don't waste resources on drawing in case screen is off
handle_display_state(s, touched == 1);
if (!s->awake) {
continue;
}
// up one notch every 5 m/s
s->sound->setVolume(fmin(MAX_VOLUME, MIN_VOLUME + s->scene.controls_state.getVEgo() / 5));
// set brightness
float clipped_brightness = fmin(512, (s->light_sensor*brightness_m) + brightness_b);
smooth_brightness = fmin(255, clipped_brightness * 0.01 + smooth_brightness * 0.99);
ui_set_brightness(s, (int)smooth_brightness);
update_offroad_layout_state(s, pm);
ui_draw(s);
double u2 = millis_since_boot();
if (!s->scene.frontview && (u2-u1 > 66)) {
// warn on sub 15fps
LOGW("slow frame(%llu) time: %.2f", (s->sm)->frame, u2-u1);
}
framebuffer_swap(s->fb);
}
handle_display_state(s, true);
delete s->sm;
delete pm;
return 0;
}