diff --git a/.dockerignore b/.dockerignore index 2681114555..5f791f3cdd 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,4 @@ -.git +**/.git .DS_Store *.dylib *.DSYM diff --git a/common/params_pyx.pyx b/common/params_pyx.pyx index cae66468a9..4f28881ce5 100755 --- a/common/params_pyx.pyx +++ b/common/params_pyx.pyx @@ -55,6 +55,7 @@ keys = { b"PandaDongleId": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT], b"Passive": [TxType.PERSISTENT], b"RecordFront": [TxType.PERSISTENT], + b"RecordFrontLock": [TxType.PERSISTENT], # for the internal fleet b"ReleaseNotes": [TxType.PERSISTENT], b"ShouldDoUpdate": [TxType.CLEAR_ON_MANAGER_START], b"SubscriberInfo": [TxType.PERSISTENT], diff --git a/launch.sh b/launch.sh deleted file mode 100755 index eeebfc9eb0..0000000000 --- a/launch.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/bash - -export PASSIVE="0" -exec ./launch_chffrplus.sh diff --git a/release/files_common b/release/files_common index 449337b00d..9afacded8f 100644 --- a/release/files_common +++ b/release/files_common @@ -1,6 +1,5 @@ .gitignore LICENSE -launch.sh launch_env.sh launch_chffrplus.sh launch_openpilot.sh diff --git a/selfdrive/car/chrysler/carcontroller.py b/selfdrive/car/chrysler/carcontroller.py index 3ab2ff842a..83c6fcf3cf 100644 --- a/selfdrive/car/chrysler/carcontroller.py +++ b/selfdrive/car/chrysler/carcontroller.py @@ -32,7 +32,7 @@ class CarController(): moving_fast = CS.out.vEgo > CS.CP.minSteerSpeed # for status message if CS.out.vEgo > (CS.CP.minSteerSpeed - 0.5): # for command high bit 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): 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 diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index e85ed25db0..fe9a290803 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -943,6 +943,7 @@ FW_VERSIONS = { ], (Ecu.fwdRadar, 0x18dab0f1, None): [ b'36802-TJB-A040\x00\x00', + b'36802-TJB-A050\x00\x00', ], (Ecu.fwdCamera, 0x18dab5f1, None): [ b'36161-TJB-A040\x00\x00', diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index c9a56449b1..39bbd9f73a 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -859,6 +859,7 @@ FW_VERSIONS = { ], (Ecu.engine, 0x7e0, None): [ 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): [ b'F152653330\x00\x00\x00\x00\x00\x00', @@ -870,6 +871,7 @@ FW_VERSIONS = { b'881515306200\x00\x00\x00\x00', ], (Ecu.eps, 0x7a1, None): [ + b'8965B53270\x00\x00\x00\x00\x00\x00', b'8965B53271\x00\x00\x00\x00\x00\x00', b'8965B53280\x00\x00\x00\x00\x00\x00', b'8965B53281\x00\x00\x00\x00\x00\x00', diff --git a/selfdrive/locationd/locationd.py b/selfdrive/locationd/locationd.py index d061452f57..f7267f0cc1 100755 --- a/selfdrive/locationd/locationd.py +++ b/selfdrive/locationd/locationd.py @@ -62,7 +62,7 @@ class Localizer(): self.calib = np.zeros(3) self.device_from_calib = np.eye(3) self.calib_from_device = np.eye(3) - self.calibrated = 0 + self.calibrated = False self.H = get_H() self.posenet_invalid_count = 0 @@ -77,7 +77,7 @@ class Localizer(): self.device_fell = False @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)) fix_ecef = predicted_state[States.ECEF_POS] @@ -130,12 +130,12 @@ class Localizer(): (fix.velocityDevice, vel_device, vel_device_std, True), (fix.accelerationDevice, predicted_state[States.ACCELERATION], predicted_std[States.ACCELERATION_ERR], 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.angularVelocityDevice, predicted_state[States.ANGULAR_VELOCITY], predicted_std[States.ANGULAR_VELOCITY_ERR], True), - (fix.velocityCalibrated, vel_calib, vel_calib_std, True), - (fix.angularVelocityCalibrated, ang_vel_calib, ang_vel_calib_std, True), - (fix.accelerationCalibrated, acc_calib, acc_calib_std, True), + (fix.velocityCalibrated, vel_calib, vel_calib_std, calibrated), + (fix.angularVelocityCalibrated, ang_vel_calib, ang_vel_calib_std, calibrated), + (fix.accelerationCalibrated, acc_calib, acc_calib_std, calibrated), ] for field, value, std, valid in measurements: @@ -147,7 +147,7 @@ class Localizer(): return fix 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 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 diff --git a/selfdrive/locationd/models/live_kf.py b/selfdrive/locationd/models/live_kf.py index 62c348272b..3d8a1f65d1 100755 --- a/selfdrive/locationd/models/live_kf.py +++ b/selfdrive/locationd/models/live_kf.py @@ -201,7 +201,7 @@ class LiveKalman(): 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.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_VEL: np.diag([.5**2, .5**2, .5**2]), ObservationKind.ECEF_ORIENTATION_FROM_GPS: np.diag([.2**2, .2**2, .2**2, .2**2])} diff --git a/selfdrive/locationd/paramsd.py b/selfdrive/locationd/paramsd.py index 263f5cc142..96b3c26dc2 100755 --- a/selfdrive/locationd/paramsd.py +++ b/selfdrive/locationd/paramsd.py @@ -5,14 +5,12 @@ import json import numpy as np import cereal.messaging as messaging -from cereal import car, log +from cereal import car from common.params import Params, put_nonblocking from selfdrive.locationd.models.car_kf import CarKalman, ObservationKind, States from selfdrive.locationd.models.constants import GENERATED_DIR from selfdrive.swaglog import cloudlog -KalmanStatus = log.LiveLocationKalman.Status - class ParamsLearner: def __init__(self, CP, steer_ratio, stiffness_factor, angle_offset): @@ -38,9 +36,10 @@ class ParamsLearner: yaw_rate = msg.angularVelocityCalibrated.value[2] yaw_rate_std = msg.angularVelocityCalibrated.std[2] + yaw_rate_valid = msg.angularVelocityCalibrated.valid 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, ObservationKind.ROAD_FRAME_YAW_RATE, np.array([[[-yaw_rate]]]), @@ -89,9 +88,10 @@ def main(sm=None, pm=None): params = None try: - if params is not None and not all(( - abs(params.get('angleOffsetAverageDeg')) < 10.0, - min_sr <= params['steerRatio'] <= max_sr)): + angle_offset_sane = abs(params.get('angleOffsetAverageDeg')) < 10.0 + steer_ratio_sane = 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}") params = None except Exception as e: diff --git a/selfdrive/manager/manager.py b/selfdrive/manager/manager.py index cf0d768e77..b6afafb917 100755 --- a/selfdrive/manager/manager.py +++ b/selfdrive/manager/manager.py @@ -45,6 +45,9 @@ def manager_init(spinner=None): ("IsDriverViewEnabled", "0"), ] + if params.get("RecordFrontLock", encoding='utf-8') == "1": + params.put("RecordFront", "1") + # set unset params for k, v in default_params: if params.get(k) is None: diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 7d815a9aa2..6276af3ea1 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -f7af4a6523a7afa631460f5168646ca32c8fa4b3 \ No newline at end of file +f88eda1b667eac0654f65281a16e7713836cb705 \ No newline at end of file diff --git a/selfdrive/test/profiling/lib.py b/selfdrive/test/profiling/lib.py index 624231f746..4a41affa9c 100644 --- a/selfdrive/test/profiling/lib.py +++ b/selfdrive/test/profiling/lib.py @@ -1,4 +1,5 @@ from collections import defaultdict +from cereal.services import service_list import cereal.messaging as messaging import capnp @@ -45,6 +46,7 @@ class SubMaster(messaging.SubMaster): self.valid = {s: True for s in services} self.logMonoTime = {} self.sock = {} + self.freq = {} # TODO: specify multiple triggers for service like plannerd that poll on more than one service cur_msgs = [] @@ -55,8 +57,10 @@ class SubMaster(messaging.SubMaster): if msg.which() == trigger: self.msgs.append(cur_msgs) cur_msgs = [] + self.msgs = list(reversed(self.msgs)) for s in services: + self.freq[s] = service_list[s].frequency try: data = messaging.new_message(s) except capnp.lib.capnp.KjException: diff --git a/selfdrive/test/profiling/profiler.py b/selfdrive/test/profiling/profiler.py index ef9f07b2eb..f48eab0dac 100755 --- a/selfdrive/test/profiling/profiler.py +++ b/selfdrive/test/profiling/profiler.py @@ -15,6 +15,7 @@ BASE_URL = "https://commadataci.blob.core.windows.net/openpilotci/" CARS = { '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"), + "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 -def profile(proc, func, car='toyota'): +def profile(proc, func, car='vw'): segment, fingerprint = CARS[car] segment = segment.replace('|', '/') rlog_url = f"{BASE_URL}{segment}/rlog.bz2" diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index 247d913a2b..83b5fe51f1 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -59,6 +59,8 @@ else: for name, branch in installers: d = {'BRANCH': f"'\"{branch}\"'"} if "internal" in name: + d['INTERNAL'] = "1" + import requests r = requests.get("https://github.com/commaci2.keys") r.raise_for_status() diff --git a/selfdrive/ui/qt/offroad/onboarding.cc b/selfdrive/ui/qt/offroad/onboarding.cc index 06b1b51a81..25e9e91317 100644 --- a/selfdrive/ui/qt/offroad/onboarding.cc +++ b/selfdrive/ui/qt/offroad/onboarding.cc @@ -6,7 +6,7 @@ #include #include #include - +#include #include "common/params.h" #include "onboarding.hpp" #include "home.hpp" @@ -14,48 +14,40 @@ #include - void TrainingGuide::mouseReleaseEvent(QMouseEvent *e) { int leftOffset = (geometry().width()-1620)/2; int mousex = e->x()-leftOffset; int mousey = e->y(); // Check for restart - if (currentIndex == boundingBox.size()-1) { - if (1050 <= mousex && mousex <= 1500 && 773 <= mousey && mousey <= 954){ - slayout->setCurrentIndex(0); - currentIndex = 0; - 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() - 1) && 1050 <= mousex && mousex <= 1500 && 773 <= mousey && mousey <= 954) { + currentIndex = 0; + } else if (boundingBox[currentIndex][0] <= mousex && mousex <= boundingBox[currentIndex][1] && boundingBox[currentIndex][2] <= mousey && mousey <= boundingBox[currentIndex][3]) { + ++currentIndex; } if (currentIndex >= boundingBox.size()) { emit completedTraining(); return; } + + image.load("../assets/training/step" + QString::number(currentIndex) + ".jpg"); + repaint(); } TrainingGuide::TrainingGuide(QWidget* parent) { - QHBoxLayout* hlayout = new QHBoxLayout; - - 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); - } + image.load("../assets/training/step0.jpg"); +} - QWidget* sw = new QWidget(); - sw->setLayout(slayout); - hlayout->addWidget(sw, 1, Qt::AlignCenter); - setLayout(hlayout); - setStyleSheet(R"( - background-color: #072339; - )"); +void TrainingGuide::paintEvent(QPaintEvent *event) { + QPainter painter(this); + + QRect devRect(0, 0, painter.device()->width(), painter.device()->height()); + QBrush bgBrush("#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 training_done = params.get("CompletedTrainingVersion", false).compare(current_training_version) == 0; - // TODO: fix this, training guide is slow // Don't initialize widgets unless neccesary. if (accepted_terms && training_done) { return; diff --git a/selfdrive/ui/qt/offroad/onboarding.hpp b/selfdrive/ui/qt/offroad/onboarding.hpp index 55e8760805..250caadae9 100644 --- a/selfdrive/ui/qt/offroad/onboarding.hpp +++ b/selfdrive/ui/qt/offroad/onboarding.hpp @@ -3,9 +3,9 @@ #include #include #include -#include #include #include +#include class TrainingGuide : public QFrame { Q_OBJECT @@ -15,10 +15,11 @@ public: protected: void mouseReleaseEvent(QMouseEvent* e) override; + void paintEvent(QPaintEvent *event) override; private: int currentIndex = 0; - QStackedLayout* slayout; + QImage image; // Vector of bounding boxes for the a given training guide step. (minx, maxx, miny, maxy) QVector> 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}, diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 27004abbf2..1d86c5b616 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -64,7 +64,7 @@ ParamsToggle::ParamsToggle(QString param, QString title, QString description, QS layout->addWidget(label); // toggle switch - Toggle *toggle = new Toggle(this); + toggle = new Toggle(this); toggle->setFixedSize(150, 100); layout->addWidget(toggle); QObject::connect(toggle, SIGNAL(stateChanged(int)), this, SLOT(checkboxClicked(int))); @@ -104,12 +104,6 @@ QWidget * toggles_panel() { "../assets/offroad/icon_warning.png" )); 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", "Enable Right-Hand Drive", "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" )); + 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; widget->setLayout(toggles_list); return widget; diff --git a/selfdrive/ui/qt/offroad/settings.hpp b/selfdrive/ui/qt/offroad/settings.hpp index 81ba92b1ae..bd7f413982 100644 --- a/selfdrive/ui/qt/offroad/settings.hpp +++ b/selfdrive/ui/qt/offroad/settings.hpp @@ -7,6 +7,8 @@ #include #include +#include "selfdrive/ui/qt/widgets/toggle.hpp" + // *** settings widgets *** class ParamsToggle : public QFrame { @@ -15,6 +17,7 @@ class ParamsToggle : public QFrame { public: explicit ParamsToggle(QString param, QString title, QString description, QString icon, QWidget *parent = 0); + Toggle *toggle; private: QString param; diff --git a/selfdrive/ui/qt/setup/installer.cc b/selfdrive/ui/qt/setup/installer.cc index 528f968782..bfbc8d08bd 100644 --- a/selfdrive/ui/qt/setup/installer.cc +++ b/selfdrive/ui/qt/setup/installer.cc @@ -37,14 +37,19 @@ int fresh_clone() { err = std::system("mv /data/tmppilot /data/openpilot"); if (err) return 1; -#ifdef SSH_KEYS +#ifdef INTERNAL err = std::system("mkdir -p /data/params/d/"); if (err) return 1; std::ofstream param; - param.open("/data/params/d/GithubSshKeys"); - param << SSH_KEYS; + param.open("/data/params/d/RecordFrontLock"); + param << "1"; param.close(); + + std::ofstream keys_param; + keys_param.open("/data/params/d/GithubSshKeys"); + keys_param << SSH_KEYS; + keys_param.close(); #endif return 0; diff --git a/selfdrive/ui/qt/widgets/input.cc b/selfdrive/ui/qt/widgets/input.cc index ef776844f8..c205dafd12 100644 --- a/selfdrive/ui/qt/widgets/input.cc +++ b/selfdrive/ui/qt/widgets/input.cc @@ -115,6 +115,7 @@ void InputDialog::setMinLength(int length){ ConfirmationDialog::ConfirmationDialog(QString prompt_text, QString confirm_text, QString cancel_text, QWidget *parent):QDialog(parent) { + setWindowFlags(Qt::Popup); layout = new QVBoxLayout(); layout->setMargin(25); diff --git a/selfdrive/ui/qt/widgets/offroad_alerts.cc b/selfdrive/ui/qt/widgets/offroad_alerts.cc index 26a2f7e5a9..4135b24077 100644 --- a/selfdrive/ui/qt/widgets/offroad_alerts.cc +++ b/selfdrive/ui/qt/widgets/offroad_alerts.cc @@ -59,6 +59,13 @@ OffroadAlert::OffroadAlert(QWidget* parent) : QFrame(parent) { } )"); 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() { @@ -109,20 +116,7 @@ void OffroadAlert::refresh() { void OffroadAlert::parse_alerts() { alerts.clear(); - - // 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()) { + for (const QString &key : alert_keys) { std::vector bytes = Params().read_db_bytes(key.toStdString().c_str()); if (bytes.size()) { diff --git a/selfdrive/ui/qt/widgets/offroad_alerts.hpp b/selfdrive/ui/qt/widgets/offroad_alerts.hpp index edd37dd898..ec48f89c7e 100644 --- a/selfdrive/ui/qt/widgets/offroad_alerts.hpp +++ b/selfdrive/ui/qt/widgets/offroad_alerts.hpp @@ -3,6 +3,7 @@ #include #include #include +#include struct Alert { QString text; @@ -15,6 +16,7 @@ class OffroadAlert : public QFrame { public: explicit OffroadAlert(QWidget *parent = 0); QVector alerts; + QStringList alert_keys; bool updateAvailable; private: