diff --git a/common/params.py b/common/params.py index d01b1b4ae9..67f3f31f38 100755 --- a/common/params.py +++ b/common/params.py @@ -85,7 +85,6 @@ keys = { "LimitSetSpeed": [TxType.PERSISTENT], "LimitSetSpeedNeural": [TxType.PERSISTENT], "LiveParameters": [TxType.PERSISTENT], - "LongitudinalControl": [TxType.PERSISTENT], "OpenpilotEnabledToggle": [TxType.PERSISTENT], "LaneChangeEnabled": [TxType.PERSISTENT], "PandaFirmware": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT], diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 0b240ca5a9..9f0777553f 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -94,7 +94,6 @@ class Controls: cp_bytes = self.CP.to_bytes() params.put("CarParams", cp_bytes) put_nonblocking("CarParamsCache", cp_bytes) - put_nonblocking("LongitudinalControl", "1" if self.CP.openpilotLongitudinalControl else "0") self.CC = car.CarControl.new_message() self.AM = AlertManager() diff --git a/selfdrive/manager.py b/selfdrive/manager.py index b7df78dc12..6487363d3c 100755 --- a/selfdrive/manager.py +++ b/selfdrive/manager.py @@ -571,7 +571,6 @@ def main(): ("IsUploadRawEnabled", "1"), ("IsLdwEnabled", "1"), ("IsGeofenceEnabled", "-1"), - ("LongitudinalControl", "0"), ("LimitSetSpeed", "0"), ("LimitSetSpeedNeural", "0"), ("LastUpdateTime", datetime.datetime.utcnow().isoformat().encode('utf8')), diff --git a/selfdrive/test/test_cpu_usage.py b/selfdrive/test/test_cpu_usage.py index 21e211a892..98f6284fde 100755 --- a/selfdrive/test/test_cpu_usage.py +++ b/selfdrive/test/test_cpu_usage.py @@ -22,10 +22,10 @@ def print_cpu_usage(first_proc, last_proc): ("selfdrive.locationd.paramsd", 11.53), ("./_modeld", 7.12), ("selfdrive.controls.radard", 9.54), - ("./_ui", 9.54), ("./camerad", 7.07), ("./_sensord", 6.17), ("selfdrive.locationd.calibrationd", 6.0), + ("./_ui", 5.82), ("./boardd", 3.63), ("./_dmonitoringmodeld", 2.67), ("selfdrive.logmessaged", 2.71), diff --git a/selfdrive/ui/android_ui.cc b/selfdrive/ui/android_ui.cc index fa7866b1de..261dee6f03 100644 --- a/selfdrive/ui/android_ui.cc +++ b/selfdrive/ui/android_ui.cc @@ -1,7 +1,7 @@ #include #include +#include #include -#include #include "common/util.h" #include "common/utilpp.h" @@ -130,9 +130,8 @@ static void handle_sidebar_touch(UIState *s, int touch_x, int touch_y) { if (touch_x >= settings_btn_x && touch_x < (settings_btn_x + settings_btn_w) && touch_y >= settings_btn_y && touch_y < (settings_btn_y + settings_btn_h)) { s->active_app = cereal::UiLayoutState::App::SETTINGS; - } - else if (touch_x >= home_btn_x && touch_x < (home_btn_x + home_btn_w) - && touch_y >= home_btn_y && touch_y < (home_btn_y + home_btn_h)) { + } else if (touch_x >= home_btn_x && touch_x < (home_btn_x + home_btn_w) + && touch_y >= home_btn_y && touch_y < (home_btn_y + home_btn_h)) { if (s->started) { s->active_app = cereal::UiLayoutState::App::NONE; s->scene.uilayout_sidebarcollapsed = true; @@ -169,7 +168,6 @@ int main(int argc, char* argv[]) { int err; setpriority(PRIO_PROCESS, 0, -14); - zsys_handler_set(NULL); signal(SIGINT, (sighandler_t)set_do_exit); UIState uistate = {}; @@ -179,12 +177,6 @@ int main(int argc, char* argv[]) { enable_event_processing(true); PubMaster *pm = new PubMaster({"offroadLayout"}); - - pthread_t connect_thread_handle; - err = pthread_create(&connect_thread_handle, NULL, - vision_connect_thread, s); - assert(err == 0); - pthread_t light_sensor_thread_handle; err = pthread_create(&light_sensor_thread_handle, NULL, light_sensor_thread, s); @@ -192,47 +184,33 @@ int main(int argc, char* argv[]) { TouchState touch = {0}; touch_init(&touch); - s->touch_fd = touch.fd; - // light sensor scaling params + // 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; assert(s->sound.init(MIN_VOLUME)); - int draws = 0; - while (!do_exit) { - bool should_swap = false; - if (!s->started) { + 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. - // Don't hold the lock while sleeping, so that vision_connect_thread have chances to get the lock. usleep(30 * 1000); } - pthread_mutex_lock(&s->lock); double u1 = millis_since_boot(); - // light sensor is only exposed on EONs - float clipped_brightness = (s->light_sensor*brightness_m) + brightness_b; - if (clipped_brightness > 512) clipped_brightness = 512; - smooth_brightness = clipped_brightness * 0.01 + smooth_brightness * 0.99; - if (smooth_brightness > 255) smooth_brightness = 255; - ui_set_brightness(s, (int)smooth_brightness); - ui_update_sizes(s); + ui_update(s); // poll for touch events int touch_x = -1, touch_y = -1; @@ -243,109 +221,44 @@ int main(int argc, char* argv[]) { handle_vision_touch(s, touch_x, touch_y); } - if (!s->started) { - // always process events offroad - check_messages(s); - } else { + // manage wakefulness + if (s->started) { set_awake(s, true); - // Car started, fetch a new rgb image from ipc - if (s->vision_connected){ - ui_update(s); - } - - check_messages(s); - - // Visiond process is just stopped, force a redraw to make screen blank again. - if (!s->started) { - s->scene.uilayout_sidebarcollapsed = false; - ui_draw(s); - glFinish(); - should_swap = true; - } } - // manage wakefulness if (s->awake_timeout > 0) { s->awake_timeout--; } else { set_awake(s, false); } - // manage hardware disconnect - if ((s->sm->frame - s->sm->rcv_frame("health")) > 5*UI_FREQ) { - s->scene.hwType = cereal::HealthData::HwType::UNKNOWN; - } - // Don't waste resources on drawing in case screen is off - if (s->awake) { - ui_draw(s); - glFinish(); - should_swap = true; + if (!s->awake) { + continue; } - s->sound.setVolume(fmin(MAX_VOLUME, MIN_VOLUME + s->scene.controls_state.getVEgo() / 5)); // up one notch every 5 m/s - - bool controls_timeout = (s->sm->frame - s->sm->rcv_frame("controlsState")) > 5*UI_FREQ; - if (s->started && !s->scene.frontview && controls_timeout) { - if (!s->controls_seen) { - // car is started, but controlsState hasn't been seen at all - s->scene.alert_text1 = "openpilot Unavailable"; - s->scene.alert_text2 = "Waiting for controls to start"; - s->scene.alert_size = cereal::ControlsState::AlertSize::MID; - } else { - // car is started, but controls is lagging or died - LOGE("Controls unresponsive"); - - if (s->scene.alert_text2 != "Controls Unresponsive") { - s->sound.play(AudibleAlert::CHIME_WARNING_REPEAT); - } - - s->scene.alert_text1 = "TAKE CONTROL IMMEDIATELY"; - s->scene.alert_text2 = "Controls Unresponsive"; - s->scene.alert_size = cereal::ControlsState::AlertSize::FULL; - update_status(s, STATUS_ALERT); - } - ui_draw_vision_alert(s, s->scene.alert_size, s->status, s->scene.alert_text1.c_str(), s->scene.alert_text2.c_str()); - } + // 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); - if (s->sm->frame % (2*UI_FREQ) == 0) { - read_param(&s->is_metric, "IsMetric"); - } else if (s->sm->frame % (3*UI_FREQ) == 0) { - int param_read = read_param(&s->last_athena_ping, "LastAthenaPingTime"); - if (param_read != 0) { // Failed to read param - s->scene.athenaStatus = NET_DISCONNECTED; - } else if (nanos_since_boot() - s->last_athena_ping < 70e9) { - s->scene.athenaStatus = NET_CONNECTED; - } else { - s->scene.athenaStatus = NET_ERROR; - } - } update_offroad_layout_state(s, pm); - pthread_mutex_unlock(&s->lock); - - // the bg thread needs to be scheduled, so the main thread needs time without the lock - // safe to do this outside the lock? - if (should_swap) { - double u2 = millis_since_boot(); - if (u2-u1 > 66) { - // warn on sub 15fps - LOGW("slow frame(%d) time: %.2f", draws, u2-u1); - } - draws++; - framebuffer_swap(s->fb); + 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); } set_awake(s, true); - // wake up bg thread to exit - pthread_mutex_lock(&s->lock); - pthread_mutex_unlock(&s->lock); - - // join light_sensor_thread? - err = pthread_join(connect_thread_handle, NULL); + err = pthread_join(light_sensor_thread_handle, NULL); assert(err == 0); delete s->sm; delete pm; diff --git a/selfdrive/ui/paint.cc b/selfdrive/ui/paint.cc index f848b0fe59..2b76ca9c0b 100644 --- a/selfdrive/ui/paint.cc +++ b/selfdrive/ui/paint.cc @@ -24,7 +24,7 @@ const mat3 intrinsic_matrix = (mat3){{ }}; const uint8_t alert_colors[][4] = { - [STATUS_STOPPED] = {0x07, 0x23, 0x39, 0xf1}, + [STATUS_OFFROAD] = {0x07, 0x23, 0x39, 0xf1}, [STATUS_DISENGAGED] = {0x17, 0x33, 0x49, 0xc8}, [STATUS_ENGAGED] = {0x17, 0x86, 0x44, 0xf1}, [STATUS_WARNING] = {0xDA, 0x6F, 0x25, 0xf1}, @@ -224,9 +224,9 @@ static void ui_draw_track(UIState *s, bool is_mpc, track_vertices_data *pvd) { NVGpaint track_bg; if (is_mpc) { // Draw colored MPC track - const uint8_t *clr = bg_colors[s->status]; + const Color clr = bg_colors[s->status]; track_bg = nvgLinearGradient(s->vg, vwp_w, vwp_h, vwp_w, vwp_h*.4, - nvgRGBA(clr[0], clr[1], clr[2], 255), nvgRGBA(clr[0], clr[1], clr[2], 255/2)); + nvgRGBA(clr.r, clr.g, clr.b, 255), nvgRGBA(clr.r, clr.g, clr.b, 255/2)); } else { // Draw white vision track track_bg = nvgLinearGradient(s->vg, vwp_w, vwp_h, vwp_w, vwp_h*.4, @@ -237,29 +237,22 @@ static void ui_draw_track(UIState *s, bool is_mpc, track_vertices_data *pvd) { } static void draw_frame(UIState *s) { - const UIScene *scene = &s->scene; - + mat4 *out_mat; if (s->scene.frontview) { glBindVertexArray(s->frame_vao[1]); - } else { - glBindVertexArray(s->frame_vao[0]); - } - - mat4 *out_mat; - if (s->scene.frontview || s->scene.fullview) { out_mat = &s->front_frame_mat; } else { + glBindVertexArray(s->frame_vao[0]); out_mat = &s->rear_frame_mat; } glActiveTexture(GL_TEXTURE0); - if (s->scene.frontview && s->cur_vision_front_idx >= 0) { - glBindTexture(GL_TEXTURE_2D, s->frame_front_texs[s->cur_vision_front_idx]); - } else if (!scene->frontview && s->cur_vision_idx >= 0) { - glBindTexture(GL_TEXTURE_2D, s->frame_texs[s->cur_vision_idx]); - - // TODO: a better way to do this? -#ifndef QCOM - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, s->rgb_width, s->rgb_height, 0, GL_RGB, GL_UNSIGNED_BYTE, s->priv_hnds[s->cur_vision_idx]); + + if (s->stream.last_idx >= 0) { + glBindTexture(GL_TEXTURE_2D, s->frame_texs[s->stream.last_idx]); +#ifndef __aarch64__ + // this is handled in ion on QCOM + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, s->stream.bufs_info.width, s->stream.bufs_info.height, + 0, GL_RGB, GL_UNSIGNED_BYTE, s->priv_hnds[s->stream.last_idx]); #endif } @@ -275,7 +268,7 @@ static void draw_frame(UIState *s) { } static inline bool valid_frame_pt(UIState *s, float x, float y) { - return x >= 0 && x <= s->rgb_width && y >= 0 && y <= s->rgb_height; + return x >= 0 && x <= s->stream.bufs_info.width && y >= 0 && y <= s->stream.bufs_info.height; } static void update_lane_line_data(UIState *s, const float *points, float off, model_path_vertices_data *pvd, float valid_len) { @@ -325,14 +318,10 @@ static void ui_draw_vision_lanes(UIState *s) { } // Draw left lane edge - ui_draw_lane( - s, pvd, - nvgRGBAf(1.0, 1.0, 1.0, scene->model.getLeftLane().getProb())); + ui_draw_lane(s, pvd, nvgRGBAf(1.0, 1.0, 1.0, scene->model.getLeftLane().getProb())); // Draw right lane edge - ui_draw_lane( - s, pvd + MODEL_LANE_PATH_CNT, - nvgRGBAf(1.0, 1.0, 1.0, scene->model.getRightLane().getProb())); + ui_draw_lane(s, pvd + MODEL_LANE_PATH_CNT, nvgRGBAf(1.0, 1.0, 1.0, scene->model.getRightLane().getProb())); if(s->sm->updated("radarState")) { update_all_track_data(s); @@ -369,7 +358,7 @@ static void ui_draw_world(UIState *s) { nvgTranslate(s->vg, -w / 2, -1080.0f / 2); nvgScale(s->vg, 2.0, 2.0); - nvgScale(s->vg, w / s->rgb_width, 1080.0f / s->rgb_height); + nvgScale(s->vg, w / s->stream.bufs_info.width, 1080.0f / s->stream.bufs_info.height); // Draw lane edges and vision/mpc tracks ui_draw_vision_lanes(s); @@ -390,17 +379,11 @@ static void ui_draw_vision_maxspeed(UIState *s) { char maxspeed_str[32]; float maxspeed = s->scene.controls_state.getVCruise(); int maxspeed_calc = maxspeed * 0.6225 + 0.5; - float speedlimit = s->scene.speedlimit; - int speedlim_calc = speedlimit * 2.2369363 + 0.5; if (s->is_metric) { maxspeed_calc = maxspeed + 0.5; - speedlim_calc = speedlimit * 3.6 + 0.5; } bool is_cruise_set = (maxspeed != 0 && maxspeed != SET_SPEED_NA); - bool is_speedlim_valid = s->scene.speedlimit_valid; - bool is_set_over_limit = is_speedlim_valid && s->scene.controls_state.getEnabled() && - is_cruise_set && maxspeed_calc > speedlim_calc; int viz_maxspeed_w = 184; int viz_maxspeed_h = 202; @@ -411,17 +394,10 @@ static void ui_draw_vision_maxspeed(UIState *s) { viz_maxspeed_xo = 0; // Draw Background - ui_draw_rect(s->vg, viz_maxspeed_x, viz_maxspeed_y, viz_maxspeed_w, viz_maxspeed_h, - is_set_over_limit ? nvgRGBA(218, 111, 37, 180) : COLOR_BLACK_ALPHA(100), 30); + ui_draw_rect(s->vg, viz_maxspeed_x, viz_maxspeed_y, viz_maxspeed_w, viz_maxspeed_h, COLOR_BLACK_ALPHA(100), 30); // Draw Border NVGcolor color = COLOR_WHITE_ALPHA(100); - if (is_set_over_limit) { - color = COLOR_OCHRE; - } else if (is_speedlim_valid) { - color = s->is_ego_over_limit ? COLOR_WHITE_ALPHA(20) : COLOR_WHITE; - } - ui_draw_rect(s->vg, viz_maxspeed_x, viz_maxspeed_y, viz_maxspeed_w, viz_maxspeed_h, color, 20, 10); nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE); @@ -549,10 +525,10 @@ static void ui_draw_vision_header(UIState *s) { (box_y+(header_h-(header_h/2.5))), ui_viz_rx, box_y+header_h, nvgRGBAf(0,0,0,0.45), nvgRGBAf(0,0,0,0)); + ui_draw_rect(s->vg, ui_viz_rx, box_y, ui_viz_rw, header_h, gradient); ui_draw_vision_maxspeed(s); - ui_draw_vision_speed(s); ui_draw_vision_event(s); } @@ -575,7 +551,7 @@ void ui_draw_vision_alert(UIState *s, cereal::ControlsState::AlertSize va_size, const uint8_t *color = alert_colors[va_color]; int alr_s = alert_size_map[va_size]; - const int alr_x = scene->ui_viz_rx- bdr_s; + const int alr_x = scene->ui_viz_rx - bdr_s; const int alr_w = scene->ui_viz_rw + (bdr_s*2); const int alr_h = alr_s+(va_size==cereal::ControlsState::AlertSize::NONE?0:bdr_s); const int alr_y = vwp_h-alr_h; @@ -619,7 +595,7 @@ static void ui_draw_vision(UIState *s) { glViewport(0, 0, s->fb_w, s->fb_h); // Draw augmented elements - if (!scene->frontview && !scene->fullview) { + if (!scene->frontview) { ui_draw_world(s); } @@ -631,7 +607,6 @@ static void ui_draw_vision(UIState *s) { } if (scene->alert_size != cereal::ControlsState::AlertSize::NONE) { - // Controls Alerts ui_draw_vision_alert(s, scene->alert_size, s->status, scene->alert_text1.c_str(), scene->alert_text2.c_str()); } else if (!scene->frontview) { @@ -640,22 +615,25 @@ static void ui_draw_vision(UIState *s) { } static void ui_draw_background(UIState *s) { - int bg_status = s->status; - assert(bg_status < ARRAYSIZE(bg_colors)); - const uint8_t *color = bg_colors[bg_status]; - - glClearColor(color[0]/256.0, color[1]/256.0, color[2]/256.0, 1.0); + const Color color = bg_colors[s->status]; + glClearColor(color.r/256.0, color.g/256.0, color.b/256.0, 1.0); glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); } void ui_draw(UIState *s) { + const bool hasSidebar = !s->scene.uilayout_sidebarcollapsed; + s->scene.ui_viz_rx = hasSidebar ? box_x : (box_x - sbr_w + (bdr_s * 2)); + s->scene.ui_viz_rw = hasSidebar ? box_w : (box_w + sbr_w - (bdr_s * 2)); + s->scene.ui_viz_ro = hasSidebar ? - (sbr_w - 6 * bdr_s) : 0; + ui_draw_background(s); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, s->fb_w, s->fb_h); nvgBeginFrame(s->vg, s->fb_w, s->fb_h, 1.0f); ui_draw_sidebar(s); - if (s->started && s->active_app == cereal::UiLayoutState::App::NONE && s->status != STATUS_STOPPED && s->vision_seen) { + if (s->started && s->active_app == cereal::UiLayoutState::App::NONE && + s->status != STATUS_OFFROAD && s->vision_connected) { ui_draw_vision(s); } nvgEndFrame(s->vg); @@ -820,7 +798,7 @@ void ui_nvg_init(UIState *s) { { 1.0, -1.0, x1, y1}, //br }; - glGenVertexArrays(1,&s->frame_vao[i]); + glGenVertexArrays(1, &s->frame_vao[i]); glBindVertexArray(s->frame_vao[i]); glGenBuffers(1, &s->frame_vbo[i]); glBindBuffer(GL_ARRAY_BUFFER, s->frame_vbo[i]); @@ -841,10 +819,8 @@ void ui_nvg_init(UIState *s) { s->front_frame_mat = matmul(device_transform, full_to_wide_frame_transform); s->rear_frame_mat = matmul(device_transform, frame_transform); - for(int i = 0;i < UI_BUF_COUNT; i++) { + for(int i = 0; i < UI_BUF_COUNT; i++) { s->khr[i] = 0; s->priv_hnds[i] = NULL; - s->khr_front[i] = 0; - s->priv_hnds_front[i] = NULL; } } diff --git a/selfdrive/ui/qt/window.cc b/selfdrive/ui/qt/window.cc index e7ddac2f99..d3b73952a7 100644 --- a/selfdrive/ui/qt/window.cc +++ b/selfdrive/ui/qt/window.cc @@ -49,7 +49,6 @@ void MainWindow::closeSettings(){ } - GLWindow::GLWindow(QWidget *parent) : QOpenGLWidget(parent) { timer = new QTimer(this); QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate())); @@ -72,24 +71,11 @@ void GLWindow::initializeGL() { ui_state->fb_w = vwp_w; ui_state->fb_h = vwp_h; - int err = pthread_create(&connect_thread_handle, NULL, - vision_connect_thread, ui_state); - assert(err == 0); - timer->start(50); } void GLWindow::timerUpdate(){ - pthread_mutex_lock(&ui_state->lock); - - ui_update_sizes(ui_state); - - check_messages(ui_state); - if (ui_state->vision_connected){ - ui_update(ui_state); - } - pthread_mutex_unlock(&ui_state->lock); - + ui_update(ui_state); update(); } @@ -98,9 +84,7 @@ void GLWindow::resizeGL(int w, int h) { } void GLWindow::paintGL() { - pthread_mutex_lock(&ui_state->lock); ui_draw(ui_state); - pthread_mutex_unlock(&ui_state->lock); } void GLWindow::mousePressEvent(QMouseEvent *e) { @@ -116,7 +100,6 @@ void GLWindow::mousePressEvent(QMouseEvent *e) { if (ui_state->started && (e->x() >= ui_state->scene.ui_viz_rx - bdr_s)){ ui_state->scene.uilayout_sidebarcollapsed = !ui_state->scene.uilayout_sidebarcollapsed; } - } diff --git a/selfdrive/ui/qt/window.hpp b/selfdrive/ui/qt/window.hpp index 9ab47c377b..927c3fa53c 100644 --- a/selfdrive/ui/qt/window.hpp +++ b/selfdrive/ui/qt/window.hpp @@ -45,7 +45,6 @@ protected: private: QTimer * timer; UIState * ui_state; - pthread_t connect_thread_handle; public slots: void timerUpdate(); diff --git a/selfdrive/ui/sidebar.cc b/selfdrive/ui/sidebar.cc index e6274f88c5..9d8f8939e4 100644 --- a/selfdrive/ui/sidebar.cc +++ b/selfdrive/ui/sidebar.cc @@ -159,13 +159,13 @@ static void ui_draw_sidebar_panda_metric(UIState *s) { } static void ui_draw_sidebar_connectivity(UIState *s) { - if (s->scene.athenaStatus == NET_DISCONNECTED) { - ui_draw_sidebar_metric(s, NULL, NULL, 1, 180+158, "CONNECT\nOFFLINE"); - } else if (s->scene.athenaStatus == NET_CONNECTED) { - ui_draw_sidebar_metric(s, NULL, NULL, 0, 180+158, "CONNECT\nONLINE"); - } else { - ui_draw_sidebar_metric(s, NULL, NULL, 2, 180+158, "CONNECT\nERROR"); - } + static std::map> connectivity_map = { + {NET_ERROR, {"CONNECT\nERROR", 2}}, + {NET_CONNECTED, {"CONNECT\nONLINE", 0}}, + {NET_DISCONNECTED, {"CONNECT\nOFFLINE", 1}}, + }; + auto net_params = connectivity_map[s->scene.athenaStatus]; + ui_draw_sidebar_metric(s, NULL, NULL, net_params.second, 180+158, net_params.first); } void ui_draw_sidebar(UIState *s) { diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index a2f59b7d4a..6da9bf3bbb 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -1,10 +1,11 @@ #include #include #include +#include #include #include +#include #include -#include #include "common/util.h" #include "common/swaglog.h" @@ -15,23 +16,20 @@ extern volatile sig_atomic_t do_exit; - int write_param_float(float param, const char* param_name, bool persistent_param) { char s[16]; int size = snprintf(s, sizeof(s), "%f", param); - return write_db_value(param_name, s, MIN(size, sizeof(s)), persistent_param); + return write_db_value(param_name, s, size < sizeof(s) ? size : sizeof(s), persistent_param); } void ui_init(UIState *s) { - pthread_mutex_init(&s->lock, NULL); s->sm = new SubMaster({"model", "controlsState", "uiLayoutState", "liveCalibration", "radarState", "thermal", - "health", "carParams", "ubloxGnss", "driverState", "dMonitoringState" - }); + "health", "carParams", "ubloxGnss", "driverState", "dMonitoringState"}); - s->ipc_fd = -1; - s->scene.satelliteCount = -1; s->started = false; - s->vision_seen = false; + s->status = STATUS_OFFROAD; + s->scene.satelliteCount = -1; + read_param(&s->is_metric, "IsMetric"); s->fb = framebuffer_init("ui", 0, true, &s->fb_w, &s->fb_h); assert(s->fb); @@ -39,41 +37,72 @@ void ui_init(UIState *s) { ui_nvg_init(s); } -static void ui_init_vision(UIState *s, const VisionStreamBufs back_bufs, - int num_back_fds, const int *back_fds, - const VisionStreamBufs front_bufs, int num_front_fds, - const int *front_fds) { - assert(num_back_fds == UI_BUF_COUNT); - assert(num_front_fds == UI_BUF_COUNT); +static void ui_init_vision(UIState *s) { + // Invisible until we receive a calibration message. + s->scene.world_objects_visible = false; - vipc_bufs_load(s->bufs, &back_bufs, num_back_fds, back_fds); - vipc_bufs_load(s->front_bufs, &front_bufs, num_front_fds, front_fds); + for (int i = 0; i < UI_BUF_COUNT; i++) { + if (s->khr[i] != 0) { + visionimg_destroy_gl(s->khr[i], s->priv_hnds[i]); + glDeleteTextures(1, &s->frame_texs[i]); + } - s->cur_vision_idx = -1; - s->cur_vision_front_idx = -1; + VisionImg img = { + .fd = s->stream.bufs[i].fd, + .format = VISIONIMG_FORMAT_RGB24, + .width = s->stream.bufs_info.width, + .height = s->stream.bufs_info.height, + .stride = s->stream.bufs_info.stride, + .bpp = 3, + .size = s->stream.bufs_info.buf_len, + }; +#ifndef QCOM + s->priv_hnds[i] = s->stream.bufs[i].addr; +#endif + s->frame_texs[i] = visionimg_to_gl(&img, &s->khr[i], &s->priv_hnds[i]); + + glBindTexture(GL_TEXTURE_2D, s->frame_texs[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + // BGR + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); + } + assert(glGetError() == GL_NO_ERROR); +} - s->scene.frontview = getenv("FRONTVIEW") != NULL; - s->scene.fullview = getenv("FULLVIEW") != NULL; - s->scene.world_objects_visible = false; // Invisible until we receive a calibration message. +void ui_update_vision(UIState *s) { - s->rgb_width = back_bufs.width; - s->rgb_height = back_bufs.height; - s->rgb_stride = back_bufs.stride; - s->rgb_buf_len = back_bufs.buf_len; + if (!s->vision_connected && s->started) { + const VisionStreamType type = s->scene.frontview ? VISION_STREAM_RGB_FRONT : VISION_STREAM_RGB_BACK; + int err = visionstream_init(&s->stream, type, true, nullptr); + if (err == 0) { + ui_init_vision(s); + s->vision_connected = true; + } + } - s->rgb_front_width = front_bufs.width; - s->rgb_front_height = front_bufs.height; - s->rgb_front_stride = front_bufs.stride; - s->rgb_front_buf_len = front_bufs.buf_len; + if (s->vision_connected) { + if (!s->started) goto destroy; + + // poll for a new frame + struct pollfd fds[1] = {{ + .fd = s->stream.ipc_fd, + .events = POLLOUT, + }}; + int ret = poll(fds, 1, 100); + if (ret > 0) { + if (!visionstream_get(&s->stream, nullptr)) goto destroy; + } + } - read_param(&s->is_metric, "IsMetric"); - read_param(&s->longitudinal_control, "LongitudinalControl"); -} + return; -void update_status(UIState *s, int status) { - if (s->status != status) { - s->status = status; - } +destroy: + visionstream_destroy(&s->stream); + s->vision_connected = false; } static inline void fill_path_points(const cereal::ModelData::PathData::Reader &path, float *points) { @@ -83,13 +112,21 @@ static inline void fill_path_points(const cereal::ModelData::PathData::Reader &p } } -void handle_message(UIState *s, SubMaster &sm) { +void update_sockets(UIState *s) { + UIScene &scene = s->scene; + SubMaster &sm = *(s->sm); + + // poll sockets + if (sm.update(0) == 0){ + return; + } + if (s->started && sm.updated("controlsState")) { auto event = sm["controlsState"]; scene.controls_state = event.getControlsState(); - s->controls_seen = true; + // TODO: the alert stuff shouldn't be handled here auto alert_sound = scene.controls_state.getAlertSound(); if (scene.alert_type.compare(scene.controls_state.getAlertType()) != 0) { if (alert_sound == AudibleAlert::NONE) { @@ -104,11 +141,11 @@ void handle_message(UIState *s, SubMaster &sm) { scene.alert_type = scene.controls_state.getAlertType(); auto alertStatus = scene.controls_state.getAlertStatus(); if (alertStatus == cereal::ControlsState::AlertStatus::USER_PROMPT) { - update_status(s, STATUS_WARNING); + s->status = STATUS_WARNING; } else if (alertStatus == cereal::ControlsState::AlertStatus::CRITICAL) { - update_status(s, STATUS_ALERT); + s->status = STATUS_ALERT; } else{ - update_status(s, scene.controls_state.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED); + s->status = scene.controls_state.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED; } float alert_blinkingrate = scene.controls_state.getAlertBlinkingRate(); @@ -147,16 +184,6 @@ void handle_message(UIState *s, SubMaster &sm) { fill_path_points(scene.model.getLeftLane(), scene.left_lane_points); fill_path_points(scene.model.getRightLane(), scene.right_lane_points); } - // else if (which == cereal::Event::LIVE_MPC) { - // auto data = event.getLiveMpc(); - // auto x_list = data.getX(); - // auto y_list = data.getY(); - // for (int i = 0; i < 50; i++){ - // scene.mpc_x[i] = x_list[i]; - // scene.mpc_y[i] = y_list[i]; - // } - // s->livempc_or_radarstate_changed = true; - // } if (sm.updated("uiLayoutState")) { auto data = sm["uiLayoutState"].getUiLayoutState(); s->active_app = data.getActiveApp(); @@ -173,6 +200,8 @@ void handle_message(UIState *s, SubMaster &sm) { } if (sm.updated("health")) { scene.hwType = sm["health"].getHealth().getHwType(); + } else if ((s->sm->frame - s->sm->rcv_frame("health")) > 5*UI_FREQ) { + scene.hwType = cereal::HealthData::HwType::UNKNOWN; } if (sm.updated("carParams")) { s->longitudinal_control = sm["carParams"].getCarParams().getOpenpilotLongitudinalControl(); @@ -184,267 +213,67 @@ void handle_message(UIState *s, SubMaster &sm) { scene.dmonitoring_state = sm["dMonitoringState"].getDMonitoringState(); scene.is_rhd = scene.dmonitoring_state.getIsRHD(); scene.frontview = scene.dmonitoring_state.getIsPreview(); - } else if ((sm.frame - sm.rcv_frame("dMonitoringState")) > 1*UI_FREQ) { + } else if ((sm.frame - sm.rcv_frame("dMonitoringState")) > UI_FREQ/2) { scene.frontview = false; } s->started = scene.thermal.getStarted() || scene.frontview; - // Handle onroad/offroad transition - if (!s->started) { - if (s->status != STATUS_STOPPED) { - update_status(s, STATUS_STOPPED); - s->vision_seen = false; - s->controls_seen = false; - s->active_app = cereal::UiLayoutState::App::HOME; - } - } else if (s->status == STATUS_STOPPED) { - update_status(s, STATUS_DISENGAGED); - s->active_app = cereal::UiLayoutState::App::NONE; - } -} - -void check_messages(UIState *s) { - if (s->sm->update(0) > 0){ - handle_message(s, *(s->sm)); - } -} - -void ui_update_sizes(UIState *s){ - // resize vision for collapsing sidebar - const bool hasSidebar = !s->scene.uilayout_sidebarcollapsed; - s->scene.ui_viz_rx = hasSidebar ? box_x : (box_x - sbr_w + (bdr_s * 2)); - s->scene.ui_viz_rw = hasSidebar ? box_w : (box_w + sbr_w - (bdr_s * 2)); - s->scene.ui_viz_ro = hasSidebar ? -(sbr_w - 6 * bdr_s) : 0; } void ui_update(UIState *s) { - int err; - - if (s->vision_connect_firstrun) { - // cant run this in connector thread because opengl. - // do this here for now in lieu of a run_on_main_thread event - - for (int i=0; ikhr[i] != 0) { - visionimg_destroy_gl(s->khr[i], s->priv_hnds[i]); - glDeleteTextures(1, &s->frame_texs[i]); - } - - VisionImg img = { - .fd = s->bufs[i].fd, - .format = VISIONIMG_FORMAT_RGB24, - .width = s->rgb_width, - .height = s->rgb_height, - .stride = s->rgb_stride, - .bpp = 3, - .size = s->rgb_buf_len, - }; - #ifndef QCOM - s->priv_hnds[i] = s->bufs[i].addr; - #endif - s->frame_texs[i] = visionimg_to_gl(&img, &s->khr[i], &s->priv_hnds[i]); - - glBindTexture(GL_TEXTURE_2D, s->frame_texs[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - // BGR - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); - } - - for (int i=0; ikhr_front[i] != 0) { - visionimg_destroy_gl(s->khr_front[i], s->priv_hnds_front[i]); - glDeleteTextures(1, &s->frame_front_texs[i]); - } - VisionImg img = { - .fd = s->front_bufs[i].fd, - .format = VISIONIMG_FORMAT_RGB24, - .width = s->rgb_front_width, - .height = s->rgb_front_height, - .stride = s->rgb_front_stride, - .bpp = 3, - .size = s->rgb_front_buf_len, - }; - #ifndef QCOM - s->priv_hnds_front[i] = s->bufs[i].addr; - #endif - s->frame_front_texs[i] = visionimg_to_gl(&img, &s->khr_front[i], &s->priv_hnds_front[i]); - - glBindTexture(GL_TEXTURE_2D, s->frame_front_texs[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - // BGR - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); - } + update_sockets(s); + ui_update_vision(s); - assert(glGetError() == GL_NO_ERROR); + // Handle onroad/offroad transition + if (!s->started && s->status != STATUS_OFFROAD) { + s->status = STATUS_OFFROAD; + s->active_app = cereal::UiLayoutState::App::HOME; + s->scene.uilayout_sidebarcollapsed = false; + } else if (s->started && s->status == STATUS_OFFROAD) { + s->status = STATUS_DISENGAGED; + s->started_frame = s->sm->frame; + s->active_app = cereal::UiLayoutState::App::NONE; s->scene.uilayout_sidebarcollapsed = true; - s->scene.ui_viz_rx = (box_x-sbr_w+bdr_s*2); - s->scene.ui_viz_rw = (box_w+sbr_w-(bdr_s*2)); - s->scene.ui_viz_ro = 0; - - s->vision_connect_firstrun = false; - - s->alert_blinking_alpha = 1.0; s->alert_blinked = false; + s->alert_blinking_alpha = 1.0; + s->scene.alert_size = cereal::ControlsState::AlertSize::NONE; } - zmq_pollitem_t polls[1] = {{0}}; - // Take an rgb image from visiond if there is one - assert(s->ipc_fd >= 0); - while(true) { - if (s->ipc_fd < 0) { - // TODO: rethink this, for now it should only trigger on PC - LOGW("vision disconnected by other thread"); - s->vision_connected = false; - return; - } - polls[0].fd = s->ipc_fd; - polls[0].events = ZMQ_POLLIN; - #ifdef UI_60FPS - // uses more CPU in both UI and surfaceflinger - // 16% / 21% - int ret = zmq_poll(polls, 1, 1); - #else - // 9% / 13% = a 14% savings - int ret = zmq_poll(polls, 1, 1000); - #endif - if (ret < 0) { - if (errno == EINTR || errno == EAGAIN) continue; - - LOGE("poll failed (%d - %d)", ret, errno); - close(s->ipc_fd); - s->ipc_fd = -1; - s->vision_connected = false; - return; - } else if (ret == 0) { - break; - } - // vision ipc event - VisionPacket rp; - err = vipc_recv(s->ipc_fd, &rp); - if (err <= 0) { - LOGW("vision disconnected"); - close(s->ipc_fd); - s->ipc_fd = -1; - s->vision_connected = false; - return; - } - if (rp.type == VIPC_STREAM_ACQUIRE) { - bool front = rp.d.stream_acq.type == VISION_STREAM_RGB_FRONT; - int idx = rp.d.stream_acq.idx; - - int release_idx; - if (front) { - release_idx = s->cur_vision_front_idx; - } else { - release_idx = s->cur_vision_idx; - } - if (release_idx >= 0) { - VisionPacket rep = { - .type = VIPC_STREAM_RELEASE, - .d = { .stream_rel = { - .type = rp.d.stream_acq.type, - .idx = release_idx, - }}, - }; - vipc_send(s->ipc_fd, &rep); + // Handle controls timeout + bool controls_timeout = ((s->sm)->frame - (s->sm)->rcv_frame("controlsState")) > 10*UI_FREQ; + if (s->started && !s->scene.frontview && controls_timeout) { + if ((s->sm)->rcv_frame("controlsState") < s->started_frame) { + // car is started, but controlsState hasn't been seen at all + s->scene.alert_text1 = "openpilot Unavailable"; + s->scene.alert_text2 = "Waiting for controls to start"; + s->scene.alert_size = cereal::ControlsState::AlertSize::MID; + } else { + // car is started, but controls is lagging or died + if (s->scene.alert_text2 != "Controls Unresponsive") { + s->sound.play(AudibleAlert::CHIME_WARNING_REPEAT); + LOGE("Controls unresponsive"); } - if (front) { - assert(idx < UI_BUF_COUNT); - s->cur_vision_front_idx = idx; - } else { - assert(idx < UI_BUF_COUNT); - s->cur_vision_idx = idx; - // printf("v %d\n", ((uint8_t*)s->bufs[idx].addr)[0]); - } - } else { - assert(false); + s->scene.alert_text1 = "TAKE CONTROL IMMEDIATELY"; + s->scene.alert_text2 = "Controls Unresponsive"; + s->scene.alert_size = cereal::ControlsState::AlertSize::FULL; + s->status = STATUS_ALERT; } - break; } -} - -static int vision_subscribe(int fd, VisionPacket *rp, VisionStreamType type) { - int err; - LOGW("vision_subscribe type:%d", type); - - VisionPacket p1 = { - .type = VIPC_STREAM_SUBSCRIBE, - .d = { .stream_sub = { .type = type, .tbuffer = true, }, }, - }; - err = vipc_send(fd, &p1); - if (err < 0) { - close(fd); - return 0; - } - - do { - err = vipc_recv(fd, rp); - if (err <= 0) { - close(fd); - return 0; - } - // release what we aren't ready for yet - if (rp->type == VIPC_STREAM_ACQUIRE) { - VisionPacket rep = { - .type = VIPC_STREAM_RELEASE, - .d = { .stream_rel = { - .type = rp->d.stream_acq.type, - .idx = rp->d.stream_acq.idx, - }}, - }; - vipc_send(fd, &rep); + // Read params + if ((s->sm)->frame % (5*UI_FREQ) == 0) { + read_param(&s->is_metric, "IsMetric"); + } else if ((s->sm)->frame % (6*UI_FREQ) == 0) { + int param_read = read_param(&s->last_athena_ping, "LastAthenaPingTime"); + if (param_read != 0) { // Failed to read param + s->scene.athenaStatus = NET_DISCONNECTED; + } else if (nanos_since_boot() - s->last_athena_ping < 70e9) { + s->scene.athenaStatus = NET_CONNECTED; + } else { + s->scene.athenaStatus = NET_ERROR; } - } while (rp->type != VIPC_STREAM_BUFS || rp->d.stream_bufs.type != type); - - return 1; -} - -void* vision_connect_thread(void *args) { - set_thread_name("vision_connect"); - - UIState *s = (UIState*)args; - while (!do_exit) { - usleep(100000); - pthread_mutex_lock(&s->lock); - bool connected = s->vision_connected; - pthread_mutex_unlock(&s->lock); - if (connected) continue; - - int fd = vipc_connect(); - if (fd < 0) continue; - - VisionPacket back_rp, front_rp; - if (!vision_subscribe(fd, &back_rp, VISION_STREAM_RGB_BACK)) continue; - if (!vision_subscribe(fd, &front_rp, VISION_STREAM_RGB_FRONT)) continue; - - pthread_mutex_lock(&s->lock); - assert(!s->vision_connected); - s->ipc_fd = fd; - - ui_init_vision(s, - back_rp.d.stream_bufs, back_rp.num_fds, back_rp.fds, - front_rp.d.stream_bufs, front_rp.num_fds, front_rp.fds); - - s->vision_connected = true; - s->vision_seen = true; - s->vision_connect_firstrun = true; - - // Drain sockets - s->sm->drain(); - - pthread_mutex_unlock(&s->lock); } - return NULL; } diff --git a/selfdrive/ui/ui.hpp b/selfdrive/ui/ui.hpp index 5d6284b919..68edcfa92d 100644 --- a/selfdrive/ui/ui.hpp +++ b/selfdrive/ui/ui.hpp @@ -11,11 +11,11 @@ #define NANOVG_GLES3_IMPLEMENTATION #define nvgCreate nvgCreateGLES3 #endif -#include +#include +#include #include #include -#include #include "nanovg.h" @@ -27,16 +27,6 @@ #include "common/params.h" #include "sound.hpp" -#define STATUS_STOPPED 0 -#define STATUS_DISENGAGED 1 -#define STATUS_ENGAGED 2 -#define STATUS_WARNING 3 -#define STATUS_ALERT 4 - -#define NET_CONNECTED 0 -#define NET_DISCONNECTED 1 -#define NET_ERROR 2 - #define COLOR_BLACK nvgRGBA(0, 0, 0, 255) #define COLOR_BLACK_ALPHA(x) nvgRGBA(0, 0, 0, x) #define COLOR_WHITE nvgRGBA(255, 255, 255, 255) @@ -45,10 +35,6 @@ #define COLOR_RED nvgRGBA(201, 34, 49, 255) #define COLOR_OCHRE nvgRGBA(218, 111, 37, 255) -#ifndef QCOM - #define UI_60FPS -#endif - #define UI_BUF_COUNT 4 // TODO: Detect dynamically @@ -82,7 +68,7 @@ const int home_btn_w = 180; const int home_btn_x = 60; const int home_btn_y = vwp_h - home_btn_h - 40; -const int UI_FREQ = 30; // Hz +const int UI_FREQ = 20; // Hz const int MODEL_PATH_MAX_VERTICES_CNT = 98; const int MODEL_LANE_PATH_CNT = 2; @@ -90,33 +76,45 @@ const int TRACK_POINTS_MAX_CNT = 50 * 2; const int SET_SPEED_NA = 255; -const uint8_t bg_colors[][4] = { - [STATUS_STOPPED] = {0x07, 0x23, 0x39, 0xff}, - [STATUS_DISENGAGED] = {0x17, 0x33, 0x49, 0xff}, - [STATUS_ENGAGED] = {0x17, 0x86, 0x44, 0xff}, - [STATUS_WARNING] = {0xDA, 0x6F, 0x25, 0xff}, - [STATUS_ALERT] = {0xC9, 0x22, 0x31, 0xff}, +typedef struct Color { + uint8_t r, g, b; +} Color; + +typedef enum NetStatus { + NET_CONNECTED, + NET_DISCONNECTED, + NET_ERROR, +} NetStatus; + +typedef enum UIStatus { + STATUS_OFFROAD, + STATUS_DISENGAGED, + STATUS_ENGAGED, + STATUS_WARNING, + STATUS_ALERT, +} UIStatus; + +static std::map bg_colors = { + {STATUS_OFFROAD, {0x07, 0x23, 0x39}}, + {STATUS_DISENGAGED, {0x17, 0x33, 0x49}}, + {STATUS_ENGAGED, {0x17, 0x86, 0x44}}, + {STATUS_WARNING, {0xDA, 0x6F, 0x25}}, + {STATUS_ALERT, {0xC9, 0x22, 0x31}}, }; typedef struct UIScene { - int frontview; - int fullview; float mpc_x[50]; float mpc_y[50]; - bool world_objects_visible; mat4 extrinsic_matrix; // Last row is 0 so we can use mat4. - - float speedlimit; - bool speedlimit_valid; + bool world_objects_visible; bool is_rhd; + bool frontview; bool uilayout_sidebarcollapsed; // responsive layout - int ui_viz_rx; - int ui_viz_rw; - int ui_viz_ro; + int ui_viz_rx, ui_viz_rw, ui_viz_ro; std::string alert_text1; std::string alert_text2; @@ -125,7 +123,7 @@ typedef struct UIScene { cereal::HealthData::HwType hwType; int satelliteCount; - uint8_t athenaStatus; + NetStatus athenaStatus; cereal::ThermalData::Reader thermal; cereal::RadarState::LeadData::Reader lead_data[2]; @@ -154,8 +152,6 @@ typedef struct { typedef struct UIState { - pthread_mutex_t lock; - // framebuffer FramebufferState *fb; int fb_w, fb_h; @@ -176,77 +172,48 @@ typedef struct UIState { int img_battery_charging; int img_network[6]; - // sockets SubMaster *sm; + Sound sound; + UIStatus status; + UIScene scene; cereal::UiLayoutState::App active_app; // vision state bool vision_connected; - bool vision_connect_firstrun; - int ipc_fd; - - VIPCBuf bufs[UI_BUF_COUNT]; - VIPCBuf front_bufs[UI_BUF_COUNT]; - int cur_vision_idx; - int cur_vision_front_idx; + VisionStream stream; + // graphics GLuint frame_program; GLuint frame_texs[UI_BUF_COUNT]; EGLImageKHR khr[UI_BUF_COUNT]; void *priv_hnds[UI_BUF_COUNT]; - GLuint frame_front_texs[UI_BUF_COUNT]; - EGLImageKHR khr_front[UI_BUF_COUNT]; - void *priv_hnds_front[UI_BUF_COUNT]; GLint frame_pos_loc, frame_texcoord_loc; GLint frame_texture_loc, frame_transform_loc; + GLuint frame_vao[2], frame_vbo[2], frame_ibo[2]; + mat4 rear_frame_mat, front_frame_mat; - int rgb_width, rgb_height, rgb_stride; - size_t rgb_buf_len; - - int rgb_front_width, rgb_front_height, rgb_front_stride; - size_t rgb_front_buf_len; - - UIScene scene; + // device state bool awake; - int awake_timeout; - bool controls_seen; + std::atomic light_sensor; - uint64_t last_athena_ping; - int status; + bool started; bool is_metric; bool longitudinal_control; - bool is_ego_over_limit; - float alert_blinking_alpha; - bool alert_blinked; - bool started; - bool vision_seen; - - std::atomic light_sensor; - - int touch_fd; - - GLuint frame_vao[2], frame_vbo[2], frame_ibo[2]; - mat4 rear_frame_mat, front_frame_mat; + uint64_t last_athena_ping; + uint64_t started_frame; - model_path_vertices_data model_path_vertices[MODEL_LANE_PATH_CNT * 2]; + bool alert_blinked; + float alert_blinking_alpha; track_vertices_data track_vertices[2]; - - Sound sound; + model_path_vertices_data model_path_vertices[MODEL_LANE_PATH_CNT * 2]; } UIState; - void ui_init(UIState *s); void ui_update(UIState *s); -void ui_update_sizes(UIState *s); - -void* vision_connect_thread(void *args); -void check_messages(UIState *s); -void update_status(UIState *s, int status); - int write_param_float(float param, const char* param_name, bool persistent_param = false); template