Merge branch 'master' of https://github.com/commaai/openpilot into qt-scrolling

pull/20392/head
Comma Device 4 years ago
commit d42cf5100e
  1. 2
      .dockerignore
  2. 1
      common/params_pyx.pyx
  3. 4
      launch.sh
  4. 1
      release/files_common
  5. 2
      selfdrive/car/chrysler/carcontroller.py
  6. 1
      selfdrive/car/honda/values.py
  7. 2
      selfdrive/car/toyota/values.py
  8. 14
      selfdrive/locationd/locationd.py
  9. 2
      selfdrive/locationd/models/live_kf.py
  10. 14
      selfdrive/locationd/paramsd.py
  11. 3
      selfdrive/manager/manager.py
  12. 2
      selfdrive/test/process_replay/ref_commit
  13. 4
      selfdrive/test/profiling/lib.py
  14. 3
      selfdrive/test/profiling/profiler.py
  15. 2
      selfdrive/ui/SConscript
  16. 49
      selfdrive/ui/qt/offroad/onboarding.cc
  17. 5
      selfdrive/ui/qt/offroad/onboarding.hpp
  18. 18
      selfdrive/ui/qt/offroad/settings.cc
  19. 3
      selfdrive/ui/qt/offroad/settings.hpp
  20. 11
      selfdrive/ui/qt/setup/installer.cc
  21. 1
      selfdrive/ui/qt/widgets/input.cc
  22. 22
      selfdrive/ui/qt/widgets/offroad_alerts.cc
  23. 2
      selfdrive/ui/qt/widgets/offroad_alerts.hpp

@ -1,4 +1,4 @@
.git **/.git
.DS_Store .DS_Store
*.dylib *.dylib
*.DSYM *.DSYM

@ -55,6 +55,7 @@ keys = {
b"PandaDongleId": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT], b"PandaDongleId": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
b"Passive": [TxType.PERSISTENT], b"Passive": [TxType.PERSISTENT],
b"RecordFront": [TxType.PERSISTENT], b"RecordFront": [TxType.PERSISTENT],
b"RecordFrontLock": [TxType.PERSISTENT], # for the internal fleet
b"ReleaseNotes": [TxType.PERSISTENT], b"ReleaseNotes": [TxType.PERSISTENT],
b"ShouldDoUpdate": [TxType.CLEAR_ON_MANAGER_START], b"ShouldDoUpdate": [TxType.CLEAR_ON_MANAGER_START],
b"SubscriberInfo": [TxType.PERSISTENT], b"SubscriberInfo": [TxType.PERSISTENT],

@ -1,4 +0,0 @@
#!/usr/bin/bash
export PASSIVE="0"
exec ./launch_chffrplus.sh

@ -1,6 +1,5 @@
.gitignore .gitignore
LICENSE LICENSE
launch.sh
launch_env.sh launch_env.sh
launch_chffrplus.sh launch_chffrplus.sh
launch_openpilot.sh launch_openpilot.sh

@ -32,7 +32,7 @@ class CarController():
moving_fast = CS.out.vEgo > CS.CP.minSteerSpeed # for status message moving_fast = CS.out.vEgo > CS.CP.minSteerSpeed # for status message
if CS.out.vEgo > (CS.CP.minSteerSpeed - 0.5): # for command high bit if CS.out.vEgo > (CS.CP.minSteerSpeed - 0.5): # for command high bit
self.gone_fast_yet = True self.gone_fast_yet = True
elif self.car_fingerprint in (CAR.PACIFICA_2019_HYBRID, CAR.JEEP_CHEROKEE_2019): elif self.car_fingerprint in (CAR.PACIFICA_2019_HYBRID, CAR.PACIFICA_2020, CAR.JEEP_CHEROKEE_2019):
if CS.out.vEgo < (CS.CP.minSteerSpeed - 3.0): if CS.out.vEgo < (CS.CP.minSteerSpeed - 3.0):
self.gone_fast_yet = False # < 14.5m/s stock turns off this bit, but fine down to 13.5 self.gone_fast_yet = False # < 14.5m/s stock turns off this bit, but fine down to 13.5
lkas_active = moving_fast and enabled lkas_active = moving_fast and enabled

@ -943,6 +943,7 @@ FW_VERSIONS = {
], ],
(Ecu.fwdRadar, 0x18dab0f1, None): [ (Ecu.fwdRadar, 0x18dab0f1, None): [
b'36802-TJB-A040\x00\x00', b'36802-TJB-A040\x00\x00',
b'36802-TJB-A050\x00\x00',
], ],
(Ecu.fwdCamera, 0x18dab5f1, None): [ (Ecu.fwdCamera, 0x18dab5f1, None): [
b'36161-TJB-A040\x00\x00', b'36161-TJB-A040\x00\x00',

@ -859,6 +859,7 @@ FW_VERSIONS = {
], ],
(Ecu.engine, 0x7e0, None): [ (Ecu.engine, 0x7e0, None): [
b'\x02353P7000\x00\x00\x00\x00\x00\x00\x00\x00530J5000\x00\x00\x00\x00\x00\x00\x00\x00', b'\x02353P7000\x00\x00\x00\x00\x00\x00\x00\x00530J5000\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x02353P9000\x00\x00\x00\x00\x00\x00\x00\x00553C1000\x00\x00\x00\x00\x00\x00\x00\x00',
], ],
(Ecu.esp, 0x7b0, None): [ (Ecu.esp, 0x7b0, None): [
b'F152653330\x00\x00\x00\x00\x00\x00', b'F152653330\x00\x00\x00\x00\x00\x00',
@ -870,6 +871,7 @@ FW_VERSIONS = {
b'881515306200\x00\x00\x00\x00', b'881515306200\x00\x00\x00\x00',
], ],
(Ecu.eps, 0x7a1, None): [ (Ecu.eps, 0x7a1, None): [
b'8965B53270\x00\x00\x00\x00\x00\x00',
b'8965B53271\x00\x00\x00\x00\x00\x00', b'8965B53271\x00\x00\x00\x00\x00\x00',
b'8965B53280\x00\x00\x00\x00\x00\x00', b'8965B53280\x00\x00\x00\x00\x00\x00',
b'8965B53281\x00\x00\x00\x00\x00\x00', b'8965B53281\x00\x00\x00\x00\x00\x00',

@ -62,7 +62,7 @@ class Localizer():
self.calib = np.zeros(3) self.calib = np.zeros(3)
self.device_from_calib = np.eye(3) self.device_from_calib = np.eye(3)
self.calib_from_device = np.eye(3) self.calib_from_device = np.eye(3)
self.calibrated = 0 self.calibrated = False
self.H = get_H() self.H = get_H()
self.posenet_invalid_count = 0 self.posenet_invalid_count = 0
@ -77,7 +77,7 @@ class Localizer():
self.device_fell = False self.device_fell = False
@staticmethod @staticmethod
def msg_from_state(converter, calib_from_device, H, predicted_state, predicted_cov): def msg_from_state(converter, calib_from_device, H, predicted_state, predicted_cov, calibrated):
predicted_std = np.sqrt(np.diagonal(predicted_cov)) predicted_std = np.sqrt(np.diagonal(predicted_cov))
fix_ecef = predicted_state[States.ECEF_POS] fix_ecef = predicted_state[States.ECEF_POS]
@ -130,12 +130,12 @@ class Localizer():
(fix.velocityDevice, vel_device, vel_device_std, True), (fix.velocityDevice, vel_device, vel_device_std, True),
(fix.accelerationDevice, predicted_state[States.ACCELERATION], predicted_std[States.ACCELERATION_ERR], True), (fix.accelerationDevice, predicted_state[States.ACCELERATION], predicted_std[States.ACCELERATION_ERR], True),
(fix.orientationECEF, orientation_ecef, orientation_ecef_std, True), (fix.orientationECEF, orientation_ecef, orientation_ecef_std, True),
(fix.calibratedOrientationECEF, calibrated_orientation_ecef, np.nan*np.zeros(3), True), (fix.calibratedOrientationECEF, calibrated_orientation_ecef, np.nan*np.zeros(3), calibrated),
(fix.orientationNED, orientation_ned, np.nan*np.zeros(3), True), (fix.orientationNED, orientation_ned, np.nan*np.zeros(3), True),
(fix.angularVelocityDevice, predicted_state[States.ANGULAR_VELOCITY], predicted_std[States.ANGULAR_VELOCITY_ERR], True), (fix.angularVelocityDevice, predicted_state[States.ANGULAR_VELOCITY], predicted_std[States.ANGULAR_VELOCITY_ERR], True),
(fix.velocityCalibrated, vel_calib, vel_calib_std, True), (fix.velocityCalibrated, vel_calib, vel_calib_std, calibrated),
(fix.angularVelocityCalibrated, ang_vel_calib, ang_vel_calib_std, True), (fix.angularVelocityCalibrated, ang_vel_calib, ang_vel_calib_std, calibrated),
(fix.accelerationCalibrated, acc_calib, acc_calib_std, True), (fix.accelerationCalibrated, acc_calib, acc_calib_std, calibrated),
] ]
for field, value, std, valid in measurements: for field, value, std, valid in measurements:
@ -147,7 +147,7 @@ class Localizer():
return fix return fix
def liveLocationMsg(self): def liveLocationMsg(self):
fix = self.msg_from_state(self.converter, self.calib_from_device, self.H, self.kf.x, self.kf.P) fix = self.msg_from_state(self.converter, self.calib_from_device, self.H, self.kf.x, self.kf.P, self.calibrated)
# experimentally found these values, no false positives in 20k minutes of driving # experimentally found these values, no false positives in 20k minutes of driving
old_mean, new_mean = np.mean(self.posenet_stds[:POSENET_STD_HIST//2]), np.mean(self.posenet_stds[POSENET_STD_HIST//2:]) old_mean, new_mean = np.mean(self.posenet_stds[:POSENET_STD_HIST//2]), np.mean(self.posenet_stds[POSENET_STD_HIST//2:])
std_spike = new_mean/old_mean > 4 and new_mean > 7 std_spike = new_mean/old_mean > 4 and new_mean > 7

@ -201,7 +201,7 @@ class LiveKalman():
ObservationKind.PHONE_ACCEL: np.diag([.5**2, .5**2, .5**2]), ObservationKind.PHONE_ACCEL: np.diag([.5**2, .5**2, .5**2]),
ObservationKind.CAMERA_ODO_ROTATION: np.diag([0.05**2, 0.05**2, 0.05**2]), ObservationKind.CAMERA_ODO_ROTATION: np.diag([0.05**2, 0.05**2, 0.05**2]),
ObservationKind.IMU_FRAME: np.diag([0.05**2, 0.05**2, 0.05**2]), ObservationKind.IMU_FRAME: np.diag([0.05**2, 0.05**2, 0.05**2]),
ObservationKind.NO_ROT: np.diag([0.00025**2, 0.00025**2, 0.00025**2]), ObservationKind.NO_ROT: np.diag([0.005**2, 0.005**2, 0.005**2]),
ObservationKind.ECEF_POS: np.diag([5**2, 5**2, 5**2]), ObservationKind.ECEF_POS: np.diag([5**2, 5**2, 5**2]),
ObservationKind.ECEF_VEL: np.diag([.5**2, .5**2, .5**2]), ObservationKind.ECEF_VEL: np.diag([.5**2, .5**2, .5**2]),
ObservationKind.ECEF_ORIENTATION_FROM_GPS: np.diag([.2**2, .2**2, .2**2, .2**2])} ObservationKind.ECEF_ORIENTATION_FROM_GPS: np.diag([.2**2, .2**2, .2**2, .2**2])}

@ -5,14 +5,12 @@ import json
import numpy as np import numpy as np
import cereal.messaging as messaging import cereal.messaging as messaging
from cereal import car, log from cereal import car
from common.params import Params, put_nonblocking from common.params import Params, put_nonblocking
from selfdrive.locationd.models.car_kf import CarKalman, ObservationKind, States from selfdrive.locationd.models.car_kf import CarKalman, ObservationKind, States
from selfdrive.locationd.models.constants import GENERATED_DIR from selfdrive.locationd.models.constants import GENERATED_DIR
from selfdrive.swaglog import cloudlog from selfdrive.swaglog import cloudlog
KalmanStatus = log.LiveLocationKalman.Status
class ParamsLearner: class ParamsLearner:
def __init__(self, CP, steer_ratio, stiffness_factor, angle_offset): def __init__(self, CP, steer_ratio, stiffness_factor, angle_offset):
@ -38,9 +36,10 @@ class ParamsLearner:
yaw_rate = msg.angularVelocityCalibrated.value[2] yaw_rate = msg.angularVelocityCalibrated.value[2]
yaw_rate_std = msg.angularVelocityCalibrated.std[2] yaw_rate_std = msg.angularVelocityCalibrated.std[2]
yaw_rate_valid = msg.angularVelocityCalibrated.valid
if self.active: if self.active:
if msg.inputsOK and msg.posenetOK and msg.status == KalmanStatus.valid: if msg.inputsOK and msg.posenetOK and yaw_rate_valid:
self.kf.predict_and_observe(t, self.kf.predict_and_observe(t,
ObservationKind.ROAD_FRAME_YAW_RATE, ObservationKind.ROAD_FRAME_YAW_RATE,
np.array([[[-yaw_rate]]]), np.array([[[-yaw_rate]]]),
@ -89,9 +88,10 @@ def main(sm=None, pm=None):
params = None params = None
try: try:
if params is not None and not all(( angle_offset_sane = abs(params.get('angleOffsetAverageDeg')) < 10.0
abs(params.get('angleOffsetAverageDeg')) < 10.0, steer_ratio_sane = min_sr <= params['steerRatio'] <= max_sr
min_sr <= params['steerRatio'] <= max_sr)): params_sane = angle_offset_sane and steer_ratio_sane
if params is not None and not params_sane:
cloudlog.info(f"Invalid starting values found {params}") cloudlog.info(f"Invalid starting values found {params}")
params = None params = None
except Exception as e: except Exception as e:

@ -45,6 +45,9 @@ def manager_init(spinner=None):
("IsDriverViewEnabled", "0"), ("IsDriverViewEnabled", "0"),
] ]
if params.get("RecordFrontLock", encoding='utf-8') == "1":
params.put("RecordFront", "1")
# set unset params # set unset params
for k, v in default_params: for k, v in default_params:
if params.get(k) is None: if params.get(k) is None:

@ -1 +1 @@
f7af4a6523a7afa631460f5168646ca32c8fa4b3 f88eda1b667eac0654f65281a16e7713836cb705

@ -1,4 +1,5 @@
from collections import defaultdict from collections import defaultdict
from cereal.services import service_list
import cereal.messaging as messaging import cereal.messaging as messaging
import capnp import capnp
@ -45,6 +46,7 @@ class SubMaster(messaging.SubMaster):
self.valid = {s: True for s in services} self.valid = {s: True for s in services}
self.logMonoTime = {} self.logMonoTime = {}
self.sock = {} self.sock = {}
self.freq = {}
# TODO: specify multiple triggers for service like plannerd that poll on more than one service # TODO: specify multiple triggers for service like plannerd that poll on more than one service
cur_msgs = [] cur_msgs = []
@ -55,8 +57,10 @@ class SubMaster(messaging.SubMaster):
if msg.which() == trigger: if msg.which() == trigger:
self.msgs.append(cur_msgs) self.msgs.append(cur_msgs)
cur_msgs = [] cur_msgs = []
self.msgs = list(reversed(self.msgs))
for s in services: for s in services:
self.freq[s] = service_list[s].frequency
try: try:
data = messaging.new_message(s) data = messaging.new_message(s)
except capnp.lib.capnp.KjException: except capnp.lib.capnp.KjException:

@ -15,6 +15,7 @@ BASE_URL = "https://commadataci.blob.core.windows.net/openpilotci/"
CARS = { CARS = {
'toyota': ("77611a1fac303767|2020-02-29--13-29-33/3", "TOYOTA COROLLA TSS2 2019"), 'toyota': ("77611a1fac303767|2020-02-29--13-29-33/3", "TOYOTA COROLLA TSS2 2019"),
'honda': ("99c94dc769b5d96e|2019-08-03--14-19-59/2", "HONDA CIVIC 2016 TOURING"), 'honda': ("99c94dc769b5d96e|2019-08-03--14-19-59/2", "HONDA CIVIC 2016 TOURING"),
"vw": ("e2a273d7e6eecec2|2021-03-03--16-05-26/4", "AUDI A3"),
} }
@ -40,7 +41,7 @@ def get_inputs(msgs, process):
return sm, pm, can_sock return sm, pm, can_sock
def profile(proc, func, car='toyota'): def profile(proc, func, car='vw'):
segment, fingerprint = CARS[car] segment, fingerprint = CARS[car]
segment = segment.replace('|', '/') segment = segment.replace('|', '/')
rlog_url = f"{BASE_URL}{segment}/rlog.bz2" rlog_url = f"{BASE_URL}{segment}/rlog.bz2"

@ -59,6 +59,8 @@ else:
for name, branch in installers: for name, branch in installers:
d = {'BRANCH': f"'\"{branch}\"'"} d = {'BRANCH': f"'\"{branch}\"'"}
if "internal" in name: if "internal" in name:
d['INTERNAL'] = "1"
import requests import requests
r = requests.get("https://github.com/commaci2.keys") r = requests.get("https://github.com/commaci2.keys")
r.raise_for_status() r.raise_for_status()

@ -6,7 +6,7 @@
#include <QGridLayout> #include <QGridLayout>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QPainter>
#include "common/params.h" #include "common/params.h"
#include "onboarding.hpp" #include "onboarding.hpp"
#include "home.hpp" #include "home.hpp"
@ -14,48 +14,40 @@
#include <QEasingCurve> #include <QEasingCurve>
void TrainingGuide::mouseReleaseEvent(QMouseEvent *e) { void TrainingGuide::mouseReleaseEvent(QMouseEvent *e) {
int leftOffset = (geometry().width()-1620)/2; int leftOffset = (geometry().width()-1620)/2;
int mousex = e->x()-leftOffset; int mousex = e->x()-leftOffset;
int mousey = e->y(); int mousey = e->y();
// Check for restart // Check for restart
if (currentIndex == boundingBox.size()-1) { if (currentIndex == (boundingBox.size() - 1) && 1050 <= mousex && mousex <= 1500 && 773 <= mousey && mousey <= 954) {
if (1050 <= mousex && mousex <= 1500 && 773 <= mousey && mousey <= 954){ currentIndex = 0;
slayout->setCurrentIndex(0); } else if (boundingBox[currentIndex][0] <= mousex && mousex <= boundingBox[currentIndex][1] && boundingBox[currentIndex][2] <= mousey && mousey <= boundingBox[currentIndex][3]) {
currentIndex = 0; ++currentIndex;
return;
}
}
if (boundingBox[currentIndex][0] <= mousex && mousex <= boundingBox[currentIndex][1] && boundingBox[currentIndex][2] <= mousey && mousey <= boundingBox[currentIndex][3]) {
slayout->setCurrentIndex(++currentIndex);
} }
if (currentIndex >= boundingBox.size()) { if (currentIndex >= boundingBox.size()) {
emit completedTraining(); emit completedTraining();
return; return;
} }
image.load("../assets/training/step" + QString::number(currentIndex) + ".jpg");
repaint();
} }
TrainingGuide::TrainingGuide(QWidget* parent) { TrainingGuide::TrainingGuide(QWidget* parent) {
QHBoxLayout* hlayout = new QHBoxLayout; image.load("../assets/training/step0.jpg");
}
slayout = new QStackedLayout(this);
for (int i = 0; i < boundingBox.size(); i++) {
QWidget* w = new QWidget;
w->setStyleSheet(".QWidget {background-image: url(../assets/training/step" + QString::number(i) + ".jpg);}");
w->setFixedSize(1620, 1080);
slayout->addWidget(w);
}
QWidget* sw = new QWidget(); void TrainingGuide::paintEvent(QPaintEvent *event) {
sw->setLayout(slayout); QPainter painter(this);
hlayout->addWidget(sw, 1, Qt::AlignCenter);
setLayout(hlayout); QRect devRect(0, 0, painter.device()->width(), painter.device()->height());
setStyleSheet(R"( QBrush bgBrush("#072339");
background-color: #072339; painter.fillRect(devRect, bgBrush);
)");
QRect rect(image.rect());
rect.moveCenter(devRect.center());
painter.drawImage(rect.topLeft(), image);
} }
@ -161,7 +153,6 @@ OnboardingWindow::OnboardingWindow(QWidget *parent) : QStackedWidget(parent) {
bool accepted_terms = params.get("HasAcceptedTerms", false).compare(current_terms_version) == 0; bool accepted_terms = params.get("HasAcceptedTerms", false).compare(current_terms_version) == 0;
bool training_done = params.get("CompletedTrainingVersion", false).compare(current_training_version) == 0; bool training_done = params.get("CompletedTrainingVersion", false).compare(current_training_version) == 0;
// TODO: fix this, training guide is slow
// Don't initialize widgets unless neccesary. // Don't initialize widgets unless neccesary.
if (accepted_terms && training_done) { if (accepted_terms && training_done) {
return; return;

@ -3,9 +3,9 @@
#include <QWidget> #include <QWidget>
#include <QScroller> #include <QScroller>
#include <QStackedWidget> #include <QStackedWidget>
#include <QStackedLayout>
#include <QTextEdit> #include <QTextEdit>
#include <QMouseEvent> #include <QMouseEvent>
#include <QImage>
class TrainingGuide : public QFrame { class TrainingGuide : public QFrame {
Q_OBJECT Q_OBJECT
@ -15,10 +15,11 @@ public:
protected: protected:
void mouseReleaseEvent(QMouseEvent* e) override; void mouseReleaseEvent(QMouseEvent* e) override;
void paintEvent(QPaintEvent *event) override;
private: private:
int currentIndex = 0; int currentIndex = 0;
QStackedLayout* slayout; QImage image;
// Vector of bounding boxes for the a given training guide step. (minx, maxx, miny, maxy) // Vector of bounding boxes for the a given training guide step. (minx, maxx, miny, maxy)
QVector<QVector<int>> boundingBox {{250, 930, 750, 900}, {280, 1280, 650, 950}, {330, 1130, 590, 900}, {910, 1580, 500, 1000}, {1180, 1300, 630, 720}, {290, 1050, 590, 960}, QVector<QVector<int>> boundingBox {{250, 930, 750, 900}, {280, 1280, 650, 950}, {330, 1130, 590, 900}, {910, 1580, 500, 1000}, {1180, 1300, 630, 720}, {290, 1050, 590, 960},

@ -64,7 +64,7 @@ ParamsToggle::ParamsToggle(QString param, QString title, QString description, QS
layout->addWidget(label); layout->addWidget(label);
// toggle switch // toggle switch
Toggle *toggle = new Toggle(this); toggle = new Toggle(this);
toggle->setFixedSize(150, 100); toggle->setFixedSize(150, 100);
layout->addWidget(toggle); layout->addWidget(toggle);
QObject::connect(toggle, SIGNAL(stateChanged(int)), this, SLOT(checkboxClicked(int))); QObject::connect(toggle, SIGNAL(stateChanged(int)), this, SLOT(checkboxClicked(int)));
@ -104,12 +104,6 @@ QWidget * toggles_panel() {
"../assets/offroad/icon_warning.png" "../assets/offroad/icon_warning.png"
)); ));
toggles_list->addWidget(horizontal_line()); toggles_list->addWidget(horizontal_line());
toggles_list->addWidget(new ParamsToggle("RecordFront",
"Record and Upload Driver Camera",
"Upload data from the driver facing camera and help improve the driver monitoring algorithm.",
"../assets/offroad/icon_network.png"
));
toggles_list->addWidget(horizontal_line());
toggles_list->addWidget(new ParamsToggle("IsRHD", toggles_list->addWidget(new ParamsToggle("IsRHD",
"Enable Right-Hand Drive", "Enable Right-Hand Drive",
"Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat.", "Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat.",
@ -128,6 +122,16 @@ QWidget * toggles_panel() {
"../assets/offroad/icon_shell.png" "../assets/offroad/icon_shell.png"
)); ));
ParamsToggle *record_toggle = new ParamsToggle("RecordFront",
"Record and Upload Driver Camera",
"Upload data from the driver facing camera and help improve the driver monitoring algorithm.",
"../assets/offroad/icon_network.png");
toggles_list->addWidget(horizontal_line());
toggles_list->addWidget(record_toggle);
bool record_lock = Params().read_db_bool("RecordFrontLock");
record_toggle->toggle->setEnabled(!record_lock);
QWidget *widget = new QWidget; QWidget *widget = new QWidget;
widget->setLayout(toggles_list); widget->setLayout(toggles_list);
return widget; return widget;

@ -7,6 +7,8 @@
#include <QButtonGroup> #include <QButtonGroup>
#include <QStackedLayout> #include <QStackedLayout>
#include "selfdrive/ui/qt/widgets/toggle.hpp"
// *** settings widgets *** // *** settings widgets ***
class ParamsToggle : public QFrame { class ParamsToggle : public QFrame {
@ -15,6 +17,7 @@ class ParamsToggle : public QFrame {
public: public:
explicit ParamsToggle(QString param, QString title, QString description, explicit ParamsToggle(QString param, QString title, QString description,
QString icon, QWidget *parent = 0); QString icon, QWidget *parent = 0);
Toggle *toggle;
private: private:
QString param; QString param;

@ -37,14 +37,19 @@ int fresh_clone() {
err = std::system("mv /data/tmppilot /data/openpilot"); err = std::system("mv /data/tmppilot /data/openpilot");
if (err) return 1; if (err) return 1;
#ifdef SSH_KEYS #ifdef INTERNAL
err = std::system("mkdir -p /data/params/d/"); err = std::system("mkdir -p /data/params/d/");
if (err) return 1; if (err) return 1;
std::ofstream param; std::ofstream param;
param.open("/data/params/d/GithubSshKeys"); param.open("/data/params/d/RecordFrontLock");
param << SSH_KEYS; param << "1";
param.close(); param.close();
std::ofstream keys_param;
keys_param.open("/data/params/d/GithubSshKeys");
keys_param << SSH_KEYS;
keys_param.close();
#endif #endif
return 0; return 0;

@ -115,6 +115,7 @@ void InputDialog::setMinLength(int length){
ConfirmationDialog::ConfirmationDialog(QString prompt_text, QString confirm_text, QString cancel_text, ConfirmationDialog::ConfirmationDialog(QString prompt_text, QString confirm_text, QString cancel_text,
QWidget *parent):QDialog(parent) { QWidget *parent):QDialog(parent) {
setWindowFlags(Qt::Popup);
layout = new QVBoxLayout(); layout = new QVBoxLayout();
layout->setMargin(25); layout->setMargin(25);

@ -59,6 +59,13 @@ OffroadAlert::OffroadAlert(QWidget* parent) : QFrame(parent) {
} }
)"); )");
main_layout->setMargin(50); main_layout->setMargin(50);
QFile inFile("../controls/lib/alerts_offroad.json");
bool ret = inFile.open(QIODevice::ReadOnly | QIODevice::Text);
assert(ret);
QJsonDocument doc = QJsonDocument::fromJson(inFile.readAll());
assert(!doc.isNull());
alert_keys = doc.object().keys();
} }
void OffroadAlert::refresh() { void OffroadAlert::refresh() {
@ -109,20 +116,7 @@ void OffroadAlert::refresh() {
void OffroadAlert::parse_alerts() { void OffroadAlert::parse_alerts() {
alerts.clear(); alerts.clear();
for (const QString &key : alert_keys) {
// TODO: only read this once
QFile inFile("../controls/lib/alerts_offroad.json");
inFile.open(QIODevice::ReadOnly | QIODevice::Text);
QByteArray data = inFile.readAll();
inFile.close();
QJsonDocument doc = QJsonDocument::fromJson(data);
if (doc.isNull()) {
qDebug() << "Parse failed";
}
QJsonObject json = doc.object();
for (const QString &key : json.keys()) {
std::vector<char> bytes = Params().read_db_bytes(key.toStdString().c_str()); std::vector<char> bytes = Params().read_db_bytes(key.toStdString().c_str());
if (bytes.size()) { if (bytes.size()) {

@ -3,6 +3,7 @@
#include <QFrame> #include <QFrame>
#include <QStackedWidget> #include <QStackedWidget>
#include <QPushButton> #include <QPushButton>
#include <QStringList>
struct Alert { struct Alert {
QString text; QString text;
@ -15,6 +16,7 @@ class OffroadAlert : public QFrame {
public: public:
explicit OffroadAlert(QWidget *parent = 0); explicit OffroadAlert(QWidget *parent = 0);
QVector<Alert> alerts; QVector<Alert> alerts;
QStringList alert_keys;
bool updateAvailable; bool updateAvailable;
private: private:

Loading…
Cancel
Save