Merge branch 'master' of https://github.com/commaai/openpilot into mqb-long

pull/23257/head
Jason Young 4 years ago
commit e2698a4672
  1. 21
      Jenkinsfile
  2. 10
      RELEASES.md
  3. 2
      cereal
  4. 2
      docs/CARS.md
  5. 9
      scripts/count_cars.py
  6. 13
      selfdrive/boardd/boardd.cc
  7. 18
      selfdrive/boardd/tests/test_boardd_loopback.py
  8. 2
      selfdrive/car/__init__.py
  9. 15
      selfdrive/car/gm/interface.py
  10. 4
      selfdrive/car/honda/carcontroller.py
  11. 2
      selfdrive/car/honda/interface.py
  12. 3
      selfdrive/car/hyundai/carcontroller.py
  13. 5
      selfdrive/car/hyundai/hyundaican.py
  14. 18
      selfdrive/car/hyundai/interface.py
  15. 56
      selfdrive/car/hyundai/values.py
  16. 4
      selfdrive/car/toyota/carcontroller.py
  17. 2
      selfdrive/common/version.h
  18. 8
      selfdrive/debug/hyundai_enable_radar_points.py
  19. 4
      selfdrive/locationd/models/live_kf.py
  20. 3
      selfdrive/loggerd/tests/test_encoder.py
  21. 21
      selfdrive/loggerd/tests/test_loggerd.py
  22. 6
      selfdrive/manager/test/test_manager.py
  23. 25
      selfdrive/modeld/models/dmonitoring.cc
  24. 1
      selfdrive/modeld/runners/runmodel.h
  25. 2
      selfdrive/test/process_replay/ref_commit
  26. 58
      selfdrive/test/test_models.py
  27. 2
      selfdrive/test/test_routes.py
  28. 141
      selfdrive/ui/qt/offroad/settings.cc
  29. 47
      selfdrive/ui/qt/offroad/settings.h
  30. 2
      selfdrive/ui/qt/offroad/wifiManager.cc
  31. 7
      selfdrive/ui/replay/logreader.cc
  32. 35
      selfdrive/ui/replay/tests/test_replay.cc
  33. 2
      selfdrive/ui/ui.h
  34. 5
      tools/README.md
  35. 2
      update_requirements.sh

21
Jenkinsfile vendored

@ -145,10 +145,10 @@ pipeline {
stages { stages {
stage('parallel tests') { stage('parallel tests') {
parallel { parallel {
stage('Devel Tests') { stage('C2: build') {
steps { steps {
phone_steps("eon-build", [ phone_steps("eon-build", [
["build devel", "cd $SOURCE_DIR/release && EXTRA_FILES='tools/' ./build_devel.sh"], ["build master-ci", "cd $SOURCE_DIR/release && EXTRA_FILES='tools/' ./build_devel.sh"],
["build openpilot", "cd selfdrive/manager && ./build.py"], ["build openpilot", "cd selfdrive/manager && ./build.py"],
["test manager", "python selfdrive/manager/test/test_manager.py"], ["test manager", "python selfdrive/manager/test/test_manager.py"],
["onroad tests", "cd selfdrive/test/ && ./test_onroad.py"], ["onroad tests", "cd selfdrive/test/ && ./test_onroad.py"],
@ -157,7 +157,7 @@ pipeline {
} }
} }
stage('Replay Tests') { stage('C2: replay') {
steps { steps {
phone_steps("eon2", [ phone_steps("eon2", [
["build", "cd selfdrive/manager && ./build.py"], ["build", "cd selfdrive/manager && ./build.py"],
@ -166,7 +166,7 @@ pipeline {
} }
} }
stage('HW + Unit Tests') { stage('C2: HW + Unit Tests') {
steps { steps {
phone_steps("eon", [ phone_steps("eon", [
["build", "cd selfdrive/manager && ./build.py"], ["build", "cd selfdrive/manager && ./build.py"],
@ -201,19 +201,22 @@ pipeline {
} }
*/ */
stage('tici Build') { stage('C3: build') {
environment { environment {
R3_PUSH = "${env.BRANCH_NAME == 'master' ? '1' : ' '}" R3_PUSH = "${env.BRANCH_NAME == 'master' ? '1' : ' '}"
} }
steps { steps {
phone_steps("tici", [ phone_steps("tici", [
["build", "cd selfdrive/manager && ./build.py"], ["build master-ci", "cd $SOURCE_DIR/release && EXTRA_FILES='tools/' ./build_devel.sh"],
["build openpilot", "cd selfdrive/manager && ./build.py"],
["test manager", "python selfdrive/manager/test/test_manager.py"],
["onroad tests", "cd selfdrive/test/ && ./test_onroad.py"], ["onroad tests", "cd selfdrive/test/ && ./test_onroad.py"],
["test car interfaces", "cd selfdrive/car/tests/ && ./test_car_interfaces.py"],
]) ])
} }
} }
stage('HW + Unit Tests (tici)') { stage('C3: HW + Unit Tests') {
steps { steps {
phone_steps("tici2", [ phone_steps("tici2", [
["build", "cd selfdrive/manager && ./build.py"], ["build", "cd selfdrive/manager && ./build.py"],
@ -224,7 +227,7 @@ pipeline {
} }
} }
stage('EON camerad') { stage('C2: camerad') {
steps { steps {
phone_steps("eon-party", [ phone_steps("eon-party", [
["build", "cd selfdrive/manager && ./build.py"], ["build", "cd selfdrive/manager && ./build.py"],
@ -234,7 +237,7 @@ pipeline {
} }
} }
stage('tici camerad') { stage('C3: camerad') {
steps { steps {
phone_steps("tici-party", [ phone_steps("tici-party", [
["build", "cd selfdrive/manager && ./build.py"], ["build", "cd selfdrive/manager && ./build.py"],

@ -1,16 +1,16 @@
Version 0.8.12 (202X-XX-XX) Version 0.8.11 (2021-11-29)
========================
* Volkswagen T-Roc 2021 support thanks to jyoung8607!
Version 0.8.11 (2021-11-22)
======================== ========================
* Support for CAN FD on the red panda
* Support for an external panda on the comma three * Support for an external panda on the comma three
* Navigation: Show more detailed instructions when approaching maneuver * Navigation: Show more detailed instructions when approaching maneuver
* Fixed occasional steering faults on GM cars thanks to jyoung8607! * Fixed occasional steering faults on GM cars thanks to jyoung8607!
* Nissan ECU firmware fingerprinting thanks to robin-reckmann, martinl, and razem-io! * Nissan ECU firmware fingerprinting thanks to robin-reckmann, martinl, and razem-io!
* Cadillac Escalade ESV 2016 support thanks to Gibby! * Cadillac Escalade ESV 2016 support thanks to Gibby!
* Genesis G70 2020 support thanks to tecandrew!
* Hyundai Santa Fe Hybrid 2022 support thanks to sunnyhaibin!
* Mazda CX-9 2021 support thanks to Jacar! * Mazda CX-9 2021 support thanks to Jacar!
* Volkswagen Polo 2020 support thanks to jyoung8607! * Volkswagen Polo 2020 support thanks to jyoung8607!
* Volkswagen T-Roc 2021 support thanks to jyoung8607!
Version 0.8.10 (2021-11-01) Version 0.8.10 (2021-11-01)
======================== ========================

@ -1 +1 @@
Subproject commit 5edffa0f494abfa2e907c497cda0f64223a421e7 Subproject commit 032aca6ca38a342e26fb9cc986b7f72b91cd9b55

@ -93,6 +93,7 @@
| Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph | | Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
| Chrysler | Pacifica Hybrid 2019-21 | Adaptive Cruise | Stock | 0mph | 39mph | | Chrysler | Pacifica Hybrid 2019-21 | Adaptive Cruise | Stock | 0mph | 39mph |
| Genesis | G70 2018 | All | Stock | 0mph | 0mph | | Genesis | G70 2018 | All | Stock | 0mph | 0mph |
| Genesis | G70 2020 | All | Stock | 0mph | 0mph |
| Genesis | G80 2018 | All | Stock | 0mph | 0mph | | Genesis | G80 2018 | All | Stock | 0mph | 0mph |
| Genesis | G90 2018 | All | Stock | 0mph | 0mph | | Genesis | G90 2018 | All | Stock | 0mph | 0mph |
| GMC | Acadia 2018<sup>1</sup> | Adaptive Cruise | openpilot | 0mph | 7mph | | GMC | Acadia 2018<sup>1</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
@ -111,6 +112,7 @@
| Hyundai | Kona Hybrid 2020 | SCC + LKAS | Stock | 0mph | 0mph | | Hyundai | Kona Hybrid 2020 | SCC + LKAS | Stock | 0mph | 0mph |
| Hyundai | Santa Fe 2019-20 | All | Stock | 0mph | 0mph | | Hyundai | Santa Fe 2019-20 | All | Stock | 0mph | 0mph |
| Hyundai | Santa Fe 2021-22 | All | Stock | 0mph | 0mph | | Hyundai | Santa Fe 2021-22 | All | Stock | 0mph | 0mph |
| Hyundai | Santa Fe Hybrid 2022 | All | Stock | 0mph | 0mph |
| Hyundai | Sonata 2018-2019 | SCC + LKAS | Stock | 0mph | 0mph | | Hyundai | Sonata 2018-2019 | SCC + LKAS | Stock | 0mph | 0mph |
| Hyundai | Sonata Hybrid 2021-22 | All | Stock | 0mph | 0mph | | Hyundai | Sonata Hybrid 2021-22 | All | Stock | 0mph | 0mph |
| Hyundai | Veloster 2019-20 | SCC + LKAS | Stock | 5mph | 0mph | | Hyundai | Veloster 2019-20 | SCC + LKAS | Stock | 5mph | 0mph |

@ -1,10 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
from collections import Counter
from pprint import pprint
from common.basedir import BASEDIR from common.basedir import BASEDIR
with open(os.path.join(BASEDIR, "docs/CARS.md")) as f: with open(os.path.join(BASEDIR, "docs/CARS.md")) as f:
lines = f.readlines() lines = f.readlines()
cars = [l for l in lines if l.strip().startswith("|") and l.strip().endswith("|") and cars = [l for l in lines if l.strip().startswith("|") and l.strip().endswith("|") and
"Make" not in l and any(c.isalpha() for c in l)] "Make" not in l and any(c.isalpha() for c in l)]
print(''.join(cars))
print(len(cars)) make_count = Counter([l.split('|')[1].split('|')[0].strip() for l in cars])
print("\n", "*"*20, len(cars), "total", "*"*20, "\n")
pprint(make_count)

@ -185,7 +185,7 @@ Panda *usb_connect(std::string serial="", uint32_t index=0) {
} }
void can_send_thread(std::vector<Panda *> pandas, bool fake_send) { void can_send_thread(std::vector<Panda *> pandas, bool fake_send) {
LOGD("start send thread"); set_thread_name("boardd_can_send");
AlignedBuffer aligned_buf; AlignedBuffer aligned_buf;
Context * context = Context::create(); Context * context = Context::create();
@ -229,7 +229,7 @@ void can_send_thread(std::vector<Panda *> pandas, bool fake_send) {
} }
void can_recv_thread(std::vector<Panda *> pandas) { void can_recv_thread(std::vector<Panda *> pandas) {
LOGD("start recv thread"); set_thread_name("boardd_can_recv");
// can = 8006 // can = 8006
PubMaster pm({"can"}); PubMaster pm({"can"});
@ -334,7 +334,6 @@ bool send_panda_states(PubMaster *pm, const std::vector<Panda *> &pandas, bool s
} }
#endif #endif
// TODO: do we still need this?
if (!panda->comms_healthy) { if (!panda->comms_healthy) {
evt.setValid(false); evt.setValid(false);
} }
@ -407,6 +406,8 @@ void send_peripheral_state(PubMaster *pm, Panda *panda) {
} }
void panda_state_thread(PubMaster *pm, std::vector<Panda *> pandas, bool spoofing_started) { void panda_state_thread(PubMaster *pm, std::vector<Panda *> pandas, bool spoofing_started) {
set_thread_name("boardd_panda_state");
Params params; Params params;
Panda *peripheral_panda = pandas[0]; Panda *peripheral_panda = pandas[0];
bool ignition_last = false; bool ignition_last = false;
@ -424,6 +425,7 @@ void panda_state_thread(PubMaster *pm, std::vector<Panda *> pandas, bool spoofin
send_peripheral_state(pm, peripheral_panda); send_peripheral_state(pm, peripheral_panda);
ignition = send_panda_states(pm, pandas, spoofing_started); ignition = send_panda_states(pm, pandas, spoofing_started);
// TODO: make this check fast, currently takes 16ms
// check if we have new pandas and are offroad // check if we have new pandas and are offroad
if (!ignition && (pandas.size() != Panda::list().size())) { if (!ignition && (pandas.size() != Panda::list().size())) {
LOGW("Reconnecting to changed amount of pandas!"); LOGW("Reconnecting to changed amount of pandas!");
@ -454,7 +456,8 @@ void panda_state_thread(PubMaster *pm, std::vector<Panda *> pandas, bool spoofin
void peripheral_control_thread(Panda *panda) { void peripheral_control_thread(Panda *panda) {
LOGD("start peripheral control thread"); set_thread_name("boardd_peripheral_control");
SubMaster sm({"deviceState", "driverCameraState"}); SubMaster sm({"deviceState", "driverCameraState"});
uint64_t last_front_frame_t = 0; uint64_t last_front_frame_t = 0;
@ -552,6 +555,8 @@ static void pigeon_publish_raw(PubMaster &pm, const std::string &dat) {
} }
void pigeon_thread(Panda *panda) { void pigeon_thread(Panda *panda) {
set_thread_name("boardd_pigeon");
PubMaster pm({"ubloxRaw"}); PubMaster pm({"ubloxRaw"});
bool ignition_last = false; bool ignition_last = false;

@ -4,33 +4,18 @@ import random
import time import time
import unittest import unittest
from collections import defaultdict from collections import defaultdict
from functools import wraps
import cereal.messaging as messaging import cereal.messaging as messaging
from cereal import car from cereal import car
from common.params import Params from common.params import Params
from common.spinner import Spinner from common.spinner import Spinner
from common.timeout import Timeout from common.timeout import Timeout
from panda import Panda
from selfdrive.boardd.boardd import can_list_to_can_capnp from selfdrive.boardd.boardd import can_list_to_can_capnp
from selfdrive.car import make_can_msg from selfdrive.car import make_can_msg
from selfdrive.hardware import TICI from selfdrive.hardware import TICI
from selfdrive.test.helpers import phone_only, with_processes from selfdrive.test.helpers import phone_only, with_processes
def reset_pandas(f):
@wraps(f)
def wrapper(*args, **kwargs):
for serial in Panda.list():
p = Panda(serial)
for i in [0, 1, 2, 3, 0xFFFF]:
p.can_clear(i)
p.reset()
p.close()
f(*args, **kwargs)
return wrapper
class TestBoardd(unittest.TestCase): class TestBoardd(unittest.TestCase):
@classmethod @classmethod
@ -44,7 +29,6 @@ class TestBoardd(unittest.TestCase):
cls.spinner.close() cls.spinner.close()
@phone_only @phone_only
@reset_pandas
@with_processes(['pandad']) @with_processes(['pandad'])
def test_loopback(self): def test_loopback(self):
# wait for boardd to init # wait for boardd to init
@ -75,7 +59,7 @@ class TestBoardd(unittest.TestCase):
can = messaging.sub_sock('can', conflate=False, timeout=100) can = messaging.sub_sock('can', conflate=False, timeout=100)
time.sleep(0.2) time.sleep(0.2)
n = 1000 n = 200
for i in range(n): for i in range(n):
self.spinner.update(f"boardd loopback {i}/{n}") self.spinner.update(f"boardd loopback {i}/{n}")

@ -99,7 +99,7 @@ def crc8_pedal(data):
return crc return crc
def create_gas_command(packer, gas_amount, idx): def create_gas_interceptor_command(packer, gas_amount, idx):
# Common gas pedal msg generator # Common gas pedal msg generator
enable = gas_amount > 0.001 enable = gas_amount > 0.001

@ -16,18 +16,24 @@ class CarInterface(CarInterfaceBase):
params = CarControllerParams() params = CarControllerParams()
return params.ACCEL_MIN, params.ACCEL_MAX return params.ACCEL_MIN, params.ACCEL_MAX
# Volt determined by iteratively plotting and minimizing error for f(angle, speed) = steer. # Determined by iteratively plotting and minimizing error for f(angle, speed) = steer.
@staticmethod @staticmethod
def get_steer_feedforward_volt(desired_angle, v_ego): def get_steer_feedforward_volt(desired_angle, v_ego):
# maps [-inf,inf] to [-1,1]: sigmoid(34.4 deg) = sigmoid(1) = 0.5
# 1 / 0.02904609 = 34.4 deg ~= 36 deg ~= 1/10 circle? Arbitrary?
desired_angle *= 0.02904609 desired_angle *= 0.02904609
sigmoid = desired_angle / (1 + fabs(desired_angle)) sigmoid = desired_angle / (1 + fabs(desired_angle))
return 0.10006696 * sigmoid * (v_ego + 3.12485927) return 0.10006696 * sigmoid * (v_ego + 3.12485927)
@staticmethod
def get_steer_feedforward_acadia(desired_angle, v_ego):
desired_angle *= 0.09760208
sigmoid = desired_angle / (1 + fabs(desired_angle))
return 0.04689655 * sigmoid * (v_ego + 10.028217)
def get_steer_feedforward_function(self): def get_steer_feedforward_function(self):
if self.CP.carFingerprint in [CAR.VOLT]: if self.CP.carFingerprint == CAR.VOLT:
return self.get_steer_feedforward_volt return self.get_steer_feedforward_volt
elif self.CP.carFingerprint == CAR.ACADIA:
return self.get_steer_feedforward_acadia
else: else:
return CarInterfaceBase.get_steer_feedforward_default return CarInterfaceBase.get_steer_feedforward_default
@ -94,6 +100,7 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 14.4 # end to end is 13.46 ret.steerRatio = 14.4 # end to end is 13.46
ret.steerRatioRear = 0. ret.steerRatioRear = 0.
ret.centerToFront = ret.wheelbase * 0.4 ret.centerToFront = ret.wheelbase * 0.4
ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_acadia()
elif candidate == CAR.BUICK_REGAL: elif candidate == CAR.BUICK_REGAL:
ret.minEnableSpeed = 18 * CV.MPH_TO_MS ret.minEnableSpeed = 18 * CV.MPH_TO_MS

@ -3,7 +3,7 @@ from cereal import car
from common.realtime import DT_CTRL from common.realtime import DT_CTRL
from selfdrive.controls.lib.drive_helpers import rate_limit from selfdrive.controls.lib.drive_helpers import rate_limit
from common.numpy_fast import clip, interp from common.numpy_fast import clip, interp
from selfdrive.car import create_gas_command from selfdrive.car import create_gas_interceptor_command
from selfdrive.car.honda import hondacan from selfdrive.car.honda import hondacan
from selfdrive.car.honda.values import CruiseButtons, VISUAL_HUD, HONDA_BOSCH, HONDA_NIDEC_ALT_PCM_ACCEL, CarControllerParams from selfdrive.car.honda.values import CruiseButtons, VISUAL_HUD, HONDA_BOSCH, HONDA_NIDEC_ALT_PCM_ACCEL, CarControllerParams
from opendbc.can.packer import CANPacker from opendbc.can.packer import CANPacker
@ -236,7 +236,7 @@ class CarController():
apply_gas = clip(gas_mult * (gas - brake + wind_brake*3/4), 0., 1.) apply_gas = clip(gas_mult * (gas - brake + wind_brake*3/4), 0., 1.)
else: else:
apply_gas = 0.0 apply_gas = 0.0
can_sends.append(create_gas_command(self.packer, apply_gas, idx)) can_sends.append(create_gas_interceptor_command(self.packer, apply_gas, idx))
hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), hud_car, hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), hud_car,
hud_lanes, fcw_display, acc_alert, steer_required) hud_lanes, fcw_display, acc_alert, steer_required)

@ -33,7 +33,7 @@ class CarInterface(CarInterfaceBase):
ret.carName = "honda" ret.carName = "honda"
if candidate in HONDA_BOSCH: if candidate in HONDA_BOSCH:
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hondaBoschHarness)] ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hondaBosch)]
ret.radarOffCan = True ret.radarOffCan = True
# Disable the radar and let openpilot control longitudinal # Disable the radar and let openpilot control longitudinal

@ -104,7 +104,8 @@ class CarController():
# 20 Hz LFA MFA message # 20 Hz LFA MFA message
if frame % 5 == 0 and self.car_fingerprint in [CAR.SONATA, CAR.PALISADE, CAR.IONIQ, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, if frame % 5 == 0 and self.car_fingerprint in [CAR.SONATA, CAR.PALISADE, CAR.IONIQ, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021,
CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_CEED, CAR.KIA_SELTOS, CAR.KONA_EV, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_CEED, CAR.KIA_SELTOS, CAR.KONA_EV,
CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022]: CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.SANTA_FE_2022,
CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.GENESIS_G70_2020]:
can_sends.append(create_lfahda_mfc(self.packer, enabled)) can_sends.append(create_lfahda_mfc(self.packer, enabled))
# 5 Hz ACC options # 5 Hz ACC options

@ -17,8 +17,9 @@ def create_lkas11(packer, frame, car_fingerprint, apply_steer, steer_req,
values["CF_Lkas_MsgCount"] = frame % 0x10 values["CF_Lkas_MsgCount"] = frame % 0x10
if car_fingerprint in [CAR.SONATA, CAR.PALISADE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.SANTA_FE, if car_fingerprint in [CAR.SONATA, CAR.PALISADE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.SANTA_FE,
CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_SELTOS, CAR.ELANTRA_2021, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_SELTOS, CAR.ELANTRA_2021, CAR.GENESIS_G70_2020,
CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_EV, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022]: CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_EV, CAR.KONA_HEV, CAR.SANTA_FE_2022,
CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022]:
values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1) values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1)
values["CF_Lkas_LdwsOpt_USM"] = 2 values["CF_Lkas_LdwsOpt_USM"] = 2

@ -3,7 +3,7 @@ from cereal import car
from panda import Panda from panda import Panda
from common.params import Params from common.params import Params
from selfdrive.config import Conversions as CV from selfdrive.config import Conversions as CV
from selfdrive.car.hyundai.values import CAR, EV_CAR, HYBRID_CAR, Buttons, CarControllerParams from selfdrive.car.hyundai.values import CAR, EV_CAR, HYBRID_CAR, LEGACY_SAFETY_MODE_CAR, Buttons, CarControllerParams
from selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR from selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config
from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.interfaces import CarInterfaceBase
@ -26,7 +26,7 @@ class CarInterface(CarInterfaceBase):
ret.radarOffCan = RADAR_START_ADDR not in fingerprint[1] ret.radarOffCan = RADAR_START_ADDR not in fingerprint[1]
# WARNING: disabling radar also disables AEB (and we show the same warning on the instrument cluster as if you manually disabled AEB) # WARNING: disabling radar also disables AEB (and we show the same warning on the instrument cluster as if you manually disabled AEB)
ret.openpilotLongitudinalControl = Params().get_bool("DisableRadar") and candidate in [CAR.SONATA, CAR.SONATA_HYBRID, CAR.PALISADE, CAR.SANTA_FE] ret.openpilotLongitudinalControl = Params().get_bool("DisableRadar") and (candidate not in LEGACY_SAFETY_MODE_CAR)
ret.pcmCruise = not ret.openpilotLongitudinalControl ret.pcmCruise = not ret.openpilotLongitudinalControl
@ -45,7 +45,7 @@ class CarInterface(CarInterfaceBase):
ret.longitudinalActuatorDelayUpperBound = 1.0 # s ret.longitudinalActuatorDelayUpperBound = 1.0 # s
if candidate in [CAR.SANTA_FE, CAR.SANTA_FE_2022]: if candidate in [CAR.SANTA_FE, CAR.SANTA_FE_2022, CAR.SANTA_FE_HEV_2022]:
ret.lateralTuning.pid.kf = 0.00005 ret.lateralTuning.pid.kf = 0.00005
ret.mass = 3982. * CV.LB_TO_KG + STD_CARGO_KG ret.mass = 3982. * CV.LB_TO_KG + STD_CARGO_KG
ret.wheelbase = 2.766 ret.wheelbase = 2.766
@ -232,6 +232,13 @@ class CarInterface(CarInterfaceBase):
ret.mass = 1640.0 + STD_CARGO_KG ret.mass = 1640.0 + STD_CARGO_KG
ret.wheelbase = 2.84 ret.wheelbase = 2.84
ret.steerRatio = 13.56 ret.steerRatio = 13.56
elif candidate == CAR.GENESIS_G70_2020:
ret.lateralTuning.pid.kf = 0.
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]]
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.112], [0.004]]
ret.mass = 3673.0 * CV.LB_TO_KG + STD_CARGO_KG
ret.wheelbase = 2.83
ret.steerRatio = 12.9
elif candidate == CAR.GENESIS_G80: elif candidate == CAR.GENESIS_G80:
ret.lateralTuning.pid.kf = 0.00005 ret.lateralTuning.pid.kf = 0.00005
ret.mass = 2060. + STD_CARGO_KG ret.mass = 2060. + STD_CARGO_KG
@ -247,10 +254,7 @@ class CarInterface(CarInterfaceBase):
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.01]] ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.01]]
# these cars require a special panda safety mode due to missing counters and checksums in the messages # these cars require a special panda safety mode due to missing counters and checksums in the messages
if candidate in [CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_SORENTO, if candidate in LEGACY_SAFETY_MODE_CAR:
CAR.SONATA_LF, CAR.KIA_NIRO_EV, CAR.KIA_OPTIMA, CAR.VELOSTER, CAR.KIA_STINGER,
CAR.GENESIS_G70, CAR.GENESIS_G80, CAR.KIA_CEED, CAR.ELANTRA, CAR.IONIQ_HEV_2022]:
assert not ret.openpilotLongitudinalControl # Legacy safety mode doesn't support longitudinal
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hyundaiLegacy)] ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hyundaiLegacy)]
# set appropriate safety param for gas signal # set appropriate safety param for gas signal

@ -10,9 +10,10 @@ class CarControllerParams:
ACCEL_MAX = 2.0 # m/s ACCEL_MAX = 2.0 # m/s
def __init__(self, CP): def __init__(self, CP):
if CP.carFingerprint in [CAR.SONATA, CAR.PALISADE, CAR.SANTA_FE, CAR.VELOSTER, CAR.GENESIS_G70, if CP.carFingerprint in [CAR.SONATA, CAR.PALISADE, CAR.SANTA_FE, CAR.VELOSTER, CAR.GENESIS_G70, CAR.GENESIS_G70_2020,
CAR.IONIQ_EV_2020, CAR.KIA_CEED, CAR.KIA_SELTOS, CAR.ELANTRA_2021, CAR.IONIQ_EV_2020, CAR.KIA_CEED, CAR.KIA_SELTOS, CAR.ELANTRA_2021,
CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.KONA_EV, CAR.KONA, CAR.IONIQ_HEV_2022]: CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.SANTA_FE_2022,
CAR.KIA_K5_2021, CAR.KONA_EV, CAR.KONA, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022]:
self.STEER_MAX = 384 self.STEER_MAX = 384
else: else:
self.STEER_MAX = 255 self.STEER_MAX = 255
@ -39,6 +40,7 @@ class CAR:
KONA_HEV = "HYUNDAI KONA HYBRID 2020" KONA_HEV = "HYUNDAI KONA HYBRID 2020"
SANTA_FE = "HYUNDAI SANTA FE 2019" SANTA_FE = "HYUNDAI SANTA FE 2019"
SANTA_FE_2022 = "HYUNDAI SANTA FE 2022" SANTA_FE_2022 = "HYUNDAI SANTA FE 2022"
SANTA_FE_HEV_2022 = "HYUNDAI SANTA FE HYBRID 2022"
SONATA = "HYUNDAI SONATA 2020" SONATA = "HYUNDAI SONATA 2020"
SONATA_LF = "HYUNDAI SONATA 2019" SONATA_LF = "HYUNDAI SONATA 2019"
PALISADE = "HYUNDAI PALISADE 2020" PALISADE = "HYUNDAI PALISADE 2020"
@ -60,6 +62,7 @@ class CAR:
# Genesis # Genesis
GENESIS_G70 = "GENESIS G70 2018" GENESIS_G70 = "GENESIS G70 2018"
GENESIS_G70_2020 = "GENESIS G70 2020"
GENESIS_G80 = "GENESIS G80 2017" GENESIS_G80 = "GENESIS G80 2017"
GENESIS_G90 = "GENESIS G90 2017" GENESIS_G90 = "GENESIS G90 2017"
@ -469,6 +472,23 @@ FW_VERSIONS = {
b'\xf1\x87954A02N250\x00\x00\x00\x00\x00\xf1\x81T02730A1 \xf1\x00T02601BL T02730A1 VTMPT25XXX730NS2\xa6\x06\x88\xf7', b'\xf1\x87954A02N250\x00\x00\x00\x00\x00\xf1\x81T02730A1 \xf1\x00T02601BL T02730A1 VTMPT25XXX730NS2\xa6\x06\x88\xf7',
], ],
}, },
CAR.SANTA_FE_HEV_2022: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x8799110CL500\xf1\x00TMhe SCC FHCUP 1.00 1.00 99110-CL500 ',
],
(Ecu.eps, 0x7d4, None): [
b'\xf1\x00TM MDPS C 1.00 1.02 56310-CLAC0 4TSHC102',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00TMH MFC AT USA LHD 1.00 1.03 99211-S1500 210224',
],
(Ecu.transmission, 0x7e1, None): [
b'\xf1\x87959102T250\x00\x00\x00\x00\x00\xf1\x81E14\x00\x00\x00\x00\x00\x00\x00\xf1\x00PSBG2333 E14\x00\x00\x00\x00\x00\x00\x00TTM2H16SA2\x80\xd7l\xb2',
],
(Ecu.engine, 0x7e0, None): [
b'\xf1\x87391312MTC1',
],
},
CAR.KIA_STINGER: { CAR.KIA_STINGER: {
(Ecu.fwdRadar, 0x7d0, None): [ (Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CK__ SCC F_CUP 1.00 1.01 96400-J5100 ', b'\xf1\x00CK__ SCC F_CUP 1.00 1.01 96400-J5100 ',
@ -611,6 +631,25 @@ FW_VERSIONS = {
(Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00IK MFC AT USA LHD 1.00 1.01 95740-G9000 170920', ], (Ecu.fwdCamera, 0x7c4, None): [b'\xf1\x00IK MFC AT USA LHD 1.00 1.01 95740-G9000 170920', ],
(Ecu.transmission, 0x7e1, None): [b'\xf1\x87VDJLT17895112DN4\x88fVf\x99\x88\x88\x88\x87fVe\x88vhwwUFU\x97eFex\x99\xff\xb7\x82\xf1\x81E25\x00\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 E25\x00\x00\x00\x00\x00\x00\x00SIK0T33NB2\x11\x1am\xda', ], (Ecu.transmission, 0x7e1, None): [b'\xf1\x87VDJLT17895112DN4\x88fVf\x99\x88\x88\x88\x87fVe\x88vhwwUFU\x97eFex\x99\xff\xb7\x82\xf1\x81E25\x00\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 E25\x00\x00\x00\x00\x00\x00\x00SIK0T33NB2\x11\x1am\xda', ],
}, },
CAR.GENESIS_G70_2020: {
(Ecu.eps, 0x7d4, None): [
b'\xf1\x00IK MDPS R 1.00 1.07 57700-G9220 4I2VL107',
],
(Ecu.transmission, 0x7e1, None): [
b'\xf1\x87VCJLP18407832DN3\x88vXfvUVT\x97eFU\x87d7v\x88eVeveFU\x89\x98\x7f\xff\xb2\xb0\xf1\x81E25\x00\x00\x00'
b'\x00\x00\x00\x00\xf1\x00bcsh8p54 E25\x00\x00\x00\x00\x00\x00\x00SIK0T33NB4\xecE\xefL',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00IK__ SCC F-CUP 1.00 1.02 96400-G9100 ',
b'\xf1\x00IK__ SCC F-CUP 1.00 1.02 96400-G9100 \xf1\xa01.02',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00IK MFC AT USA LHD 1.00 1.01 95740-G9000 170920',
],
(Ecu.engine, 0x7e0, None): [
b'\xf1\x81640J0051\x00\x00\x00\x00\x00\x00\x00\x00',
],
},
CAR.KONA: { CAR.KONA: {
(Ecu.fwdRadar, 0x7d0, None): [b'\xf1\x00OS__ SCC F-CUP 1.00 1.00 95655-J9200 ', ], (Ecu.fwdRadar, 0x7d0, None): [b'\xf1\x00OS__ SCC F-CUP 1.00 1.00 95655-J9200 ', ],
(Ecu.esp, 0x7d1, None): [b'\xf1\x816V5RAK00018.ELF\xf1\x00\x00\x00\x00\x00\x00\x00', ], (Ecu.esp, 0x7d1, None): [b'\xf1\x816V5RAK00018.ELF\xf1\x00\x00\x00\x00\x00\x00\x00', ],
@ -912,7 +951,7 @@ FW_VERSIONS = {
} }
CHECKSUM = { CHECKSUM = {
"crc8": [CAR.SANTA_FE, CAR.SONATA, CAR.PALISADE, CAR.KIA_SELTOS, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.SANTA_FE_2022, CAR.KIA_K5_2021], "crc8": [CAR.SANTA_FE, CAR.SONATA, CAR.PALISADE, CAR.KIA_SELTOS, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.SANTA_FE_HEV_2022],
"6B": [CAR.KIA_SORENTO, CAR.HYUNDAI_GENESIS], "6B": [CAR.KIA_SORENTO, CAR.HYUNDAI_GENESIS],
} }
@ -920,15 +959,18 @@ FEATURES = {
# which message has the gear # which message has the gear
"use_cluster_gears": set([CAR.ELANTRA, CAR.ELANTRA_GT_I30, CAR.KONA]), "use_cluster_gears": set([CAR.ELANTRA, CAR.ELANTRA_GT_I30, CAR.KONA]),
"use_tcu_gears": set([CAR.KIA_OPTIMA, CAR.SONATA_LF, CAR.VELOSTER]), "use_tcu_gears": set([CAR.KIA_OPTIMA, CAR.SONATA_LF, CAR.VELOSTER]),
"use_elect_gears": set([CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021,CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ_HEV_2022]), "use_elect_gears": set([CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021,CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022]),
# these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12 # these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12
"use_fca": set([CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.ELANTRA_GT_I30, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022]), "use_fca": set([CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.ELANTRA_GT_I30, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022]),
} }
HYBRID_CAR = set([CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.KIA_NIRO_HEV, CAR.KIA_NIRO_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ, CAR.IONIQ_HEV_2022]) # these cars use a different gas signal HYBRID_CAR = set([CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.KIA_NIRO_HEV, CAR.KIA_NIRO_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022]) # these cars use a different gas signal
EV_CAR = set([CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.KIA_NIRO_EV]) EV_CAR = set([CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.KIA_NIRO_EV])
# these cars require a special panda safety mode due to missing counters and checksums in the messages
LEGACY_SAFETY_MODE_CAR = set([CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_SORENTO, CAR.SONATA_LF, CAR.KIA_NIRO_EV, CAR.KIA_OPTIMA, CAR.VELOSTER, CAR.KIA_STINGER, CAR.GENESIS_G70, CAR.GENESIS_G80, CAR.KIA_CEED, CAR.ELANTRA, CAR.IONIQ_HEV_2022])
# If 0x500 is present on bus 1 it probably has a Mando radar outputting radar points. # If 0x500 is present on bus 1 it probably has a Mando radar outputting radar points.
# If no points are outputted by default it might be possible to turn it on using selfdrive/debug/hyundai_enable_radar_points.py # If no points are outputted by default it might be possible to turn it on using selfdrive/debug/hyundai_enable_radar_points.py
DBC = { DBC = {
@ -937,6 +979,7 @@ DBC = {
CAR.ELANTRA_HEV_2021: dbc_dict('hyundai_kia_generic', None), CAR.ELANTRA_HEV_2021: dbc_dict('hyundai_kia_generic', None),
CAR.ELANTRA_GT_I30: dbc_dict('hyundai_kia_generic', None), CAR.ELANTRA_GT_I30: dbc_dict('hyundai_kia_generic', None),
CAR.GENESIS_G70: dbc_dict('hyundai_kia_generic', None), CAR.GENESIS_G70: dbc_dict('hyundai_kia_generic', None),
CAR.GENESIS_G70_2020: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar'),
CAR.GENESIS_G80: dbc_dict('hyundai_kia_generic', None), CAR.GENESIS_G80: dbc_dict('hyundai_kia_generic', None),
CAR.GENESIS_G90: dbc_dict('hyundai_kia_generic', None), CAR.GENESIS_G90: dbc_dict('hyundai_kia_generic', None),
CAR.HYUNDAI_GENESIS: dbc_dict('hyundai_kia_generic', None), CAR.HYUNDAI_GENESIS: dbc_dict('hyundai_kia_generic', None),
@ -960,6 +1003,7 @@ DBC = {
CAR.KONA_HEV: dbc_dict('hyundai_kia_generic', None), CAR.KONA_HEV: dbc_dict('hyundai_kia_generic', None),
CAR.SANTA_FE: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar'), CAR.SANTA_FE: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar'),
CAR.SANTA_FE_2022: dbc_dict('hyundai_kia_generic', None), CAR.SANTA_FE_2022: dbc_dict('hyundai_kia_generic', None),
CAR.SANTA_FE_HEV_2022: dbc_dict('hyundai_kia_generic', None),
CAR.SONATA: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar'), CAR.SONATA: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar'),
CAR.SONATA_LF: dbc_dict('hyundai_kia_generic', None), # Has 0x5XX messages, but different format CAR.SONATA_LF: dbc_dict('hyundai_kia_generic', None), # Has 0x5XX messages, but different format
CAR.PALISADE: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar'), CAR.PALISADE: dbc_dict('hyundai_kia_generic', 'hyundai_kia_mando_front_radar'),

@ -1,6 +1,6 @@
from cereal import car from cereal import car
from common.numpy_fast import clip, interp from common.numpy_fast import clip, interp
from selfdrive.car import apply_toyota_steer_torque_limits, create_gas_command, make_can_msg from selfdrive.car import apply_toyota_steer_torque_limits, create_gas_interceptor_command, make_can_msg
from selfdrive.car.toyota.toyotacan import create_steer_command, create_ui_command, \ from selfdrive.car.toyota.toyotacan import create_steer_command, create_ui_command, \
create_accel_command, create_acc_cancel_command, \ create_accel_command, create_acc_cancel_command, \
create_fcw_command, create_lta_steer_command create_fcw_command, create_lta_steer_command
@ -123,7 +123,7 @@ class CarController():
if frame % 2 == 0 and CS.CP.enableGasInterceptor: if frame % 2 == 0 and CS.CP.enableGasInterceptor:
# send exactly zero if gas cmd is zero. Interceptor will send the max between read value and gas cmd. # send exactly zero if gas cmd is zero. Interceptor will send the max between read value and gas cmd.
# This prevents unexpected pedal range rescaling # This prevents unexpected pedal range rescaling
can_sends.append(create_gas_command(self.packer, interceptor_gas_cmd, frame // 2)) can_sends.append(create_gas_interceptor_command(self.packer, interceptor_gas_cmd, frame // 2))
# ui mesg is at 100Hz but we send asap if: # ui mesg is at 100Hz but we send asap if:
# - there is something to display # - there is something to display

@ -1 +1 @@
#define COMMA_VERSION "0.8.12" #define COMMA_VERSION "0.8.11"

@ -42,7 +42,13 @@ SUPPORTED_FW_VERSIONS = {
b"TM__ SCC F-CUP 1.00 1.03 99110-S2000\x19\x050\x13' ": { b"TM__ SCC F-CUP 1.00 1.03 99110-S2000\x19\x050\x13' ": {
"default_config": b"\x00\x00\x00\x01\x00\x00", "default_config": b"\x00\x00\x00\x01\x00\x00",
"tracks_enabled": b"\x00\x00\x00\x01\x00\x01", "tracks_enabled": b"\x00\x00\x00\x01\x00\x01",
} },
# 2020 GENESIS G70
b'IK__ SCC F-CUP 1.00 1.02 96400-G9100\x18\x07\x06\x17\x12 ': {
"default config": b"\x00\x00\x00\x01\x00\x00",
"tracks_enabled": b"\x00\x00\x00\x01\x00\x01",
},
} }
if __name__ == "__main__": if __name__ == "__main__":

@ -57,8 +57,8 @@ class LiveKalman():
0, 0, 0]) 0, 0, 0])
# state covariance # state covariance
initial_P_diag = np.array([10**2, 10**2, 10**2, initial_P_diag = np.array([1e3**2, 1e3**2, 1e3**2,
0.01**2, 0.01**2, 0.01**2, 0.5**2, 0.5**2, 0.5**2,
10**2, 10**2, 10**2, 10**2, 10**2, 10**2,
1**2, 1**2, 1**2, 1**2, 1**2, 1**2,
1**2, 1**2, 1**2, 1**2, 1**2, 1**2,

@ -102,8 +102,7 @@ class TestEncoder(unittest.TestCase):
# TODO: this ffprobe call is really slow # TODO: this ffprobe call is really slow
# check frame count # check frame count
cmd = f"ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames \ cmd = f"ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 {file_path}"
-of default=nokey=1:noprint_wrappers=1 {file_path}"
if TICI: if TICI:
cmd = "LD_LIBRARY_PATH=/usr/local/lib " + cmd cmd = "LD_LIBRARY_PATH=/usr/local/lib " + cmd

@ -117,15 +117,15 @@ class TestLoggerd(unittest.TestCase):
expected_files.add("ecamera.hevc") expected_files.add("ecamera.hevc")
# give camerad time to start # give camerad time to start
time.sleep(5) time.sleep(3)
for _ in range(5): for _ in range(5):
num_segs = random.randint(1, 10) num_segs = random.randint(2, 5)
length = random.randint(2, 5) length = random.randint(1, 3)
os.environ["LOGGERD_SEGMENT_LENGTH"] = str(length) os.environ["LOGGERD_SEGMENT_LENGTH"] = str(length)
managed_processes["loggerd"].start() managed_processes["loggerd"].start()
time.sleep((num_segs + 1) * length) time.sleep(num_segs*length + 1)
managed_processes["loggerd"].stop() managed_processes["loggerd"].stop()
route_path = str(self._get_latest_log_dir()).rsplit("--", 1)[0] route_path = str(self._get_latest_log_dir()).rsplit("--", 1)[0]
@ -177,7 +177,9 @@ class TestLoggerd(unittest.TestCase):
# sleep enough for the first poll to time out # sleep enough for the first poll to time out
# TOOD: fix loggerd bug dropping the msgs from the first poll # TOOD: fix loggerd bug dropping the msgs from the first poll
managed_processes["loggerd"].start() managed_processes["loggerd"].start()
time.sleep(2) for s in services:
while not pm.all_readers_updated(s):
time.sleep(0.1)
sent_msgs = defaultdict(list) sent_msgs = defaultdict(list)
for _ in range(random.randint(2, 10) * 100): for _ in range(random.randint(2, 10) * 100):
@ -220,9 +222,11 @@ class TestLoggerd(unittest.TestCase):
pm = messaging.PubMaster(services) pm = messaging.PubMaster(services)
# sleep enough for the first poll to time out # sleep enough for the first poll to time out
# TOOD: fix loggerd bug dropping the msgs from the first poll # TODO: fix loggerd bug dropping the msgs from the first poll
managed_processes["loggerd"].start() managed_processes["loggerd"].start()
time.sleep(2) for s in services:
while not pm.all_readers_updated(s):
time.sleep(0.1)
sent_msgs = defaultdict(list) sent_msgs = defaultdict(list)
for _ in range(random.randint(2, 10) * 100): for _ in range(random.randint(2, 10) * 100):
@ -233,9 +237,8 @@ class TestLoggerd(unittest.TestCase):
m = messaging.new_message(s, random.randint(2, 10)) m = messaging.new_message(s, random.randint(2, 10))
pm.send(s, m) pm.send(s, m)
sent_msgs[s].append(m) sent_msgs[s].append(m)
time.sleep(0.01)
time.sleep(1) time.sleep(2)
managed_processes["loggerd"].stop() managed_processes["loggerd"].stop()
lr = list(LogReader(os.path.join(self._get_latest_log_dir(), "rlog.bz2"))) lr = list(LogReader(os.path.join(self._get_latest_log_dir(), "rlog.bz2")))

@ -5,7 +5,7 @@ import time
import unittest import unittest
import selfdrive.manager.manager as manager import selfdrive.manager.manager as manager
from selfdrive.hardware import EON from selfdrive.hardware import EON, TICI, HARDWARE
from selfdrive.manager.process import DaemonProcess from selfdrive.manager.process import DaemonProcess
from selfdrive.manager.process_config import managed_processes from selfdrive.manager.process_config import managed_processes
@ -37,8 +37,8 @@ class TestManager(unittest.TestCase):
# ensure all processes exit cleanly # ensure all processes exit cleanly
def test_clean_exit(self): def test_clean_exit(self):
HARDWARE.set_power_save(False)
manager.manager_prepare() manager.manager_prepare()
for p in ALL_PROCESSES: for p in ALL_PROCESSES:
managed_processes[p].start() managed_processes[p].start()
@ -49,7 +49,7 @@ class TestManager(unittest.TestCase):
self.assertTrue(state.running, f"{p} not running") self.assertTrue(state.running, f"{p} not running")
exit_code = managed_processes[p].stop(retry=False) exit_code = managed_processes[p].stop(retry=False)
if (p == 'ui') or (EON and p == 'logcatd'): if (TICI and p in ['ui', 'navd']) or (EON and p == 'logcatd'):
# TODO: make Qt UI exit gracefully # TODO: make Qt UI exit gracefully
continue continue

@ -13,11 +13,30 @@
#define MODEL_HEIGHT 640 #define MODEL_HEIGHT 640
#define FULL_W 852 // should get these numbers from camerad #define FULL_W 852 // should get these numbers from camerad
template <class T>
static inline T *get_buffer(std::vector<T> &buf, const size_t size) {
if (buf.size() < size) buf.resize(size);
return buf.data();
}
static inline void init_yuv_buf(std::vector<uint8_t> &buf, const int width, int height) {
uint8_t *y = get_buffer(buf, width * height * 3 / 2);
uint8_t *u = y + width * height;
uint8_t *v = u + (width / 2) * (height / 2);
// needed on comma two to make the padded border black
// equivalent to RGB(0,0,0) in YUV space
memset(y, 16, width * height);
memset(u, 128, (width / 2) * (height / 2));
memset(v, 128, (width / 2) * (height / 2));
}
void dmonitoring_init(DMonitoringModelState* s) { void dmonitoring_init(DMonitoringModelState* s) {
s->is_rhd = Params().getBool("IsRHD"); s->is_rhd = Params().getBool("IsRHD");
for (int x = 0; x < std::size(s->tensor); ++x) { for (int x = 0; x < std::size(s->tensor); ++x) {
s->tensor[x] = (x - 128.f) * 0.0078125f; s->tensor[x] = (x - 128.f) * 0.0078125f;
} }
init_yuv_buf(s->resized_buf, MODEL_WIDTH, MODEL_HEIGHT);
#ifdef USE_ONNX_MODEL #ifdef USE_ONNX_MODEL
s->m = new ONNXModel("../../models/dmonitoring_model.onnx", &s->output[0], OUTPUT_SIZE, USE_DSP_RUNTIME); s->m = new ONNXModel("../../models/dmonitoring_model.onnx", &s->output[0], OUTPUT_SIZE, USE_DSP_RUNTIME);
@ -26,12 +45,6 @@ void dmonitoring_init(DMonitoringModelState* s) {
#endif #endif
} }
template <class T>
static inline T *get_buffer(std::vector<T> &buf, const size_t size) {
if (buf.size() < size) buf.resize(size);
return buf.data();
}
static inline auto get_yuv_buf(std::vector<uint8_t> &buf, const int width, int height) { static inline auto get_yuv_buf(std::vector<uint8_t> &buf, const int width, int height) {
uint8_t *y = get_buffer(buf, width * height * 3 / 2); uint8_t *y = get_buffer(buf, width * height * 3 / 2);
uint8_t *u = y + width * height; uint8_t *u = y + width * height;

@ -1,6 +1,7 @@
#pragma once #pragma once
class RunModel { class RunModel {
public: public:
virtual ~RunModel() {}
virtual void addRecurrent(float *state, int state_size) {} virtual void addRecurrent(float *state, int state_size) {}
virtual void addDesire(float *state, int state_size) {} virtual void addDesire(float *state, int state_size) {}
virtual void addTrafficConvention(float *state, int state_size) {} virtual void addTrafficConvention(float *state, int state_size) {}

@ -1 +1 @@
848bc88a069b182d6f50698dd785ba360915e8dc 567866c06976f8f95fa7d1670b51d8723e663ea1

@ -7,10 +7,10 @@ from collections import defaultdict, Counter
from parameterized import parameterized_class from parameterized import parameterized_class
from cereal import log, car from cereal import log, car
from common.params import Params
from selfdrive.car.fingerprints import all_known_cars from selfdrive.car.fingerprints import all_known_cars
from selfdrive.car.car_helpers import interfaces from selfdrive.car.car_helpers import interfaces
from selfdrive.car.honda.values import HONDA_BOSCH from selfdrive.car.honda.values import HONDA_BOSCH, CAR as HONDA
from selfdrive.car.honda.values import CAR as HONDA
from selfdrive.car.chrysler.values import CAR as CHRYSLER from selfdrive.car.chrysler.values import CAR as CHRYSLER
from selfdrive.car.hyundai.values import CAR as HYUNDAI from selfdrive.car.hyundai.values import CAR as HYUNDAI
from selfdrive.test.test_routes import routes, non_tested_cars from selfdrive.test.test_routes import routes, non_tested_cars
@ -60,6 +60,9 @@ class TestCarModel(unittest.TestCase):
if lr is None: if lr is None:
raise Exception("Route not found. Is it uploaded?") raise Exception("Route not found. Is it uploaded?")
params = Params()
params.clear_all()
can_msgs = [] can_msgs = []
fingerprint = {i: dict() for i in range(3)} fingerprint = {i: dict() for i in range(3)}
for msg in lr: for msg in lr:
@ -68,15 +71,26 @@ class TestCarModel(unittest.TestCase):
if m.src < 128: if m.src < 128:
fingerprint[m.src][m.address] = len(m.dat) fingerprint[m.src][m.address] = len(m.dat)
can_msgs.append(msg) can_msgs.append(msg)
elif msg.which() == "carParams":
if msg.carParams.openpilotLongitudinalControl:
params.put_bool("DisableRadar", True)
cls.can_msgs = sorted(can_msgs, key=lambda msg: msg.logMonoTime) cls.can_msgs = sorted(can_msgs, key=lambda msg: msg.logMonoTime)
CarInterface, CarController, CarState = interfaces[cls.car_model] cls.CarInterface, cls.CarController, cls.CarState = interfaces[cls.car_model]
cls.CP = CarInterface.get_params(cls.car_model, fingerprint, []) cls.CP = cls.CarInterface.get_params(cls.car_model, fingerprint, [])
assert cls.CP assert cls.CP
cls.CI = CarInterface(cls.CP, CarController, CarState) def setUp(self):
assert cls.CI self.CI = self.CarInterface(self.CP, self.CarController, self.CarState)
assert self.CI
# TODO: check safetyModel is in release panda build
self.safety = libpandasafety_py.libpandasafety
set_status = self.safety.set_safety_hooks(self.CP.safetyConfigs[0].safetyModel.raw, self.CP.safetyConfigs[0].safetyParam)
self.assertEqual(0, set_status, f"failed to set safetyModel {self.CP.safetyConfigs[0].safetyModel}")
self.safety.init_tests()
def test_car_params(self): def test_car_params(self):
if self.CP.dashcamOnly: if self.CP.dashcamOnly:
@ -95,11 +109,6 @@ class TestCarModel(unittest.TestCase):
elif tuning == 'indi': elif tuning == 'indi':
self.assertTrue(len(self.CP.lateralTuning.indi.outerLoopGainV)) self.assertTrue(len(self.CP.lateralTuning.indi.outerLoopGainV))
# TODO: check safetyModel is in release panda build
safety = libpandasafety_py.libpandasafety
set_status = safety.set_safety_hooks(self.CP.safetyConfigs[0].safetyModel.raw, self.CP.safetyConfigs[0].safetyParam)
self.assertEqual(0, set_status, f"failed to set safetyModel {self.CP.safetyConfigs[0].safetyModel}")
def test_car_interface(self): def test_car_interface(self):
# TODO: also check for checkusm and counter violations from can parser # TODO: also check for checkusm and counter violations from can parser
can_invalid_cnt = 0 can_invalid_cnt = 0
@ -132,30 +141,25 @@ class TestCarModel(unittest.TestCase):
if self.CP.dashcamOnly: if self.CP.dashcamOnly:
self.skipTest("no need to check panda safety for dashcamOnly") self.skipTest("no need to check panda safety for dashcamOnly")
safety = libpandasafety_py.libpandasafety
set_status = safety.set_safety_hooks(self.CP.safetyConfigs[0].safetyModel.raw, self.CP.safetyConfigs[0].safetyParam)
self.assertEqual(0, set_status)
failed_addrs = Counter() failed_addrs = Counter()
for can in self.can_msgs: for can in self.can_msgs:
for msg in can.can: for msg in can.can:
if msg.src >= 128: if msg.src >= 128:
continue continue
to_send = package_can_msg([msg.address, 0, msg.dat, msg.src]) to_send = package_can_msg([msg.address, 0, msg.dat, msg.src])
if not safety.safety_rx_hook(to_send): if self.safety.safety_rx_hook(to_send) != 1:
failed_addrs[hex(msg.address)] += 1 failed_addrs[hex(msg.address)] += 1
self.assertFalse(len(failed_addrs), f"panda safety RX check failed: {failed_addrs}") self.assertFalse(len(failed_addrs), f"panda safety RX check failed: {failed_addrs}")
def test_panda_safety_carstate(self): def test_panda_safety_carstate(self):
"""
Assert that panda safety matches openpilot's carState
"""
if self.CP.dashcamOnly: if self.CP.dashcamOnly:
self.skipTest("no need to check panda safety for dashcamOnly") self.skipTest("no need to check panda safety for dashcamOnly")
if self.car_model in ignore_carstate_check: if self.car_model in ignore_carstate_check:
self.skipTest("see comments in test_models.py") self.skipTest("see comments in test_models.py")
safety = libpandasafety_py.libpandasafety
set_status = safety.set_safety_hooks(self.CP.safetyConfigs[0].safetyModel.raw, self.CP.safetyConfigs[0].safetyParam)
self.assertEqual(0, set_status)
checks = defaultdict(lambda: 0) checks = defaultdict(lambda: 0)
CC = car.CarControl.new_message() CC = car.CarControl.new_message()
for can in self.can_msgs: for can in self.can_msgs:
@ -163,14 +167,20 @@ class TestCarModel(unittest.TestCase):
if msg.src >= 128: if msg.src >= 128:
continue continue
to_send = package_can_msg([msg.address, 0, msg.dat, msg.src]) to_send = package_can_msg([msg.address, 0, msg.dat, msg.src])
safety.safety_rx_hook(to_send) ret = self.safety.safety_rx_hook(to_send)
self.assertEqual(1, ret, f"safety rx failed ({ret=}): {to_send}")
CS = self.CI.update(CC, (can.as_builder().to_bytes(),)) CS = self.CI.update(CC, (can.as_builder().to_bytes(),))
# TODO: check steering state # TODO: check steering state
# check that openpilot and panda safety agree on the car's state # check that openpilot and panda safety agree on the car's state
checks['gasPressed'] += CS.gasPressed != safety.get_gas_pressed_prev() checks['gasPressed'] += CS.gasPressed != self.safety.get_gas_pressed_prev()
checks['brakePressed'] += CS.brakePressed != safety.get_brake_pressed_prev() checks['brakePressed'] += CS.brakePressed != self.safety.get_brake_pressed_prev()
checks['controlsAllowed'] += not CS.cruiseState.enabled and safety.get_controls_allowed() if self.CP.pcmCruise:
checks['controlsAllowed'] += not CS.cruiseState.enabled and self.safety.get_controls_allowed()
# TODO: extend this to all cars
if self.CP.carName == "honda":
checks['mainOn'] += CS.cruiseState.available != self.safety.get_acc_main_on()
# TODO: reduce tolerance to 0 # TODO: reduce tolerance to 0
failed_checks = {k: v for k, v in checks.items() if v > 25} failed_checks = {k: v for k, v in checks.items() if v > 25}

@ -71,6 +71,7 @@ routes = [
TestRoute("6b301bf83f10aa90|2020-11-22--16-45-07", HYUNDAI.GENESIS_G80), TestRoute("6b301bf83f10aa90|2020-11-22--16-45-07", HYUNDAI.GENESIS_G80),
TestRoute("38bfd238edecbcd7|2018-08-29--22-02-15", HYUNDAI.SANTA_FE), TestRoute("38bfd238edecbcd7|2018-08-29--22-02-15", HYUNDAI.SANTA_FE),
TestRoute("bf43d9df2b660eb0|2021-09-23--14-16-37", HYUNDAI.SANTA_FE_2022), TestRoute("bf43d9df2b660eb0|2021-09-23--14-16-37", HYUNDAI.SANTA_FE_2022),
TestRoute("37398f32561a23ad|2021-11-18--00-11-35", HYUNDAI.SANTA_FE_HEV_2022),
TestRoute("e0e98335f3ebc58f|2021-03-07--16-38-29", HYUNDAI.KIA_CEED), TestRoute("e0e98335f3ebc58f|2021-03-07--16-38-29", HYUNDAI.KIA_CEED),
TestRoute("7653b2bce7bcfdaa|2020-03-04--15-34-32", HYUNDAI.KIA_OPTIMA), TestRoute("7653b2bce7bcfdaa|2020-03-04--15-34-32", HYUNDAI.KIA_OPTIMA),
TestRoute("c75a59efa0ecd502|2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS), TestRoute("c75a59efa0ecd502|2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS),
@ -97,6 +98,7 @@ routes = [
TestRoute("82e9cdd3f43bf83e|2021-05-15--02-42-51", HYUNDAI.ELANTRA_2021), TestRoute("82e9cdd3f43bf83e|2021-05-15--02-42-51", HYUNDAI.ELANTRA_2021),
TestRoute("715ac05b594e9c59|2021-06-20--16-21-07", HYUNDAI.ELANTRA_HEV_2021), TestRoute("715ac05b594e9c59|2021-06-20--16-21-07", HYUNDAI.ELANTRA_HEV_2021),
TestRoute("7120aa90bbc3add7|2021-08-02--07-12-31", HYUNDAI.SONATA_HYBRID), TestRoute("7120aa90bbc3add7|2021-08-02--07-12-31", HYUNDAI.SONATA_HYBRID),
TestRoute("715ac05b594e9c59|2021-10-27--23-24-56", HYUNDAI.GENESIS_G70_2020),
TestRoute("00c829b1b7613dea|2021-06-24--09-10-10", TOYOTA.ALPHARD_TSS2), TestRoute("00c829b1b7613dea|2021-06-24--09-10-10", TOYOTA.ALPHARD_TSS2),
TestRoute("000cf3730200c71c|2021-05-24--10-42-05", TOYOTA.AVALON), TestRoute("000cf3730200c71c|2021-05-24--10-42-05", TOYOTA.AVALON),

@ -25,69 +25,88 @@
#include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/qt_window.h" #include "selfdrive/ui/qt/qt_window.h"
TogglesPanel::TogglesPanel(QWidget *parent) : ListWidget(parent) { TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
auto params = Params(); // param, title, desc, icon
addItem(new ParamControl("OpenpilotEnabledToggle", std::vector<std::tuple<QString, QString, QString, QString>> toggles{
"Enable openpilot", {
"Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off.", "OpenpilotEnabledToggle",
"../assets/offroad/icon_openpilot.png", "Enable openpilot",
this)); "Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off.",
addItem(new ParamControl("IsLdwEnabled", "../assets/offroad/icon_openpilot.png",
"Enable Lane Departure Warnings", },
"Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31mph (50kph).", {
"../assets/offroad/icon_warning.png", "IsLdwEnabled",
this)); "Enable Lane Departure Warnings",
addItem(new ParamControl("IsRHD", "Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31mph (50kph).",
"Enable Right-Hand Drive", "../assets/offroad/icon_warning.png",
"Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat.", },
"../assets/offroad/icon_openpilot_mirrored.png", {
this)); "IsRHD",
addItem(new ParamControl("IsMetric", "Enable Right-Hand Drive",
"Use Metric System", "Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat.",
"Display speed in km/h instead of mph.", "../assets/offroad/icon_openpilot_mirrored.png",
"../assets/offroad/icon_metric.png", },
this)); {
addItem(new ParamControl("CommunityFeaturesToggle", "IsMetric",
"Enable Community Features", "Use Metric System",
"Use features, such as community supported hardware, from the open source community that are not maintained or supported by comma.ai and have not been confirmed to meet the standard safety model. Be extra cautious when using these features", "Display speed in km/h instead of mph.",
"../assets/offroad/icon_shell.png", "../assets/offroad/icon_metric.png",
this)); },
{
addItem(new ParamControl("UploadRaw", "CommunityFeaturesToggle",
"Upload Raw Logs", "Enable Community Features",
"Upload full logs and full resolution video by default while on Wi-Fi. If not enabled, individual logs can be marked for upload at useradmin.comma.ai.", "Use features, such as community supported hardware, from the open source community that are not maintained or supported by comma.ai and have not been confirmed to meet the standard safety model. Be extra cautious when using these features",
"../assets/offroad/icon_network.png", "../assets/offroad/icon_shell.png",
this)); },
{
ParamControl *record_toggle = new ParamControl("RecordFront", "UploadRaw",
"Record and Upload Driver Camera", "Upload Raw Logs",
"Upload data from the driver facing camera and help improve the driver monitoring algorithm.", "Upload full logs and full resolution video by default while on Wi-Fi. If not enabled, individual logs can be marked for upload at useradmin.comma.ai.",
"../assets/offroad/icon_monitoring.png", "../assets/offroad/icon_network.png",
this); },
addItem(record_toggle); {
addItem(new ParamControl("EndToEndToggle", "RecordFront",
"\U0001f96c Disable use of lanelines (Alpha) \U0001f96c", "Record and Upload Driver Camera",
"In this mode openpilot will ignore lanelines and just drive how it thinks a human would.", "Upload data from the driver facing camera and help improve the driver monitoring algorithm.",
"../assets/offroad/icon_road.png", "../assets/offroad/icon_monitoring.png",
this)); },
{
"EndToEndToggle",
"\U0001f96c Disable use of lanelines (Alpha) \U0001f96c",
"In this mode openpilot will ignore lanelines and just drive how it thinks a human would.",
"../assets/offroad/icon_road.png",
},
#ifdef ENABLE_MAPS #ifdef ENABLE_MAPS
addItem(new ParamControl("NavSettingTime24h", {
"Show ETA in 24h format", "NavSettingTime24h",
"Use 24h format instead of am/pm", "Show ETA in 24h format",
"../assets/offroad/icon_metric.png", "Use 24h format instead of am/pm",
this)); "../assets/offroad/icon_metric.png",
},
#endif #endif
if (params.getBool("DisableRadar_Allow")) {
addItem(new ParamControl("DisableRadar",
"openpilot Longitudinal Control",
"openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB!",
"../assets/offroad/icon_speed_limit.png",
this));
};
Params params;
if (params.getBool("DisableRadar_Allow")) {
toggles.push_back({
"DisableRadar",
"openpilot Longitudinal Control",
"openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB!",
"../assets/offroad/icon_speed_limit.png",
});
} }
bool record_lock = params.getBool("RecordFrontLock"); for (auto &[param, title, desc, icon] : toggles) {
record_toggle->setEnabled(!record_lock); auto toggle = new ParamControl(param, title, desc, icon, this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
if (!locked) {
connect(parent, &SettingsWindow::offroadTransition, toggle, &ParamControl::setEnabled);
}
addItem(toggle);
}
} }
DevicePanel::DevicePanel(QWidget* parent) : ListWidget(parent) { DevicePanel::DevicePanel(QWidget* parent) : ListWidget(parent) {
@ -123,8 +142,8 @@ DevicePanel::DevicePanel(QWidget* parent) : ListWidget(parent) {
double pitch = calib.getRpyCalib()[1] * (180 / M_PI); double pitch = calib.getRpyCalib()[1] * (180 / M_PI);
double yaw = calib.getRpyCalib()[2] * (180 / M_PI); double yaw = calib.getRpyCalib()[2] * (180 / M_PI);
desc += QString(" Your device is pointed %1° %2 and %3° %4.") desc += QString(" Your device is pointed %1° %2 and %3° %4.")
.arg(QString::number(std::abs(pitch), 'g', 1), pitch > 0 ? "up" : "down", .arg(QString::number(std::abs(pitch), 'g', 1), pitch > 0 ? "up" : "down",
QString::number(std::abs(yaw), 'g', 1), yaw > 0 ? "right" : "left"); QString::number(std::abs(yaw), 'g', 1), yaw > 0 ? "right" : "left");
} }
} catch (kj::Exception) { } catch (kj::Exception) {
qInfo() << "invalid CalibrationParams"; qInfo() << "invalid CalibrationParams";
@ -358,7 +377,7 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
const int padding = panels.size() > 3 ? 25 : 35; const int padding = panels.size() > 3 ? 25 : 35;
nav_btns = new QButtonGroup(); nav_btns = new QButtonGroup(this);
for (auto &[name, panel] : panels) { for (auto &[name, panel] : panels) {
QPushButton *btn = new QPushButton(name); QPushButton *btn = new QPushButton(name);
btn->setCheckable(true); btn->setCheckable(true);

@ -12,6 +12,28 @@
#include "selfdrive/ui/qt/widgets/controls.h" #include "selfdrive/ui/qt/widgets/controls.h"
// ********** settings window + top-level panels ********** // ********** settings window + top-level panels **********
class SettingsWindow : public QFrame {
Q_OBJECT
public:
explicit SettingsWindow(QWidget *parent = 0);
protected:
void hideEvent(QHideEvent *event) override;
void showEvent(QShowEvent *event) override;
signals:
void closeSettings();
void offroadTransition(bool offroad);
void reviewTrainingGuide();
void showDriverView();
private:
QPushButton *sidebar_alert_widget;
QWidget *sidebar_widget;
QButtonGroup *nav_btns;
QStackedWidget *panel_widget;
};
class DevicePanel : public ListWidget { class DevicePanel : public ListWidget {
Q_OBJECT Q_OBJECT
@ -25,7 +47,7 @@ signals:
class TogglesPanel : public ListWidget { class TogglesPanel : public ListWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit TogglesPanel(QWidget *parent = nullptr); explicit TogglesPanel(SettingsWindow *parent);
}; };
class SoftwarePanel : public ListWidget { class SoftwarePanel : public ListWidget {
@ -47,26 +69,3 @@ private:
Params params; Params params;
QFileSystemWatcher *fs_watch; QFileSystemWatcher *fs_watch;
}; };
class SettingsWindow : public QFrame {
Q_OBJECT
public:
explicit SettingsWindow(QWidget *parent = 0);
protected:
void hideEvent(QHideEvent *event) override;
void showEvent(QShowEvent *event) override;
signals:
void closeSettings();
void offroadTransition(bool offroad);
void reviewTrainingGuide();
void showDriverView();
private:
QPushButton *sidebar_alert_widget;
QWidget *sidebar_widget;
QButtonGroup *nav_btns;
QStackedWidget *panel_widget;
};

@ -9,7 +9,7 @@
#include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/util.h"
template <typename T> template <typename T>
T get_response(QDBusMessage response) { T get_response(const QDBusMessage &response) {
QVariant first = response.arguments().at(0); QVariant first = response.arguments().at(0);
QDBusVariant dbvFirst = first.value<QDBusVariant>(); QDBusVariant dbvFirst = first.value<QDBusVariant>();
QVariant vFirst = dbvFirst.variant(); QVariant vFirst = dbvFirst.variant();

@ -36,13 +36,12 @@ LogReader::LogReader(bool local_cache, int chunk_size, int retries, size_t memor
} }
LogReader::~LogReader() { LogReader::~LogReader() {
#ifdef HAS_MEMORY_RESOURCE
delete mbr_;
::operator delete(pool_buffer_);
#else
for (Event *e : events) { for (Event *e : events) {
delete e; delete e;
} }
#ifdef HAS_MEMORY_RESOURCE
delete mbr_;
::operator delete(pool_buffer_);
#endif #endif
} }

@ -57,7 +57,7 @@ TEST_CASE("FileReader") {
} }
TEST_CASE("Segment") { TEST_CASE("Segment") {
auto flags = GENERATE(REPLAY_FLAG_NONE, REPLAY_FLAG_QCAMERA); auto flags = GENERATE(REPLAY_FLAG_DCAM | REPLAY_FLAG_ECAM, REPLAY_FLAG_QCAMERA);
Route demo_route(DEMO_ROUTE); Route demo_route(DEMO_ROUTE);
REQUIRE(demo_route.load()); REQUIRE(demo_route.load());
REQUIRE(demo_route.segments().size() == 11); REQUIRE(demo_route.segments().size() == 11);
@ -68,21 +68,32 @@ TEST_CASE("Segment") {
REQUIRE(segment.isLoaded() == true); REQUIRE(segment.isLoaded() == true);
REQUIRE(segment.log != nullptr); REQUIRE(segment.log != nullptr);
REQUIRE(segment.frames[RoadCam] != nullptr); REQUIRE(segment.frames[RoadCam] != nullptr);
REQUIRE(segment.frames[DriverCam] == nullptr); if (flags & REPLAY_FLAG_DCAM) {
REQUIRE(segment.frames[WideRoadCam] == nullptr); REQUIRE(segment.frames[DriverCam] != nullptr);
}
if (flags & REPLAY_FLAG_ECAM) {
REQUIRE(segment.frames[WideRoadCam] != nullptr);
}
// LogReader & FrameReader // test LogReader & FrameReader
REQUIRE(segment.log->events.size() > 0); REQUIRE(segment.log->events.size() > 0);
REQUIRE(std::is_sorted(segment.log->events.begin(), segment.log->events.end(), Event::lessThan())); REQUIRE(std::is_sorted(segment.log->events.begin(), segment.log->events.end(), Event::lessThan()));
auto &fr = segment.frames[RoadCam]; for (auto cam : ALL_CAMERAS) {
REQUIRE(fr->getFrameCount() == 1200); auto &fr = segment.frames[cam];
std::unique_ptr<uint8_t[]> rgb_buf = std::make_unique<uint8_t[]>(fr->getRGBSize()); if (!fr) continue;
std::unique_ptr<uint8_t[]> yuv_buf = std::make_unique<uint8_t[]>(fr->getYUVSize());
// sequence get 50 frames if (cam == RoadCam || cam == WideRoadCam) {
for (int i = 0; i < 50; ++i) { REQUIRE(fr->getFrameCount() == 1200);
REQUIRE(fr->get(i, rgb_buf.get(), yuv_buf.get())); }
std::unique_ptr<uint8_t[]> rgb_buf = std::make_unique<uint8_t[]>(fr->getRGBSize());
std::unique_ptr<uint8_t[]> yuv_buf = std::make_unique<uint8_t[]>(fr->getYUVSize());
// sequence get 50 frames
for (int i = 0; i < 50; ++i) {
REQUIRE(fr->get(i, rgb_buf.get(), yuv_buf.get()));
}
} }
loop.quit(); loop.quit();
}); });
loop.exec(); loop.exec();
@ -134,7 +145,7 @@ void TestReplay::test_seek() {
stream_thread_ = new QThread(this); stream_thread_ = new QThread(this);
QEventLoop loop; QEventLoop loop;
std::thread thread = std::thread([&]() { std::thread thread = std::thread([&]() {
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 50; ++i) {
testSeekTo(random_int(0, 3 * 60)); testSeekTo(random_int(0, 3 * 60));
} }
loop.quit(); loop.quit();

@ -188,7 +188,7 @@ private:
// auto brightness // auto brightness
const float accel_samples = 5*UI_FREQ; const float accel_samples = 5*UI_FREQ;
bool awake; bool awake = false;
int awake_timeout = 0; int awake_timeout = 0;
float accel_prev = 0; float accel_prev = 0;
float gyro_prev = 0; float gyro_prev = 0;

@ -1,6 +1,11 @@
openpilot tools openpilot tools
============ ============
CTF
============
Learn about the openpilot ecosystem and tools by playing our [CTF](/tools/CTF.md).
SSH SSH
============ ============

@ -33,7 +33,7 @@ pip install pipenv==2021.5.29
echo "pip packages install ..." echo "pip packages install ..."
if [ -d "./xx" ]; then if [ -d "./xx" ]; then
PIPENV_PIPFILE=./xx/Pipfile pipenv install --system --dev --deploy export PIPENV_PIPFILE=./xx/Pipfile
pipenv install --system --dev --deploy pipenv install --system --dev --deploy
RUN="" RUN=""
else else

Loading…
Cancel
Save