From f210b2da08cd2cf95cd6f47b33d83febd772b3ac Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Thu, 8 Jun 2023 21:05:38 -0700 Subject: [PATCH 01/14] Update SSH README --- tools/ssh/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/ssh/README.md b/tools/ssh/README.md index 67b5271a42..588ea71579 100644 --- a/tools/ssh/README.md +++ b/tools/ssh/README.md @@ -24,14 +24,12 @@ The `id_rsa` key in this directory only works while your device is in the setup See the [community wiki](https://github.com/commaai/openpilot/wiki/SSH) for more detailed instructions and information. # Connecting to ssh.comma.ai -SSH into your comma device from anywhere with `ssh.comma.ai`. +SSH into your comma device from anywhere with `ssh.comma.ai`. Requires a [comma prime subscription](https://comma.ai/connect). ## Setup With software version 0.6.1 or newer, enter your GitHub username on your device under Developer Settings. Your GitHub authorized public keys will become your authorized SSH keys for `ssh.comma.ai`. You can add any additional keys in `/system/comma/home/.ssh/authorized_keys.persist`. -Requires [comma SIM with comma prime](https://comma.ai/shop) activated with comma connect, available on iOS and Android. comma two and EON ship with a pre-inserted comma SIM. - ## Recommended .ssh/config With the below SSH configuration, you can type `ssh comma-{dongleid}` to connect to your device through `ssh.comma.ai`.
From 0e67d41eef5fd39c57c5c75f181194ebff85a252 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Sat, 10 Jun 2023 01:50:25 +0800 Subject: [PATCH 02/14] cabana: fix bg color issue for inactive item (#28468) --- tools/cabana/signalview.cc | 2 +- tools/cabana/util.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cabana/signalview.cc b/tools/cabana/signalview.cc index 3fda5796d4..46dfef1004 100644 --- a/tools/cabana/signalview.cc +++ b/tools/cabana/signalview.cc @@ -331,7 +331,7 @@ void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op if (item && item->type == SignalModel::Item::Sig) { painter->setRenderHint(QPainter::Antialiasing); if (option.state & QStyle::State_Selected) { - painter->fillRect(option.rect, option.palette.highlight()); + painter->fillRect(option.rect, option.palette.brush(QPalette::Normal, QPalette::Highlight)); } int h_margin = option.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; diff --git a/tools/cabana/util.cc b/tools/cabana/util.cc index b0bba891db..7a606b133e 100644 --- a/tools/cabana/util.cc +++ b/tools/cabana/util.cc @@ -96,7 +96,7 @@ void MessageBytesDelegate::paint(QPainter *painter, const QStyleOptionViewItem & int v_margin = option.widget->style()->pixelMetric(QStyle::PM_FocusFrameVMargin); int h_margin = option.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin); if (option.state & QStyle::State_Selected) { - painter->fillRect(option.rect, option.palette.highlight()); + painter->fillRect(option.rect, option.palette.brush(QPalette::Normal, QPalette::Highlight)); } const QPoint pt{option.rect.left() + h_margin, option.rect.top() + v_margin}; From b2288b366697a7ac16323e06419243a1785b371b Mon Sep 17 00:00:00 2001 From: Lee Jong Mun <43285072+crwusiz@users.noreply.github.com> Date: Sat, 10 Jun 2023 02:54:39 +0900 Subject: [PATCH 03/14] kor translation update (#28469) --- selfdrive/ui/translations/main_ko.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index b751e9cf57..1936805aa5 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -1053,23 +1053,23 @@ This may take up to a minute. Aggressive - + 공격적 Standard - + 표준 Relaxed - + 편안한 Driving Personality - + 주행 모드 Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. - + 표준 모드를 권장합니다. 공격적 모드에서는 openpilot은 앞차를 더 가까이 따라가며 가속과 감속을 더 공격적으로 사용합니다. 편안한 모드에서 openpilot은 선두 차량에서 더 멀리 떨어져 있습니다. From 376144dca3ed6875fa8b2cc2ccfea5593ae85e78 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Sat, 10 Jun 2023 01:54:52 +0800 Subject: [PATCH 04/14] cabana: add "view" menu to the menu bar (#28467) --- tools/cabana/mainwin.cc | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index 3ae26106cf..f424a3eecf 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -77,6 +77,7 @@ MainWindow::MainWindow() : QMainWindow() { } void MainWindow::createActions() { + // File menu QMenu *file_menu = menuBar()->addMenu(tr("&File")); file_menu->addAction(tr("Open Stream..."), this, &MainWindow::openStream); close_stream_act = file_menu->addAction(tr("Close stream"), this, &MainWindow::closeStream); @@ -124,6 +125,7 @@ void MainWindow::createActions() { file_menu->addSeparator(); file_menu->addAction(tr("E&xit"), qApp, &QApplication::closeAllWindows)->setShortcuts(QKeySequence::Quit); + // Edit Menu QMenu *edit_menu = menuBar()->addMenu(tr("&Edit")); auto undo_act = UndoStack::instance()->createUndoAction(this, tr("&Undo")); undo_act->setShortcuts(QKeySequence::Undo); @@ -138,14 +140,22 @@ void MainWindow::createActions() { commands_act->setDefaultWidget(new QUndoView(UndoStack::instance())); commands_menu->addAction(commands_act); - edit_menu->addSeparator(); - edit_menu->addAction(tr("Reset Window Layout"), - [this]() { restoreState(default_state); }); - + // View Menu + QMenu *view_menu = menuBar()->addMenu(tr("&View")); + auto act = view_menu->addAction(tr("Full Screen"), this, &MainWindow::toggleFullScreen, QKeySequence::FullScreen); + addAction(act); + view_menu->addSeparator(); + view_menu->addAction(messages_dock->toggleViewAction()); + view_menu->addAction(video_dock->toggleViewAction()); + view_menu->addSeparator(); + view_menu->addAction(tr("Reset Window Layout"), [this]() { restoreState(default_state); }); + + // Tools Menu tools_menu = menuBar()->addMenu(tr("&Tools")); tools_menu->addAction(tr("Find &Similar Bits"), this, &MainWindow::findSimilarBits); tools_menu->addAction(tr("&Find Signal"), this, &MainWindow::findSignal); + // Help Menu QMenu *help_menu = menuBar()->addMenu(tr("&Help")); help_menu->addAction(tr("Help"), this, &MainWindow::onlineHelp)->setShortcuts(QKeySequence::HelpContents); help_menu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); @@ -155,13 +165,13 @@ void MainWindow::createDockWindows() { messages_dock = new QDockWidget(tr("MESSAGES"), this); messages_dock->setObjectName("MessagesPanel"); messages_dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); - messages_dock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); + messages_dock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable); addDockWidget(Qt::LeftDockWidgetArea, messages_dock); video_dock = new QDockWidget("", this); video_dock->setObjectName(tr("VideoPanel")); video_dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - video_dock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); + video_dock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable); addDockWidget(Qt::RightDockWidgetArea, video_dock); } @@ -206,8 +216,6 @@ void MainWindow::createStatusBar() { void MainWindow::createShortcuts() { auto shortcut = new QShortcut(QKeySequence(Qt::Key_Space), this, nullptr, nullptr, Qt::ApplicationShortcut); QObject::connect(shortcut, &QShortcut::activated, []() { can->pause(!can->isPaused()); }); - shortcut = new QShortcut(QKeySequence(QKeySequence::FullScreen), this, nullptr, nullptr, Qt::ApplicationShortcut); - QObject::connect(shortcut, &QShortcut::activated, this, &MainWindow::toggleFullScreen); // TODO: add more shortcuts here. } From 7a64385fcd5354efd3bd9dcf6972669c46d99c10 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 9 Jun 2023 11:20:42 -0700 Subject: [PATCH 05/14] Honda: set autoResumeSng for docs (#28458) set autoResumeSng for Honda --- docs/CARS.md | 20 ++++++++++---------- selfdrive/car/honda/interface.py | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/CARS.md b/docs/CARS.md index 373851932f..a4af5fc4c0 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -8,8 +8,8 @@ A supported vehicle is one that just works when you install a comma three. All s |Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Hardware Needed
 |Video| |---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:| -|Acura|ILX 2016-19|AcuraWatch Plus|openpilot|25 mph|25 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Acura|RDX 2016-18|AcuraWatch Plus|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Acura|ILX 2016-19|AcuraWatch Plus|openpilot|25 mph|25 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Acura|RDX 2016-18|AcuraWatch Plus|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Acura|RDX 2019-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,10](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 J533 connector
- 1 USB-C coupler
- 1 comma three
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,10](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 J533 connector
- 1 USB-C coupler
- 1 comma three
- 1 harness box
- 1 long OBD-C cable
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| @@ -55,20 +55,20 @@ A supported vehicle is one that just works when you install a comma three. All s |Honda|Civic 2022|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch B connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|Civic Hatchback 2017-21|Honda Sensing|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|Civic Hatchback 2022|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch B connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|CR-V 2015-16|Touring Trim|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|CR-V 2015-16|Touring Trim|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|CR-V 2017-22|Honda Sensing|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|CR-V Hybrid 2017-19|Honda Sensing|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|e 2020|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|Fit 2018-20|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|Freed 2020|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|HR-V 2019-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|Fit 2018-20|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|Freed 2020|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|HR-V 2019-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|HR-V 2023|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch B connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|Insight 2019-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Honda|Inspire 2018|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Bosch A connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|Odyssey 2018-20|Honda Sensing|openpilot|25 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|Passport 2019-23|All|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|Pilot 2016-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Honda|Ridgeline 2017-23|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|Odyssey 2018-20|Honda Sensing|openpilot|25 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|Passport 2019-23|All|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|Pilot 2016-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Honda|Ridgeline 2017-23|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
View- 1 Honda Nidec connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Elantra 2017-19|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Hyundai B connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Elantra GT 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
View- 1 Hyundai E connector
- 1 RJ45 cable (7 ft)
- 1 comma power v2
- 1 comma three
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 2c936cf3b6..11eff61b33 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -292,8 +292,8 @@ class CarInterface(CarInterfaceBase): # min speed to enable ACC. if car can do stop and go, then set enabling speed # to a negative value, so it won't matter. Otherwise, add 0.5 mph margin to not # conflict with PCM acc - stop_and_go = candidate in (HONDA_BOSCH | {CAR.CIVIC}) or ret.enableGasInterceptor - ret.minEnableSpeed = -1. if stop_and_go else 25.5 * CV.MPH_TO_MS + ret.autoResumeSng = candidate in (HONDA_BOSCH | {CAR.CIVIC}) or ret.enableGasInterceptor + ret.minEnableSpeed = -1. if ret.autoResumeSng else 25.5 * CV.MPH_TO_MS # TODO: start from empirically derived lateral slip stiffness for the civic and scale by # mass and CG position, so all cars will have approximately similar dyn behaviors From 181b44b28ea51429e270eb2c7a0cac20a871f214 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Fri, 9 Jun 2023 14:13:22 -0700 Subject: [PATCH 06/14] car docs: test print_docs_diff (#28459) * test print docs * delete * remove this * print --- selfdrive/car/tests/test_docs.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/selfdrive/car/tests/test_docs.py b/selfdrive/car/tests/test_docs.py index f42c094856..7ea9f6c9fe 100755 --- a/selfdrive/car/tests/test_docs.py +++ b/selfdrive/car/tests/test_docs.py @@ -1,12 +1,16 @@ #!/usr/bin/env python3 from collections import defaultdict +import os import re import unittest +from common.basedir import BASEDIR from selfdrive.car.car_helpers import interfaces, get_interface_attr from selfdrive.car.docs import CARS_MD_OUT, CARS_MD_TEMPLATE, generate_cars_md, get_all_car_info from selfdrive.car.docs_definitions import Cable, Column, PartType, Star from selfdrive.car.honda.values import CAR as HONDA +from selfdrive.debug.dump_car_info import dump_car_info +from selfdrive.debug.print_docs_diff import print_car_info_diff class TestCarDocs(unittest.TestCase): @@ -22,6 +26,12 @@ class TestCarDocs(unittest.TestCase): self.assertEqual(generated_cars_md, current_cars_md, "Run selfdrive/car/docs.py to update the compatibility documentation") + def test_docs_diff(self): + dump_path = os.path.join(BASEDIR, "selfdrive", "car", "tests", "cars_dump") + dump_car_info(dump_path) + print_car_info_diff(dump_path) + os.remove(dump_path) + def test_duplicate_years(self): make_model_years = defaultdict(list) for car in self.all_cars: From d1499fa5d8e28722dbaddae0c5941f9be12013bf Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 9 Jun 2023 14:44:57 -0700 Subject: [PATCH 07/14] bump cereal and panda --- cereal | 2 +- panda | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cereal b/cereal index c331e76b96..44c93ef17c 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit c331e76b966d324a4f8d56b48db44f59601423dc +Subproject commit 44c93ef17cd0973347935b93c67b65ddd5ace22c diff --git a/panda b/panda index 1a9a94c519..b563405904 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 1a9a94c519cb74e9e0f57bea4d316a54c27ea8aa +Subproject commit b56340590485bba2428538259e020f176127458c From a412cd07b105807a3fcd5fdc8b9caae0e227cf06 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 9 Jun 2023 15:36:15 -0700 Subject: [PATCH 08/14] cloudlog process not running (#28472) * cloudlog process not running * error --- selfdrive/controls/controlsd.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 3903340c8d..82c66a20f9 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -170,6 +170,7 @@ class Controls: self.events_prev = [] self.current_alert_types = [ET.PERMANENT] self.logged_comm_issue = None + self.not_running_prev = None self.last_actuators = car.CarControl.Actuators.new_message() self.steer_limited = False self.desired_curvature = 0.0 @@ -330,6 +331,9 @@ class Controls: not_running = {p.name for p in self.sm['managerState'].processes if not p.running and p.shouldBeRunning} if self.sm.rcv_frame['managerState'] and (not_running - IGNORE_PROCESSES): self.events.add(EventName.processNotRunning) + if not_running != self.not_running_prev: + cloudlog.event("process_not_running", not_running=not_running, error=True) + self.not_running_prev = not_running else: if not SIMULATION and not self.rk.lagging: if not self.sm.all_alive(self.camera_packets): From dec3c5a57d5893bd2f456fc88d3799300095a02e Mon Sep 17 00:00:00 2001 From: Comma Device Date: Fri, 9 Jun 2023 15:36:41 -0700 Subject: [PATCH 09/14] test_amp: wait for panda --- system/hardware/tici/tests/test_amplifier.py | 1 + 1 file changed, 1 insertion(+) diff --git a/system/hardware/tici/tests/test_amplifier.py b/system/hardware/tici/tests/test_amplifier.py index 5d5a86c512..4cacef4080 100755 --- a/system/hardware/tici/tests/test_amplifier.py +++ b/system/hardware/tici/tests/test_amplifier.py @@ -21,6 +21,7 @@ class TestAmplifier(unittest.TestCase): # clear dmesg subprocess.check_call("sudo dmesg -C", shell=True) + Panda.wait_for_panda(None, 30) self.panda = Panda() self.panda.reset() From f7f5537af74625e3a08352fef73eebffd4991a49 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Fri, 9 Jun 2023 17:08:57 -0700 Subject: [PATCH 10/14] MapPanel cleanup (#28474) --- selfdrive/ui/qt/maps/map_settings.cc | 78 +++++++++++++--------------- selfdrive/ui/qt/maps/map_settings.h | 9 +++- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/selfdrive/ui/qt/maps/map_settings.cc b/selfdrive/ui/qt/maps/map_settings.cc index 3205ca517d..f626925ad4 100644 --- a/selfdrive/ui/qt/maps/map_settings.cc +++ b/selfdrive/ui/qt/maps/map_settings.cc @@ -13,46 +13,46 @@ static QString shorten(const QString &str, int max_len) { } MapPanel::MapPanel(QWidget* parent) : QWidget(parent) { - stack = new QStackedWidget; + QStackedLayout *stack = new QStackedLayout(this); - QWidget * main_widget = new QWidget; + QWidget *main_widget = new QWidget; QVBoxLayout *main_layout = new QVBoxLayout(main_widget); - const int icon_size = 200; - - // Home - QHBoxLayout *home_layout = new QHBoxLayout; - home_button = new QPushButton; - home_button->setIconSize(QSize(icon_size, icon_size)); - home_layout->addWidget(home_button); - - home_address = new QLabel; - home_address->setWordWrap(true); - home_layout->addSpacing(30); - home_layout->addWidget(home_address); - home_layout->addStretch(); - - // Work - QHBoxLayout *work_layout = new QHBoxLayout; - work_button = new QPushButton; - work_button->setIconSize(QSize(icon_size, icon_size)); - work_layout->addWidget(work_button); - - work_address = new QLabel; - work_address->setWordWrap(true); - work_layout->addSpacing(30); - work_layout->addWidget(work_address); - work_layout->addStretch(); + main_layout->setSpacing(20); // Home & Work layout QHBoxLayout *home_work_layout = new QHBoxLayout; - home_work_layout->addLayout(home_layout, 1); - home_work_layout->addSpacing(50); - home_work_layout->addLayout(work_layout, 1); + { + // Home + home_button = new QPushButton; + home_button->setIconSize(QSize(MAP_PANEL_ICON_SIZE, MAP_PANEL_ICON_SIZE)); + home_address = new QLabel; + home_address->setWordWrap(true); + + QHBoxLayout *home_layout = new QHBoxLayout; + home_layout->addWidget(home_button); + home_layout->addSpacing(30); + home_layout->addWidget(home_address); + home_layout->addStretch(); + + // Work + work_button = new QPushButton; + work_button->setIconSize(QSize(MAP_PANEL_ICON_SIZE, MAP_PANEL_ICON_SIZE)); + work_address = new QLabel; + work_address->setWordWrap(true); + + QHBoxLayout *work_layout = new QHBoxLayout; + work_layout->addWidget(work_button); + work_layout->addSpacing(30); + work_layout->addWidget(work_address); + work_layout->addStretch(); + + home_work_layout->addLayout(home_layout, 1); + home_work_layout->addSpacing(50); + home_work_layout->addLayout(work_layout, 1); + } main_layout->addLayout(home_work_layout); - main_layout->addSpacing(20); main_layout->addWidget(horizontal_line()); - main_layout->addSpacing(20); // Current route { @@ -81,7 +81,6 @@ MapPanel::MapPanel(QWidget* parent) : QWidget(parent) { QLabel *recents_title = new QLabel(tr("Recent Destinations")); recents_title->setStyleSheet("font-size: 55px"); main_layout->addWidget(recents_title); - main_layout->addSpacing(20); recent_layout = new QVBoxLayout; QWidget *recent_widget = new LayoutWidget(recent_layout, this); @@ -119,9 +118,6 @@ MapPanel::MapPanel(QWidget* parent) : QWidget(parent) { stack->setCurrentIndex(prime_type ? 0 : 1); }); - QVBoxLayout *wrapper = new QVBoxLayout(this); - wrapper->addWidget(stack); - clear(); @@ -207,8 +203,9 @@ void MapPanel::refresh() { prev_destinations = cur_destinations; clear(); + // add favorites before recents bool has_recents = false; - for (auto &save_type: {"favorite", "recent"}) { + for (auto &save_type: {NAV_TYPE_FAVORITE, NAV_TYPE_RECENT}) { for (auto location : doc.array()) { auto obj = location.toObject(); @@ -219,7 +216,7 @@ void MapPanel::refresh() { if (type != save_type) continue; - if (type == "favorite" && label == "home") { + if (type == NAV_TYPE_FAVORITE && label == NAV_FAVORITE_LABEL_HOME) { home_address->setText(name); home_address->setStyleSheet(R"(font-size: 50px; color: white;)"); home_button->setIcon(QPixmap("../assets/navigation/home.png")); @@ -227,7 +224,7 @@ void MapPanel::refresh() { navigateTo(obj); emit closeSettings(); }); - } else if (type == "favorite" && label == "work") { + } else if (type == NAV_TYPE_FAVORITE && label == NAV_FAVORITE_LABEL_WORK) { work_address->setText(name); work_address->setStyleSheet(R"(font-size: 50px; color: white;)"); work_button->setIcon(QPixmap("../assets/navigation/work.png")); @@ -245,7 +242,7 @@ void MapPanel::refresh() { sp.setRetainSizeWhenHidden(true); star->setSizePolicy(sp); - star->setVisible(type == "favorite"); + star->setVisible(type == NAV_TYPE_FAVORITE); star->setStyleSheet(R"(font-size: 60px;)"); layout->addWidget(star); layout->addSpacing(10); @@ -284,7 +281,6 @@ void MapPanel::refresh() { has_recents = true; } } - } if (!has_recents) { diff --git a/selfdrive/ui/qt/maps/map_settings.h b/selfdrive/ui/qt/maps/map_settings.h index 165673b7c1..8dd044c374 100644 --- a/selfdrive/ui/qt/maps/map_settings.h +++ b/selfdrive/ui/qt/maps/map_settings.h @@ -11,6 +11,14 @@ #include "common/params.h" #include "selfdrive/ui/qt/widgets/controls.h" +const int MAP_PANEL_ICON_SIZE = 200; + +const QString NAV_TYPE_FAVORITE = "favorite"; +const QString NAV_TYPE_RECENT = "recent"; + +const QString NAV_FAVORITE_LABEL_HOME = "home"; +const QString NAV_FAVORITE_LABEL_WORK = "work"; + class MapPanel : public QWidget { Q_OBJECT public: @@ -27,7 +35,6 @@ private: Params params; QString prev_destinations, cur_destinations; - QStackedWidget *stack; QPushButton *home_button, *work_button; QLabel *home_address, *work_address; QVBoxLayout *recent_layout; From 838346d8a3a139a160e3cc602ba38d6f3b09a00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20R=C4=85czy?= Date: Sat, 10 Jun 2023 04:17:50 +0200 Subject: [PATCH 11/14] process_replay: deprecated message migration (#28456) * Move migration code to new file * Migrate messages in process replay. Remove old code * Fix old_logtime * Keep old logtimes on migrated messages * Update ref commit --- selfdrive/test/process_replay/migration.py | 65 +++++++++++++++++++ .../test/process_replay/process_replay.py | 3 +- selfdrive/test/process_replay/ref_commit | 2 +- selfdrive/test/process_replay/regen.py | 59 +---------------- 4 files changed, 70 insertions(+), 59 deletions(-) create mode 100644 selfdrive/test/process_replay/migration.py diff --git a/selfdrive/test/process_replay/migration.py b/selfdrive/test/process_replay/migration.py new file mode 100644 index 0000000000..31b3acde56 --- /dev/null +++ b/selfdrive/test/process_replay/migration.py @@ -0,0 +1,65 @@ +from cereal import messaging + + +def migrate_all(lr, old_logtime=False): + msgs = migrate_sensorEvents(lr, old_logtime) + msgs = migrate_carParams(msgs, old_logtime) + + return msgs + + +def migrate_carParams(lr, old_logtime=False): + all_msgs = [] + for msg in lr: + if msg.which() == 'carParams': + CP = messaging.new_message('carParams') + CP.carParams = msg.carParams.as_builder() + for car_fw in CP.carParams.carFw: + car_fw.brand = CP.carParams.carName + if old_logtime: + CP.logMonoTime = msg.logMonoTime + msg = CP.as_reader() + all_msgs.append(msg) + + return all_msgs + + +def migrate_sensorEvents(lr, old_logtime=False): + all_msgs = [] + for msg in lr: + if msg.which() != 'sensorEventsDEPRECATED': + all_msgs.append(msg) + continue + + # migrate to split sensor events + for evt in msg.sensorEventsDEPRECATED: + # build new message for each sensor type + sensor_service = '' + if evt.which() == 'acceleration': + sensor_service = 'accelerometer' + elif evt.which() == 'gyro' or evt.which() == 'gyroUncalibrated': + sensor_service = 'gyroscope' + elif evt.which() == 'light' or evt.which() == 'proximity': + sensor_service = 'lightSensor' + elif evt.which() == 'magnetic' or evt.which() == 'magneticUncalibrated': + sensor_service = 'magnetometer' + elif evt.which() == 'temperature': + sensor_service = 'temperatureSensor' + + m = messaging.new_message(sensor_service) + m.valid = True + if old_logtime: + m.logMonoTime = msg.logMonoTime + + m_dat = getattr(m, sensor_service) + m_dat.version = evt.version + m_dat.sensor = evt.sensor + m_dat.type = evt.type + m_dat.source = evt.source + if old_logtime: + m_dat.timestamp = evt.timestamp + setattr(m_dat, evt.which(), getattr(evt, evt.which())) + + all_msgs.append(m.as_reader()) + + return all_msgs diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 9261aee838..22d1516373 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -18,6 +18,7 @@ from panda.python import ALTERNATIVE_EXPERIENCE from selfdrive.car.car_helpers import get_car, interfaces from selfdrive.manager.process_config import managed_processes from selfdrive.test.process_replay.helpers import OpenpilotPrefix +from selfdrive.test.process_replay.migration import migrate_all # Numpy gives different results based on CPU features after version 19 NUMPY_TOLERANCE = 1e-7 @@ -342,7 +343,7 @@ def replay_process_with_name(name, lr, *args, **kwargs): def replay_process(cfg, lr, fingerprint=None, return_all_logs=False, disable_progress=False): - all_msgs = list(lr) + all_msgs = migrate_all(lr, old_logtime=True) process_logs = _replay_single_process(cfg, all_msgs, fingerprint, disable_progress) if return_all_logs: diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 2332054b69..f3a9408671 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -3e684aef4483b8d311d71bab3bb543d7bad26563 +67bcd498f0432252a3f11a9fd2b59b344ee214ba diff --git a/selfdrive/test/process_replay/regen.py b/selfdrive/test/process_replay/regen.py index cc697bb9bf..18c7e3a8dc 100755 --- a/selfdrive/test/process_replay/regen.py +++ b/selfdrive/test/process_replay/regen.py @@ -20,6 +20,7 @@ from selfdrive.car.toyota.values import EPS_SCALE from selfdrive.manager.process import ensure_running from selfdrive.manager.process_config import managed_processes from selfdrive.test.process_replay.process_replay import CONFIGS, FAKEDATA, setup_env, check_openpilot_enabled +from selfdrive.test.process_replay.migration import migrate_all from selfdrive.test.update_ci_routes import upload_route from tools.lib.route import Route from tools.lib.framereader import FrameReader @@ -179,67 +180,11 @@ def replay_cameras(lr, frs, disable_tqdm=False): return vs, p -def migrate_carparams(lr): - all_msgs = [] - for msg in lr: - if msg.which() == 'carParams': - CP = messaging.new_message('carParams') - CP.carParams = msg.carParams.as_builder() - for car_fw in CP.carParams.carFw: - car_fw.brand = CP.carParams.carName - msg = CP.as_reader() - all_msgs.append(msg) - - return all_msgs - - -def migrate_sensorEvents(lr, old_logtime=False): - all_msgs = [] - for msg in lr: - if msg.which() != 'sensorEventsDEPRECATED': - all_msgs.append(msg) - continue - - # migrate to split sensor events - for evt in msg.sensorEventsDEPRECATED: - # build new message for each sensor type - sensor_service = '' - if evt.which() == 'acceleration': - sensor_service = 'accelerometer' - elif evt.which() == 'gyro' or evt.which() == 'gyroUncalibrated': - sensor_service = 'gyroscope' - elif evt.which() == 'light' or evt.which() == 'proximity': - sensor_service = 'lightSensor' - elif evt.which() == 'magnetic' or evt.which() == 'magneticUncalibrated': - sensor_service = 'magnetometer' - elif evt.which() == 'temperature': - sensor_service = 'temperatureSensor' - - m = messaging.new_message(sensor_service) - m.valid = True - if old_logtime: - m.logMonoTime = msg.logMonoTime - - m_dat = getattr(m, sensor_service) - m_dat.version = evt.version - m_dat.sensor = evt.sensor - m_dat.type = evt.type - m_dat.source = evt.source - if old_logtime: - m_dat.timestamp = evt.timestamp - setattr(m_dat, evt.which(), getattr(evt, evt.which())) - - all_msgs.append(m.as_reader()) - - return all_msgs - - def regen_segment(lr, frs=None, daemons="all", outdir=FAKEDATA, disable_tqdm=False): if not isinstance(daemons, str) and not hasattr(daemons, "__iter__"): raise ValueError("whitelist_proc must be a string or iterable") - lr = migrate_carparams(list(lr)) - lr = migrate_sensorEvents(list(lr)) + lr = migrate_all(lr) if frs is None: frs = dict() From a77d226f33f618b965204c700fd0bfeb5f1547ab Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 9 Jun 2023 20:15:13 -0700 Subject: [PATCH 12/14] thermald: lower threshold to exit red band --- selfdrive/thermald/thermald.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index 57387e5186..aa78978619 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -41,7 +41,7 @@ HardwareState = namedtuple("HardwareState", ['network_type', 'network_info', 'ne THERMAL_BANDS = OrderedDict({ ThermalStatus.green: ThermalBand(None, 80.0), ThermalStatus.yellow: ThermalBand(75.0, 96.0), - ThermalStatus.red: ThermalBand(80.0, 107.), + ThermalStatus.red: ThermalBand(88.0, 107.), ThermalStatus.danger: ThermalBand(94.0, None), }) From fc9660c96206220e3b7f4656826fd2a88ea1ad4b Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 9 Jun 2023 22:04:56 -0700 Subject: [PATCH 13/14] env: add dateutil types (#28478) * add dateutil types * lock --- poetry.lock | 14 +++++++++++++- pyproject.toml | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index e2ef2fc29e..679d4b40a1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4565,6 +4565,14 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "types-python-dateutil" +version = "2.8.19.13" +description = "Typing stubs for python-dateutil" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "types-pyyaml" version = "6.0.12" @@ -4804,7 +4812,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "1.1" python-versions = "~3.8" -content-hash = "8c0419671beb3e8c8f0add750929f5be32be6fa3f077d44614cbd598b4cadc00" +content-hash = "2e03ebb1f6c441a0154531ee92f6f1f8c9e74544d4295d3753029bb8dcd457d1" [metadata.files] adal = [ @@ -8597,6 +8605,10 @@ types-pycurl = [ {file = "types-pycurl-7.45.1.tar.gz", hash = "sha256:82e00aa2981595bfa55e5a3bac42221eb3435b0026dffbe1177f6ac9f2d51200"}, {file = "types_pycurl-7.45.1-py3-none-any.whl", hash = "sha256:9eab3414da4a1b1e9a628bd288fc5172b8c182e1d9fb6d8d082441b0fd64baed"}, ] +types-python-dateutil = [ + {file = "types-python-dateutil-2.8.19.13.tar.gz", hash = "sha256:09a0275f95ee31ce68196710ed2c3d1b9dc42e0b61cc43acc369a42cb939134f"}, + {file = "types_python_dateutil-2.8.19.13-py3-none-any.whl", hash = "sha256:0b0e7c68e7043b0354b26a1e0225cb1baea7abb1b324d02b50e2d08f1221043f"}, +] types-pyyaml = [ {file = "types-PyYAML-6.0.12.tar.gz", hash = "sha256:f6f350418125872f3f0409d96a62a5a5ceb45231af5cc07ee0034ec48a3c82fa"}, {file = "types_PyYAML-6.0.12-py3-none-any.whl", hash = "sha256:29228db9f82df4f1b7febee06bbfb601677882e98a3da98132e31c6874163e15"}, diff --git a/pyproject.toml b/pyproject.toml index 52dd7f2a02..8877a262ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -106,6 +106,7 @@ tenacity = "^8.0.1" types-atomicwrites = "^1.4.5" types-certifi = "^2021.10.8" types-pycurl = "^7.45.1" +types-python-dateutil = "^2.8.19.13" types-PyYAML = "^6.0" types-requests = "^2.28.11" types-tabulate = "^0.8.10" From f5e032b67f6e37d2c12dcd90168a2b33b3b78831 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 9 Jun 2023 22:51:55 -0700 Subject: [PATCH 14/14] FwQueryConfig: add platform code support and tests (#28475) * add config options * you know what, platform codes don't need to be related to fuzzy fingerprinting at all * better comment? * add comment * add test from other PR * add platform code function to hyundai * comment and add eps! * clean up config test * fix test * add error message to test * until we have multiple ways a brand can set up fuzzy FP, let's leave func name fuzzy-specific * rename in comment too * hyundai tests * simpler test! * check all ecus with platform codes * add types-python-dateutil = "^2.8.19.13" * these aren't used any more * Update selfdrive/car/hyundai/tests/test_hyundai.py * not to imply this is active yet --- selfdrive/car/fw_query_definitions.py | 8 ++- selfdrive/car/hyundai/tests/test_hyundai.py | 62 ++++++++++++++++++++- selfdrive/car/hyundai/values.py | 43 +++++++++++++- selfdrive/car/tests/test_fw_fingerprint.py | 15 +++++ 4 files changed, 125 insertions(+), 3 deletions(-) diff --git a/selfdrive/car/fw_query_definitions.py b/selfdrive/car/fw_query_definitions.py index 7ae9bee404..b3fb8476e5 100755 --- a/selfdrive/car/fw_query_definitions.py +++ b/selfdrive/car/fw_query_definitions.py @@ -3,7 +3,7 @@ import capnp import copy from dataclasses import dataclass, field import struct -from typing import Dict, List, Optional, Tuple +from typing import Callable, Dict, List, Optional, Set, Tuple import panda.python.uds as uds @@ -75,6 +75,12 @@ class FwQueryConfig: # Ecus added for data collection, not to be fingerprinted on extra_ecus: List[Tuple[capnp.lib.capnp._EnumModule, int, Optional[int]]] = field(default_factory=list) + # Brand-specific fuzzy fingerprinting config options: + # A function to get unique, platform-specific identification codes for a set of versions + fuzzy_get_platform_codes: Optional[Callable[[List[bytes]], Set[bytes]]] = None + # List of ECUs expected to have platform codes + platform_code_ecus: List[capnp.lib.capnp._EnumModule] = field(default_factory=list) + def __post_init__(self): for i in range(len(self.requests)): if self.requests[i].auxiliary: diff --git a/selfdrive/car/hyundai/tests/test_hyundai.py b/selfdrive/car/hyundai/tests/test_hyundai.py index fba99ae74d..f2e27788a6 100755 --- a/selfdrive/car/hyundai/tests/test_hyundai.py +++ b/selfdrive/car/hyundai/tests/test_hyundai.py @@ -2,7 +2,8 @@ import unittest from cereal import car -from selfdrive.car.hyundai.values import CANFD_CAR, FW_QUERY_CONFIG, FW_VERSIONS, CAN_GEARS, LEGACY_SAFETY_MODE_CAR, CHECKSUM, CAMERA_SCC_CAR +from selfdrive.car.hyundai.values import CAMERA_SCC_CAR, CANFD_CAR, CAN_GEARS, CAR, CHECKSUM, FW_QUERY_CONFIG, \ + FW_VERSIONS, LEGACY_SAFETY_MODE_CAR Ecu = car.CarParams.Ecu ECU_NAME = {v: k for k, v in Ecu.schema.enumerants.items()} @@ -24,6 +25,65 @@ class TestHyundaiFingerprint(unittest.TestCase): ecu_strings = ", ".join([f'Ecu.{ECU_NAME[ecu]}' for ecu in ecus_not_in_whitelist]) self.assertEqual(len(ecus_not_in_whitelist), 0, f'{car_model}: Car model has ECUs not in auxiliary request whitelists: {ecu_strings}') + def test_platform_code_ecus_available(self): + no_eps_platforms = CANFD_CAR | {CAR.KIA_SORENTO, CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, + CAR.SONATA_LF, CAR.TUCSON, CAR.GENESIS_G90, CAR.GENESIS_G80} + + # Asserts ECU keys essential for fuzzy fingerprinting are available on all platforms + for car_model, ecus in FW_VERSIONS.items(): + with self.subTest(car_model=car_model): + for fuzzy_ecu in FW_QUERY_CONFIG.platform_code_ecus: + if fuzzy_ecu in (Ecu.fwdRadar, Ecu.eps) and car_model == CAR.HYUNDAI_GENESIS: + continue + if fuzzy_ecu == Ecu.eps and car_model in no_eps_platforms: + continue + self.assertIn(fuzzy_ecu, [e[0] for e in ecus]) + + def test_fuzzy_fw_dates(self): + # Some newer platforms have date codes in a different format we don't yet parse, + # for now assert date format is consistent for all FW across each platform + for car_model, ecus in FW_VERSIONS.items(): + with self.subTest(car_model=car_model): + for ecu, fws in ecus.items(): + if ecu[0] not in FW_QUERY_CONFIG.platform_code_ecus: + continue + + codes = set() + for fw in fws: + codes |= FW_QUERY_CONFIG.fuzzy_get_platform_codes([fw]) + + # Either no dates should be parsed or all dates should be parsed + self.assertEqual(len({b'-' in code for code in codes}), 1) + + def test_fuzzy_platform_codes(self): + # Asserts basic platform code parsing behavior + codes = FW_QUERY_CONFIG.fuzzy_get_platform_codes([b'\xf1\x00DH LKAS 1.1 -150210']) + self.assertEqual(codes, {b"DH-1502"}) + + # Some cameras and all radars do not have dates + codes = FW_QUERY_CONFIG.fuzzy_get_platform_codes([b'\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 ']) + self.assertEqual(codes, {b"AEhe"}) + + codes = FW_QUERY_CONFIG.fuzzy_get_platform_codes([b'\xf1\x00CV1_ RDR ----- 1.00 1.01 99110-CV000 ']) + self.assertEqual(codes, {b"CV1"}) + + codes = FW_QUERY_CONFIG.fuzzy_get_platform_codes([ + b'\xf1\x00DH LKAS 1.1 -150210', + b'\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 ', + b'\xf1\x00CV1_ RDR ----- 1.00 1.01 99110-CV000 ', + ]) + self.assertEqual(codes, {b"DH-1502", b"AEhe", b"CV1"}) + + # Returned platform codes must inclusively contain start/end dates + codes = FW_QUERY_CONFIG.fuzzy_get_platform_codes([ + b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.07 99211-S8100 220222', + b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.08 99211-S8100 211103', + b'\xf1\x00ON MFC AT USA LHD 1.00 1.01 99211-S9100 190405', + b'\xf1\x00ON MFC AT USA LHD 1.00 1.03 99211-S9100 190720', + ]) + self.assertEqual(codes, {b'LX2-2111', b'LX2-2112', b'LX2-2201', b'LX2-2202', + b'ON-1904', b'ON-1905', b'ON-1906', b'ON-1907'}) + if __name__ == "__main__": unittest.main() diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 86ebaabf04..7852f389f3 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -1,6 +1,10 @@ +import re +from datetime import datetime +from dateutil import rrule +from collections import defaultdict from dataclasses import dataclass from enum import Enum, IntFlag -from typing import Dict, List, Optional, Union +from typing import DefaultDict, Dict, List, Optional, Set, Union from cereal import car from panda.python import uds @@ -8,6 +12,7 @@ from common.conversions import Conversions as CV from selfdrive.car import dbc_dict from selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column from selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16 +from system.swaglog import cloudlog Ecu = car.CarParams.Ecu @@ -342,6 +347,36 @@ FINGERPRINTS = { }], } + +def get_platform_codes(fw_versions: List[bytes]) -> Set[bytes]: + codes: DefaultDict[bytes, Set[bytes]] = defaultdict(set) + for fw in fw_versions: + match = PLATFORM_CODE_PATTERN.search(fw) + if match is not None: + code, date = match.groups() + codes[code].add(date) + + # Create platform codes for all dates inclusive if ECU has FW dates + final_codes = set() + for code, dates in codes.items(): + # Radar and some cameras don't have FW dates + if None in dates: + final_codes.add(code) + continue + + try: + parsed = {datetime.strptime(date.decode()[:4], '%y%m') for date in dates} + except ValueError: + cloudlog.exception(f'Error parsing date in FW versions: {code!r}, {dates}') + final_codes.add(code) + continue + + for date in rrule.rrule(rrule.MONTHLY, dtstart=min(parsed), until=max(parsed)): + final_codes.add(code + b'-' + date.strftime('%y%m').encode()) + + return final_codes + + HYUNDAI_VERSION_REQUEST_LONG = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ p16(0xf100) # Long description @@ -355,6 +390,9 @@ HYUNDAI_VERSION_REQUEST_MULTI = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER] HYUNDAI_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) +PLATFORM_CODE_PATTERN = re.compile(b'((?<=' + HYUNDAI_VERSION_REQUEST_LONG[1:] + + b')[A-Z]{2}[A-Za-z0-9]{0,2})(?:.*([0-9]{6}))?') + FW_QUERY_CONFIG = FwQueryConfig( requests=[ # TODO: minimize shared whitelists for CAN and cornerRadar for CAN-FD @@ -411,6 +449,9 @@ FW_QUERY_CONFIG = FwQueryConfig( (Ecu.hvac, 0x7b3, None), # HVAC Control Assembly (Ecu.cornerRadar, 0x7b7, None), ], + fuzzy_get_platform_codes=get_platform_codes, + # Camera and radar should exist on all cars + platform_code_ecus=[Ecu.fwdRadar, Ecu.fwdCamera, Ecu.eps], ) FW_VERSIONS = { diff --git a/selfdrive/car/tests/test_fw_fingerprint.py b/selfdrive/car/tests/test_fw_fingerprint.py index b90120a1e2..97441f89af 100755 --- a/selfdrive/car/tests/test_fw_fingerprint.py +++ b/selfdrive/car/tests/test_fw_fingerprint.py @@ -123,6 +123,21 @@ class TestFwFingerprint(unittest.TestCase): with self.subTest(): self.fail(f"Brands do not implement FW_QUERY_CONFIG: {brand_versions - brand_configs}") + def test_fuzzy_fingerprint_config(self): + for brand, config in FW_QUERY_CONFIGS.items(): + with self.subTest(brand=brand): + if config.fuzzy_get_platform_codes is None: + self.assertEqual(len(config.platform_code_ecus), 0, "Cannot specify platform code ECUs without full config") + else: + self.assertGreater(len(config.platform_code_ecus), 0, "Need to specify platform code ECUs") + + # Assert every supported ECU FW version returns one platform code + for fw_by_addr in VERSIONS[brand].values(): + for addr, fws in fw_by_addr.items(): + if addr[0] in config.platform_code_ecus: + for f in fws: + self.assertEqual(1, len(config.fuzzy_get_platform_codes([f])), f"Unable to parse FW: {f}") + def test_fw_request_ecu_whitelist(self): for brand, config in FW_QUERY_CONFIGS.items(): with self.subTest(brand=brand):