From e23a25c3ae82e65b8adad47e799c588cc46bba0e Mon Sep 17 00:00:00 2001 From: Kurt Nistelberger Date: Fri, 4 Nov 2022 21:54:06 -0700 Subject: [PATCH 01/54] fix gps test runner --- tools/gpstest/run_unittest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpstest/run_unittest.sh b/tools/gpstest/run_unittest.sh index 9f93fdfc9a..e0ca017a6d 100755 --- a/tools/gpstest/run_unittest.sh +++ b/tools/gpstest/run_unittest.sh @@ -4,7 +4,7 @@ # run limeGPS with random static location timeout 300 ./simulate_gps_signal.py 32.7518 -117.1962 & -gps_PID=$(ps -aux | grep -m 1 "timeout 300" | cut -d ' ' -f 7) +gps_PID=$(ps -aux | grep -m 1 "timeout 300" | awk '{print $2}') echo "starting limeGPS..." sleep 10 From 50fddb52ba2e816123fa89a802a9e603e7407ada Mon Sep 17 00:00:00 2001 From: Lee Jong Mun <43285072+crwusiz@users.noreply.github.com> Date: Sat, 5 Nov 2022 17:44:18 +0900 Subject: [PATCH 02/54] Multilang: kor translation update (#26380) --- selfdrive/ui/translations/main_ko.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index 397b43f545..f58c4f34d5 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -240,11 +240,11 @@ Reset - + 리셋 Review - + 다시보기 @@ -475,11 +475,11 @@ location set ParamControl Ok - 확인 + 확인 Cancel - 취소 + 취소 @@ -864,7 +864,7 @@ location set Uninstall - + 삭제 @@ -1070,7 +1070,7 @@ location set Forget - + 저장안함 From 5768af09c06bc5e4774a30e1f94bba32d50721c4 Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Sat, 5 Nov 2022 13:24:38 -0700 Subject: [PATCH 03/54] DM: lower bound ee calib (#26370) keep in linear region --- selfdrive/monitoring/driver_monitor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/selfdrive/monitoring/driver_monitor.py b/selfdrive/monitoring/driver_monitor.py index 48163dcf2a..e3f6a5094d 100644 --- a/selfdrive/monitoring/driver_monitor.py +++ b/selfdrive/monitoring/driver_monitor.py @@ -34,6 +34,7 @@ class DRIVER_MONITOR_SETTINGS(): self._EE_THRESH11 = 0.275 self._EE_THRESH12 = 5.5 self._EE_MAX_OFFSET1 = 0.06 + self._EE_MIN_OFFSET1 = 0.025 self._EE_THRESH21 = 0.01 self._EE_THRESH22 = 0.35 @@ -206,7 +207,7 @@ class DriverStatus(): distracted_types.append(DistractedType.DISTRACTED_BLINK) if self.ee1_calibrated: - ee1_dist = self.eev1 > min(self.ee1_offseter.filtered_stat.M, self.settings._EE_MAX_OFFSET1) * self.settings._EE_THRESH12 + ee1_dist = self.eev1 > max(min(self.ee1_offseter.filtered_stat.M, self.settings._EE_MAX_OFFSET1), self.settings._EE_MIN_OFFSET1) * self.settings._EE_THRESH12 else: ee1_dist = self.eev1 > self.settings._EE_THRESH11 # if self.ee2_calibrated: From e079751f79c5256b1881cb34d1a92d08faa128d7 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Sat, 5 Nov 2022 15:05:30 -0700 Subject: [PATCH 04/54] ui: revert e2e path changes (#26382) * Revert "ui: fade to default path color when inactive (#26375)" This reverts commit 0b385a5650c4e0b06eb83e44bdba3fcff117beeb. * Revert "ui: minor e2e path tweaks (#26351)" This reverts commit d257e28479f49339e7f79491ff9d67e9ba034dfe. * stronger colors 45 --- selfdrive/ui/qt/onroad.cc | 17 +++++++++-------- selfdrive/ui/qt/onroad.h | 1 - selfdrive/ui/ui.cc | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index c4e4beb76a..bfd2f44561 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -170,7 +170,7 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) { } -AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* parent) : fps_filter(UI_FREQ, 3, 1. / UI_FREQ), accel_filter(UI_FREQ, .5, 1. / UI_FREQ), CameraWidget("camerad", type, true, parent) { +AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* parent) : fps_filter(UI_FREQ, 3, 1. / UI_FREQ), CameraWidget("camerad", type, true, parent) { pm = std::make_unique>({"uiDebug"}); engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size}); @@ -463,18 +463,19 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) { if (scene.end_to_end_long) { const auto &acceleration = (*s->sm)["modelV2"].getModelV2().getAcceleration(); float acceleration_future = 0; - if (acceleration.getZ().size() > 10 && (*s->sm)["carControl"].getCarControl().getLongActive()) { - acceleration_future = acceleration.getX()[10]; // 1.0 second + if (acceleration.getZ().size() > 16) { + acceleration_future = acceleration.getX()[16]; // 2.5 seconds } - // speed up: 148, slow down: 0 - start_hue = fmax(fmin(60 + accel_filter.update(acceleration_future) * 80, 148), 0); + start_hue = 60; + // speed up: 120, slow down: 0 + end_hue = fmax(fmin(start_hue + acceleration_future * 45, 148), 0); // FIXME: painter.drawPolygon can be slow if hue is not rounded - start_hue = int(start_hue * 100 + 0.5) / 100; + end_hue = int(end_hue * 100 + 0.5) / 100; bg.setColorAt(0.0, QColor::fromHslF(start_hue / 360., 0.97, 0.56, 0.4)); - bg.setColorAt(0.75, QColor::fromHslF(63 / 360., 1.0, 0.68, 0.35)); - bg.setColorAt(1.0, QColor::fromHslF(63 / 360., 1.0, 0.68, 0.0)); + bg.setColorAt(0.5, QColor::fromHslF(end_hue / 360., 1.0, 0.68, 0.35)); + bg.setColorAt(1.0, QColor::fromHslF(end_hue / 360., 1.0, 0.68, 0.0)); } else { const auto &orientation = (*s->sm)["modelV2"].getModelV2().getOrientation(); float orientation_future = 0; diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index 1f6a49bf8c..7edca6b3d5 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -87,7 +87,6 @@ protected: double prev_draw_t = 0; FirstOrderFilter fps_filter; - FirstOrderFilter accel_filter; }; // container for all onroad widgets diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 0198405769..945218ec11 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -214,7 +214,7 @@ void UIState::updateStatus() { UIState::UIState(QObject *parent) : QObject(parent) { sm = std::make_unique>({ - "modelV2", "carControl", "controlsState", "liveCalibration", "radarState", "deviceState", "roadCameraState", + "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "roadCameraState", "pandaStates", "carParams", "driverMonitoringState", "carState", "liveLocationKalman", "wideRoadCameraState", "managerState", "navInstruction", "navRoute", "gnssMeasurements", }); From ac76cc93256578f24db255cefd10c013dd906c28 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Sun, 6 Nov 2022 07:52:16 +0800 Subject: [PATCH 05/54] Cabana: cleanup code (#26369) * remove ChartView::enterEvent * cleanup ChartsWidget::removeAll * group graphics items * remove rubber->setPalette * helper function DBCManager::parseId * remove variable name from dbcManager * fix readme/Usage * use QSlider::setRange * cleanup include * use emplace_back * remove varialbe routeName from CanMessages * remove tmp variable * remove blank line * cleanup layout * clean settings layout * connect to streamStarted * cleanup signal/slot --- tools/cabana/README.md | 2 +- tools/cabana/canmessages.cc | 14 +++------- tools/cabana/canmessages.h | 5 ++-- tools/cabana/chartswidget.cc | 47 ++++++++-------------------------- tools/cabana/chartswidget.h | 3 +-- tools/cabana/dbcmanager.cc | 20 ++++++--------- tools/cabana/dbcmanager.h | 7 +++-- tools/cabana/detailwidget.cc | 8 ++---- tools/cabana/detailwidget.h | 3 --- tools/cabana/mainwin.cc | 3 +-- tools/cabana/messageswidget.cc | 2 +- tools/cabana/settings.cc | 7 ++--- tools/cabana/videowidget.cc | 13 +++++----- tools/cabana/videowidget.h | 1 - 14 files changed, 42 insertions(+), 93 deletions(-) diff --git a/tools/cabana/README.md b/tools/cabana/README.md index 99d0d4c9ce..dd131880a6 100644 --- a/tools/cabana/README.md +++ b/tools/cabana/README.md @@ -8,7 +8,7 @@ Cabana is a tool developed to view raw CAN data. One use for this is creating an ```bash $ ./cabana -h -Usage: ./_cabana [options] route +Usage: ./cabana [options] route Options: -h, --help Displays this help. diff --git a/tools/cabana/canmessages.cc b/tools/cabana/canmessages.cc index 3ffc29916f..f1f5c2cd23 100644 --- a/tools/cabana/canmessages.cc +++ b/tools/cabana/canmessages.cc @@ -1,6 +1,5 @@ #include "tools/cabana/canmessages.h" -#include #include #include "tools/cabana/dbcmanager.h" @@ -9,7 +8,6 @@ CANMessages *can = nullptr; CANMessages::CANMessages(QObject *parent) : QObject(parent) { can = this; - QObject::connect(this, &CANMessages::received, this, &CANMessages::process, Qt::QueuedConnection); QObject::connect(&settings, &Settings::changed, this, &CANMessages::settingChanged); } @@ -24,11 +22,11 @@ static bool event_filter(const Event *e, void *opaque) { } bool CANMessages::loadRoute(const QString &route, const QString &data_dir, bool use_qcam) { - routeName = route; replay = new Replay(route, {"can", "roadEncodeIdx", "carParams"}, {}, nullptr, use_qcam ? REPLAY_FLAG_QCAMERA : 0, data_dir, this); replay->setSegmentCacheLimit(settings.cached_segment_limit); replay->installEventFilter(event_filter, this); QObject::connect(replay, &Replay::segmentsMerged, this, &CANMessages::eventsMerged); + QObject::connect(replay, &Replay::streamStarted, this, &CANMessages::streamStarted); if (replay->load()) { replay->start(); return true; @@ -40,12 +38,9 @@ QList CANMessages::findSignalValues(const QString &id, const Signal *si auto evts = events(); if (!evts) return {}; - auto l = id.split(':'); - int bus = l[0].toInt(); - uint32_t address = l[1].toUInt(nullptr, 16); - QList ret; ret.reserve(max_count); + auto [bus, address] = DBCManager::parseId(id); for (auto &evt : *evts) { if (evt->which != cereal::Event::Which::CAN) continue; @@ -101,10 +96,9 @@ bool CANMessages::eventFilter(const Event *event) { data.bus_time = c.getBusTime(); data.dat.append((char *)c.getDat().begin(), c.getDat().size()); - auto &count = counters[id]; - data.count = ++count; + data.count = ++counters[id]; if (double delta = (current_sec - counters_begin_sec); delta > 0) { - data.freq = count / delta; + data.freq = data.count / delta; } (*new_msgs)[id] = data; } diff --git a/tools/cabana/canmessages.h b/tools/cabana/canmessages.h index 5fbccdbe12..14e2423d01 100644 --- a/tools/cabana/canmessages.h +++ b/tools/cabana/canmessages.h @@ -32,7 +32,7 @@ public: QList findSignalValues(const QString&id, const Signal* signal, double value, FindFlags flag, int max_count); bool eventFilter(const Event *event); - inline QString route() const { return routeName; } + inline QString route() const { return replay->route()->name(); } inline QString carFingerprint() const { return replay->carFingerprint().c_str(); } inline double totalSeconds() const { return replay->totalSeconds(); } inline double routeStartTime() const { return replay->routeStartTime() / (double)1e9; } @@ -47,6 +47,7 @@ public: inline const std::vector> getTimeline() { return replay->getTimeline(); } signals: + void streamStarted(); void eventsMerged(); void updated(); void received(QHash *); @@ -58,9 +59,7 @@ protected: void process(QHash *); void settingChanged(); - QString routeName; Replay *replay = nullptr; - std::mutex lock; std::atomic counters_begin_sec = 0; QHash counters; diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 7540abbcb2..6432cb7079 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -176,16 +176,8 @@ void ChartsWidget::removeChart(ChartWidget *chart) { } void ChartsWidget::removeAll(const Signal *sig) { - QMutableListIterator it(charts); - while (it.hasNext()) { - auto c = it.next(); - if (sig == nullptr || c->signal == sig) { - c->deleteLater(); - emit chartClosed(c->id, c->signal); - it.remove(); - } - } - updateTitleBar(); + for (auto c : charts.toVector()) + if (!sig || c->signal == sig) removeChart(c); } void ChartsWidget::signalUpdated(const Signal *sig) { @@ -267,26 +259,21 @@ ChartView::ChartView(const QString &id, const Signal *sig, QWidget *parent) chart->setMargins({0, 0, 0, 0}); chart->layout()->setContentsMargins(0, 0, 0, 0); + line_marker = new QGraphicsLineItem(chart); + line_marker->setZValue(chart->zValue() + 10); + track_line = new QGraphicsLineItem(chart); - track_line->setZValue(chart->zValue() + 10); track_line->setPen(QPen(Qt::darkGray, 1, Qt::DashLine)); track_ellipse = new QGraphicsEllipseItem(chart); - track_ellipse->setZValue(chart->zValue() + 10); track_ellipse->setBrush(Qt::darkGray); value_text = new QGraphicsTextItem(chart); - value_text->setZValue(chart->zValue() + 10); - line_marker = new QGraphicsLineItem(chart); - line_marker->setZValue(chart->zValue() + 10); + item_group = scene()->createItemGroup({track_line, track_ellipse, value_text}); + item_group->setZValue(chart->zValue() + 10); setChart(chart); setRenderHint(QPainter::Antialiasing); setRubberBand(QChartView::HorizontalRubberBand); - if (auto rubber = findChild()) { - QPalette pal; - pal.setBrush(QPalette::Base, QColor(0, 0, 0, 80)); - rubber->setPalette(pal); - } QTimer *timer = new QTimer(this); timer->setInterval(100); @@ -335,12 +322,9 @@ void ChartView::updateSeries(const std::pair range) { auto events = can->events(); if (!events) return; - auto l = id.split(':'); - int bus = l[0].toInt(); - uint32_t address = l[1].toUInt(nullptr, 16); - vals.clear(); vals.reserve((range.second - range.first) * 1000); // [n]seconds * 1000hz + auto [bus, address] = DBCManager::parseId(id); double route_start_time = can->routeStartTime(); Event begin_event(cereal::Event::Which::INIT_DATA, (route_start_time + range.first) * 1e9); auto begin = std::lower_bound(events->begin(), events->end(), &begin_event, Event::lessThan()); @@ -380,17 +364,8 @@ void ChartView::updateAxisY() { } } -void ChartView::enterEvent(QEvent *event) { - track_line->setVisible(true); - value_text->setVisible(true); - track_ellipse->setVisible(true); - QChartView::enterEvent(event); -} - void ChartView::leaveEvent(QEvent *event) { - track_line->setVisible(false); - value_text->setVisible(false); - track_ellipse->setVisible(false); + item_group->setVisible(false); QChartView::leaveEvent(event); } @@ -442,9 +417,7 @@ void ChartView::mouseMoveEvent(QMouseEvent *ev) { } value_text->setPos(text_x, pos.y() - 10); } - track_line->setVisible(value != vals.end()); - value_text->setVisible(value != vals.end()); - track_ellipse->setVisible(value != vals.end()); + item_group->setVisible(value != vals.end()); } else { setViewportUpdateMode(QGraphicsView::FullViewportUpdate); } diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index ff56008e7d..70e0774c3e 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "tools/cabana/canmessages.h" @@ -33,11 +32,11 @@ signals: private: void mouseReleaseEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *ev) override; - void enterEvent(QEvent *event) override; void leaveEvent(QEvent *event) override; void adjustChartMargins(); void updateAxisY(); + QGraphicsItemGroup *item_group; QGraphicsLineItem *track_line; QGraphicsEllipseItem *track_ellipse; QGraphicsTextItem *value_text; diff --git a/tools/cabana/dbcmanager.cc b/tools/cabana/dbcmanager.cc index 0ab67dd305..3ddcf41788 100644 --- a/tools/cabana/dbcmanager.cc +++ b/tools/cabana/dbcmanager.cc @@ -9,8 +9,7 @@ DBCManager::DBCManager(QObject *parent) : QObject(parent) {} DBCManager::~DBCManager() {} void DBCManager::open(const QString &dbc_file_name) { - dbc_name = dbc_file_name; - dbc = const_cast(dbc_lookup(dbc_name.toStdString())); + dbc = const_cast(dbc_lookup(dbc_file_name.toStdString())); msg_map.clear(); for (auto &msg : dbc->msgs) { msg_map[msg.address] = &msg; @@ -19,7 +18,6 @@ void DBCManager::open(const QString &dbc_file_name) { } void DBCManager::open(const QString &name, const QString &content) { - this->dbc_name = name; std::istringstream stream(content.toStdString()); dbc = const_cast(dbc_parse_from_stream(name.toStdString(), stream)); msg_map.clear(); @@ -51,22 +49,19 @@ QString DBCManager::generateDBC() { } void DBCManager::updateMsg(const QString &id, const QString &name, uint32_t size) { - auto m = const_cast(msg(id)); - if (m) { + if (auto m = const_cast(msg(id))) { m->name = name.toStdString(); m->size = size; } else { - uint32_t address = addressFromId(id); - dbc->msgs.push_back({.address = address, .name = name.toStdString(), .size = size}); - msg_map[address] = &dbc->msgs.back(); + m = &dbc->msgs.emplace_back(Msg{.address = parseId(id).second, .name = name.toStdString(), .size = size}); + msg_map[m->address] = m; } emit msgUpdated(id); } void DBCManager::addSignal(const QString &id, const Signal &sig) { if (Msg *m = const_cast(msg(id))) { - m->sigs.push_back(sig); - emit signalAdded(&m->sigs.back()); + emit signalAdded(&m->sigs.emplace_back(sig)); } } @@ -90,8 +85,9 @@ void DBCManager::removeSignal(const QString &id, const QString &sig_name) { } } -uint32_t DBCManager::addressFromId(const QString &id) { - return id.mid(id.indexOf(':') + 1).toUInt(nullptr, 16); +std::pair DBCManager::parseId(const QString &id) { + const auto list = id.split(':'); + return {list[0].toInt(), list[1].toUInt(nullptr, 16)}; } DBCManager *dbc() { diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index 913445d44e..d8a8da9b7a 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -18,13 +18,13 @@ public: void updateSignal(const QString &id, const QString &sig_name, const Signal &sig); void removeSignal(const QString &id, const QString &sig_name); - static uint32_t addressFromId(const QString &id); + static std::pair parseId(const QString &id); inline static std::vector allDBCNames() { return get_dbc_names(); } - inline QString name() const { return dbc_name; } + inline QString name() const { return dbc ? dbc->name.c_str() : ""; } void updateMsg(const QString &id, const QString &name, uint32_t size); inline const DBC *getDBC() const { return dbc; } - inline const Msg *msg(const QString &id) const { return msg(addressFromId(id)); } + inline const Msg *msg(const QString &id) const { return msg(parseId(id).second); } inline const Msg *msg(uint32_t address) const { auto it = msg_map.find(address); return it != msg_map.end() ? it->second : nullptr; @@ -38,7 +38,6 @@ signals: void DBCFileChanged(); private: - QString dbc_name; DBC *dbc = nullptr; std::unordered_map msg_map; }; diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index f3e3438229..db731333d3 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -277,9 +277,7 @@ void DetailWidget::removeSignal(const Signal *sig) { EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Edit message")); - QVBoxLayout *main_layout = new QVBoxLayout(this); - - QFormLayout *form_layout = new QFormLayout(); + QFormLayout *form_layout = new QFormLayout(this); form_layout->addRow("ID", new QLabel(msg_id)); name_edit = new QLineEdit(title, this); @@ -291,10 +289,8 @@ EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title size_spin->setValue(size); form_layout->addRow(tr("Size"), size_spin); - main_layout->addLayout(form_layout); - auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - main_layout->addWidget(buttonBox); + form_layout->addRow(buttonBox); setFixedWidth(parent->width() * 0.9); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index ce3468e472..ac32d5952e 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -26,9 +26,6 @@ public: void setMessage(const QString &message_id); void dbcMsgChanged(int show_form_idx = -1); -signals: - void binaryViewMoved(bool in); - private: void updateChartState(const QString &id, const Signal *sig, bool opened); void showTabBarContextMenu(const QPoint &pt); diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index c2baca4d22..be643c58d9 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -81,11 +81,10 @@ MainWindow::MainWindow() : QWidget() { QObject::connect(this, &MainWindow::showMessage, status_bar, &QStatusBar::showMessage); QObject::connect(this, &MainWindow::updateProgressBar, this, &MainWindow::updateDownloadProgress); QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, detail_widget, &DetailWidget::setMessage); - QObject::connect(detail_widget, &DetailWidget::binaryViewMoved, [this](bool in) { splitter->setSizes({in ? 100 : 0, 500}); }); QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts); QObject::connect(charts_widget, &ChartsWidget::rangeChanged, video_widget, &VideoWidget::rangeChanged); QObject::connect(settings_btn, &QPushButton::clicked, this, &MainWindow::setOption); - QObject::connect(can, &CANMessages::eventsMerged, [=]() { fingerprint_label->setText(can->carFingerprint() ); }); + QObject::connect(can, &CANMessages::streamStarted, [=]() { fingerprint_label->setText(can->carFingerprint() ); }); main_win = this; qInstallMessageHandler(qLogMessageHandler); diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index e80a66bce9..3639789239 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -67,7 +67,7 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { // signals/slots QObject::connect(filter, &QLineEdit::textChanged, model, &MessageListModel::setFilterString); - QObject::connect(can, &CANMessages::eventsMerged, this, &MessagesWidget::loadDBCFromFingerprint); + QObject::connect(can, &CANMessages::streamStarted, this, &MessagesWidget::loadDBCFromFingerprint); QObject::connect(can, &CANMessages::updated, [this]() { model->updateState(); }); QObject::connect(dbc_combo, SIGNAL(activated(const QString &)), SLOT(loadDBCFromName(const QString &))); QObject::connect(load_from_paste, &QPushButton::clicked, this, &MessagesWidget::loadDBCFromPaste); diff --git a/tools/cabana/settings.cc b/tools/cabana/settings.cc index bba59c0d74..b173b41df3 100644 --- a/tools/cabana/settings.cc +++ b/tools/cabana/settings.cc @@ -36,8 +36,7 @@ void Settings::load() { SettingsDlg::SettingsDlg(QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Settings")); - QVBoxLayout *main_layout = new QVBoxLayout(this); - QFormLayout *form_layout = new QFormLayout(); + QFormLayout *form_layout = new QFormLayout(this); fps = new QSpinBox(this); fps->setRange(10, 100); @@ -74,10 +73,8 @@ SettingsDlg::SettingsDlg(QWidget *parent) : QDialog(parent) { chart_theme->setCurrentIndex(settings.chart_theme == 1 ? 1 : 0); form_layout->addRow(tr("Chart theme"), chart_theme); - main_layout->addLayout(form_layout); - auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - main_layout->addWidget(buttonBox); + form_layout->addRow(buttonBox); setFixedWidth(360); connect(buttonBox, &QDialogButtonBox::accepted, this, &SettingsDlg::save); diff --git a/tools/cabana/videowidget.cc b/tools/cabana/videowidget.cc index 9a28f71bb9..d5e640b5f7 100644 --- a/tools/cabana/videowidget.cc +++ b/tools/cabana/videowidget.cc @@ -28,11 +28,9 @@ VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent) { slider = new Slider(this); slider->setSingleStep(0); - slider->setMinimum(0); - slider->setMaximum(can->totalSeconds() * 1000); slider_layout->addWidget(slider); - end_time_label = new QLabel(formatTime(can->totalSeconds())); + end_time_label = new QLabel(this); slider_layout->addWidget(end_time_label); main_layout->addLayout(slider_layout); @@ -61,6 +59,10 @@ VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent) { QObject::connect(slider, &QSlider::valueChanged, [=](int value) { time_label->setText(formatTime(value / 1000)); }); QObject::connect(cam_widget, &CameraWidget::clicked, [this]() { pause(!can->isPaused()); }); QObject::connect(play_btn, &QPushButton::clicked, [=]() { pause(!can->isPaused()); }); + QObject::connect(can, &CANMessages::streamStarted, [this]() { + end_time_label->setText(formatTime(can->totalSeconds())); + slider->setRange(0, can->totalSeconds() * 1000); + }); } void VideoWidget::pause(bool pause) { @@ -74,8 +76,7 @@ void VideoWidget::rangeChanged(double min, double max, bool is_zoomed) { max = can->totalSeconds(); } end_time_label->setText(formatTime(max)); - slider->setMinimum(min * 1000); - slider->setMaximum(max * 1000); + slider->setRange(min * 1000, max * 1000); } void VideoWidget::updateState() { @@ -91,7 +92,7 @@ Slider::Slider(QWidget *parent) : QSlider(Qt::Horizontal, parent) { timeline = can->getTimeline(); update(); }); - timer->start(); + QObject::connect(can, SIGNAL(streamStarted()), timer, SLOT(start())); } void Slider::sliderChange(QAbstractSlider::SliderChange change) { diff --git a/tools/cabana/videowidget.h b/tools/cabana/videowidget.h index 51dae4c76f..16f60b0b03 100644 --- a/tools/cabana/videowidget.h +++ b/tools/cabana/videowidget.h @@ -3,7 +3,6 @@ #include #include #include -#include #include "selfdrive/ui/qt/widgets/cameraview.h" #include "tools/cabana/canmessages.h" From ea5587d1d14e01b7a2aeae34f8abc73886699519 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 7 Nov 2022 03:03:57 +0800 Subject: [PATCH 06/54] Cabana: fix wrong hardcoded column index (#26392) fix wrong column count --- tools/cabana/messageswidget.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index 3639789239..9444ea9c48 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -224,7 +224,7 @@ void MessageListModel::updateState(bool sort) { changePersistentIndex(idx, index(std::distance(msgs.begin(), it), idx.column())); } } - emit dataChanged(index(0, 0), index(msgs.size() - 1, 3), {Qt::DisplayRole}); + emit dataChanged(index(0, 0), index(msgs.size() - 1, columnCount() - 1), {Qt::DisplayRole}); } } From 529504e201a4130bad7ff9ab712e01c1341ac349 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 7 Nov 2022 03:05:14 +0800 Subject: [PATCH 07/54] Cabana: move dbc related code from MessagesWidget to MainWin (#26387) * move dbc related code to mainwin * trigger ci --- tools/cabana/mainwin.cc | 138 ++++++++++++++++++++++++++++++++- tools/cabana/mainwin.h | 31 ++++++++ tools/cabana/messageswidget.cc | 133 +------------------------------ tools/cabana/messageswidget.h | 31 -------- 4 files changed, 167 insertions(+), 166 deletions(-) diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index be643c58d9..d3d7ff4156 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -1,7 +1,13 @@ #include "tools/cabana/mainwin.h" #include +#include +#include +#include +#include +#include #include +#include #include #include @@ -23,8 +29,38 @@ MainWindow::MainWindow() : QWidget() { splitter = new QSplitter(Qt::Horizontal, this); splitter->setHandleWidth(11); + + // DBC file selector + QWidget *messages_container = new QWidget(this); + QVBoxLayout *messages_layout = new QVBoxLayout(messages_container); + messages_layout->setContentsMargins(0, 0, 0, 0); + QHBoxLayout *dbc_file_layout = new QHBoxLayout(); + dbc_combo = new QComboBox(this); + auto dbc_names = dbc()->allDBCNames(); + for (const auto &name : dbc_names) { + dbc_combo->addItem(QString::fromStdString(name)); + } + dbc_combo->model()->sort(0); + dbc_combo->setEditable(true); + dbc_combo->setCurrentText(QString()); + dbc_combo->setInsertPolicy(QComboBox::NoInsert); + dbc_combo->completer()->setCompletionMode(QCompleter::PopupCompletion); + QFont font; + font.setBold(true); + dbc_combo->lineEdit()->setFont(font); + dbc_file_layout->addWidget(dbc_combo); + + QPushButton *load_from_paste = new QPushButton(tr("Load from paste"), this); + dbc_file_layout->addWidget(load_from_paste); + + dbc_file_layout->addStretch(); + QPushButton *save_btn = new QPushButton(tr("Save DBC"), this); + dbc_file_layout->addWidget(save_btn); + messages_layout->addLayout(dbc_file_layout); + messages_widget = new MessagesWidget(this); - splitter->addWidget(messages_widget); + messages_layout->addWidget(messages_widget); + splitter->addWidget(messages_container); charts_widget = new ChartsWidget(this); detail_widget = new DetailWidget(charts_widget, this); @@ -78,16 +114,55 @@ MainWindow::MainWindow() : QWidget() { emit updateProgressBar(cur, total, success); }); + main_win = this; + qInstallMessageHandler(qLogMessageHandler); + QFile json_file("./car_fingerprint_to_dbc.json"); + if (json_file.open(QIODevice::ReadOnly)) { + fingerprint_to_dbc = QJsonDocument::fromJson(json_file.readAll()); + } + + QObject::connect(dbc_combo, SIGNAL(activated(const QString &)), SLOT(loadDBCFromName(const QString &))); + QObject::connect(load_from_paste, &QPushButton::clicked, this, &MainWindow::loadDBCFromPaste); + QObject::connect(save_btn, &QPushButton::clicked, this, &MainWindow::saveDBC); QObject::connect(this, &MainWindow::showMessage, status_bar, &QStatusBar::showMessage); QObject::connect(this, &MainWindow::updateProgressBar, this, &MainWindow::updateDownloadProgress); QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, detail_widget, &DetailWidget::setMessage); QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts); QObject::connect(charts_widget, &ChartsWidget::rangeChanged, video_widget, &VideoWidget::rangeChanged); QObject::connect(settings_btn, &QPushButton::clicked, this, &MainWindow::setOption); + QObject::connect(can, &CANMessages::streamStarted, this, &MainWindow::loadDBCFromFingerprint); QObject::connect(can, &CANMessages::streamStarted, [=]() { fingerprint_label->setText(can->carFingerprint() ); }); +} - main_win = this; - qInstallMessageHandler(qLogMessageHandler); +void MainWindow::loadDBCFromName(const QString &name) { + if (name != dbc()->name()) { + dbc()->open(name); + dbc_combo->setCurrentText(name); + } +} + +void MainWindow::loadDBCFromPaste() { + LoadDBCDialog dlg(this); + if (dlg.exec()) { + dbc()->open("from paste", dlg.dbc_edit->toPlainText()); + dbc_combo->setCurrentText("loaded from paste"); + } +} + +void MainWindow::loadDBCFromFingerprint() { + auto fingerprint = can->carFingerprint(); + if (!fingerprint.isEmpty() && dbc()->name().isEmpty()) { + auto dbc_name = fingerprint_to_dbc[fingerprint]; + if (dbc_name != QJsonValue::Undefined) { + loadDBCFromName(dbc_name.toString()); + } + } +} + +void MainWindow::saveDBC() { + SaveDBCDialog dlg(this); + dlg.dbc_edit->setText(dbc()->generateDBC()); + dlg.exec(); } void MainWindow::updateDownloadProgress(uint64_t cur, uint64_t total, bool success) { @@ -127,3 +202,60 @@ void MainWindow::setOption() { SettingsDlg dlg(this); dlg.exec(); } + +// LoadDBCDialog + +LoadDBCDialog::LoadDBCDialog(QWidget *parent) : QDialog(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + dbc_edit = new QTextEdit(this); + dbc_edit->setAcceptRichText(false); + dbc_edit->setPlaceholderText(tr("paste DBC file here")); + main_layout->addWidget(dbc_edit); + auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + main_layout->addWidget(buttonBox); + + setMinimumSize({640, 480}); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); +} + +// SaveDBCDialog + +SaveDBCDialog::SaveDBCDialog(QWidget *parent) : QDialog(parent) { + setWindowTitle(tr("Save DBC")); + QVBoxLayout *main_layout = new QVBoxLayout(this); + dbc_edit = new QTextEdit(this); + dbc_edit->setAcceptRichText(false); + main_layout->addWidget(dbc_edit); + + QPushButton *copy_to_clipboard = new QPushButton(tr("Copy To Clipboard"), this); + QPushButton *save_as = new QPushButton(tr("Save As"), this); + + QHBoxLayout *btn_layout = new QHBoxLayout(); + btn_layout->addStretch(); + btn_layout->addWidget(copy_to_clipboard); + btn_layout->addWidget(save_as); + main_layout->addLayout(btn_layout); + setMinimumSize({640, 480}); + + QObject::connect(copy_to_clipboard, &QPushButton::clicked, this, &SaveDBCDialog::copytoClipboard); + QObject::connect(save_as, &QPushButton::clicked, this, &SaveDBCDialog::saveAs); +} + +void SaveDBCDialog::copytoClipboard() { + dbc_edit->selectAll(); + dbc_edit->copy(); + QDialog::accept(); +} + +void SaveDBCDialog::saveAs() { + QString file_name = QFileDialog::getSaveFileName(this, tr("Save File"), + QDir::homePath() + "/untitled.dbc", tr("DBC (*.dbc)")); + if (!file_name.isEmpty()) { + QFile file(file_name); + if (file.open(QIODevice::WriteOnly)) { + file.write(dbc_edit->toPlainText().toUtf8()); + } + QDialog::accept(); + } +} diff --git a/tools/cabana/mainwin.h b/tools/cabana/mainwin.h index b77744ba9c..f6853a5ea3 100644 --- a/tools/cabana/mainwin.h +++ b/tools/cabana/mainwin.h @@ -1,8 +1,12 @@ #pragma once +#include +#include +#include #include #include #include +#include #include "tools/cabana/chartswidget.h" #include "tools/cabana/detailwidget.h" @@ -17,6 +21,12 @@ public: void dockCharts(bool dock); void showStatusMessage(const QString &msg, int timeout = 0) { status_bar->showMessage(msg, timeout); } +public slots: + void loadDBCFromName(const QString &name); + void loadDBCFromFingerprint(); + void loadDBCFromPaste(); + void saveDBC(); + signals: void showMessage(const QString &msg, int timeout); void updateProgressBar(uint64_t cur, uint64_t total, bool success); @@ -35,4 +45,25 @@ protected: QVBoxLayout *r_layout; QProgressBar *progress_bar; QStatusBar *status_bar; + QJsonDocument fingerprint_to_dbc; + QComboBox *dbc_combo; +}; + + +class LoadDBCDialog : public QDialog { + Q_OBJECT + +public: + LoadDBCDialog(QWidget *parent); + QTextEdit *dbc_edit; +}; + +class SaveDBCDialog : public QDialog { + Q_OBJECT + +public: + SaveDBCDialog(QWidget *parent); + void copytoClipboard(); + void saveAs(); + QTextEdit *dbc_edit; }; diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index 9444ea9c48..b2e8e50b55 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -1,15 +1,8 @@ #include "tools/cabana/messageswidget.h" -#include -#include -#include -#include -#include #include #include #include -#include -#include #include #include "tools/cabana/dbcmanager.h" @@ -18,31 +11,6 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); main_layout->setContentsMargins(0, 0, 0, 0); - // DBC file selector - QHBoxLayout *dbc_file_layout = new QHBoxLayout(); - dbc_combo = new QComboBox(this); - auto dbc_names = dbc()->allDBCNames(); - for (const auto &name : dbc_names) { - dbc_combo->addItem(QString::fromStdString(name)); - } - dbc_combo->model()->sort(0); - dbc_combo->setEditable(true); - dbc_combo->setCurrentText(QString()); - dbc_combo->setInsertPolicy(QComboBox::NoInsert); - dbc_combo->completer()->setCompletionMode(QCompleter::PopupCompletion); - QFont font; - font.setBold(true); - dbc_combo->lineEdit()->setFont(font); - dbc_file_layout->addWidget(dbc_combo); - - QPushButton *load_from_paste = new QPushButton(tr("Load from paste"), this); - dbc_file_layout->addWidget(load_from_paste); - - dbc_file_layout->addStretch(); - QPushButton *save_btn = new QPushButton(tr("Save DBC"), this); - dbc_file_layout->addWidget(save_btn); - main_layout->addLayout(dbc_file_layout); - // message filter QLineEdit *filter = new QLineEdit(this); filter->setClearButtonEnabled(true); @@ -67,55 +35,13 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { // signals/slots QObject::connect(filter, &QLineEdit::textChanged, model, &MessageListModel::setFilterString); - QObject::connect(can, &CANMessages::streamStarted, this, &MessagesWidget::loadDBCFromFingerprint); QObject::connect(can, &CANMessages::updated, [this]() { model->updateState(); }); - QObject::connect(dbc_combo, SIGNAL(activated(const QString &)), SLOT(loadDBCFromName(const QString &))); - QObject::connect(load_from_paste, &QPushButton::clicked, this, &MessagesWidget::loadDBCFromPaste); - QObject::connect(save_btn, &QPushButton::clicked, this, &MessagesWidget::saveDBC); + QObject::connect(dbc(), &DBCManager::DBCFileChanged, [this]() { model->updateState(true); }); QObject::connect(table_widget->selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex ¤t, const QModelIndex &previous) { if (current.isValid()) { emit msgSelectionChanged(current.data(Qt::UserRole).toString()); } }); - - QFile json_file("./car_fingerprint_to_dbc.json"); - if (json_file.open(QIODevice::ReadOnly)) { - fingerprint_to_dbc = QJsonDocument::fromJson(json_file.readAll()); - } -} - -void MessagesWidget::loadDBCFromName(const QString &name) { - if (name != dbc()->name()) { - dbc()->open(name); - dbc_combo->setCurrentText(name); - // re-sort model to refresh column 'Name' - model->updateState(true); - } -} - -void MessagesWidget::loadDBCFromPaste() { - LoadDBCDialog dlg(this); - if (dlg.exec()) { - dbc()->open("from paste", dlg.dbc_edit->toPlainText()); - dbc_combo->setCurrentText("loaded from paste"); - model->updateState(true); - } -} - -void MessagesWidget::loadDBCFromFingerprint() { - auto fingerprint = can->carFingerprint(); - if (!fingerprint.isEmpty() && dbc()->name().isEmpty()) { - auto dbc_name = fingerprint_to_dbc[fingerprint]; - if (dbc_name != QJsonValue::Undefined) { - loadDBCFromName(dbc_name.toString()); - } - } -} - -void MessagesWidget::saveDBC() { - SaveDBCDialog dlg(this); - dlg.dbc_edit->setText(dbc()->generateDBC()); - dlg.exec(); } // MessageListModel @@ -235,60 +161,3 @@ void MessageListModel::sort(int column, Qt::SortOrder order) { updateState(true); } } - -// LoadDBCDialog - -LoadDBCDialog::LoadDBCDialog(QWidget *parent) : QDialog(parent) { - QVBoxLayout *main_layout = new QVBoxLayout(this); - dbc_edit = new QTextEdit(this); - dbc_edit->setAcceptRichText(false); - dbc_edit->setPlaceholderText(tr("paste DBC file here")); - main_layout->addWidget(dbc_edit); - auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - main_layout->addWidget(buttonBox); - - setMinimumSize({640, 480}); - QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); - QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); -} - -// SaveDBCDialog - -SaveDBCDialog::SaveDBCDialog(QWidget *parent) : QDialog(parent) { - setWindowTitle(tr("Save DBC")); - QVBoxLayout *main_layout = new QVBoxLayout(this); - dbc_edit = new QTextEdit(this); - dbc_edit->setAcceptRichText(false); - main_layout->addWidget(dbc_edit); - - QPushButton *copy_to_clipboard = new QPushButton(tr("Copy To Clipboard"), this); - QPushButton *save_as = new QPushButton(tr("Save As"), this); - - QHBoxLayout *btn_layout = new QHBoxLayout(); - btn_layout->addStretch(); - btn_layout->addWidget(copy_to_clipboard); - btn_layout->addWidget(save_as); - main_layout->addLayout(btn_layout); - setMinimumSize({640, 480}); - - QObject::connect(copy_to_clipboard, &QPushButton::clicked, this, &SaveDBCDialog::copytoClipboard); - QObject::connect(save_as, &QPushButton::clicked, this, &SaveDBCDialog::saveAs); -} - -void SaveDBCDialog::copytoClipboard() { - dbc_edit->selectAll(); - dbc_edit->copy(); - QDialog::accept(); -} - -void SaveDBCDialog::saveAs() { - QString file_name = QFileDialog::getSaveFileName(this, tr("Save File"), - QDir::homePath() + "/untitled.dbc", tr("DBC (*.dbc)")); - if (!file_name.isEmpty()) { - QFile file(file_name); - if (file.open(QIODevice::WriteOnly)) { - file.write(dbc_edit->toPlainText().toUtf8()); - } - QDialog::accept(); - } -} diff --git a/tools/cabana/messageswidget.h b/tools/cabana/messageswidget.h index 255dce7dc8..450c7003b7 100644 --- a/tools/cabana/messageswidget.h +++ b/tools/cabana/messageswidget.h @@ -1,32 +1,9 @@ #pragma once #include -#include -#include -#include #include -#include #include "tools/cabana/canmessages.h" - -class LoadDBCDialog : public QDialog { - Q_OBJECT - -public: - LoadDBCDialog(QWidget *parent); - QTextEdit *dbc_edit; -}; - -class SaveDBCDialog : public QDialog { - Q_OBJECT - -public: - SaveDBCDialog(QWidget *parent); - void copytoClipboard(); - void saveAs(); - QTextEdit *dbc_edit; -}; - class MessageListModel : public QAbstractTableModel { Q_OBJECT @@ -58,18 +35,10 @@ class MessagesWidget : public QWidget { public: MessagesWidget(QWidget *parent); -public slots: - void loadDBCFromName(const QString &name); - void loadDBCFromFingerprint(); - void loadDBCFromPaste(); - void saveDBC(); - signals: void msgSelectionChanged(const QString &message_id); protected: QTableView *table_widget; - QComboBox *dbc_combo; MessageListModel *model; - QJsonDocument fingerprint_to_dbc; }; From 3dc5dbf103290355b85a146f213f733cbb1dfeb5 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 7 Nov 2022 03:05:46 +0800 Subject: [PATCH 08/54] Cabana: move the chart title into graphics view (#26389) remove class ChartWidget --- tools/cabana/chartswidget.cc | 109 ++++++++++++++--------------------- tools/cabana/chartswidget.h | 45 +++++---------- 2 files changed, 55 insertions(+), 99 deletions(-) diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 6432cb7079..9a8d95633c 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -2,9 +2,9 @@ #include #include -#include #include #include +#include #include #include #include @@ -13,7 +13,6 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); - main_layout->setContentsMargins(0, 0, 0, 0); // title bar title_bar = new QWidget(this); @@ -120,14 +119,14 @@ void ChartsWidget::updateState() { if (prev_range != display_range) { QFutureSynchronizer future_synchronizer; for (auto c : charts) - future_synchronizer.addFuture(QtConcurrent::run(c->chart_view, &ChartView::updateSeries, display_range)); + future_synchronizer.addFuture(QtConcurrent::run(c, &ChartView::updateSeries, display_range)); } } const auto &range = is_zoomed ? zoomed_range : display_range; for (auto c : charts) { - c->chart_view->setRange(range.first, range.second); - c->chart_view->updateLineMarker(current_sec); + c->setRange(range.first, range.second); + c->updateLineMarker(current_sec); } } @@ -150,11 +149,11 @@ void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show) { if (it != charts.end()) { if (!show) removeChart((*it)); } else if (show) { - auto chart = new ChartWidget(id, sig, this); - chart->chart_view->updateSeries(display_range); - QObject::connect(chart, &ChartWidget::remove, [=]() { removeChart(chart); }); - QObject::connect(chart->chart_view, &ChartView::zoomIn, this, &ChartsWidget::zoomIn); - QObject::connect(chart->chart_view, &ChartView::zoomReset, this, &ChartsWidget::zoomReset); + auto chart = new ChartView(id, sig, this); + chart->updateSeries(display_range); + QObject::connect(chart, &ChartView::remove, [=]() { removeChart(chart); }); + QObject::connect(chart, &ChartView::zoomIn, this, &ChartsWidget::zoomIn); + QObject::connect(chart, &ChartView::zoomReset, this, &ChartsWidget::zoomReset); charts_layout->insertWidget(0, chart); charts.push_back(chart); emit chartOpened(chart->id, chart->signal); @@ -168,7 +167,7 @@ bool ChartsWidget::isChartOpened(const QString &id, const Signal *sig) { return it != charts.end(); } -void ChartsWidget::removeChart(ChartWidget *chart) { +void ChartsWidget::removeChart(ChartView *chart) { charts.removeOne(chart); chart->deleteLater(); updateTitleBar(); @@ -184,8 +183,8 @@ void ChartsWidget::signalUpdated(const Signal *sig) { for (auto c : charts) { if (c->signal == sig) { c->updateTitle(); - c->chart_view->updateSeries(display_range); - c->chart_view->setRange(display_range.first, display_range.second, true); + c->updateSeries(display_range); + c->setRange(display_range.first, display_range.second, true); } } } @@ -198,54 +197,6 @@ bool ChartsWidget::eventFilter(QObject *obj, QEvent *event) { return false; } -// ChartWidget - -ChartWidget::ChartWidget(const QString &id, const Signal *sig, QWidget *parent) : id(id), signal(sig), QWidget(parent) { - QVBoxLayout *main_layout = new QVBoxLayout(this); - main_layout->setSpacing(0); - main_layout->setContentsMargins(0, 0, 0, 0); - - header = new QWidget(this); - QGridLayout *header_layout = new QGridLayout(header); - header_layout->setContentsMargins(11, 11, 11, 0); - msg_name_label = new QLabel(this); - msg_name_label->setTextFormat(Qt::RichText); - header_layout->addWidget(msg_name_label, 0, 0, Qt::AlignLeft); - sig_name_label = new QLabel(this); - header_layout->addWidget(sig_name_label, 0, 1, Qt::AlignCenter); //, 0, Qt::AlignCenter); - - remove_btn = new QPushButton("✖", this); - remove_btn->setFixedSize(20, 20); - remove_btn->setToolTip(tr("Remove chart")); - header_layout->addWidget(remove_btn, 0, 2, Qt::AlignRight); - main_layout->addWidget(header); - - chart_view = new ChartView(id, sig, this); - main_layout->addWidget(chart_view); - main_layout->addStretch(); - - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - updateTitle(); - updateFromSettings(); - - QObject::connect(remove_btn, &QPushButton::clicked, [=]() { emit remove(id, sig); }); - QObject::connect(&settings, &Settings::changed, this, &ChartWidget::updateFromSettings); -} - -void ChartWidget::updateTitle() { - msg_name_label->setText(tr("%1 %2").arg(dbc()->msg(id)->name.c_str()).arg(id)); - sig_name_label->setText(signal->name.c_str()); -} - -void ChartWidget::updateFromSettings() { - header->setStyleSheet(settings.chart_theme == 0 ? "background-color:white" : "background-color:#23242c"); - QString color_style = settings.chart_theme == 0 ? "color:black" : "color:white"; - sig_name_label->setStyleSheet("font-weight:bold;" + color_style); - msg_name_label->setStyleSheet(color_style); - remove_btn->setStyleSheet(color_style); - chart_view->updateFromSettings(); -} - // ChartView ChartView::ChartView(const QString &id, const Signal *sig, QWidget *parent) @@ -256,7 +207,6 @@ ChartView::ChartView(const QString &id, const Signal *sig, QWidget *parent) chart->addSeries(series); chart->createDefaultAxes(); chart->legend()->hide(); - chart->setMargins({0, 0, 0, 0}); chart->layout()->setContentsMargins(0, 0, 0, 0); line_marker = new QGraphicsLineItem(chart); @@ -270,26 +220,51 @@ ChartView::ChartView(const QString &id, const Signal *sig, QWidget *parent) item_group = scene()->createItemGroup({track_line, track_ellipse, value_text}); item_group->setZValue(chart->zValue() + 10); - setChart(chart); + // title + msg_title = new QGraphicsTextItem(chart); + QToolButton *remove_btn = new QToolButton(); + remove_btn->setText("X"); + remove_btn->setAutoRaise(true); + remove_btn->setToolTip(tr("Remove Chart")); + close_btn_proxy = new QGraphicsProxyWidget(chart); + close_btn_proxy->setWidget(remove_btn); + setChart(chart); setRenderHint(QPainter::Antialiasing); setRubberBand(QChartView::HorizontalRubberBand); + updateFromSettings(); + updateTitle(); QTimer *timer = new QTimer(this); timer->setInterval(100); timer->setSingleShot(true); timer->callOnTimeout(this, &ChartView::adjustChartMargins); + QObject::connect(&settings, &Settings::changed, this, &ChartView::updateFromSettings); + QObject::connect(remove_btn, &QToolButton::clicked, [=]() { emit remove(id, sig); }); QObject::connect(chart, &QChart::plotAreaChanged, [=](const QRectF &plotArea) { // use a singleshot timer to avoid recursion call. timer->start(); }); } +void ChartView::resizeEvent(QResizeEvent *event) { + QChartView::resizeEvent(event); + msg_title->setPos(11, 6); + close_btn_proxy->setPos(event->size().width() - close_btn_proxy->size().width() - 11, 8); +} + +void ChartView::updateTitle() { + chart()->setTitle(signal->name.c_str()); + msg_title->setHtml(tr("%1 %2").arg(dbc()->msg(id)->name.c_str()).arg(id)); +} + void ChartView::updateFromSettings() { setFixedHeight(settings.chart_height); chart()->setTheme(settings.chart_theme == 0 ? QChart::ChartThemeLight : QChart::QChart::ChartThemeDark); - line_marker->setPen(QPen(settings.chart_theme == 0 ? Qt::black : Qt::white, 2)); + auto color = chart()->titleBrush().color(); + line_marker->setPen(QPen(color, 2)); + msg_title->setDefaultTextColor(color); } void ChartView::setRange(double min, double max, bool force_update) { @@ -305,7 +280,7 @@ void ChartView::adjustChartMargins() { const int aligned_pos = 60; if (chart()->plotArea().left() != aligned_pos) { const float left_margin = chart()->margins().left() + aligned_pos - chart()->plotArea().left(); - chart()->setMargins(QMargins(left_margin, 0, 0, 0)); + chart()->setMargins(QMargins(left_margin, 11, 0, 0)); } } @@ -314,7 +289,7 @@ void ChartView::updateLineMarker(double current_sec) { int x = chart()->plotArea().left() + chart()->plotArea().width() * (current_sec - axis_x->min()) / (axis_x->max() - axis_x->min()); if (int(line_marker->line().x1()) != x) { - line_marker->setLine(x, 0, x, height()); + line_marker->setLine(x, chart()->plotArea().top() - chart()->margins().top() + 3, x, height()); } } @@ -402,7 +377,7 @@ void ChartView::mouseMoveEvent(QMouseEvent *ev) { if (!is_zooming) { const auto plot_area = chart()->plotArea(); auto axis_x = dynamic_cast(chart()->axisX()); - double x = std::clamp((double)ev->pos().x(), plot_area.left(), plot_area.right()-1); + double x = std::clamp((double)ev->pos().x(), plot_area.left(), plot_area.right() - 1); double sec = axis_x->min() + (axis_x->max() - axis_x->min()) * (x - plot_area.left()) / plot_area.width(); auto value = std::upper_bound(vals.begin(), vals.end(), sec, [](double x, auto &p) { return x < p.x(); }); if (value != vals.end()) { diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index 70e0774c3e..4d33e91cb9 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -1,10 +1,9 @@ #pragma once -#include - #include #include #include +#include #include #include #include @@ -24,48 +23,31 @@ public: void setRange(double min, double max, bool force_update = false); void updateLineMarker(double current_sec); void updateFromSettings(); + void updateTitle(); + + QString id; + const Signal *signal; signals: void zoomIn(double min, double max); void zoomReset(); + void remove(const QString &msg_id, const Signal *sig); private: void mouseReleaseEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *ev) override; void leaveEvent(QEvent *event) override; + void resizeEvent(QResizeEvent *event) override; void adjustChartMargins(); void updateAxisY(); QGraphicsItemGroup *item_group; - QGraphicsLineItem *track_line; + QGraphicsLineItem *line_marker, *track_line; QGraphicsEllipseItem *track_ellipse; - QGraphicsTextItem *value_text; - QGraphicsLineItem *line_marker; + QGraphicsTextItem *value_text, *msg_title; + QGraphicsProxyWidget *close_btn_proxy; QVector vals; - QString id; - const Signal *signal; -}; - -class ChartWidget : public QWidget { -Q_OBJECT - -public: - ChartWidget(const QString &id, const Signal *sig, QWidget *parent); - void updateTitle(); - void updateFromSettings(); - -signals: - void remove(const QString &msg_id, const Signal *sig); - -public: - QString id; - const Signal *signal; - QWidget *header; - QLabel *msg_name_label; - QLabel *sig_name_label; - QPushButton *remove_btn; - ChartView *chart_view = nullptr; -}; + }; class ChartsWidget : public QWidget { Q_OBJECT @@ -73,7 +55,7 @@ class ChartsWidget : public QWidget { public: ChartsWidget(QWidget *parent = nullptr); void showChart(const QString &id, const Signal *sig, bool show); - void removeChart(ChartWidget *chart); + void removeChart(ChartView *chart); bool isChartOpened(const QString &id, const Signal *sig); signals: @@ -100,8 +82,7 @@ private: QPushButton *reset_zoom_btn; QPushButton *remove_all_btn; QVBoxLayout *charts_layout; - QList charts; - + QList charts; bool is_zoomed = false; std::pair event_range; std::pair display_range; From cdcc0fb3695d75e781053f9feda6b6b91a08ea86 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 7 Nov 2022 03:06:10 +0800 Subject: [PATCH 09/54] Cabana: Reimplement HistoryLog::sizeHintForColumn to improve performance (#26393) Reimplement sizeHintForColumn to improve performance --- tools/cabana/historylog.cc | 6 +++++- tools/cabana/historylog.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index 7bb2f37699..4b1818cf68 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -1,7 +1,6 @@ #include "tools/cabana/historylog.h" #include -#include // HistoryLogModel @@ -89,3 +88,8 @@ HistoryLog::HistoryLog(QWidget *parent) : QTableView(parent) { setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); setStyleSheet("QTableView::item { border:0px; padding-left:5px; padding-right:5px; }"); } + +int HistoryLog::sizeHintForColumn(int column) const { + // sizeHintForColumn is only called for column 0 (ResizeToContents) + return itemDelegate()->sizeHint(viewOptions(), model->index(0, 0)).width() + 1; // +1 for grid +} diff --git a/tools/cabana/historylog.h b/tools/cabana/historylog.h index e1c1319166..e8b0f5a35b 100644 --- a/tools/cabana/historylog.h +++ b/tools/cabana/historylog.h @@ -9,7 +9,7 @@ class HeaderView : public QHeaderView { public: HeaderView(Qt::Orientation orientation, QWidget *parent = nullptr) : QHeaderView(orientation, parent) {} - QSize sectionSizeFromContents(int logicalIndex) const; + QSize sectionSizeFromContents(int logicalIndex) const override; }; class HistoryLogModel : public QAbstractTableModel { @@ -40,5 +40,6 @@ public: void setMessage(const QString &message_id) { model->setMessage(message_id); } void updateState() { model->updateState(); } private: + int sizeHintForColumn(int column) const override; HistoryLogModel *model; }; From 45891c79079ae4404b8828d9bcfe5cd79bce0c90 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 7 Nov 2022 03:06:42 +0800 Subject: [PATCH 10/54] Cabana: use QToolBar to manage the controls in ChartsView (#26388) use QToolBar --- tools/cabana/chartswidget.cc | 73 +++++++++++++----------------------- tools/cabana/chartswidget.h | 9 ++--- 2 files changed, 30 insertions(+), 52 deletions(-) diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 9a8d95633c..b4d6d89e6d 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -8,47 +8,31 @@ #include #include #include +#include // ChartsWidget ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); - // title bar - title_bar = new QWidget(this); - title_bar->setVisible(false); - QHBoxLayout *title_layout = new QHBoxLayout(title_bar); - title_layout->setContentsMargins(0, 0, 0, 0); - title_label = new QLabel(tr("Charts")); - - title_layout->addWidget(title_label); - title_layout->addStretch(); - - range_label = new QLabel(); - title_layout->addWidget(range_label); - - reset_zoom_btn = new QPushButton("⟲", this); - reset_zoom_btn->setFixedSize(30, 30); + // toolbar + QToolBar *toolbar = new QToolBar(tr("Charts"), this); + title_label = new QLabel(); + title_label->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); + toolbar->addWidget(title_label); + toolbar->addWidget(range_label = new QLabel()); + reset_zoom_btn = toolbar->addAction("⟲"); reset_zoom_btn->setToolTip(tr("Reset zoom (drag on chart to zoom X-Axis)")); - title_layout->addWidget(reset_zoom_btn); - - remove_all_btn = new QPushButton("✖", this); + remove_all_btn = toolbar->addAction("✖"); remove_all_btn->setToolTip(tr("Remove all charts")); - remove_all_btn->setFixedSize(30, 30); - title_layout->addWidget(remove_all_btn); - - dock_btn = new QPushButton(); - dock_btn->setFixedSize(30, 30); - title_layout->addWidget(dock_btn); - - main_layout->addWidget(title_bar, 0, Qt::AlignTop); + dock_btn = toolbar->addAction(""); + main_layout->addWidget(toolbar); + updateToolBar(); // charts QWidget *charts_container = new QWidget(this); - QVBoxLayout *charts_main = new QVBoxLayout(charts_container); - charts_layout = new QVBoxLayout(); - charts_main->addLayout(charts_layout); - charts_main->addStretch(); + charts_layout = new QVBoxLayout(charts_container); + charts_layout->addStretch(); QScrollArea *charts_scroll = new QScrollArea(this); charts_scroll->setWidgetResizable(true); @@ -67,12 +51,12 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { }); QObject::connect(can, &CANMessages::eventsMerged, this, &ChartsWidget::eventsMerged); QObject::connect(can, &CANMessages::updated, this, &ChartsWidget::updateState); - QObject::connect(remove_all_btn, &QPushButton::clicked, [this]() { removeAll(); }); - QObject::connect(reset_zoom_btn, &QPushButton::clicked, this, &ChartsWidget::zoomReset); - QObject::connect(dock_btn, &QPushButton::clicked, [this]() { + QObject::connect(remove_all_btn, &QAction::triggered, [this]() { removeAll(); }); + QObject::connect(reset_zoom_btn, &QAction::triggered, this, &ChartsWidget::zoomReset); + QObject::connect(dock_btn, &QAction::triggered, [this]() { emit dock(!docking); docking = !docking; - updateTitleBar(); + updateToolBar(); }); } @@ -91,7 +75,7 @@ void ChartsWidget::eventsMerged() { void ChartsWidget::zoomIn(double min, double max) { zoomed_range = {min, max}; is_zoomed = zoomed_range != display_range; - updateTitleBar(); + updateToolBar(); emit rangeChanged(min, max, is_zoomed); updateState(); } @@ -130,16 +114,11 @@ void ChartsWidget::updateState() { } } -void ChartsWidget::updateTitleBar() { - title_bar->setVisible(!charts.isEmpty()); - if (charts.isEmpty()) return; - - range_label->setVisible(is_zoomed); +void ChartsWidget::updateToolBar() { + remove_all_btn->setEnabled(!charts.isEmpty()); reset_zoom_btn->setEnabled(is_zoomed); - if (is_zoomed) { - range_label->setText(tr("%1 - %2").arg(zoomed_range.first, 0, 'f', 2).arg(zoomed_range.second, 0, 'f', 2)); - } - title_label->setText(tr("Charts (%1)").arg(charts.size())); + range_label->setText(is_zoomed ? tr("%1 - %2").arg(zoomed_range.first, 0, 'f', 2).arg(zoomed_range.second, 0, 'f', 2) : ""); + title_label->setText(charts.size() > 0 ? tr("Charts (%1)").arg(charts.size()) : tr("Charts")); dock_btn->setText(docking ? "⬈" : "⬋"); dock_btn->setToolTip(docking ? tr("Undock charts") : tr("Dock charts")); } @@ -159,7 +138,7 @@ void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show) { emit chartOpened(chart->id, chart->signal); updateState(); } - updateTitleBar(); + updateToolBar(); } bool ChartsWidget::isChartOpened(const QString &id, const Signal *sig) { @@ -170,7 +149,7 @@ bool ChartsWidget::isChartOpened(const QString &id, const Signal *sig) { void ChartsWidget::removeChart(ChartView *chart) { charts.removeOne(chart); chart->deleteLater(); - updateTitleBar(); + updateToolBar(); emit chartClosed(chart->id, chart->signal); } @@ -191,7 +170,7 @@ void ChartsWidget::signalUpdated(const Signal *sig) { bool ChartsWidget::eventFilter(QObject *obj, QEvent *event) { if (obj != this && event->type() == QEvent::Close) { - emit dock_btn->clicked(); + emit dock_btn->triggered(); return true; } return false; diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index 4d33e91cb9..e32a6697ce 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -70,17 +70,16 @@ private: void zoomIn(double min, double max); void zoomReset(); void signalUpdated(const Signal *sig); - void updateTitleBar(); + void updateToolBar(); void removeAll(const Signal *sig = nullptr); bool eventFilter(QObject *obj, QEvent *event) override; - QWidget *title_bar; QLabel *title_label; QLabel *range_label; bool docking = true; - QPushButton *dock_btn; - QPushButton *reset_zoom_btn; - QPushButton *remove_all_btn; + QAction *dock_btn; + QAction *reset_zoom_btn; + QAction *remove_all_btn; QVBoxLayout *charts_layout; QList charts; bool is_zoomed = false; From 253e5d7f9d7741e61f010f2ffd6b82a2e908019a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Sun, 6 Nov 2022 12:17:07 -0800 Subject: [PATCH 11/54] FCW: less false positives (#26366) * Less FP for FCW * enable fcw for e2e long --- selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py | 5 +++-- selfdrive/controls/lib/longitudinal_planner.py | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py index 49eb5988e2..080782ad0f 100644 --- a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py @@ -36,7 +36,7 @@ A_EGO_COST = 0. J_EGO_COST = 5.0 A_CHANGE_COST = 200. DANGER_ZONE_COST = 100. -CRASH_DISTANCE = .5 +CRASH_DISTANCE = .25 LEAD_DANGER_FACTOR = 0.75 LIMIT_COST = 1e6 ACADOS_SOLVER_TYPE = 'SQP_RTI' @@ -49,6 +49,7 @@ MAX_T = 10.0 T_IDXS_LST = [index_function(idx, max_val=MAX_T, max_idx=N) for idx in range(N+1)] T_IDXS = np.array(T_IDXS_LST) +FCW_IDXS = T_IDXS < 5.0 T_DIFFS = np.diff(T_IDXS, prepend=[0.]) MIN_ACCEL = -3.5 MAX_ACCEL = 2.0 @@ -369,7 +370,7 @@ class LongitudinalMpc: self.params[:,4] = T_FOLLOW self.run() - if (np.any(lead_xv_0[:,0] - self.x_sol[:,0] < CRASH_DISTANCE) and + if (np.any(lead_xv_0[FCW_IDXS,0] - self.x_sol[FCW_IDXS,0] < CRASH_DISTANCE) and radarstate.leadOne.modelProb > 0.9): self.crash_cnt += 1 else: diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 457065d3b5..5a336d18c9 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -132,8 +132,7 @@ class LongitudinalPlanner: self.j_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC[:-1], self.mpc.j_solution) # TODO counter is only needed because radar is glitchy, remove once radar is gone - # TODO write fcw in e2e_long mode - self.fcw = self.mpc.mode == 'acc' and self.mpc.crash_cnt > 5 and not sm['carState'].standstill + self.fcw = self.mpc.crash_cnt > 2 and not sm['carState'].standstill if self.fcw: cloudlog.info("FCW triggered") From 1cf293f3a6c02bb44af9ef1e715b005104de1bc1 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 7 Nov 2022 23:53:42 +0800 Subject: [PATCH 12/54] Cabana: improve message sorting,filtering and updating. (#26396) * optimize sort/filter/update * helper function msgName * cleanup --- tools/cabana/canmessages.cc | 3 +- tools/cabana/canmessages.h | 1 + tools/cabana/dbcmanager.h | 5 +- tools/cabana/detailwidget.cc | 7 +-- tools/cabana/messageswidget.cc | 108 +++++++++++++-------------------- tools/cabana/messageswidget.h | 13 ++-- 6 files changed, 56 insertions(+), 81 deletions(-) diff --git a/tools/cabana/canmessages.cc b/tools/cabana/canmessages.cc index f1f5c2cd23..e670ee8c94 100644 --- a/tools/cabana/canmessages.cc +++ b/tools/cabana/canmessages.cc @@ -62,8 +62,9 @@ void CANMessages::process(QHash *messages) { for (auto it = messages->begin(); it != messages->end(); ++it) { can_msgs[it.key()] = it.value(); } - delete messages; emit updated(); + emit msgsReceived(messages); + delete messages; } bool CANMessages::eventFilter(const Event *event) { diff --git a/tools/cabana/canmessages.h b/tools/cabana/canmessages.h index 14e2423d01..5ee33bce0d 100644 --- a/tools/cabana/canmessages.h +++ b/tools/cabana/canmessages.h @@ -50,6 +50,7 @@ signals: void streamStarted(); void eventsMerged(); void updated(); + void msgsReceived(const QHash *); void received(QHash *); public: diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index d8a8da9b7a..cbe4531d2a 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -48,5 +48,8 @@ int bigEndianStartBitsIndex(int start_bit); int bigEndianBitIndex(int index); void updateSigSizeParamsFromRange(Signal &s, int from, int to); std::pair getSignalRange(const Signal *s); - DBCManager *dbc(); +inline QString msgName(const QString &id, const char *def = "untitled") { + auto msg = dbc()->msg(id); + return msg ? msg->name.c_str() : def; +} diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index db731333d3..18510c86ea 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -132,8 +132,7 @@ void DetailWidget::setMessage(const QString &message_id) { } if (index == -1) { index = tabbar->addTab(message_id); - auto msg = dbc()->msg(message_id); - tabbar->setTabToolTip(index, msg ? msg->name.c_str() : "untitled"); + tabbar->setTabToolTip(index, msgName(message_id)); } tabbar->setCurrentIndex(index); msg_id = message_id; @@ -173,7 +172,7 @@ void DetailWidget::dbcMsgChanged(int show_form_idx) { } edit_btn->setVisible(true); - name_label->setText(msg ? msg->name.c_str() : "untitled"); + name_label->setText(msgName(msg_id)); binary_view->setMessage(msg_id); history_log->setMessage(msg_id); @@ -212,7 +211,7 @@ void DetailWidget::updateChartState(const QString &id, const Signal *sig, bool o void DetailWidget::editMsg() { auto msg = dbc()->msg(msg_id); - QString name = msg ? msg->name.c_str() : "untitled"; + QString name = msgName(msg_id); int size = msg ? msg->size : can->lastMessage(msg_id).dat.size(); EditMessageDialog dlg(msg_id, name, size, this); if (dlg.exec()) { diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index b2e8e50b55..f24b6b0317 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -35,13 +35,19 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { // signals/slots QObject::connect(filter, &QLineEdit::textChanged, model, &MessageListModel::setFilterString); - QObject::connect(can, &CANMessages::updated, [this]() { model->updateState(); }); - QObject::connect(dbc(), &DBCManager::DBCFileChanged, [this]() { model->updateState(true); }); + QObject::connect(can, &CANMessages::msgsReceived, model, &MessageListModel::msgsReceived); + QObject::connect(dbc(), &DBCManager::DBCFileChanged, model, &MessageListModel::sortMessages); + QObject::connect(dbc(), &DBCManager::msgUpdated, model, &MessageListModel::sortMessages); QObject::connect(table_widget->selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex ¤t, const QModelIndex &previous) { - if (current.isValid()) { - emit msgSelectionChanged(current.data(Qt::UserRole).toString()); + if (current.isValid() && current.row() < model->msgs.size()) { + current_msg_id = model->msgs[current.row()]; + emit msgSelectionChanged(current_msg_id); } }); + QObject::connect(model, &MessageListModel::modelReset, [this]() { + if (int row = model->msgs.indexOf(current_msg_id); row != -1) + table_widget->selectionModel()->select(model->index(row, 0), QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); + }); } // MessageListModel @@ -54,103 +60,71 @@ QVariant MessageListModel::headerData(int section, Qt::Orientation orientation, QVariant MessageListModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) { - const auto &m = msgs[index.row()]; - auto &can_data = can->lastMessage(m->id); + const auto &id = msgs[index.row()]; + auto &can_data = can->lastMessage(id); switch (index.column()) { - case 0: return m->name; - case 1: return m->id; + case 0: return msgName(id); + case 1: return id; case 2: return can_data.freq; case 3: return can_data.count; case 4: return toHex(can_data.dat); } - } else if (role == Qt::UserRole) { - return msgs[index.row()]->id; - } else if (role == Qt::FontRole) { - if (index.column() == columnCount() - 1) { - return QFontDatabase::systemFont(QFontDatabase::FixedFont); - } + } else if (role == Qt::FontRole && index.column() == columnCount() - 1) { + return QFontDatabase::systemFont(QFontDatabase::FixedFont); } return {}; } -void MessageListModel::setFilterString(const QString &string) { +void MessageListModel::setFilterString(const QString &string) { filter_str = string; - updateState(true); -} - -bool MessageListModel::updateMessages(bool sort) { - if (msgs.size() == can->can_msgs.size() && filter_str.isEmpty() && !sort) - return false; - - // update message list - int i = 0; bool search_id = filter_str.contains(':'); + msgs.clear(); for (auto it = can->can_msgs.begin(); it != can->can_msgs.end(); ++it) { - const Msg *msg = dbc()->msg(it.key()); - QString msg_name = msg ? msg->name.c_str() : "untitled"; - if (!filter_str.isEmpty() && !(search_id ? it.key() : msg_name).contains(filter_str, Qt::CaseInsensitive)) - continue; - auto &m = i < msgs.size() ? msgs[i] : msgs.emplace_back(new Message); - m->id = it.key(); - m->name = msg_name; - ++i; + if ((search_id ? it.key() : msgName(it.key())).contains(filter_str, Qt::CaseInsensitive)) + msgs.push_back(it.key()); } - msgs.resize(i); + sortMessages(); +} +void MessageListModel::sortMessages() { + beginResetModel(); if (sort_column == 0) { std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) { - bool ret = l->name < r->name || (l->name == r->name && l->id < r->id); + bool ret = std::pair{msgName(l), l} < std::pair{msgName(r), r}; return sort_order == Qt::AscendingOrder ? ret : !ret; }); } else if (sort_column == 1) { std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) { - return sort_order == Qt::AscendingOrder ? l->id < r->id : l->id > r->id; + return sort_order == Qt::AscendingOrder ? l < r : l > r; }); } else if (sort_column == 2) { - // sort by frequency std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) { - uint32_t lfreq = can->lastMessage(l->id).freq; - uint32_t rfreq = can->lastMessage(r->id).freq; - bool ret = lfreq < rfreq || (lfreq == rfreq && l->id < r->id); + bool ret = std::pair{can->lastMessage(l).freq, l} < std::pair{can->lastMessage(r).freq, r}; return sort_order == Qt::AscendingOrder ? ret : !ret; }); } else if (sort_column == 3) { - // sort by count std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) { - uint32_t lcount = can->lastMessage(l->id).count; - uint32_t rcount = can->lastMessage(r->id).count; - bool ret = lcount < rcount || (lcount == rcount && l->id < r->id); + bool ret = std::pair{can->lastMessage(l).count, l} < std::pair{can->lastMessage(r).count, r}; return sort_order == Qt::AscendingOrder ? ret : !ret; }); } - return true; + endResetModel(); } -void MessageListModel::updateState(bool sort) { +void MessageListModel::msgsReceived(const QHash *new_msgs) { int prev_row_count = msgs.size(); - auto prev_idx = persistentIndexList(); - QString selected_msg_id = prev_idx.empty() ? "" : prev_idx[0].data(Qt::UserRole).toString(); - - bool msg_updated = updateMessages(sort); - int delta = msgs.size() - prev_row_count; - if (delta > 0) { - beginInsertRows({}, prev_row_count, msgs.size() - 1); - endInsertRows(); - } else if (delta < 0) { - beginRemoveRows({}, msgs.size(), prev_row_count - 1); - endRemoveRows(); + if (filter_str.isEmpty() && msgs.size() != can->can_msgs.size()) { + msgs = can->can_msgs.keys(); } - - if (!msgs.empty()) { - if (msg_updated && !prev_idx.isEmpty()) { - // keep selection - auto it = std::find_if(msgs.begin(), msgs.end(), [&](auto &m) { return m->id == selected_msg_id; }); - if (it != msgs.end()) { - for (auto &idx : prev_idx) - changePersistentIndex(idx, index(std::distance(msgs.begin(), it), idx.column())); - } + if (msgs.size() != prev_row_count) { + sortMessages(); + return; + } + for (int i = 0; i < msgs.size(); ++i) { + if (new_msgs->contains(msgs[i])) { + for (int col = 2; col < columnCount(); ++col) + emit dataChanged(index(i, col), index(i, col), {Qt::DisplayRole}); } - emit dataChanged(index(0, 0), index(msgs.size() - 1, columnCount() - 1), {Qt::DisplayRole}); } } @@ -158,6 +132,6 @@ void MessageListModel::sort(int column, Qt::SortOrder order) { if (column != columnCount() - 1) { sort_column = column; sort_order = order; - updateState(true); + sortMessages(); } } diff --git a/tools/cabana/messageswidget.h b/tools/cabana/messageswidget.h index 450c7003b7..3a42bed4be 100644 --- a/tools/cabana/messageswidget.h +++ b/tools/cabana/messageswidget.h @@ -4,6 +4,7 @@ #include #include "tools/cabana/canmessages.h" + class MessageListModel : public QAbstractTableModel { Q_OBJECT @@ -14,16 +15,12 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; int rowCount(const QModelIndex &parent = QModelIndex()) const override { return msgs.size(); } void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; - void updateState(bool sort = false); void setFilterString(const QString &string); + void msgsReceived(const QHash *new_msgs = nullptr); + void sortMessages(); + QStringList msgs; private: - bool updateMessages(bool sort); - - struct Message { - QString id, name; - }; - std::vector> msgs; QString filter_str; int sort_column = 0; Qt::SortOrder sort_order = Qt::AscendingOrder; @@ -34,11 +31,11 @@ class MessagesWidget : public QWidget { public: MessagesWidget(QWidget *parent); - signals: void msgSelectionChanged(const QString &message_id); protected: QTableView *table_widget; + QString current_msg_id; MessageListModel *model; }; From 1fe45ab3c5bae9983c11a82fed04167802f75b36 Mon Sep 17 00:00:00 2001 From: Alen <3875050+alenl2@users.noreply.github.com> Date: Mon, 7 Nov 2022 23:07:40 +0100 Subject: [PATCH 13/54] Kia EV6: Add EU fwdCamera firmware (#26398) --- selfdrive/car/hyundai/values.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 536af7cf01..972aad0c90 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -1374,6 +1374,7 @@ FW_VERSIONS = { b'\xf1\x00CV1 MFC AT USA LHD 1.00 1.05 99210-CV000 211027', b'\xf1\x00CV1 MFC AT USA LHD 1.00 1.06 99210-CV000 220328', b'\xf1\x00CV1 MFC AT EUR LHD 1.00 1.05 99210-CV000 211027', + b'\xf1\x00CV1 MFC AT EUR LHD 1.00 1.06 99210-CV000 220328', ], }, CAR.IONIQ_5: { From ed3bf4f12332556c6684141f1a8b2aed6b342ecc Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 7 Nov 2022 16:39:53 -0800 Subject: [PATCH 14/54] onroad ui: fix opacity affecting other drawn icons (#26378) * save painter in drawIcon * fix * Update selfdrive/ui/qt/onroad.cc --- selfdrive/ui/qt/onroad.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index bfd2f44561..b4925c2f73 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -404,6 +404,7 @@ void AnnotatedCameraWidget::drawText(QPainter &p, int x, int y, const QString &t } void AnnotatedCameraWidget::drawIcon(QPainter &p, int x, int y, QPixmap &img, QBrush bg, float opacity) { + p.setOpacity(1.0); // bg dictates opacity of ellipse p.setPen(Qt::NoPen); p.setBrush(bg); p.drawEllipse(x - radius / 2, y - radius / 2, radius, radius); From ea813a9a7dd1457899d5c1fe5ac67449c674eb0f Mon Sep 17 00:00:00 2001 From: brownspaceman Date: Mon, 7 Nov 2022 16:48:54 -0800 Subject: [PATCH 15/54] Subaru: add missing engine FW for 2019 Impreza (#26385) added fw for 2019 subaru impreza --- selfdrive/car/subaru/values.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py index da5ff1785a..7a1e9a8a3d 100644 --- a/selfdrive/car/subaru/values.py +++ b/selfdrive/car/subaru/values.py @@ -196,6 +196,7 @@ FW_VERSIONS = { b'\xaa!dt\a', b'\xc5!ar\a', b'\xbe!as\a', + b'\xc5!as\x07', b'\xc5!ds\a', b'\xc5!`s\a', b'\xaa!au\a', From 1b6e37daa64c6fda8eaf0ade26d6d8c11274ef68 Mon Sep 17 00:00:00 2001 From: Jason Wen <47793918+sunnyhaibin@users.noreply.github.com> Date: Mon, 7 Nov 2022 19:51:32 -0500 Subject: [PATCH 16/54] Hyundai: update Ioniq 5 HDA I supported model years (#26376) * Hyundai: Add FW for 2023 Ioniq 5 HDA2 * Update values.py * Update CARS.md * Update values.py * Update CARS.md --- docs/CARS.md | 2 +- selfdrive/car/hyundai/values.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CARS.md b/docs/CARS.md index c347868968..7066b94f61 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -60,7 +60,7 @@ A supported vehicle is one that just works when you install a comma three. All s |Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai J| |Hyundai|i30 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E| |Hyundai|Ioniq 5 (with HDA II) 2022-23|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai Q| -|Hyundai|Ioniq 5 (without HDA II) 2022|Highway Driving Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K| +|Hyundai|Ioniq 5 (without HDA II) 2022-23|Highway Driving Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K| |Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| |Hyundai|Ioniq Electric 2020|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| |Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 972aad0c90..4b2ef474b8 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -145,7 +145,7 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = { CAR.VELOSTER: HyundaiCarInfo("Hyundai Veloster 2019-20", min_enable_speed=5. * CV.MPH_TO_MS, harness=Harness.hyundai_e), CAR.SONATA_HYBRID: HyundaiCarInfo("Hyundai Sonata Hybrid 2020-22", "All", harness=Harness.hyundai_a), CAR.IONIQ_5: [ - HyundaiCarInfo("Hyundai Ioniq 5 (without HDA II) 2022" , "Highway Driving Assist", harness=Harness.hyundai_k), + HyundaiCarInfo("Hyundai Ioniq 5 (without HDA II) 2022-23" , "Highway Driving Assist", harness=Harness.hyundai_k), HyundaiCarInfo("Hyundai Ioniq 5 (with HDA II) 2022-23", "Highway Driving Assist II", harness=Harness.hyundai_q), ], CAR.TUCSON_HYBRID_4TH_GEN: HyundaiCarInfo("Hyundai Tucson Hybrid 2022", "All", harness=Harness.hyundai_n), From e9eb5d99ff659a3f5e1b4e0bead321c469d8d889 Mon Sep 17 00:00:00 2001 From: Vivek Aithal Date: Mon, 7 Nov 2022 17:01:24 -0800 Subject: [PATCH 17/54] [torqued] Fix high speed oscillations (#26338) * modify low speed factor during high speeds and rescale friction * update refs --- selfdrive/car/interfaces.py | 2 +- selfdrive/controls/lib/latcontrol_torque.py | 8 +++++--- selfdrive/test/process_replay/ref_commit | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 4647a04244..982ba40b17 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -23,7 +23,7 @@ TorqueFromLateralAccelCallbackType = Callable[[float, car.CarParams.LateralTorqu MAX_CTRL_SPEED = (V_CRUISE_MAX + 4) * CV.KPH_TO_MS ACCEL_MAX = 2.0 ACCEL_MIN = -3.5 -FRICTION_THRESHOLD = 0.2 +FRICTION_THRESHOLD = 0.3 TORQUE_PARAMS_PATH = os.path.join(BASEDIR, 'selfdrive/car/torque_data/params.yaml') TORQUE_OVERRIDE_PATH = os.path.join(BASEDIR, 'selfdrive/car/torque_data/override.yaml') diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index 51676086ba..d10d39d945 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -17,7 +17,8 @@ from selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY # friction in the steering wheel that needs to be overcome to # move it at all, this is compensated for too. -LOW_SPEED_FACTOR = 200 +LOW_SPEED_X = [0, 10, 20, 30] +LOW_SPEED_Y = [15, 13, 10, 5] class LatControlTorque(LatControl): @@ -57,8 +58,9 @@ class LatControlTorque(LatControl): actual_lateral_accel = actual_curvature * CS.vEgo ** 2 lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2 - setpoint = desired_lateral_accel + LOW_SPEED_FACTOR * desired_curvature - measurement = actual_lateral_accel + LOW_SPEED_FACTOR * actual_curvature + low_speed_factor = interp(CS.vEgo, LOW_SPEED_X, LOW_SPEED_Y)**2 + setpoint = desired_lateral_accel + low_speed_factor * desired_curvature + measurement = actual_lateral_accel + low_speed_factor * actual_curvature error = setpoint - measurement gravity_adjusted_lateral_accel = desired_lateral_accel - params.roll * ACCELERATION_DUE_TO_GRAVITY pid_log.error = self.torque_from_lateral_accel(error, self.torque_params, error, diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 8bc13f37d4..0608a6d14b 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -24a8d02b148b7f6d20f641d56a7bed71c244b6e3 \ No newline at end of file +2991a54ea491633f93fae76da4f5f1d265ce311a \ No newline at end of file From f63f0de80a78ade6ad12fe98ea27094035d97457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Mon, 7 Nov 2022 17:49:36 -0800 Subject: [PATCH 18/54] E2e long model: calibrate model speed to wheel speed (#26395) * calibrate! * Fix test * Fix proc replay * check len * get v_ego from model 8501d20-bb59-4193-aa82-82b2737dedd6/449 609d90f3-65e6-4617-a60c-d6d99eead408/700 * bump cereal * initialize v_model_error * typo * better names * cleanup * bump cereal * update model replay ref commit * bump to cereal master Co-authored-by: Yassine Yousfi --- cereal | 2 +- selfdrive/controls/lib/longitudinal_planner.py | 12 ++++++++---- selfdrive/modeld/models/driving.cc | 11 +++++++++++ selfdrive/modeld/models/driving.h | 9 +++++++++ selfdrive/modeld/models/supercombo.onnx | 4 ++-- .../test/process_replay/model_replay_ref_commit | 2 +- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/cereal b/cereal index 1d25fc3f20..cdba1aafec 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit 1d25fc3f202d5ddeee97848480323e9b14f9bdfa +Subproject commit cdba1aafec5e36505ef6ace675568e1f15003c47 diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 5a336d18c9..19ea40a8f4 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -58,6 +58,7 @@ class LongitudinalPlanner: self.a_desired = init_a self.v_desired_filter = FirstOrderFilter(init_v, 2.0, DT_MDL) + self.v_model_error = 0.0 self.v_desired_trajectory = np.zeros(CONTROL_N) self.a_desired_trajectory = np.zeros(CONTROL_N) @@ -68,12 +69,12 @@ class LongitudinalPlanner: e2e = self.params.get_bool('EndToEndLong') and self.CP.openpilotLongitudinalControl self.mpc.mode = 'blended' if e2e else 'acc' - def parse_model(self, model_msg): + def parse_model(self, model_msg, model_error): if (len(model_msg.position.x) == 33 and len(model_msg.velocity.x) == 33 and len(model_msg.acceleration.x) == 33): - x = np.interp(T_IDXS_MPC, T_IDXS, model_msg.position.x) - v = np.interp(T_IDXS_MPC, T_IDXS, model_msg.velocity.x) + x = np.interp(T_IDXS_MPC, T_IDXS, model_msg.position.x) - model_error * T_IDXS_MPC + v = np.interp(T_IDXS_MPC, T_IDXS, model_msg.velocity.x) - model_error a = np.interp(T_IDXS_MPC, T_IDXS, model_msg.acceleration.x) j = np.zeros(len(T_IDXS_MPC)) else: @@ -112,6 +113,9 @@ class LongitudinalPlanner: # Prevent divergence, smooth in current v_ego self.v_desired_filter.x = max(0.0, self.v_desired_filter.update(v_ego)) + # Compute model v_ego error + if len(sm['modelV2'].temporalPose.trans): + self.v_model_error = sm['modelV2'].temporalPose.trans[0] - v_ego if force_slow_decel: # if required so, force a smooth deceleration @@ -124,7 +128,7 @@ class LongitudinalPlanner: self.mpc.set_weights(prev_accel_constraint) self.mpc.set_accel_limits(accel_limits_turns[0], accel_limits_turns[1]) self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired) - x, v, a, j = self.parse_model(sm['modelV2']) + x, v, a, j = self.parse_model(sm['modelV2'], self.v_model_error) self.mpc.update(sm['carState'], sm['radarState'], v_cruise, x, v, a, j) self.v_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC, self.mpc.v_solution) diff --git a/selfdrive/modeld/models/driving.cc b/selfdrive/modeld/models/driving.cc index cc4a83de62..4015731c42 100644 --- a/selfdrive/modeld/models/driving.cc +++ b/selfdrive/modeld/models/driving.cc @@ -337,6 +337,17 @@ void fill_model(cereal::ModelDataV2::Builder &framed, const ModelOutput &net_out for (int i=0; i Date: Mon, 7 Nov 2022 18:25:39 -0800 Subject: [PATCH 19/54] [controlsd] Revert Rav4 TSS2 to PID control (#26403) * revert rav4 tss2 to pid control * Update interface.py --- selfdrive/car/toyota/interface.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 02e4caa9d6..6c360fc2c7 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -110,6 +110,19 @@ class CarInterface(CarInterfaceBase): ret.steerRatio = 14.3 tire_stiffness_factor = 0.7933 ret.mass = 3585. * CV.LB_TO_KG + STD_CARGO_KG # Average between ICE and Hybrid + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kpV = [0.6] + ret.lateralTuning.pid.kiV = [0.1] + ret.lateralTuning.pid.kf = 0.00007818594 + + # 2019+ RAV4 TSS2 uses two different steering racks and specific tuning seems to be necessary. + # See https://github.com/commaai/openpilot/pull/21429#issuecomment-873652891 + for fw in car_fw: + if fw.ecu == "eps" and (fw.fwVersion.startswith(b'\x02') or fw.fwVersion in [b'8965B42181\x00\x00\x00\x00\x00\x00']): + ret.lateralTuning.pid.kpV = [0.15] + ret.lateralTuning.pid.kiV = [0.05] + ret.lateralTuning.pid.kf = 0.00004 + break elif candidate in (CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2): stop_and_go = True From e971bb11c2170d8d6d66f430741d7234a77a0499 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 7 Nov 2022 22:14:47 -0800 Subject: [PATCH 20/54] Hyundai: bump safety params (#26407) * bump panda * bump panda * bump panda * update refs * bump panda * bump panda --- panda | 2 +- selfdrive/test/process_replay/ref_commit | 2 +- selfdrive/test/process_replay/test_processes.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/panda b/panda index f3fc343262..ca681ff829 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit f3fc343262818801f037e9dca1a96ca99d7e64c5 +Subproject commit ca681ff8299c91491558c0e44f4a4779dc0a2998 diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 0608a6d14b..3120b8a7cf 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -2991a54ea491633f93fae76da4f5f1d265ce311a \ No newline at end of file +cf8700aa252d55d4d5b9f5bec136e34151c2de61 \ No newline at end of file diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py index 5c754d9312..c58909bf7f 100755 --- a/selfdrive/test/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -18,7 +18,7 @@ from tools.lib.logreader import LogReader source_segments = [ ("BODY", "937ccb7243511b65|2022-05-24--16-03-09--1"), # COMMA.BODY ("HYUNDAI", "02c45f73a2e5c6e9|2021-01-01--19-08-22--1"), # HYUNDAI.SONATA - ("HYUNDAI2", "d545129f3ca90f28|2022-10-19--09-22-54--9"), # HYUNDAI.KIA_EV6 + ("HYUNDAI2", "d545129f3ca90f28|2022-11-07--20-43-08--3"), # HYUNDAI.KIA_EV6 ("TOYOTA", "0982d79ebb0de295|2021-01-04--17-13-21--13"), # TOYOTA.PRIUS (INDI) ("TOYOTA2", "0982d79ebb0de295|2021-01-03--20-03-36--6"), # TOYOTA.RAV4 (LQR) ("TOYOTA3", "f7d7e3538cda1a2a|2021-08-16--08-55-34--6"), # TOYOTA.COROLLA_TSS2 @@ -41,7 +41,7 @@ source_segments = [ segments = [ ("BODY", "regenFA002A80700|2022-09-27--15-37-02--0"), ("HYUNDAI", "regenBE53A59065B|2022-09-27--16-52-03--0"), - ("HYUNDAI2", "d545129f3ca90f28|2022-10-19--09-22-54--9"), + ("HYUNDAI2", "d545129f3ca90f28|2022-11-07--20-43-08--3"), ("TOYOTA", "regen929C5790007|2022-09-27--16-27-47--0"), ("TOYOTA2", "regenEA3950D7F22|2022-09-27--15-43-24--0"), ("TOYOTA3", "regen89026F6BD8D|2022-09-27--15-45-37--0"), From d62cdc400ce5f49b22ac42d5e9b74398e7c636b6 Mon Sep 17 00:00:00 2001 From: Jason Wen <47793918+sunnyhaibin@users.noreply.github.com> Date: Tue, 8 Nov 2022 02:03:36 -0500 Subject: [PATCH 21/54] HKG: Car Port for Genesis GV70 2022 (#26373) * HKG: Car Port for Genesis GV70 2023 thanks to @zunichky! Co-authored-by: kyle zunich * Update docs * Update selfdrive/car/hyundai/values.py * GV70 does radar SCC, separate them * One more * bump panda * Gate 0x1A0 away from bus 6 * Can't leave out the OG * EV6 non-HDA2 too? * bump panda * bump panda * Check 0x1a0 based on param * bump panda * bump panda * bit simpler * fix bit op * fixes * bump panda to master * cmt * flip Co-authored-by: kyle zunich Co-authored-by: Shane Smiskol --- RELEASES.md | 1 + docs/CARS.md | 3 ++- panda | 2 +- selfdrive/car/hyundai/carstate.py | 16 +++++++++------- selfdrive/car/hyundai/interface.py | 10 +++++++++- selfdrive/car/hyundai/values.py | 17 ++++++++++++++++- selfdrive/car/tests/routes.py | 1 + selfdrive/car/torque_data/override.yaml | 1 + 8 files changed, 40 insertions(+), 11 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 83b3ac46f4..4103361b93 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -15,6 +15,7 @@ Version 0.8.17 (2022-XX-XX) * Added button to bookmark events while driving; view them later in comma connect * AGNOS 6 * tools: new and improved cabana thanks to deanlee! +* Genesis GV70 2022-23 support thanks to zunichky and sunnyhaibin! * Hyundai Santa Cruz 2021-22 support thanks to sunnyhaibin! * Kia Sportage 2023 support thanks to sunnyhaibin! * Kia Sportage Hybrid 2023 support thanks to sunnyhaibin! diff --git a/docs/CARS.md b/docs/CARS.md index 7066b94f61..04f7712016 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -4,7 +4,7 @@ A supported vehicle is one that just works when you install a comma three. All supported cars provide a better experience than any stock system. -# 213 Supported Cars +# 214 Supported Cars |Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Harness| |---|---|---|:---:|:---:|:---:|:---:|:---:|:---:| @@ -31,6 +31,7 @@ A supported vehicle is one that just works when you install a comma three. All s |Genesis|G70 2020|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai F| |Genesis|G80 2017-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| |Genesis|G90 2017-18|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|Genesis|GV70 2022-23|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L| |GMC|Acadia 2018[3](#footnotes)|Adaptive Cruise Control (ACC)|openpilot|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|OBD-II| |GMC|Sierra 1500 2020-21|Driver Alert Package II|openpilot available[1](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|GM| |Honda|Accord 2018-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| diff --git a/panda b/panda index ca681ff829..1ccdff90c5 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit ca681ff8299c91491558c0e44f4a4779dc0a2998 +Subproject commit 1ccdff90c564154489a3394691a4830a4ae19027 diff --git a/selfdrive/car/hyundai/carstate.py b/selfdrive/car/hyundai/carstate.py index 7cf1515fda..2c309fa0df 100644 --- a/selfdrive/car/hyundai/carstate.py +++ b/selfdrive/car/hyundai/carstate.py @@ -200,7 +200,7 @@ class CarState(CarStateBase): self.is_metric = cp.vl["CLUSTER_INFO"]["DISTANCE_UNIT"] != 1 if not self.CP.openpilotLongitudinalControl: speed_factor = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS - cp_cruise_info = cp if self.CP.flags & HyundaiFlags.CANFD_HDA2 else cp_cam + cp_cruise_info = cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp ret.cruiseState.speed = cp_cruise_info.vl["SCC_CONTROL"]["VSetDis"] * speed_factor ret.cruiseState.standstill = cp_cruise_info.vl["SCC_CONTROL"]["CRUISE_STANDSTILL"] == 1 ret.cruiseState.enabled = cp_cruise_info.vl["SCC_CONTROL"]["ACCMode"] in (1, 2) @@ -467,7 +467,7 @@ class CarState(CarStateBase): ("BLINDSPOTS_REAR_CORNERS", 20), ] - if CP.flags & HyundaiFlags.CANFD_HDA2 and not CP.openpilotLongitudinalControl: + if not (CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value) and not CP.openpilotLongitudinalControl: signals += [ ("ACCMode", "SCC_CONTROL"), ("VSetDis", "SCC_CONTROL"), @@ -504,11 +504,13 @@ class CarState(CarStateBase): @staticmethod def get_cam_can_parser_canfd(CP): + signals = [] + checks = [] if CP.flags & HyundaiFlags.CANFD_HDA2: - signals = [(f"BYTE{i}", "CAM_0x2a4") for i in range(3, 24)] - checks = [("CAM_0x2a4", 20)] - else: - signals = [ + signals += [(f"BYTE{i}", "CAM_0x2a4") for i in range(3, 24)] + checks += [("CAM_0x2a4", 20)] + elif CP.flags & HyundaiFlags.CANFD_CAMERA_SCC: + signals += [ ("COUNTER", "SCC_CONTROL"), ("NEW_SIGNAL_1", "SCC_CONTROL"), ("MainMode_ACC", "SCC_CONTROL"), @@ -521,7 +523,7 @@ class CarState(CarStateBase): ("VSetDis", "SCC_CONTROL"), ] - checks = [ + checks += [ ("SCC_CONTROL", 50), ] diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index 6c8d0076f1..0306f7e104 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -2,7 +2,7 @@ from cereal import car from panda import Panda from common.conversions import Conversions as CV -from selfdrive.car.hyundai.values import HyundaiFlags, CAR, DBC, CANFD_CAR, CAMERA_SCC_CAR, EV_CAR, HYBRID_CAR, LEGACY_SAFETY_MODE_CAR, Buttons, CarControllerParams +from selfdrive.car.hyundai.values import HyundaiFlags, CAR, DBC, CANFD_CAR, CAMERA_SCC_CAR, CANFD_RADAR_SCC_CAR, EV_CAR, HYBRID_CAR, LEGACY_SAFETY_MODE_CAR, Buttons, CarControllerParams from selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR from selfdrive.car import STD_CARGO_KG, create_button_event, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase @@ -44,6 +44,8 @@ class CarInterface(CarInterfaceBase): # ICE cars do not have 0x130; GEARS message on 0x40 instead if 0x130 not in fingerprint[4]: ret.flags |= HyundaiFlags.CANFD_ALT_GEARS.value + if candidate not in CANFD_RADAR_SCC_CAR: + ret.flags |= HyundaiFlags.CANFD_CAMERA_SCC.value ret.steerActuatorDelay = 0.1 # Default delay ret.steerLimitTimer = 0.4 @@ -200,6 +202,10 @@ class CarInterface(CarInterfaceBase): ret.mass = 3673.0 * CV.LB_TO_KG + STD_CARGO_KG ret.wheelbase = 2.83 ret.steerRatio = 12.9 + elif candidate == CAR.GENESIS_GV70_1ST_GEN: + ret.mass = 1950. + STD_CARGO_KG + ret.wheelbase = 2.87 + ret.steerRatio = 14.6 elif candidate == CAR.GENESIS_G80: ret.mass = 2060. + STD_CARGO_KG ret.wheelbase = 3.01 @@ -244,6 +250,8 @@ class CarInterface(CarInterfaceBase): ret.safetyConfigs[1].safetyParam |= Panda.FLAG_HYUNDAI_CANFD_HDA2 if ret.flags & HyundaiFlags.CANFD_ALT_BUTTONS: ret.safetyConfigs[1].safetyParam |= Panda.FLAG_HYUNDAI_CANFD_ALT_BUTTONS + if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC: + ret.safetyConfigs[1].safetyParam |= Panda.FLAG_HYUNDAI_CAMERA_SCC else: if candidate in LEGACY_SAFETY_MODE_CAR: # these cars require a special panda safety mode due to missing counters and checksums in the messages diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 4b2ef474b8..e5ddc5cac7 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -48,6 +48,7 @@ class HyundaiFlags(IntFlag): CANFD_HDA2 = 1 CANFD_ALT_BUTTONS = 2 CANFD_ALT_GEARS = 4 + CANFD_CAMERA_SCC = 8 class CAR: @@ -100,6 +101,7 @@ class CAR: # Genesis GENESIS_G70 = "GENESIS G70 2018" GENESIS_G70_2020 = "GENESIS G70 2020" + GENESIS_GV70_1ST_GEN = "GENESIS GV70 1ST GEN" GENESIS_G80 = "GENESIS G80 2017" GENESIS_G90 = "GENESIS G90 2017" @@ -188,6 +190,7 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = { # Genesis CAR.GENESIS_G70: HyundaiCarInfo("Genesis G70 2018-19", "All", harness=Harness.hyundai_f), CAR.GENESIS_G70_2020: HyundaiCarInfo("Genesis G70 2020", "All", harness=Harness.hyundai_f), + CAR.GENESIS_GV70_1ST_GEN: HyundaiCarInfo("Genesis GV70 2022-23", "All", harness=Harness.hyundai_l), CAR.GENESIS_G80: HyundaiCarInfo("Genesis G80 2017-19", "All", harness=Harness.hyundai_h), CAR.GENESIS_G90: HyundaiCarInfo("Genesis G90 2017-18", "All", harness=Harness.hyundai_c), } @@ -1423,6 +1426,14 @@ FW_VERSIONS = { b'\xf1\x00NQ5__ 1.00 1.03 99110-P1000 ', ], }, + CAR.GENESIS_GV70_1ST_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.04 99211-AR000 210204', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JK1_ SCC FHCUP 1.00 1.02 99110-AR000 ', + ], + }, } CHECKSUM = { @@ -1440,7 +1451,10 @@ FEATURES = { "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, 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, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022}, } -CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN, CAR.SANTA_CRUZ_1ST_GEN, CAR.KIA_SPORTAGE_5TH_GEN} +CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN, CAR.SANTA_CRUZ_1ST_GEN, CAR.KIA_SPORTAGE_5TH_GEN, CAR.GENESIS_GV70_1ST_GEN} + +# The radar does SCC on these cars when HDA I, rather than the camera +CANFD_RADAR_SCC_CAR = {CAR.GENESIS_GV70_1ST_GEN, } # The camera does SCC on these cars, rather than the radar CAMERA_SCC_CAR = {CAR.KONA_EV_2022, } @@ -1500,4 +1514,5 @@ DBC = { CAR.SANTA_CRUZ_1ST_GEN: dbc_dict('hyundai_canfd', None), CAR.KIA_SPORTAGE_5TH_GEN: dbc_dict('hyundai_canfd', None), CAR.KIA_SPORTAGE_HYBRID_5TH_GEN: dbc_dict('hyundai_canfd', None), + CAR.GENESIS_GV70_1ST_GEN: dbc_dict('hyundai_canfd', None), } diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py index bf949d3492..d0051454a6 100644 --- a/selfdrive/car/tests/routes.py +++ b/selfdrive/car/tests/routes.py @@ -81,6 +81,7 @@ routes = [ CarTestRoute("6fe86b4e410e4c37|2020-07-22--16-27-13", HYUNDAI.HYUNDAI_GENESIS), CarTestRoute("70c5bec28ec8e345|2020-08-08--12-22-23", HYUNDAI.GENESIS_G70), + CarTestRoute("ca4de5b12321bd98|2022-10-18--21-15-59", HYUNDAI.GENESIS_GV70_1ST_GEN), CarTestRoute("6b301bf83f10aa90|2020-11-22--16-45-07", HYUNDAI.GENESIS_G80), CarTestRoute("f0709d2bc6ca451f|2022-10-15--08-13-54", HYUNDAI.SANTA_CRUZ_1ST_GEN), CarTestRoute("4dbd55df87507948|2022-03-01--09-45-38", HYUNDAI.SANTA_FE), diff --git a/selfdrive/car/torque_data/override.yaml b/selfdrive/car/torque_data/override.yaml index c5a316aaaf..2ef5a1cd0f 100644 --- a/selfdrive/car/torque_data/override.yaml +++ b/selfdrive/car/torque_data/override.yaml @@ -34,6 +34,7 @@ HYUNDAI TUCSON HYBRID 4TH GEN: [2.5, 2.5, 0.0] HYUNDAI SANTA CRUZ 1ST GEN: [2.7, 2.7, 0.0] KIA SPORTAGE 5TH GEN: [2.7, 2.7, 0.0] KIA SPORTAGE HYBRID 5TH GEN: [2.5, 2.5, 0.0] +GENESIS GV70 1ST GEN: [2.42, 2.42, 0.01] # Dashcam or fallback configured as ideal car mock: [10.0, 10, 0.0] From 52a644e6564582632559255230c82b550db50c76 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 8 Nov 2022 00:03:23 -0800 Subject: [PATCH 22/54] Toyota: add hysteresis to cluster speed (#26386) * add hysteresis to cluster speed * add minimum cluster scaling * fix * Update ref_commit --- selfdrive/car/toyota/carstate.py | 2 ++ selfdrive/test/process_replay/ref_commit | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index 4758149916..a959633281 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -15,6 +15,8 @@ class CarState(CarStateBase): can_define = CANDefine(DBC[CP.carFingerprint]["pt"]) self.shifter_values = can_define.dv["GEAR_PACKET"]["GEAR"] self.eps_torque_scale = EPS_SCALE[CP.carFingerprint] / 100. + self.cluster_speed_hyst_gap = CV.KPH_TO_MS / 2. + self.cluster_min_speed = CV.KPH_TO_MS / 2. # On cars with cp.vl["STEER_TORQUE_SENSOR"]["STEER_ANGLE"] # the signal is zeroed to where the steering angle is at start. diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 3120b8a7cf..08eb063d41 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -cf8700aa252d55d4d5b9f5bec136e34151c2de61 \ No newline at end of file +caa8fb2a046a6c2c186e66af339212a5fae6b7a4 From 5960ba5def7c42b3944f96cf103a0c4a6e633754 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 8 Nov 2022 12:49:22 -0800 Subject: [PATCH 23/54] UI: widecam only in e2e mode (#26412) --- selfdrive/ui/qt/onroad.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index b4925c2f73..15672d33c1 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -567,6 +567,7 @@ void AnnotatedCameraWidget::paintGL() { } else if (v_ego > 15) { wide_cam_requested = false; } + wide_cam_requested = wide_cam_requested && s->scene.end_to_end_long; // TODO: also detect when ecam vision stream isn't available // for replay of old routes, never go to widecam wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid; From 8ba9a5107b353cc0fc5ab3bbab589b70c2fe9aaa Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 8 Nov 2022 13:21:07 -0800 Subject: [PATCH 24/54] boardd: SPI support (#26374) * spi handle * put usb back * handle eintr Co-authored-by: Comma Device --- common/util.cc | 9 ++ common/util.h | 1 + release/files_common | 1 + selfdrive/boardd/SConscript | 4 +- selfdrive/boardd/panda.cc | 6 +- selfdrive/boardd/panda_comms.h | 22 +++ selfdrive/boardd/spi.cc | 252 +++++++++++++++++++++++++++++++ system/hardware/tici/hardware.py | 3 + 8 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 selfdrive/boardd/spi.cc diff --git a/common/util.cc b/common/util.cc index b6a8322a27..010fe8a11a 100644 --- a/common/util.cc +++ b/common/util.cc @@ -1,5 +1,6 @@ #include "common/util.h" +#include #include #include @@ -149,6 +150,14 @@ int safe_fflush(FILE *stream) { return ret; } +int safe_ioctl(int fd, unsigned long request, void *argp) { + int ret; + do { + ret = ioctl(fd, request, argp); + } while ((ret == -1) && (errno == EINTR)); + return ret; +} + std::string readlink(const std::string &path) { char buff[4096]; ssize_t len = ::readlink(path.c_str(), buff, sizeof(buff)-1); diff --git a/common/util.h b/common/util.h index e13f4dc130..b46f7bde4a 100644 --- a/common/util.h +++ b/common/util.h @@ -86,6 +86,7 @@ int write_file(const char* path, const void* data, size_t size, int flags = O_WR FILE* safe_fopen(const char* filename, const char* mode); size_t safe_fwrite(const void * ptr, size_t size, size_t count, FILE * stream); int safe_fflush(FILE *stream); +int safe_ioctl(int fd, unsigned long request, void *argp); std::string readlink(const std::string& path); bool file_exists(const std::string& fn); diff --git a/release/files_common b/release/files_common index 61d16a2088..26662f1ef1 100644 --- a/release/files_common +++ b/release/files_common @@ -90,6 +90,7 @@ selfdrive/boardd/boardd_api_impl.pyx selfdrive/boardd/can_list_to_can_capnp.cc selfdrive/boardd/panda.cc selfdrive/boardd/panda.h +selfdrive/boardd/spi.cc selfdrive/boardd/panda_comms.h selfdrive/boardd/panda_comms.cc selfdrive/boardd/set_time.py diff --git a/selfdrive/boardd/SConscript b/selfdrive/boardd/SConscript index 356b5de663..d99e67a9f0 100644 --- a/selfdrive/boardd/SConscript +++ b/selfdrive/boardd/SConscript @@ -1,9 +1,9 @@ Import('env', 'envCython', 'common', 'cereal', 'messaging') libs = ['usb-1.0', common, cereal, messaging, 'pthread', 'zmq', 'capnp', 'kj'] -env.Program('boardd', ['main.cc', 'boardd.cc', 'panda.cc', 'panda_comms.cc'], LIBS=libs) +env.Program('boardd', ['main.cc', 'boardd.cc', 'panda.cc', 'panda_comms.cc', 'spi.cc'], LIBS=libs) env.Library('libcan_list_to_can_capnp', ['can_list_to_can_capnp.cc']) envCython.Program('boardd_api_impl.so', 'boardd_api_impl.pyx', LIBS=["can_list_to_can_capnp", 'capnp', 'kj'] + envCython["LIBS"]) if GetOption('test'): - env.Program('tests/test_boardd_usbprotocol', ['tests/test_boardd_usbprotocol.cc', 'panda.cc', 'panda_comms.cc'], LIBS=libs) + env.Program('tests/test_boardd_usbprotocol', ['tests/test_boardd_usbprotocol.cc', 'panda.cc', 'panda_comms.cc', 'spi.cc'], LIBS=libs) diff --git a/selfdrive/boardd/panda.cc b/selfdrive/boardd/panda.cc index e68558632e..deccee3e76 100644 --- a/selfdrive/boardd/panda.cc +++ b/selfdrive/boardd/panda.cc @@ -12,7 +12,11 @@ Panda::Panda(std::string serial, uint32_t bus_offset) : bus_offset(bus_offset) { // TODO: support SPI here one day... - handle = std::make_unique(serial); + if (serial.find("spi") != std::string::npos) { + handle = std::make_unique(serial); + } else { + handle = std::make_unique(serial); + } hw_type = get_hw_type(); diff --git a/selfdrive/boardd/panda_comms.h b/selfdrive/boardd/panda_comms.h index c5143b16b3..08d0c1a2af 100644 --- a/selfdrive/boardd/panda_comms.h +++ b/selfdrive/boardd/panda_comms.h @@ -8,6 +8,7 @@ #include #define TIMEOUT 0 +#define SPI_BUF_SIZE 1024 // comms base class @@ -49,3 +50,24 @@ private: std::vector recv_buf; void handle_usb_issue(int err, const char func[]); }; + +class PandaSpiHandle : public PandaCommsHandle { +public: + PandaSpiHandle(std::string serial); + ~PandaSpiHandle(); + int control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout=TIMEOUT); + int control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout=TIMEOUT); + int bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT); + int bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT); + void cleanup(); + + static std::vector list(); + +private: + int spi_fd = -1; + int spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len); + int wait_for_ack(); + + uint8_t tx_buf[SPI_BUF_SIZE]; + uint8_t rx_buf[SPI_BUF_SIZE]; +}; diff --git a/selfdrive/boardd/spi.cc b/selfdrive/boardd/spi.cc new file mode 100644 index 0000000000..1ec5e89c71 --- /dev/null +++ b/selfdrive/boardd/spi.cc @@ -0,0 +1,252 @@ +#include +#include + +#include +#include + +#include "common/util.h" +#include "common/swaglog.h" +#include "selfdrive/boardd/panda_comms.h" + + +#define SPI_SYNC 0x5AU +#define SPI_HACK 0x79U +#define SPI_DACK 0x85U +#define SPI_NACK 0x1FU +#define SPI_CHECKSUM_START 0xABU + +struct __attribute__((packed)) spi_header { + uint8_t sync; + uint8_t endpoint; + uint16_t tx_len; + uint16_t max_rx_len; +}; + +struct __attribute__((packed)) spi_control_packet { + uint16_t request; + uint16_t param1; + uint16_t param2; + uint16_t length; +}; + + +PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { + LOGD("opening SPI panda: %s", serial.c_str()); + + int err; + uint32_t spi_mode = SPI_MODE_0; + uint32_t spi_speed = 30000000; + uint8_t spi_bits_per_word = 8; + + spi_fd = open(serial.c_str(), O_RDWR); + if (spi_fd < 0) { + LOGE("failed setting SPI mode %d", err); + goto fail; + } + + // SPI settings + err = util::safe_ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode); + if (err < 0) { + LOGE("failed setting SPI mode %d", err); + goto fail; + } + + err = util::safe_ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed); + if (err < 0) { + LOGE("failed setting SPI speed"); + goto fail; + } + + err = util::safe_ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word); + if (err < 0) { + LOGE("failed setting SPI bits per word"); + goto fail; + } + + return; + +fail: + cleanup(); + throw std::runtime_error("Error connecting to panda"); +} + +PandaSpiHandle::~PandaSpiHandle() { + std::lock_guard lk(hw_lock); + cleanup(); +} + +void PandaSpiHandle::cleanup() { + if (spi_fd != -1) { + close(spi_fd); + spi_fd = -1; + } +} + + + +int PandaSpiHandle::control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout) { + int err; + + std::lock_guard lk(hw_lock); + do { + spi_control_packet packet = { + .request = request, + .param1 = param1, + .param2 = param2, + .length = 0 + }; + + // TODO: handle error + err = spi_transfer(0, (uint8_t *) &packet, sizeof(packet), NULL, 0); + } while (err < 0 && connected); + + return err; +} + +int PandaSpiHandle::control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout) { + int err; + + std::lock_guard lk(hw_lock); + do { + spi_control_packet packet = { + .request = request, + .param1 = param1, + .param2 = param2, + .length = length + }; + + // TODO: handle error + err = spi_transfer(0, (uint8_t *) &packet, sizeof(packet), data, length); + } while (err < 0 && connected); + + return err; +} + +int PandaSpiHandle::bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { + return 0; +} + +int PandaSpiHandle::bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { + return 0; +} + +std::vector PandaSpiHandle::list() { + // TODO: list all pandas available over SPI + return {}; +} + + + +void add_checksum(uint8_t *data, int data_len) { + data[data_len] = SPI_CHECKSUM_START; + for (int i=0; i < data_len; i++) { + data[data_len] ^= data[i]; + } +} + + +int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len) { + int ret; + uint16_t rx_data_len; + + // needs to be less, since we need to have space for the checksum + assert(tx_len < SPI_BUF_SIZE); + assert(max_rx_len < SPI_BUF_SIZE); + + spi_header header = { + .sync = SPI_SYNC, + .endpoint = endpoint, + .tx_len = tx_len, + .max_rx_len = max_rx_len + }; + + spi_ioc_transfer transfer = { + .tx_buf = (uint64_t)tx_buf, + .rx_buf = (uint64_t)rx_buf + }; + + // Send header + memcpy(tx_buf, &header, sizeof(header)); + add_checksum(tx_buf, sizeof(header)); + transfer.len = sizeof(header) + 1; + ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); + if (ret < 0) { + LOGE("SPI: failed to send header"); + goto transfer_fail; + } + + // Wait for (N)ACK + tx_buf[0] = 0x12; + transfer.len = 1; + while (true) { + ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); + if (ret < 0) { + LOGE("SPI: failed to send ACK request"); + goto transfer_fail; + } + + if (rx_buf[0] == SPI_HACK) { + break; + } else if (rx_buf[0] == SPI_NACK) { + LOGW("SPI: got header NACK"); + goto transfer_fail; + } + } + + // Send data + if (tx_data != NULL) { + memcpy(tx_buf, tx_data, tx_len); + } + add_checksum(tx_buf, tx_len); + transfer.len = tx_len + 1; + ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); + if (ret < 0) { + LOGE("SPI: failed to send data"); + goto transfer_fail; + } + + // Wait for (N)ACK + tx_buf[0] = 0xab; + transfer.len = 1; + while (true) { + ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); + if (ret < 0) { + LOGE("SPI: failed to send ACK request"); + goto transfer_fail; + } + + if (rx_buf[0] == SPI_DACK) { + break; + } else if (rx_buf[0] == SPI_NACK) { + LOGE("SPI: got data NACK"); + goto transfer_fail; + } + } + + // Read data len + transfer.len = 2; + ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); + if (ret < 0) { + LOGE("SPI: failed to read rx data len"); + goto transfer_fail; + } + rx_data_len = *(uint16_t *)rx_buf; + assert(rx_data_len < SPI_BUF_SIZE); + + // Read data + transfer.len = rx_data_len + 1; + ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); + if (ret < 0) { + LOGE("SPI: failed to read rx data"); + goto transfer_fail; + } + // TODO: check checksum + + if (rx_data != NULL) { + memcpy(rx_data, rx_buf, rx_data_len); + } + ret = rx_data_len; + +transfer_fail: + return ret; +} diff --git a/system/hardware/tici/hardware.py b/system/hardware/tici/hardware.py index e2fd20c1be..c5b931ddae 100644 --- a/system/hardware/tici/hardware.py +++ b/system/hardware/tici/hardware.py @@ -431,6 +431,9 @@ class Tici(HardwareBase): def initialize_hardware(self): self.amplifier.initialize_configuration() + # TODO: this should go in AGNOS + os.system("sudo chmod 666 /dev/spidev0.0") + # Allow thermald to write engagement status to kmsg os.system("sudo chmod a+w /dev/kmsg") From 4ec1c7e614a2ca3fbf38f302a82b87d112d06b02 Mon Sep 17 00:00:00 2001 From: Kurt Nistelberger Date: Tue, 8 Nov 2022 22:51:16 +0100 Subject: [PATCH 25/54] CI: camera box update (#26414) * check if all frames are laggy * apply tolerance Co-authored-by: Kurt Nistelberger --- system/camerad/test/test_camerad.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/system/camerad/test/test_camerad.py b/system/camerad/test/test_camerad.py index 3c6d466a69..6c2ef1c7bc 100755 --- a/system/camerad/test/test_camerad.py +++ b/system/camerad/test/test_camerad.py @@ -11,7 +11,7 @@ from system.hardware import TICI TEST_TIMESPAN = 30 LAG_FRAME_TOLERANCE = {log.FrameData.ImageSensor.ar0321: 0.5, # ARs use synced pulses for frame starts - log.FrameData.ImageSensor.ox03c10: 1.0} # OXs react to out-of-sync at next frame + log.FrameData.ImageSensor.ox03c10: 1.0} # OXs react to out-of-sync at next frame CAMERAS = ('roadCameraState', 'driverCameraState', 'wideRoadCameraState') @@ -68,12 +68,17 @@ class TestCamerad(unittest.TestCase): frame_times = {frame_id: [getattr(m, m.which()).timestampSof for m in msgs] for frame_id, msgs in self.log_by_frame_id.items()} diffs = {frame_id: (max(ts) - min(ts))/1e6 for frame_id, ts in frame_times.items()} - def get_desc(fid, diff): cam_times = [(m.which(), getattr(m, m.which()).timestampSof/1e6) for m in self.log_by_frame_id[fid]] - return f"{diff=} {cam_times=}" + return (diff, cam_times) laggy_frames = {k: get_desc(k, v) for k, v in diffs.items() if v > LAG_FRAME_TOLERANCE[sensor_type]} - assert len(laggy_frames) == 0, f"Frames not synced properly: {laggy_frames=}" + + def in_tol(diff): + return 50 - LAG_FRAME_TOLERANCE[sensor_type] < diff and diff < 50 + LAG_FRAME_TOLERANCE[sensor_type] + if len(laggy_frames) != 0 and all( in_tol(laggy_frames[lf][0]) for lf in laggy_frames): + print("TODO: handle camera out of sync") + else: + assert len(laggy_frames) == 0, f"Frames not synced properly: {laggy_frames=}" if __name__ == "__main__": unittest.main() From 1181efb288db18420e5a376ed5dba53eadf8c2cb Mon Sep 17 00:00:00 2001 From: Kurt Nistelberger Date: Tue, 8 Nov 2022 23:01:07 +0100 Subject: [PATCH 26/54] CI: update qcom tests (#26404) update qcom tests Co-authored-by: Kurt Nistelberger --- tools/gpstest/test_gps_qcom.py | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/tools/gpstest/test_gps_qcom.py b/tools/gpstest/test_gps_qcom.py index 0909316c5e..b3ce93fc81 100644 --- a/tools/gpstest/test_gps_qcom.py +++ b/tools/gpstest/test_gps_qcom.py @@ -40,14 +40,10 @@ class TestGPS(unittest.TestCase): if ublox_available: raise unittest.SkipTest - @unittest.skip("Skip cold start test due to time") - def test_quectel_cold_start(self): + def test_a_quectel_cold_start(self): # delete assistance data to enforce cold start for GNSS # testing shows that this takes up to 20min - # invalidate supl setting, cannot be reset - _, err = exec_mmcli("--location-set-supl-server=unittest:1") - _, err = exec_mmcli("--command='AT+QGPSDEL=0'") assert len(err) == 0, f"GPSDEL failed: {err}" @@ -55,27 +51,6 @@ class TestGPS(unittest.TestCase): start_time = time.monotonic() glo = messaging.sub_sock("gpsLocation", timeout=0.1) - timeout = 10*60*25 # 25 minute - timedout = wait_for_location(glo, timeout) - managed_processes['rawgpsd'].stop() - - assert timedout is False, "Waiting for location timed out (25min)!" - - duration = time.monotonic() - start_time - assert duration < 50, f"Received GPS location {duration}!" - - - def test_a_quectel_cold_start_AGPS(self): - _, err = exec_mmcli("--command='AT+QGPSDEL=0'") - assert len(err) == 0, f"GPSDEL failed: {err}" - - # setup AGPS - exec_mmcli("--location-set-supl-server=supl.google.com:7276") - - managed_processes['rawgpsd'].start() - start_time = time.monotonic() - glo = messaging.sub_sock("gpsLocation", timeout=0.1) - timeout = 10*60*3 # 3 minute timedout = wait_for_location(glo, timeout) managed_processes['rawgpsd'].stop() @@ -87,15 +62,11 @@ class TestGPS(unittest.TestCase): def test_b_quectel_startup(self): - - # setup AGPS - exec_mmcli("--location-set-supl-server=supl.google.com:7276") - managed_processes['rawgpsd'].start() start_time = time.monotonic() glo = messaging.sub_sock("gpsLocation", timeout=0.1) - timeout = 10*60*3 # 3 minute + timeout = 10*60 # 1 minute timedout = wait_for_location(glo, timeout) managed_processes['rawgpsd'].stop() From 9a3f46805104c4bcb5cffa304b9b322874ccf412 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 8 Nov 2022 14:45:01 -0800 Subject: [PATCH 27/54] experimental mode (#26416) * experimental mode * rename param * red lights --- RELEASES.md | 8 +++- common/params.cc | 2 +- selfdrive/controls/controlsd.py | 2 +- .../controls/lib/longitudinal_planner.py | 2 +- selfdrive/controls/tests/test_cruise_speed.py | 2 +- .../controls/tests/test_following_distance.py | 2 +- .../test_longitudinal.py | 4 +- selfdrive/ui/qt/offroad/settings.cc | 41 +++++++++++-------- selfdrive/ui/qt/onroad.cc | 4 +- selfdrive/ui/translations/main_ja.ts | 24 +++++------ selfdrive/ui/translations/main_ko.ts | 24 +++++------ selfdrive/ui/translations/main_pt-BR.ts | 24 +++++------ selfdrive/ui/translations/main_zh-CHS.ts | 24 +++++------ selfdrive/ui/translations/main_zh-CHT.ts | 24 +++++------ selfdrive/ui/ui.cc | 2 +- selfdrive/ui/ui.h | 2 +- 16 files changed, 101 insertions(+), 90 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 4103361b93..e175050eaf 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,9 +1,13 @@ -Version 0.8.17 (2022-XX-XX) +Version 0.8.17 (2022-11-XX) ======================== * New driving model * Internal feature space accuracy increased tenfold during training, this makes the model dramatically more accurate. * New driver monitoring model * New end-to-end distracted trigger +* Experimental driving mode + * End-to-end longitudinal control + * Stops for red lights and stop signs + * openpilot defaults to chill mode, enable experimental in settings * Self-tuning torque lateral controller parameters * Parameters learned live for each car * Torque controller used on all Toyota, Lexus, Hyundai, Kia, and Genesis models @@ -12,7 +16,7 @@ Version 0.8.17 (2022-XX-XX) * Matched speeds shown on car's dash * Improved update experience * Border turns grey while overriding steering - * Added button to bookmark events while driving; view them later in comma connect + * Bookmark events while driving; view them in comma connect * AGNOS 6 * tools: new and improved cabana thanks to deanlee! * Genesis GV70 2022-23 support thanks to zunichky and sunnyhaibin! diff --git a/common/params.cc b/common/params.cc index 155bc88487..e17d1f1b13 100644 --- a/common/params.cc +++ b/common/params.cc @@ -102,7 +102,7 @@ std::unordered_map keys = { {"DashcamOverride", PERSISTENT}, {"DisableLogging", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON}, {"DisablePowerDown", PERSISTENT}, - {"EndToEndLong", PERSISTENT}, + {"ExperimentalMode", PERSISTENT}, {"ExperimentalLongitudinalEnabled", PERSISTENT}, // WARNING: THIS MAY DISABLE AEB {"DisableUpdates", PERSISTENT}, {"DisengageOnAccelerator", PERSISTENT}, diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 1adbba4171..0bdaadf6ef 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -147,7 +147,7 @@ class Controls: if not self.CP.experimentalLongitudinalAvailable: self.params.remove("ExperimentalLongitudinalEnabled") if not self.CP.openpilotLongitudinalControl: - self.params.remove("EndToEndLong") + self.params.remove("ExperimentalMode") self.CC = car.CarControl.new_message() self.CS_prev = car.CarState.new_message() diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 19ea40a8f4..2fa13bfb15 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -66,7 +66,7 @@ class LongitudinalPlanner: self.solverExecutionTime = 0.0 def read_param(self): - e2e = self.params.get_bool('EndToEndLong') and self.CP.openpilotLongitudinalControl + e2e = self.params.get_bool('ExperimentalMode') and self.CP.openpilotLongitudinalControl self.mpc.mode = 'blended' if e2e else 'acc' def parse_model(self, model_msg, model_error): diff --git a/selfdrive/controls/tests/test_cruise_speed.py b/selfdrive/controls/tests/test_cruise_speed.py index a972bfb073..ca070f1c3f 100644 --- a/selfdrive/controls/tests/test_cruise_speed.py +++ b/selfdrive/controls/tests/test_cruise_speed.py @@ -26,7 +26,7 @@ class TestCruiseSpeed(unittest.TestCase): def test_cruise_speed(self): params = Params() for e2e in [False, True]: - params.put_bool("EndToEndLong", e2e) + params.put_bool("ExperimentalMode", e2e) for speed in np.arange(5, 40, 5): print(f'Testing {speed} m/s') cruise_speed = float(speed) diff --git a/selfdrive/controls/tests/test_following_distance.py b/selfdrive/controls/tests/test_following_distance.py index 3534f58235..0535caab84 100644 --- a/selfdrive/controls/tests/test_following_distance.py +++ b/selfdrive/controls/tests/test_following_distance.py @@ -27,7 +27,7 @@ class TestFollowingDistance(unittest.TestCase): def test_following_distance(self): params = Params() for e2e in [False, True]: - params.put_bool("EndToEndLong", e2e) + params.put_bool("ExperimentalMode", e2e) for speed in np.arange(0, 40, 5): print(f'Testing {speed} m/s') v_lead = float(speed) diff --git a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py index c7c2915878..7cc95b104a 100755 --- a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py +++ b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py @@ -143,11 +143,11 @@ def run_maneuver_worker(k): params = Params() man = maneuvers[k] - params.put_bool("EndToEndLong", True) + params.put_bool("ExperimentalMode", True) print(man.title, ' in e2e mode') valid, _ = man.evaluate() self.assertTrue(valid, msg=man.title) - params.put_bool("EndToEndLong", False) + params.put_bool("ExperimentalMode", False) print(man.title, ' in acc mode') valid, _ = man.evaluate() self.assertTrue(valid, msg=man.title) diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 51b5ce6bd7..29069155b2 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -36,6 +36,21 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { "../assets/offroad/icon_openpilot.png", false, }, + { + "ExperimentalMode", + tr("Experimental mode"), + "", + "../assets/offroad/icon_road.png", + false, + }, + { + "ExperimentalLongitudinalEnabled", + tr("Experimental openpilot longitudinal control"), + tr("WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.
\ + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control."), + "../assets/offroad/icon_speed_limit.png", + true, + }, { "IsLdwEnabled", tr("Enable Lane Departure Warnings"), @@ -64,20 +79,6 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { "../assets/offroad/icon_disengage_on_accelerator.svg", false, }, - { - "EndToEndLong", - tr("🌮 End-to-end longitudinal (extremely alpha) 🌮"), - "", - "../assets/offroad/icon_road.png", - false, - }, - { - "ExperimentalLongitudinalEnabled", - tr("Experimental openpilot longitudinal control"), - tr("WARNING: openpilot longitudinal control is experimental for this car and will disable AEB."), - "../assets/offroad/icon_speed_limit.png", - true, - }, #ifdef ENABLE_MAPS { "NavSettingTime24h", @@ -116,9 +117,15 @@ void TogglesPanel::showEvent(QShowEvent *event) { } void TogglesPanel::updateToggles() { - auto e2e_toggle = toggles["EndToEndLong"]; + auto e2e_toggle = toggles["ExperimentalMode"]; auto op_long_toggle = toggles["ExperimentalLongitudinalEnabled"]; - const QString e2e_description = tr("Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental."); + const QString e2e_description = tr("\ + openpilot defaults to driving in chill mode.\ + Experimental mode enables alpha-level features that aren't ready for chill mode. \ + Experimental features are listed below:\ +
\ +

🌮 End-to-End Longitudinal Control 🌮

\ + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs."); auto cp_bytes = params.get("CarParamsPersistent"); if (!cp_bytes.empty()) { @@ -140,7 +147,7 @@ void TogglesPanel::updateToggles() { } else { // no long for now e2e_toggle->setEnabled(false); - params.remove("EndToEndLong"); + params.remove("ExperimentalMode"); const QString no_long = tr("openpilot longitudinal control is not currently available for this car."); const QString exp_long = tr("Enable experimental longitudinal control to enable this."); diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 15672d33c1..37c1913743 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -461,7 +461,7 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) { // paint path QLinearGradient bg(0, height(), 0, height() / 4); float start_hue, end_hue; - if (scene.end_to_end_long) { + if (scene.experimental_mode) { const auto &acceleration = (*s->sm)["modelV2"].getModelV2().getAcceleration(); float acceleration_future = 0; if (acceleration.getZ().size() > 16) { @@ -567,7 +567,7 @@ void AnnotatedCameraWidget::paintGL() { } else if (v_ego > 15) { wide_cam_requested = false; } - wide_cam_requested = wide_cam_requested && s->scene.end_to_end_long; + wide_cam_requested = wide_cam_requested && s->scene.experimental_mode; // TODO: also detect when ecam vision stream isn't available // for replay of old routes, never go to widecam wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid; diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 5ee2d86756..039ad7b2a4 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -966,22 +966,10 @@ location set Upload data from the driver facing camera and help improve the driver monitoring algorithm. 車内カメラの映像をアップロードし、ドライバー監視システムのアルゴリズムの向上に役立てます。 - - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - 🌮 エンドツーエンドのアクセル制御 (超α版) 🌮 - Experimental openpilot longitudinal control 実験段階のopenpilotによるアクセル制御 - - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b> - <b>警告: openpilotによるアクセル制御は実験段階であり、AEBを無効化します。</b> - - - Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental. - アクセルとブレーキの制御をopenpilotに任せます。openpilotが人間と同じように運転します。最初期の実験段階です。 - openpilot longitudinal control is not currently available for this car. openpilotによるアクセル制御は、この車では現在利用できません。 @@ -1014,6 +1002,18 @@ location set Show map on left side when in split screen view. 分割画面表示の場合、ディスプレイの左側にマップを表示します。 + + Experimental mode + + + + <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. + + Updater diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index f58c4f34d5..e9b4943650 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -966,22 +966,10 @@ location set Upload data from the driver facing camera and help improve the driver monitoring algorithm. 운전자 카메라에서 데이터를 업로드하고 운전자 모니터링 알고리즘을 개선합니다. - - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - 🌮 e2e 롱컨트롤 사용 (매우 실험적) 🌮 - Experimental openpilot longitudinal control openpilot 롱컨트롤 (실험적) - - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b> - <b>경고: openpilot 롱컨트롤은 실험적인 기능으로 차량의 AEB를 비활성화합니다.</b> - - - Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental. - 주행모델이 가속과 감속을 제어하도록 하면 openpilot은 운전자가 생각하는것처럼 운전합니다. (매우 실험적) - openpilot longitudinal control is not currently available for this car. 현재 이 차량에는 openpilot 롱컨트롤을 사용할 수 없습니다. @@ -1014,6 +1002,18 @@ location set Show map on left side when in split screen view. 분할 화면 보기에서 지도를 왼쪽에 표시합니다. + + Experimental mode + + + + <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. + + Updater diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 6774555b73..a5187af50f 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -970,22 +970,10 @@ trabalho definido Upload data from the driver facing camera and help improve the driver monitoring algorithm. Upload dados da câmera voltada para o motorista e ajude a melhorar o algoritmo de monitoramentor. - - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - 🌮 End-to-end longitudinal (experimental) 🌮 - Experimental openpilot longitudinal control Controle longitudinal experimental openpilot - - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b> - <b>AVISO: o controle longitudinal openpilot é experimental para este carro e irá desabilitar AEB.</b> - - - Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental. - Deixe o modelo controlar o acelerador e os freios. openpilot irá conduzir como pensa que um humano faria. Super experimental. - openpilot longitudinal control is not currently available for this car. controle longitudinal openpilot não está disponível para este carro. @@ -1018,6 +1006,18 @@ trabalho definido Show map on left side when in split screen view. Exibir mapa do lado esquerdo quando a tela for dividida. + + Experimental mode + + + + <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. + + Updater diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 6189a235e8..44e707e49c 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -964,22 +964,10 @@ location set Upload data from the driver facing camera and help improve the driver monitoring algorithm. 上传驾驶员摄像头的数据,帮助改进驾驶员监控算法。 - - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - 🌮 端对端纵向控制(实验性功能) 🌮 - Experimental openpilot longitudinal control - - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b> - - - - Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental. - 让驾驶模型直接控制油门和刹车,openpilot将会模仿人类司机的驾驶方式。该功能仍非常实验性。 - openpilot longitudinal control is not currently available for this car. @@ -1012,6 +1000,18 @@ location set Show map on left side when in split screen view. 在分屏模式中,将地图置于屏幕左侧。 + + Experimental mode + + + + <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. + + Updater diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 0b0dbe4ae5..274cff3a5a 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -966,22 +966,10 @@ location set Upload data from the driver facing camera and help improve the driver monitoring algorithm. 上傳駕駛監控的錄像來協助我們提升駕駛監控的準確率。 - - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - 🌮 端對端縱向控制(實驗性功能) 🌮 - Experimental openpilot longitudinal control 使用 openpilot 縱向控制(實驗) - - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b> - <b>注意:這台車的 openpilot 縱向控制仍然是實驗中的功能,開啟這功能將會關閉自動緊急煞車 (AEB)。</b> - - - Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental. - 讓駕駛模型直接控製油門和剎車,openpilot將會模仿人類司機的駕駛方式。該功能仍非常實驗性。 - openpilot longitudinal control is not currently available for this car. openpilot 縱向控制目前不適用於這輛車。 @@ -1014,6 +1002,18 @@ location set Show map on left side when in split screen view. 進入分割畫面後,地圖將會顯示在畫面的左側。 + + Experimental mode + + + + <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. + + Updater diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 945218ec11..970448359e 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -174,7 +174,7 @@ void ui_update_params(UIState *s) { auto params = Params(); s->scene.is_metric = params.getBool("IsMetric"); s->scene.map_on_left = params.getBool("NavSettingLeftSide"); - s->scene.end_to_end_long = params.getBool("EndToEndLong"); + s->scene.experimental_mode = params.getBool("ExperimentalMode"); } void UIState::updateStatus() { diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index e550afd5f2..38e2ffe3ce 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -104,7 +104,7 @@ typedef struct UIScene { QPointF lead_vertices[2]; float light_sensor; - bool started, ignition, is_metric, map_on_left, longitudinal_control, end_to_end_long; + bool started, ignition, is_metric, map_on_left, longitudinal_control, experimental_mode; uint64_t started_frame; } UIScene; From 191b8081b2a9f3f9db0131edd270e40166570cfa Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 8 Nov 2022 20:52:35 -0800 Subject: [PATCH 28/54] GM Camera: use ECM brake pressed bit (#26400) * GM camera: use ECM brake pressed bit * bump panda and use more reliable bit * bump panda * back to ECMEngineStatus * bump * Update selfdrive/car/gm/carstate.py * bump panda * Update ref_commit --- panda | 2 +- selfdrive/car/gm/carstate.py | 14 +++++++++----- selfdrive/test/process_replay/ref_commit | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/panda b/panda index 1ccdff90c5..281eb7731b 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 1ccdff90c564154489a3394691a4830a4ae19027 +Subproject commit 281eb7731b4338fef049977593fdf3315adf09e9 diff --git a/selfdrive/car/gm/carstate.py b/selfdrive/car/gm/carstate.py index af69307a2c..f4b3f88e99 100644 --- a/selfdrive/car/gm/carstate.py +++ b/selfdrive/car/gm/carstate.py @@ -51,12 +51,15 @@ class CarState(CarStateBase): else: ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(pt_cp.vl["ECMPRDNL2"]["PRNDL2"], None)) - # Some Volt 2016-17 have loose brake pedal push rod retainers which causes the ECM to believe - # that the brake is being intermittently pressed without user interaction. - # To avoid a cruise fault we need to match the ECM's brake pressed signal and threshold - # https://static.nhtsa.gov/odi/tsbs/2017/MC-10137629-9999.pdf ret.brake = pt_cp.vl["ECMAcceleratorPos"]["BrakePedalPos"] - ret.brakePressed = ret.brake >= 8 + if self.CP.networkLocation == NetworkLocation.fwdCamera: + ret.brakePressed = pt_cp.vl["ECMEngineStatus"]["BrakePressed"] != 0 + else: + # Some Volt 2016-17 have loose brake pedal push rod retainers which causes the ECM to believe + # that the brake is being intermittently pressed without user interaction. + # To avoid a cruise fault we need to use a conservative brake position threshold + # https://static.nhtsa.gov/odi/tsbs/2017/MC-10137629-9999.pdf + ret.brakePressed = ret.brake >= 8 # Regen braking is braking if self.CP.transmissionType == TransmissionType.direct: @@ -154,6 +157,7 @@ class CarState(CarStateBase): ("TractionControlOn", "ESPStatus"), ("ParkBrake", "VehicleIgnitionAlt"), ("CruiseMainOn", "ECMEngineStatus"), + ("BrakePressed", "ECMEngineStatus"), ] checks = [ diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 08eb063d41..da954d76a6 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -caa8fb2a046a6c2c186e66af339212a5fae6b7a4 +372a67c524342bbf15e22f0caea08d2038973281 From 9f1fe1193c4779f692028e1b054d4c76b6e55119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Tue, 8 Nov 2022 21:57:01 -0800 Subject: [PATCH 29/54] Update RELEASES.md --- RELEASES.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index e175050eaf..18817bda4d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,7 +1,11 @@ Version 0.8.17 (2022-11-XX) ======================== * New driving model - * Internal feature space accuracy increased tenfold during training, this makes the model dramatically more accurate. + * Internal feature space information content increased tenfold during training (to ~700 bits), this makes the model dramatically more accurate + * Less reliance on previous frames makes model more reactive and snappy + * Trained in new reprojective simulator + * Model trained in openpilot was trained in 36hrs from scratch, compared to around 1 week of previous releases + * Model training now simulates lateral and longitudinal behavior, this allows openpilot to slow down for turns, stop at traffic lights, etc,... in experimental mode * New driver monitoring model * New end-to-end distracted trigger * Experimental driving mode From 34f580e75ee148398e6a44980053c20bf10f9797 Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Wed, 9 Nov 2022 04:55:37 -0500 Subject: [PATCH 30/54] VW PQ: Fix exception with openpilot longitudinal (#26417) * VW PQ: Fix exception in long control * move default value to init --- selfdrive/car/volkswagen/carstate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/volkswagen/carstate.py b/selfdrive/car/volkswagen/carstate.py index d09420cf7a..def14ab019 100644 --- a/selfdrive/car/volkswagen/carstate.py +++ b/selfdrive/car/volkswagen/carstate.py @@ -12,6 +12,7 @@ class CarState(CarStateBase): super().__init__(CP) self.CCP = CarControllerParams(CP) self.button_states = {button.event_type: False for button in self.CCP.BUTTONS} + self.esp_hold_confirmation = False def create_button_events(self, pt_cp, buttons): button_events = [] From fc872271ae73a0139be6b085b90467c2e8d83c66 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Thu, 10 Nov 2022 03:10:57 +0800 Subject: [PATCH 31/54] Cabana: add menu bar to main window (#26419) * add menu bar * show DBC name in title * cleanup --- tools/cabana/chartswidget.cc | 1 + tools/cabana/mainwin.cc | 197 ++++++++++++++--------------------- tools/cabana/mainwin.h | 36 ++----- 3 files changed, 87 insertions(+), 147 deletions(-) diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index b4d6d89e6d..812a805810 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -14,6 +14,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); // toolbar QToolBar *toolbar = new QToolBar(tr("Charts"), this); diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index d3d7ff4156..9b85ba7e8d 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -1,14 +1,17 @@ #include "tools/cabana/mainwin.h" #include +#include #include -#include #include #include #include #include -#include +#include +#include +#include #include +#include #include #include "tools/replay/util.h" @@ -18,15 +21,13 @@ void qLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const if (main_win) emit main_win->showMessage(msg, 0); } -MainWindow::MainWindow() : QWidget() { - QVBoxLayout *main_layout = new QVBoxLayout(this); - main_layout->setContentsMargins(11, 11, 11, 5); +MainWindow::MainWindow() : QMainWindow() { + setWindowTitle("Cabana"); + QWidget *central_widget = new QWidget(this); + QHBoxLayout *main_layout = new QHBoxLayout(central_widget); + main_layout->setContentsMargins(11, 11, 11, 0); main_layout->setSpacing(0); - QHBoxLayout *h_layout = new QHBoxLayout(); - h_layout->setContentsMargins(0, 0, 0, 0); - main_layout->addLayout(h_layout); - splitter = new QSplitter(Qt::Horizontal, this); splitter->setHandleWidth(11); @@ -34,7 +35,6 @@ MainWindow::MainWindow() : QWidget() { QWidget *messages_container = new QWidget(this); QVBoxLayout *messages_layout = new QVBoxLayout(messages_container); messages_layout->setContentsMargins(0, 0, 0, 0); - QHBoxLayout *dbc_file_layout = new QHBoxLayout(); dbc_combo = new QComboBox(this); auto dbc_names = dbc()->allDBCNames(); for (const auto &name : dbc_names) { @@ -42,21 +42,9 @@ MainWindow::MainWindow() : QWidget() { } dbc_combo->model()->sort(0); dbc_combo->setEditable(true); - dbc_combo->setCurrentText(QString()); dbc_combo->setInsertPolicy(QComboBox::NoInsert); dbc_combo->completer()->setCompletionMode(QCompleter::PopupCompletion); - QFont font; - font.setBold(true); - dbc_combo->lineEdit()->setFont(font); - dbc_file_layout->addWidget(dbc_combo); - - QPushButton *load_from_paste = new QPushButton(tr("Load from paste"), this); - dbc_file_layout->addWidget(load_from_paste); - - dbc_file_layout->addStretch(); - QPushButton *save_btn = new QPushButton(tr("Save DBC"), this); - dbc_file_layout->addWidget(save_btn); - messages_layout->addLayout(dbc_file_layout); + messages_layout->addWidget(dbc_combo); messages_widget = new MessagesWidget(this); messages_layout->addWidget(messages_widget); @@ -65,8 +53,7 @@ MainWindow::MainWindow() : QWidget() { charts_widget = new ChartsWidget(this); detail_widget = new DetailWidget(charts_widget, this); splitter->addWidget(detail_widget); - - h_layout->addWidget(splitter); + main_layout->addWidget(splitter); // right widgets QWidget *right_container = new QWidget(this); @@ -74,35 +61,21 @@ MainWindow::MainWindow() : QWidget() { r_layout = new QVBoxLayout(right_container); r_layout->setContentsMargins(11, 0, 0, 0); QHBoxLayout *right_hlayout = new QHBoxLayout(); - QLabel *fingerprint_label = new QLabel(this); - right_hlayout->addWidget(fingerprint_label); + fingerprint_label = new QLabel(this); + right_hlayout->addWidget(fingerprint_label, 0, Qt::AlignLeft); // TODO: click to select another route. - right_hlayout->addWidget(new QLabel(can->route())); - QPushButton *settings_btn = new QPushButton("Settings"); - right_hlayout->addWidget(settings_btn, 0, Qt::AlignRight); - + right_hlayout->addWidget(new QLabel(can->route()), 0, Qt::AlignRight); r_layout->addLayout(right_hlayout); video_widget = new VideoWidget(this); r_layout->addWidget(video_widget, 0, Qt::AlignTop); - r_layout->addWidget(charts_widget); + main_layout->addWidget(right_container); - h_layout->addWidget(right_container); - - // status bar - status_bar = new QStatusBar(this); - status_bar->setFixedHeight(20); - status_bar->setContentsMargins(0, 0, 0, 0); - status_bar->setSizeGripEnabled(true); - progress_bar = new QProgressBar(); - progress_bar->setRange(0, 100); - progress_bar->setTextVisible(true); - progress_bar->setFixedSize({230, 16}); - progress_bar->setVisible(false); - status_bar->addPermanentWidget(progress_bar); - main_layout->addWidget(status_bar); + setCentralWidget(central_widget); + createActions(); + createStatusBar(); qRegisterMetaType("uint64_t"); qRegisterMetaType("ReplyMsgType"); @@ -122,35 +95,65 @@ MainWindow::MainWindow() : QWidget() { } QObject::connect(dbc_combo, SIGNAL(activated(const QString &)), SLOT(loadDBCFromName(const QString &))); - QObject::connect(load_from_paste, &QPushButton::clicked, this, &MainWindow::loadDBCFromPaste); - QObject::connect(save_btn, &QPushButton::clicked, this, &MainWindow::saveDBC); - QObject::connect(this, &MainWindow::showMessage, status_bar, &QStatusBar::showMessage); + QObject::connect(this, &MainWindow::showMessage, statusBar(), &QStatusBar::showMessage); QObject::connect(this, &MainWindow::updateProgressBar, this, &MainWindow::updateDownloadProgress); QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, detail_widget, &DetailWidget::setMessage); QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts); QObject::connect(charts_widget, &ChartsWidget::rangeChanged, video_widget, &VideoWidget::rangeChanged); - QObject::connect(settings_btn, &QPushButton::clicked, this, &MainWindow::setOption); QObject::connect(can, &CANMessages::streamStarted, this, &MainWindow::loadDBCFromFingerprint); - QObject::connect(can, &CANMessages::streamStarted, [=]() { fingerprint_label->setText(can->carFingerprint() ); }); + QObject::connect(dbc(), &DBCManager::DBCFileChanged, [this]() { + dbc_combo->setCurrentText(QFileInfo(dbc()->name()).baseName()); + setWindowTitle(tr("%1 - Cabana").arg(dbc()->name())); + }); +} + +void MainWindow::createActions() { + QMenu *file_menu = menuBar()->addMenu(tr("&File")); + file_menu->addAction(tr("Open DBC File..."), this, &MainWindow::loadDBCFromFile); + file_menu->addAction(tr("Load DBC From Clipboard"), this, &MainWindow::loadDBCFromClipboard); + file_menu->addSeparator(); + file_menu->addAction(tr("Save DBC As..."), this, &MainWindow::saveDBCToFile); + file_menu->addAction(tr("Copy DBC To Clipboard"), this, &MainWindow::saveDBCToClipboard); + file_menu->addSeparator(); + file_menu->addAction(tr("Settings..."), this, &MainWindow::setOption); + QMenu *help_menu = menuBar()->addMenu(tr("&Help")); + help_menu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); +} + +void MainWindow::createStatusBar() { + progress_bar = new QProgressBar(); + progress_bar->setRange(0, 100); + progress_bar->setTextVisible(true); + progress_bar->setFixedSize({230, 16}); + progress_bar->setVisible(false); + statusBar()->addPermanentWidget(progress_bar); } void MainWindow::loadDBCFromName(const QString &name) { - if (name != dbc()->name()) { + if (name != dbc()->name()) dbc()->open(name); - dbc_combo->setCurrentText(name); - } } -void MainWindow::loadDBCFromPaste() { - LoadDBCDialog dlg(this); - if (dlg.exec()) { - dbc()->open("from paste", dlg.dbc_edit->toPlainText()); - dbc_combo->setCurrentText("loaded from paste"); +void MainWindow::loadDBCFromFile() { + QString file_name = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::homePath(), "DBC (*.dbc)"); + if (!file_name.isEmpty()) { + QFile file(file_name); + if (file.open(QIODevice::ReadOnly)) { + auto dbc_name = QFileInfo(file_name).baseName(); + dbc()->open(dbc_name, file.readAll()); + } } } +void MainWindow::loadDBCFromClipboard() { + QString dbc_str = QGuiApplication::clipboard()->text(); + dbc()->open("From Clipboard", dbc_str); + QMessageBox::information(this, tr("Load From Clipboard"), tr("DBC Successfully Loaded!")); +} + void MainWindow::loadDBCFromFingerprint() { auto fingerprint = can->carFingerprint(); + fingerprint_label->setText(fingerprint); if (!fingerprint.isEmpty() && dbc()->name().isEmpty()) { auto dbc_name = fingerprint_to_dbc[fingerprint]; if (dbc_name != QJsonValue::Undefined) { @@ -159,14 +162,23 @@ void MainWindow::loadDBCFromFingerprint() { } } -void MainWindow::saveDBC() { - SaveDBCDialog dlg(this); - dlg.dbc_edit->setText(dbc()->generateDBC()); - dlg.exec(); +void MainWindow::saveDBCToFile() { + QString file_name = QFileDialog::getSaveFileName(this, tr("Save File"), + QDir::homePath() + "/untitled.dbc", tr("DBC (*.dbc)")); + if (!file_name.isEmpty()) { + QFile file(file_name); + if (file.open(QIODevice::WriteOnly)) + file.write(dbc()->generateDBC().toUtf8()); + } +} + +void MainWindow::saveDBCToClipboard() { + QGuiApplication::clipboard()->setText(dbc()->generateDBC()); + QMessageBox::information(this, tr("Copy To Clipboard"), tr("DBC Successfully copied!")); } void MainWindow::updateDownloadProgress(uint64_t cur, uint64_t total, bool success) { - if (success && cur < total) { + if (success && cur < total) { progress_bar->setValue((cur / (double)total) * 100); progress_bar->setFormat(tr("Downloading %p% (%1)").arg(formattedDataSize(total).c_str())); progress_bar->show(); @@ -202,60 +214,3 @@ void MainWindow::setOption() { SettingsDlg dlg(this); dlg.exec(); } - -// LoadDBCDialog - -LoadDBCDialog::LoadDBCDialog(QWidget *parent) : QDialog(parent) { - QVBoxLayout *main_layout = new QVBoxLayout(this); - dbc_edit = new QTextEdit(this); - dbc_edit->setAcceptRichText(false); - dbc_edit->setPlaceholderText(tr("paste DBC file here")); - main_layout->addWidget(dbc_edit); - auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - main_layout->addWidget(buttonBox); - - setMinimumSize({640, 480}); - QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); - QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); -} - -// SaveDBCDialog - -SaveDBCDialog::SaveDBCDialog(QWidget *parent) : QDialog(parent) { - setWindowTitle(tr("Save DBC")); - QVBoxLayout *main_layout = new QVBoxLayout(this); - dbc_edit = new QTextEdit(this); - dbc_edit->setAcceptRichText(false); - main_layout->addWidget(dbc_edit); - - QPushButton *copy_to_clipboard = new QPushButton(tr("Copy To Clipboard"), this); - QPushButton *save_as = new QPushButton(tr("Save As"), this); - - QHBoxLayout *btn_layout = new QHBoxLayout(); - btn_layout->addStretch(); - btn_layout->addWidget(copy_to_clipboard); - btn_layout->addWidget(save_as); - main_layout->addLayout(btn_layout); - setMinimumSize({640, 480}); - - QObject::connect(copy_to_clipboard, &QPushButton::clicked, this, &SaveDBCDialog::copytoClipboard); - QObject::connect(save_as, &QPushButton::clicked, this, &SaveDBCDialog::saveAs); -} - -void SaveDBCDialog::copytoClipboard() { - dbc_edit->selectAll(); - dbc_edit->copy(); - QDialog::accept(); -} - -void SaveDBCDialog::saveAs() { - QString file_name = QFileDialog::getSaveFileName(this, tr("Save File"), - QDir::homePath() + "/untitled.dbc", tr("DBC (*.dbc)")); - if (!file_name.isEmpty()) { - QFile file(file_name); - if (file.open(QIODevice::WriteOnly)) { - file.write(dbc_edit->toPlainText().toUtf8()); - } - QDialog::accept(); - } -} diff --git a/tools/cabana/mainwin.h b/tools/cabana/mainwin.h index f6853a5ea3..bb9280c3ea 100644 --- a/tools/cabana/mainwin.h +++ b/tools/cabana/mainwin.h @@ -1,37 +1,40 @@ #pragma once #include -#include #include +#include #include #include #include -#include #include "tools/cabana/chartswidget.h" #include "tools/cabana/detailwidget.h" #include "tools/cabana/messageswidget.h" #include "tools/cabana/videowidget.h" -class MainWindow : public QWidget { +class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); void dockCharts(bool dock); - void showStatusMessage(const QString &msg, int timeout = 0) { status_bar->showMessage(msg, timeout); } + void showStatusMessage(const QString &msg, int timeout = 0) { statusBar()->showMessage(msg, timeout); } public slots: void loadDBCFromName(const QString &name); void loadDBCFromFingerprint(); - void loadDBCFromPaste(); - void saveDBC(); + void loadDBCFromFile(); + void loadDBCFromClipboard(); + void saveDBCToFile(); + void saveDBCToClipboard(); signals: void showMessage(const QString &msg, int timeout); void updateProgressBar(uint64_t cur, uint64_t total, bool success); protected: + void createActions(); + void createStatusBar(); void closeEvent(QCloseEvent *event) override; void updateDownloadProgress(uint64_t cur, uint64_t total, bool success); void setOption(); @@ -44,26 +47,7 @@ protected: QWidget *floating_window = nullptr; QVBoxLayout *r_layout; QProgressBar *progress_bar; - QStatusBar *status_bar; + QLabel *fingerprint_label; QJsonDocument fingerprint_to_dbc; QComboBox *dbc_combo; }; - - -class LoadDBCDialog : public QDialog { - Q_OBJECT - -public: - LoadDBCDialog(QWidget *parent); - QTextEdit *dbc_edit; -}; - -class SaveDBCDialog : public QDialog { - Q_OBJECT - -public: - SaveDBCDialog(QWidget *parent); - void copytoClipboard(); - void saveAs(); - QTextEdit *dbc_edit; -}; From c64e2c228a57dd82685f9ca4251c49e953e1ac69 Mon Sep 17 00:00:00 2001 From: Vivek Aithal Date: Wed, 9 Nov 2022 12:09:55 -0800 Subject: [PATCH 32/54] [controlsd] Toyota Rav4 TSS2 bugfix (#26421) bugfix toyota rav4 pid init values --- selfdrive/car/toyota/interface.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 6c360fc2c7..3f4edb36d2 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -111,6 +111,8 @@ class CarInterface(CarInterfaceBase): tire_stiffness_factor = 0.7933 ret.mass = 3585. * CV.LB_TO_KG + STD_CARGO_KG # Average between ICE and Hybrid ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kiBP = [0.0] + ret.lateralTuning.pid.kpBP = [0.0] ret.lateralTuning.pid.kpV = [0.6] ret.lateralTuning.pid.kiV = [0.1] ret.lateralTuning.pid.kf = 0.00007818594 From 0ca9d1810c39d96ec0ebefc80df16dd68eb3387e Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 12:10:08 -0800 Subject: [PATCH 33/54] interrfaces: more complete PID tests (#26422) * more complete PID tests * doesn't need to be fancy * less fancy --- selfdrive/car/tests/test_car_interfaces.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py index aabf652c8c..8d22173671 100755 --- a/selfdrive/car/tests/test_car_interfaces.py +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -34,15 +34,18 @@ class TestCarInterfaces(unittest.TestCase): self.assertGreater(car_params.maxLateralAccel, 0) if car_params.steerControlType != car.CarParams.SteerControlType.angle: - tuning = car_params.lateralTuning.which() - if tuning == 'pid': - self.assertTrue(len(car_params.lateralTuning.pid.kpV)) - elif tuning == 'torque': - kf = car_params.lateralTuning.torque.kf - self.assertTrue(not math.isnan(kf) and kf > 0) - self.assertTrue(not math.isnan(car_params.lateralTuning.torque.friction)) - elif tuning == 'indi': - self.assertTrue(len(car_params.lateralTuning.indi.outerLoopGainV)) + tune = car_params.lateralTuning + if tune.which() == 'pid': + self.assertTrue(not math.isnan(tune.pid.kf) and tune.pid.kf > 0) + self.assertTrue(len(tune.pid.kpV) > 0 and len(tune.pid.kpV) == len(tune.pid.kpBP)) + self.assertTrue(len(tune.pid.kiV) > 0 and len(tune.pid.kiV) == len(tune.pid.kiBP)) + + elif tune.which() == 'torque': + self.assertTrue(not math.isnan(tune.torque.kf) and tune.torque.kf > 0) + self.assertTrue(not math.isnan(tune.torque.friction)) + + elif tune.which() == 'indi': + self.assertTrue(len(tune.indi.outerLoopGainV)) # Run car interface CC = car.CarControl.new_message() From 59bf2fc0085420b13b7854d1a106c1706d7df265 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Thu, 10 Nov 2022 06:19:11 +0800 Subject: [PATCH 34/54] Cabana: support deleting message (#26418) delete message --- tools/cabana/chartswidget.cc | 8 ++++-- tools/cabana/dbcmanager.cc | 33 ++++++++++++++++-------- tools/cabana/dbcmanager.h | 5 +++- tools/cabana/detailwidget.cc | 46 +++++++++++++++++++++------------- tools/cabana/detailwidget.h | 5 +++- tools/cabana/messageswidget.cc | 9 ++++--- 6 files changed, 71 insertions(+), 35 deletions(-) diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 812a805810..3a170bccdc 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -45,9 +45,13 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { QObject::connect(dbc(), &DBCManager::DBCFileChanged, [this]() { removeAll(nullptr); }); QObject::connect(dbc(), &DBCManager::signalRemoved, this, &ChartsWidget::removeAll); QObject::connect(dbc(), &DBCManager::signalUpdated, this, &ChartsWidget::signalUpdated); - QObject::connect(dbc(), &DBCManager::msgUpdated, [this](const QString &msg_id) { + QObject::connect(dbc(), &DBCManager::msgRemoved, [this](uint32_t address) { + for (auto c : charts.toVector()) + if (DBCManager::parseId(c->id).second == address) removeChart(c); + }); + QObject::connect(dbc(), &DBCManager::msgUpdated, [this](uint32_t address) { for (auto c : charts) { - if (c->id == msg_id) c->updateTitle(); + if (DBCManager::parseId(c->id).second == address) c->updateTitle(); } }); QObject::connect(can, &CANMessages::eventsMerged, this, &ChartsWidget::eventsMerged); diff --git a/tools/cabana/dbcmanager.cc b/tools/cabana/dbcmanager.cc index 3ddcf41788..184fab38eb 100644 --- a/tools/cabana/dbcmanager.cc +++ b/tools/cabana/dbcmanager.cc @@ -10,21 +10,21 @@ DBCManager::~DBCManager() {} void DBCManager::open(const QString &dbc_file_name) { dbc = const_cast(dbc_lookup(dbc_file_name.toStdString())); - msg_map.clear(); - for (auto &msg : dbc->msgs) { - msg_map[msg.address] = &msg; - } + updateMsgMap(); emit DBCFileChanged(); } void DBCManager::open(const QString &name, const QString &content) { std::istringstream stream(content.toStdString()); dbc = const_cast(dbc_parse_from_stream(name.toStdString(), stream)); + updateMsgMap(); + emit DBCFileChanged(); +} + +void DBCManager::updateMsgMap() { msg_map.clear(); - for (auto &msg : dbc->msgs) { + for (auto &msg : dbc->msgs) msg_map[msg.address] = &msg; - } - emit DBCFileChanged(); } QString DBCManager::generateDBC() { @@ -49,14 +49,25 @@ QString DBCManager::generateDBC() { } void DBCManager::updateMsg(const QString &id, const QString &name, uint32_t size) { - if (auto m = const_cast(msg(id))) { + auto [bus, address] = parseId(id); + if (auto m = const_cast(msg(address))) { m->name = name.toStdString(); m->size = size; } else { - m = &dbc->msgs.emplace_back(Msg{.address = parseId(id).second, .name = name.toStdString(), .size = size}); - msg_map[m->address] = m; + m = &dbc->msgs.emplace_back(Msg{.address = address, .name = name.toStdString(), .size = size}); + msg_map[address] = m; + } + emit msgUpdated(address); +} + +void DBCManager::removeMsg(const QString &id) { + uint32_t address = parseId(id).second; + auto it = std::find_if(dbc->msgs.begin(), dbc->msgs.end(), [address](auto &m) { return m.address == address; }); + if (it != dbc->msgs.end()) { + dbc->msgs.erase(it); + updateMsgMap(); + emit msgRemoved(address); } - emit msgUpdated(id); } void DBCManager::addSignal(const QString &id, const Signal &sig) { diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index cbe4531d2a..2b6aca41d7 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -23,6 +23,7 @@ public: inline QString name() const { return dbc ? dbc->name.c_str() : ""; } void updateMsg(const QString &id, const QString &name, uint32_t size); + void removeMsg(const QString &id); inline const DBC *getDBC() const { return dbc; } inline const Msg *msg(const QString &id) const { return msg(parseId(id).second); } inline const Msg *msg(uint32_t address) const { @@ -34,10 +35,12 @@ signals: void signalAdded(const Signal *sig); void signalRemoved(const Signal *sig); void signalUpdated(const Signal *sig); - void msgUpdated(const QString &id); + void msgUpdated(uint32_t address); + void msgRemoved(uint32_t address); void DBCFileChanged(); private: + void updateMsgMap(); DBC *dbc = nullptr; std::unordered_map msg_map; }; diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 18510c86ea..287c75a617 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -33,20 +33,21 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart title_frame->setFrameShape(QFrame::StyledPanel); // message title - QHBoxLayout *title_layout = new QHBoxLayout(); - title_layout->addWidget(new QLabel("time:")); + toolbar = new QToolBar(this); + toolbar->addWidget(new QLabel("time:")); time_label = new QLabel(this); time_label->setStyleSheet("font-weight:bold"); - title_layout->addWidget(time_label); - title_layout->addStretch(); + toolbar->addWidget(time_label); name_label = new QLabel(this); name_label->setStyleSheet("font-weight:bold;"); - title_layout->addWidget(name_label); - title_layout->addStretch(); - edit_btn = new QPushButton(tr("Edit"), this); - edit_btn->setVisible(false); - title_layout->addWidget(edit_btn); - frame_layout->addLayout(title_layout); + name_label->setAlignment(Qt::AlignCenter); + name_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + toolbar->addWidget(name_label); + toolbar->addAction("🖍", this, &DetailWidget::editMsg)->setToolTip(tr("Edit Message")); + remove_msg_act = toolbar->addAction("X", this, &DetailWidget::removeMsg); + remove_msg_act->setToolTip(tr("Remove Message")); + toolbar->setVisible(false); + frame_layout->addWidget(toolbar); // warning warning_widget = new QWidget(this); @@ -85,7 +86,6 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart history_log = new HistoryLog(this); container_layout->addWidget(history_log); - QObject::connect(edit_btn, &QPushButton::clicked, this, &DetailWidget::editMsg); QObject::connect(binary_view, &BinaryView::resizeSignal, this, &DetailWidget::resizeSignal); QObject::connect(binary_view, &BinaryView::addSignal, this, &DetailWidget::addSignal); QObject::connect(can, &CANMessages::updated, this, &DetailWidget::updateState); @@ -171,7 +171,8 @@ void DetailWidget::dbcMsgChanged(int show_form_idx) { warnings.push_back(tr("Message size (%1) is incorrect.").arg(msg->size)); } - edit_btn->setVisible(true); + toolbar->setVisible(!msg_id.isEmpty()); + remove_msg_act->setEnabled(msg != nullptr); name_label->setText(msgName(msg_id)); binary_view->setMessage(msg_id); @@ -210,16 +211,27 @@ void DetailWidget::updateChartState(const QString &id, const Signal *sig, bool o } void DetailWidget::editMsg() { - auto msg = dbc()->msg(msg_id); - QString name = msgName(msg_id); - int size = msg ? msg->size : can->lastMessage(msg_id).dat.size(); - EditMessageDialog dlg(msg_id, name, size, this); + QString id = msg_id; + auto msg = dbc()->msg(id); + int size = msg ? msg->size : can->lastMessage(id).dat.size(); + EditMessageDialog dlg(id, msgName(id), size, this); if (dlg.exec()) { - dbc()->updateMsg(msg_id, dlg.name_edit->text(), dlg.size_spin->value()); + dbc()->updateMsg(id, dlg.name_edit->text(), dlg.size_spin->value()); dbcMsgChanged(); } } +void DetailWidget::removeMsg() { + QString id = msg_id; + if (auto msg = dbc()->msg(id)) { + QString text = tr("Are you sure you want to remove '%1'").arg(msg->name.c_str()); + if (QMessageBox::Yes == QMessageBox::question(this, tr("Remove Message"), text)) { + dbc()->removeMsg(id); + dbcMsgChanged(); + } + } +} + void DetailWidget::addSignal(int from, int to) { if (auto msg = dbc()->msg(msg_id)) { Signal sig = {}; diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index ac32d5952e..7cb3a505ee 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -2,6 +2,7 @@ #include #include +#include #include "tools/cabana/binaryview.h" #include "tools/cabana/chartswidget.h" @@ -34,15 +35,17 @@ private: void saveSignal(const Signal *sig, const Signal &new_sig); void removeSignal(const Signal *sig); void editMsg(); + void removeMsg(); void showForm(); void updateState(); QString msg_id; QLabel *name_label, *time_label, *warning_label; QWidget *warning_widget; - QPushButton *edit_btn; QWidget *signals_container; QTabBar *tabbar; + QToolBar *toolbar; + QAction *remove_msg_act; HistoryLog *history_log; BinaryView *binary_view; QScrollArea *scroll; diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index f24b6b0317..dbf87a3da2 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -38,15 +38,18 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { QObject::connect(can, &CANMessages::msgsReceived, model, &MessageListModel::msgsReceived); QObject::connect(dbc(), &DBCManager::DBCFileChanged, model, &MessageListModel::sortMessages); QObject::connect(dbc(), &DBCManager::msgUpdated, model, &MessageListModel::sortMessages); + QObject::connect(dbc(), &DBCManager::msgRemoved, model, &MessageListModel::sortMessages); QObject::connect(table_widget->selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex ¤t, const QModelIndex &previous) { if (current.isValid() && current.row() < model->msgs.size()) { - current_msg_id = model->msgs[current.row()]; - emit msgSelectionChanged(current_msg_id); + if (model->msgs[current.row()] != current_msg_id) { + current_msg_id = model->msgs[current.row()]; + emit msgSelectionChanged(current_msg_id); + } } }); QObject::connect(model, &MessageListModel::modelReset, [this]() { if (int row = model->msgs.indexOf(current_msg_id); row != -1) - table_widget->selectionModel()->select(model->index(row, 0), QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); + table_widget->selectionModel()->setCurrentIndex(model->index(row, 0), QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); }); } From f38fe7cfb1b3011ea48a34b0500f352338e05b25 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Wed, 9 Nov 2022 14:53:41 -0800 Subject: [PATCH 35/54] ui: increase toggle confirmation font size (#26413) * ui: make toggle confirmation text larger * center title * reduce line breaks * slightly reduce font size --- selfdrive/ui/qt/widgets/controls.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/ui/qt/widgets/controls.h b/selfdrive/ui/qt/widgets/controls.h index 243c078f85..8679de57b0 100644 --- a/selfdrive/ui/qt/widgets/controls.h +++ b/selfdrive/ui/qt/widgets/controls.h @@ -142,8 +142,8 @@ public: ParamControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, const bool confirm, QWidget *parent = nullptr) : ToggleControl(title, desc, icon, false, parent) { key = param.toStdString(); QObject::connect(this, &ParamControl::toggleFlipped, [=](bool state) { - QString content("

" + title + "



" - "

" + getDescription() + "

"); + QString content("

" + title + "


" + "

" + getDescription() + "

"); ConfirmationDialog dialog(content, tr("Ok"), tr("Cancel"), true, this); if (!confirm || !state || dialog.exec()) { params.putBool(key, state); From 584842488f4cab62bb9d5e4d8fc2cc3090634fb7 Mon Sep 17 00:00:00 2001 From: AlexandreSato <66435071+AlexandreSato@users.noreply.github.com> Date: Wed, 9 Nov 2022 20:13:17 -0300 Subject: [PATCH 36/54] Multilang: update pt-BR (#26420) * update pt-BR translations * fix some cutoff texts * Update pt-BR translations --- selfdrive/ui/translations/main_pt-BR.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index a5187af50f..c2ee98d340 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -240,11 +240,11 @@ Reset - + Resetar Review - + Revisar
@@ -476,11 +476,11 @@ trabalho definido ParamControl Ok - OK + OK Cancel - Cancelar + Cancelar @@ -868,7 +868,7 @@ trabalho definido Uninstall - + Desinstalar @@ -1008,15 +1008,15 @@ trabalho definido Experimental mode - + Modo Experimental <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. - + <b>AVISO: o controle longitudinal openpilot é experimental para este carro e irá desabilitar AEB.</b><br> O padrão do openpilot é o ACC integrado do carro em vez do controle longitudinal do openpilot neste carro. Habilite isto para alternar para controle longitudinal do openpilot. openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. - + o padrão do openpilot é dirigir no <b>modo chill</b>. Modo experimental habilita <b>recursos de nível-alfa</b> que não estão prontos para o modo chill. Os recursos experimentais estão listados abaixo: <br> <h4>🌮 Controle Longitudinal de Ponta a Ponta 🌮</h4> Deixe o modelo de direção controlar o acelerador e os freios. openpilot irá conduzir como pensa que um ser humano faria, incluindo parar para sinais vermelhos e sinais de parada. @@ -1074,7 +1074,7 @@ trabalho definido Forget - + Esquecer From 048cce2149db34ea0e32df3673248fbbc8e804ad Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 16:04:19 -0800 Subject: [PATCH 37/54] Hyundai: add missing Sonata 2022 FW versions (#26428) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added FW Versions for 2022 Elantra and 2022 Sonata. Added for CAR.ELANTRA_2021 : Ecu.transmission : b’\xf1\x87CXMQFM3421815JB2ww\x96y\xaa\x98x\x87\x88wtwTfuwWh\x9f\xff\x8a\xff\xff\xffE\xe3\xf1\x89HT6VA640A1\xf1\x82CCN0N20NS5\x00\x00\x00\x00\x00\x00' Ecu.engine : b'\xf1\x870\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\x82CNDWD0AMFCXCSG8A' Added for CAR.SONATA : Ecu.engine : b'\xf1\x870\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\x81HM6M1_0a0_J10' Ecu.transmission: b'\xf1\x00T02601BL T02832A1 VDN8T25XXX832NS8G\x0e\xfeE' b'\xf1\x87954A02N060\x00\x00\x00\x00\x00\xf1\x81T02832A1 \xf1\x00T02601BL T02832A1 VDN8T25XXX832NS8G\x0e\xfeE' b'\xf1\x87954A02N060\x00\x00\x00\x00\x00\xf1\x82VDN8T25XXX832NS8' * Update values.py * Removed FW Versions for Elantra_2021. * fix Co-authored-by: humza2000 <111622889+humza2000@users.noreply.github.com> --- selfdrive/car/hyundai/values.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index e5ddc5cac7..b7e28825c3 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -468,6 +468,7 @@ FW_VERSIONS = { b'\xf1\x82DNBWN5TMDCXXXG2E', b'\xf1\x82DNCVN5GMCCXXXF0A', b'\xf1\x82DNCVN5GMCCXXXG2B', + b'\xf1\x870\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\x81HM6M1_0a0_J10', b'\xf1\x870\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf1\x82DNDWN5TMDCXXXJ1A', b'\xf1\x87391162M003', b'\xf1\x87391162M013', @@ -492,6 +493,7 @@ FW_VERSIONS = { b'\xf1\x8756310L0010\x00\xf1\x00DN8 MDPS C 1.00 1.01 56310L0010\x00 4DNAC101', b'\xf1\x8756310L0210\x00\xf1\x00DN8 MDPS C 1.00 1.01 56310L0210\x00 4DNAC101', b'\xf1\x8757700-L0000\xf1\x00DN8 MDPS R 1.00 1.00 57700-L0000 4DNAP100', + b'\xf1\x00DN8 MDPS R 1.00 1.00 57700-L0000 4DNAP101', ], (Ecu.fwdCamera, 0x7c4, None): [ b'\xf1\x00DN8 MFC AT KOR LHD 1.00 1.02 99211-L1000 190422', @@ -512,6 +514,7 @@ FW_VERSIONS = { b'\xf1\x00HT6WA250BLHT6WA910A1SDN8G25NB1\x00\x00\x00\x00\x00\x00\x96\xa1\xf1\x92', b'\xf1\x00HT6WA280BLHT6WAD10A1SDN8G25NB2\x00\x00\x00\x00\x00\x00\x08\xc9O:', b'\xf1\x00T02601BL T02730A1 VDN8T25XXX730NS5\xf7_\x92\xf5', + b'\xf1\x00T02601BL T02832A1 VDN8T25XXX832NS8G\x0e\xfeE', b'\xf1\x87954A02N060\x00\x00\x00\x00\x00\xf1\x81T02730A1 \xf1\x00T02601BL T02730A1 VDN8T25XXX730NS5\xf7_\x92\xf5', b'\xf1\x87SAKFBA2926554GJ2VefVww\x87xwwwww\x88\x87xww\x87wTo\xfb\xffvUo\xff\x8d\x16\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v', b'\xf1\x87SAKFBA3030524GJ2UVugww\x97yx\x88\x87\x88vw\x87gww\x87wto\xf9\xfffUo\xff\xa2\x0c\xf1\x81U903\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 U903\x00\x00\x00\x00\x00\x00SDN8T16NB0z{\xd4v', From 52378c97ecde4c489e18e23d01021f27c3acf073 Mon Sep 17 00:00:00 2001 From: AlexandreSato <66435071+AlexandreSato@users.noreply.github.com> Date: Wed, 9 Nov 2022 21:06:36 -0300 Subject: [PATCH 38/54] Toyota: Add missing Corolla Cross FW verions (#26426) * add geraldo fingerprint * add to non-H * Update selfdrive/car/tests/routes.py * Update non-us cross model years * add test route * Update routes.py Co-authored-by: Shane Smiskol --- docs/CARS.md | 2 +- selfdrive/car/toyota/values.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/CARS.md b/docs/CARS.md index 04f7712016..07bcf44257 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -167,7 +167,7 @@ A supported vehicle is one that just works when you install a comma three. All s |Toyota|Camry Hybrid 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| |Toyota|Corolla 2017-19|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| |Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Corolla Cross (Non-US only) 2020-21|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| |Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| |Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| |Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index 9e96118085..2ce1cba92c 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -119,7 +119,7 @@ CAR_INFO: Dict[str, Union[ToyotaCarInfo, List[ToyotaCarInfo]]] = { CAR.COROLLA: ToyotaCarInfo("Toyota Corolla 2017-19"), CAR.COROLLA_TSS2: [ ToyotaCarInfo("Toyota Corolla 2020-22", video_link="https://www.youtube.com/watch?v=_66pXk0CBYA"), - ToyotaCarInfo("Toyota Corolla Cross (Non-US only) 2020-21", min_enable_speed=7.5), + ToyotaCarInfo("Toyota Corolla Cross (Non-US only) 2020-23", min_enable_speed=7.5), ToyotaCarInfo("Toyota Corolla Hatchback 2019-22", video_link="https://www.youtube.com/watch?v=_66pXk0CBYA"), ], CAR.COROLLAH_TSS2: [ @@ -713,6 +713,7 @@ FW_VERSIONS = { }, CAR.COROLLA_TSS2: { (Ecu.engine, 0x700, None): [ + b'\x01896630A22000\x00\x00\x00\x00', b'\x01896630ZG2000\x00\x00\x00\x00', b'\x01896630ZG5000\x00\x00\x00\x00', b'\x01896630ZG5100\x00\x00\x00\x00', @@ -792,6 +793,7 @@ FW_VERSIONS = { b'F152602191\x00\x00\x00\x00\x00\x00', b'\x01F152612862\x00\x00\x00\x00\x00\x00', b'\x01F152612B91\x00\x00\x00\x00\x00\x00', + b'\x01F15260A070\x00\x00\x00\x00\x00\x00', ], (Ecu.fwdRadar, 0x750, 0xf): [ b'\x018821F3301100\x00\x00\x00\x00', @@ -809,6 +811,7 @@ FW_VERSIONS = { b'\x028646F1202100\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', b'\x028646F1202200\x00\x00\x00\x008646G2601500\x00\x00\x00\x00', b'\x028646F1601100\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F1601300\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', ], }, CAR.COROLLAH_TSS2: { From 26d66ac671a6b15be4611face27844bae90b185f Mon Sep 17 00:00:00 2001 From: Lee Jong Mun <43285072+crwusiz@users.noreply.github.com> Date: Thu, 10 Nov 2022 09:15:44 +0900 Subject: [PATCH 39/54] Multilang: Korean translation update (#26424) fix --- selfdrive/ui/translations/main_ko.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index e9b4943650..ff09581e61 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -1004,15 +1004,15 @@ location set Experimental mode - + 실험 모드 <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. - + <b>경고: openpilot 롱컨트롤은 실험적인 기능으로 차량의 AEB를 비활성화합니다.</b><br> openpilot은 차량의 내장 ACC로 기본 설정됩니다. 롱컨트롤으로 전환하려면 이 옵션을 활성화하세요. openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. - + openpilot은 <b>chill 모드</b>로 기본 설정됩니다. 실험 모드는 chill 모드에 준비되지 않은 <b>알파 수준 기능</b>을 활성화 합니다. 실험 모드의 특징은 아래에 나열되어 있습니다 <br> <h4>🌮 E2E 롱컨트롤 🌮</h4> 주행모델이 가속과 감속을 제어하도록 합니다. openpilot은 신호등과 정지표지판을 보고 멈추는 것을 포함하여 운전자가 생각하는것처럼 주행합니다. From f540002e3fb6bcb15323add59d87269e7da6d00f Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 16:49:17 -0800 Subject: [PATCH 40/54] translation badges: add number of unfinished translations (#26429) * some clean up and add missing translations * unfinished * set proper width * make this variable common --- selfdrive/ui/tests/test_translations.py | 3 ++- selfdrive/ui/translations/create_badges.py | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/selfdrive/ui/tests/test_translations.py b/selfdrive/ui/tests/test_translations.py index 11ecd30ae0..26d6c39349 100755 --- a/selfdrive/ui/tests/test_translations.py +++ b/selfdrive/ui/tests/test_translations.py @@ -9,6 +9,7 @@ import xml.etree.ElementTree as ET from selfdrive.ui.update_translations import TRANSLATIONS_DIR, LANGUAGES_FILE, update_translations TMP_TRANSLATIONS_DIR = os.path.join(TRANSLATIONS_DIR, "tmp") +UNFINISHED_TRANSLATION_TAG = "" not in cur_translations, + self.assertTrue(UNFINISHED_TRANSLATION_TAG not in cur_translations, f"{file} ({name}) translation file has unfinished translations. Finish translations or mark them as completed in Qt Linguist") def test_vanished_translations(self): diff --git a/selfdrive/ui/translations/create_badges.py b/selfdrive/ui/translations/create_badges.py index 32904f242a..e403972e36 100755 --- a/selfdrive/ui/translations/create_badges.py +++ b/selfdrive/ui/translations/create_badges.py @@ -2,19 +2,22 @@ import json import os import requests +import xml.etree.ElementTree as ET from common.basedir import BASEDIR +from selfdrive.ui.tests.test_translations import UNFINISHED_TRANSLATION_TAG from selfdrive.ui.update_translations import LANGUAGES_FILE, TRANSLATIONS_DIR TRANSLATION_TAG = "'] + badge_svg = [] + max_badge_width = 0 # keep track of max width to set parent element for idx, (name, file) in enumerate(translation_files.items()): with open(os.path.join(TRANSLATIONS_DIR, f"{file}.ts"), "r") as tr_f: tr_file = tr_f.read() @@ -28,19 +31,28 @@ if __name__ == "__main__": unfinished_translations += 1 percent_finished = int(100 - (unfinished_translations / total_translations * 100.)) - color = "green" if percent_finished == 100 else "orange" if percent_finished >= 70 else "red" + color = "green" if percent_finished == 100 else "orange" if percent_finished > 90 else "red" - r = requests.get(f"https://img.shields.io/badge/LANGUAGE {name}-{percent_finished}%25 complete-{color}", timeout=10) + # Download badge + badge_label = f"LANGUAGE {name}" + badge_message = f"{percent_finished}% complete" + if unfinished_translations != 0: + badge_message += f" ({unfinished_translations} unfinished translations)" + + r = requests.get(f"{SHIELDS_URL}/{badge_label}-{badge_message}-{color}", timeout=10) assert r.status_code == 200, "Error downloading badge" content_svg = r.content.decode("utf-8") - # make tag ids in each badge unique + max_badge_width = max(max_badge_width, int(ET.fromstring(content_svg).get("width"))) + + # Make tag ids in each badge unique to combine them into one svg for tag in ("r", "s"): content_svg = content_svg.replace(f'id="{tag}"', f'id="{tag}{idx}"') content_svg = content_svg.replace(f'"url(#{tag})"', f'"url(#{tag}{idx})"') badge_svg.extend([f'', content_svg, ""]) + badge_svg.insert(0, f'') badge_svg.append("") with open(os.path.join(BASEDIR, "translation_badge.svg"), "w") as badge_f: From d8327bd9bed9833eb3d58a51097215c2de803d1b Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 16:58:02 -0800 Subject: [PATCH 41/54] multilang badges: no need to handle plurals --- selfdrive/ui/translations/create_badges.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/ui/translations/create_badges.py b/selfdrive/ui/translations/create_badges.py index e403972e36..893ac1b412 100755 --- a/selfdrive/ui/translations/create_badges.py +++ b/selfdrive/ui/translations/create_badges.py @@ -37,7 +37,7 @@ if __name__ == "__main__": badge_label = f"LANGUAGE {name}" badge_message = f"{percent_finished}% complete" if unfinished_translations != 0: - badge_message += f" ({unfinished_translations} unfinished translations)" + badge_message += f" ({unfinished_translations} unfinished)" r = requests.get(f"{SHIELDS_URL}/{badge_label}-{badge_message}-{color}", timeout=10) assert r.status_code == 200, "Error downloading badge" From bbc14656d937cadacbcb87ed88cb8800eb6b62fa Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 17:30:33 -0800 Subject: [PATCH 42/54] Multilang badges: assert width exists in xml --- selfdrive/ui/translations/create_badges.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/selfdrive/ui/translations/create_badges.py b/selfdrive/ui/translations/create_badges.py index 893ac1b412..575584dd50 100755 --- a/selfdrive/ui/translations/create_badges.py +++ b/selfdrive/ui/translations/create_badges.py @@ -43,7 +43,9 @@ if __name__ == "__main__": assert r.status_code == 200, "Error downloading badge" content_svg = r.content.decode("utf-8") - max_badge_width = max(max_badge_width, int(ET.fromstring(content_svg).get("width"))) + xml = ET.fromstring(content_svg) + assert "width" in xml.attrib + max_badge_width = max(max_badge_width, int(xml.attrib["width"])) # Make tag ids in each badge unique to combine them into one svg for tag in ("r", "s"): From 6c03e093c6d1d9d45dc342cce2374656b80ecaa9 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 17:31:58 -0800 Subject: [PATCH 43/54] Multilang: mark some translations finished (#26430) * mark finished translations * fix * cleanup * revert --- selfdrive/ui/translations/main_ja.ts | 4 ++-- selfdrive/ui/translations/main_zh-CHS.ts | 6 +++--- selfdrive/ui/translations/main_zh-CHT.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 039ad7b2a4..3ddf71518c 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -475,11 +475,11 @@ location set ParamControl Ok - OK + OK Cancel - キャンセル + キャンセル diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 44e707e49c..28ec6f750a 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -376,7 +376,7 @@ Get turn-by-turn directions displayed and more with a comma prime subscription. Sign up now: https://connect.comma.ai - 订阅comma prime以获取导航。 + 订阅comma prime以获取导航。 立即注册:https://connect.comma.ai @@ -473,11 +473,11 @@ location set ParamControl Ok - 好的 + 好的 Cancel - 取消 + 取消 diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 274cff3a5a..c99b818cbf 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -475,11 +475,11 @@ location set ParamControl Ok - 確定 + 確定 Cancel - 取消 + 取消 From e1001a3036fb93d6d0340d139d4ae2a1f2419d52 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 18:27:30 -0800 Subject: [PATCH 44/54] Toyota: factor on cluster speed to match dash (#26408) * add a minimum factort * Update ref_commit --- selfdrive/car/toyota/carstate.py | 1 + selfdrive/test/process_replay/ref_commit | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index a959633281..8efb2c79e3 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -54,6 +54,7 @@ class CarState(CarStateBase): ) ret.vEgoRaw = mean([ret.wheelSpeeds.fl, ret.wheelSpeeds.fr, ret.wheelSpeeds.rl, ret.wheelSpeeds.rr]) ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) + ret.vEgoCluster = ret.vEgo * 1.015 # minimum of all the cars ret.standstill = ret.vEgoRaw == 0 diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index da954d76a6..cac678ca1f 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -372a67c524342bbf15e22f0caea08d2038973281 +a36f7e2fd922fcadca6f8a3d777f4db787cba016 From 1fda075c7306976099bcfbb6b0a6303e819036b4 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 9 Nov 2022 18:42:51 -0800 Subject: [PATCH 45/54] UI: add set speed clarification for e2e long --- selfdrive/ui/qt/offroad/settings.cc | 2 +- selfdrive/ui/translations/main_ja.ts | 2 +- selfdrive/ui/translations/main_ko.ts | 4 ++-- selfdrive/ui/translations/main_pt-BR.ts | 4 ++-- selfdrive/ui/translations/main_zh-CHS.ts | 2 +- selfdrive/ui/translations/main_zh-CHT.ts | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 29069155b2..a30b66a2fd 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -125,7 +125,7 @@ void TogglesPanel::updateToggles() { Experimental features are listed below:\
\

🌮 End-to-End Longitudinal Control 🌮

\ - Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs."); + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound."); auto cp_bytes = params.get("CarParamsPersistent"); if (!cp_bytes.empty()) { diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 3ddf71518c..be3fbe104c 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -1011,7 +1011,7 @@ location set - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound.
diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index ff09581e61..4e11e80332 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -1011,8 +1011,8 @@ location set <b>경고: openpilot 롱컨트롤은 실험적인 기능으로 차량의 AEB를 비활성화합니다.</b><br> openpilot은 차량의 내장 ACC로 기본 설정됩니다. 롱컨트롤으로 전환하려면 이 옵션을 활성화하세요. - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. - openpilot은 <b>chill 모드</b>로 기본 설정됩니다. 실험 모드는 chill 모드에 준비되지 않은 <b>알파 수준 기능</b>을 활성화 합니다. 실험 모드의 특징은 아래에 나열되어 있습니다 <br> <h4>🌮 E2E 롱컨트롤 🌮</h4> 주행모델이 가속과 감속을 제어하도록 합니다. openpilot은 신호등과 정지표지판을 보고 멈추는 것을 포함하여 운전자가 생각하는것처럼 주행합니다. + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. + diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index c2ee98d340..fde669c919 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -1015,8 +1015,8 @@ trabalho definido <b>AVISO: o controle longitudinal openpilot é experimental para este carro e irá desabilitar AEB.</b><br> O padrão do openpilot é o ACC integrado do carro em vez do controle longitudinal do openpilot neste carro. Habilite isto para alternar para controle longitudinal do openpilot. - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. - o padrão do openpilot é dirigir no <b>modo chill</b>. Modo experimental habilita <b>recursos de nível-alfa</b> que não estão prontos para o modo chill. Os recursos experimentais estão listados abaixo: <br> <h4>🌮 Controle Longitudinal de Ponta a Ponta 🌮</h4> Deixe o modelo de direção controlar o acelerador e os freios. openpilot irá conduzir como pensa que um ser humano faria, incluindo parar para sinais vermelhos e sinais de parada. + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. + diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 28ec6f750a..230205a4a8 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -1009,7 +1009,7 @@ location set - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index c99b818cbf..4e8d733933 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -1011,7 +1011,7 @@ location set - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. From 5a3c5e7a4b78853d6b350f551432a1bb6050eba9 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 19:33:42 -0800 Subject: [PATCH 46/54] Multilang: clean up translation string (#26435) * update translations * do pt * do pt * do ko * do ko * Update selfdrive/ui/translations/main_pt-BR.ts --- selfdrive/ui/qt/offroad/settings.cc | 5 +++-- selfdrive/ui/translations/main_ja.ts | 8 ++++++-- selfdrive/ui/translations/main_ko.ts | 12 ++++++++---- selfdrive/ui/translations/main_pt-BR.ts | 12 ++++++++---- selfdrive/ui/translations/main_zh-CHS.ts | 8 ++++++-- selfdrive/ui/translations/main_zh-CHT.ts | 8 ++++++-- 6 files changed, 37 insertions(+), 16 deletions(-) diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index a30b66a2fd..bf886ae159 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -46,8 +46,9 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { { "ExperimentalLongitudinalEnabled", tr("Experimental openpilot longitudinal control"), - tr("WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.
\ - openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control."), + QString("%1
%2") + .arg(tr("WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.")) + .arg(tr("openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control.")), "../assets/offroad/icon_speed_limit.png", true, }, diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index be3fbe104c..2e38295368 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -1007,11 +1007,15 @@ location set - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. + WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. + + + + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index 4e11e80332..42b73430f1 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -1006,14 +1006,18 @@ location set Experimental mode 실험 모드 - - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. - <b>경고: openpilot 롱컨트롤은 실험적인 기능으로 차량의 AEB를 비활성화합니다.</b><br> openpilot은 차량의 내장 ACC로 기본 설정됩니다. 롱컨트롤으로 전환하려면 이 옵션을 활성화하세요. - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. + + WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. + 경고: openpilot 롱컨트롤은 실험적인 기능으로 차량의 AEB를 비활성화합니다. + + + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + openpilot은 차량의 내장 ACC로 기본 설정됩니다. 롱컨트롤으로 전환하려면 이 옵션을 활성화하세요. + Updater diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index fde669c919..394d73c86a 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -1010,14 +1010,18 @@ trabalho definido Experimental mode Modo Experimental - - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. - <b>AVISO: o controle longitudinal openpilot é experimental para este carro e irá desabilitar AEB.</b><br> O padrão do openpilot é o ACC integrado do carro em vez do controle longitudinal do openpilot neste carro. Habilite isto para alternar para controle longitudinal do openpilot. - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. + + WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. + AVISO: o controle longitudinal openpilot é experimental para este carro e irá desabilitar AEB. + + + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + O padrão do openpilot é o ACC integrado do carro em vez do controle longitudinal do openpilot neste carro. Habilite isto para alternar para controle longitudinal do openpilot. + Updater diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 230205a4a8..541ed20dee 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -1005,11 +1005,15 @@ location set - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. + WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. + + + + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 4e8d733933..99c64a194b 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -1007,11 +1007,15 @@ location set - <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b><br> openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. - openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. + WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. + + + + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. From a3cd50c5bbb924eaf40ab18d76f603edfc2f5a2a Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 19:38:17 -0800 Subject: [PATCH 47/54] ParamControl dialog: more explicit confirmation text (#26431) * Use enable * vanish * fill in missing translation * Update selfdrive/ui/translations/main_pt-BR.ts --- selfdrive/ui/qt/widgets/controls.h | 2 +- selfdrive/ui/translations/main_ja.ts | 8 ++++---- selfdrive/ui/translations/main_ko.ts | 8 ++++---- selfdrive/ui/translations/main_pt-BR.ts | 8 ++++---- selfdrive/ui/translations/main_zh-CHS.ts | 8 ++++---- selfdrive/ui/translations/main_zh-CHT.ts | 8 ++++---- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/selfdrive/ui/qt/widgets/controls.h b/selfdrive/ui/qt/widgets/controls.h index 8679de57b0..b67224b33d 100644 --- a/selfdrive/ui/qt/widgets/controls.h +++ b/selfdrive/ui/qt/widgets/controls.h @@ -144,7 +144,7 @@ public: QObject::connect(this, &ParamControl::toggleFlipped, [=](bool state) { QString content("

" + title + "


" "

" + getDescription() + "

"); - ConfirmationDialog dialog(content, tr("Ok"), tr("Cancel"), true, this); + ConfirmationDialog dialog(content, tr("Enable"), tr("Cancel"), true, this); if (!confirm || !state || dialog.exec()) { params.putBool(key, state); } else { diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 2e38295368..14c3404ad1 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -473,14 +473,14 @@ location set ParamControl - - Ok - OK - Cancel キャンセル + + Enable + を有効化 + PrimeAdWidget diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index 42b73430f1..9ca28e9e2c 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -473,14 +473,14 @@ location set ParamControl - - Ok - 확인 - Cancel 취소 + + Enable + 사용 + PrimeAdWidget diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 394d73c86a..3559d4b422 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -474,14 +474,14 @@ trabalho definido ParamControl - - Ok - OK - Cancel Cancelar + + Enable + Ativar + PrimeAdWidget diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 541ed20dee..3dfd7794ec 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -471,14 +471,14 @@ location set ParamControl - - Ok - 好的 - Cancel 取消 + + Enable + 启用 + PrimeAdWidget diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 99c64a194b..35fd944ddb 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -473,14 +473,14 @@ location set ParamControl - - Ok - 確定 - Cancel 取消 + + Enable + 啟用 + PrimeAdWidget From af84f1b3506082d644c2f52f88390fabcc9f7835 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 19:42:34 -0800 Subject: [PATCH 48/54] experimental long toggle: adjust description (#26437) * Spell out AEB * vanish --- selfdrive/ui/qt/offroad/settings.cc | 2 +- selfdrive/ui/translations/main_ja.ts | 4 ++-- selfdrive/ui/translations/main_ko.ts | 8 ++++---- selfdrive/ui/translations/main_pt-BR.ts | 8 ++++---- selfdrive/ui/translations/main_zh-CHS.ts | 4 ++-- selfdrive/ui/translations/main_zh-CHT.ts | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index bf886ae159..2acbb4ed7d 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -47,7 +47,7 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { "ExperimentalLongitudinalEnabled", tr("Experimental openpilot longitudinal control"), QString("%1
%2") - .arg(tr("WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.")) + .arg(tr("WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).")) .arg(tr("openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control.")), "../assets/offroad/icon_speed_limit.png", true, diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 14c3404ad1..78434439dd 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -1011,11 +1011,11 @@ location set - WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. - openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).
diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index 9ca28e9e2c..9409f82a1d 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -1010,14 +1010,14 @@ location set openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. - - WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. - 경고: openpilot 롱컨트롤은 실험적인 기능으로 차량의 AEB를 비활성화합니다. - openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. openpilot은 차량의 내장 ACC로 기본 설정됩니다. 롱컨트롤으로 전환하려면 이 옵션을 활성화하세요. + + WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB). + + Updater diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 3559d4b422..55ae75d20e 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -1014,14 +1014,14 @@ trabalho definido openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: <br> <h4>🌮 End-to-End Longitudinal Control 🌮</h4> Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound. - - WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. - AVISO: o controle longitudinal openpilot é experimental para este carro e irá desabilitar AEB. - openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. O padrão do openpilot é o ACC integrado do carro em vez do controle longitudinal do openpilot neste carro. Habilite isto para alternar para controle longitudinal do openpilot. + + WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB). + + Updater diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 3dfd7794ec..165aacfa5a 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -1009,11 +1009,11 @@ location set - WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. - openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB). diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 35fd944ddb..e3cd908d18 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -1011,11 +1011,11 @@ location set - WARNING: openpilot longitudinal control is experimental for this car and will disable AEB. + openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. - openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control. + WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB). From d3122cc77e169d8eb87663741bacc165f7062d56 Mon Sep 17 00:00:00 2001 From: Nelson Chen Date: Wed, 9 Nov 2022 19:59:12 -0800 Subject: [PATCH 49/54] Toyota: add missing engine FW for RAV4H_TSS2 (#26432) "rav4 hybrid xse 2020" From Rogrhoa#2158 on Discord. Example Route: 64edc30d23cad8cb|2022-11-09--20-02-03 --- selfdrive/car/toyota/values.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index 2ce1cba92c..ba26c7e03b 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -1392,6 +1392,7 @@ FW_VERSIONS = { b'\x02896634A14001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', b'\x02896634A23000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'\x02896634A23001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', + b'\x02896634A23101\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', b'\x02896634A14001\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', b'\x02896634A14101\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', ], From 0941e40177eb0eb7a49bb08628e5aad2deb19c7f Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 20:31:38 -0800 Subject: [PATCH 50/54] ui: static color non-e2e path (#26406) * remove orientation color changing * "just green" --- selfdrive/ui/qt/onroad.cc | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 37c1913743..23986726c8 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -478,21 +478,9 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) { bg.setColorAt(0.5, QColor::fromHslF(end_hue / 360., 1.0, 0.68, 0.35)); bg.setColorAt(1.0, QColor::fromHslF(end_hue / 360., 1.0, 0.68, 0.0)); } else { - const auto &orientation = (*s->sm)["modelV2"].getModelV2().getOrientation(); - float orientation_future = 0; - if (orientation.getZ().size() > 16) { - orientation_future = std::abs(orientation.getZ()[16]); // 2.5 seconds - } - start_hue = 148; - // straight: 112, in turns: 70 - end_hue = fmax(70, 112 - (orientation_future * 420)); - - // FIXME: painter.drawPolygon can be slow if hue is not rounded - end_hue = int(end_hue * 100 + 0.5) / 100; - - bg.setColorAt(0.0, QColor::fromHslF(start_hue / 360., 0.94, 0.51, 0.4)); - bg.setColorAt(0.5, QColor::fromHslF(end_hue / 360., 1.0, 0.68, 0.35)); - bg.setColorAt(1.0, QColor::fromHslF(end_hue / 360., 1.0, 0.68, 0.0)); + bg.setColorAt(0.0, QColor::fromHslF(148 / 360., 0.94, 0.51, 0.4)); + bg.setColorAt(0.5, QColor::fromHslF(112 / 360., 1.0, 0.68, 0.35)); + bg.setColorAt(1.0, QColor::fromHslF(112 / 360., 1.0, 0.68, 0.0)); } painter.setBrush(bg); From 4efb01ece2a9ef54152682c1dc3756d3e4161241 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 9 Nov 2022 20:33:01 -0800 Subject: [PATCH 51/54] Toggle titles: proper capitalization (#26438) * proper caps * update translations update translations update translations * Update selfdrive/ui/translations/main_pt-BR.ts --- selfdrive/ui/qt/offroad/settings.cc | 6 +++--- selfdrive/ui/translations/main_ar.ts | 4 ++-- selfdrive/ui/translations/main_ja.ts | 6 +++--- selfdrive/ui/translations/main_ko.ts | 6 +++--- selfdrive/ui/translations/main_nl.ts | 4 ++-- selfdrive/ui/translations/main_pl.ts | 4 ++-- selfdrive/ui/translations/main_pt-BR.ts | 6 +++--- selfdrive/ui/translations/main_th.ts | 4 ++-- selfdrive/ui/translations/main_zh-CHS.ts | 6 +++--- selfdrive/ui/translations/main_zh-CHT.ts | 6 +++--- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 2acbb4ed7d..a03cf02010 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -38,14 +38,14 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { }, { "ExperimentalMode", - tr("Experimental mode"), + tr("Experimental Mode"), "", "../assets/offroad/icon_road.png", false, }, { "ExperimentalLongitudinalEnabled", - tr("Experimental openpilot longitudinal control"), + tr("Experimental openpilot Longitudinal Control"), QString("%1
%2") .arg(tr("WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).")) .arg(tr("openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control.")), @@ -75,7 +75,7 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { }, { "DisengageOnAccelerator", - tr("Disengage On Accelerator Pedal"), + tr("Disengage on Accelerator Pedal"), tr("When enabled, pressing the accelerator pedal will disengage openpilot."), "../assets/offroad/icon_disengage_on_accelerator.svg", false, diff --git a/selfdrive/ui/translations/main_ar.ts b/selfdrive/ui/translations/main_ar.ts index 3c47e6e8e8..07a84fca08 100644 --- a/selfdrive/ui/translations/main_ar.ts +++ b/selfdrive/ui/translations/main_ar.ts @@ -1023,7 +1023,7 @@ location set قم بتحميل البيانات من الكاميرا المواجهة للسائق وساعد في تحسين خوارزمية مراقبة السائق. - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal فك الارتباط على دواسة التسريع @@ -1059,7 +1059,7 @@ location set - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 78434439dd..87c60516fc 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -967,7 +967,7 @@ location set 車内カメラの映像をアップロードし、ドライバー監視システムのアルゴリズムの向上に役立てます。 - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control 実験段階のopenpilotによるアクセル制御 @@ -979,7 +979,7 @@ location set ここ機能を使う為には、「実験段階のopenpilotによるアクセル制御」を先に有効化してください。 - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal アクセルを踏むと openpilot を中断 @@ -1003,7 +1003,7 @@ location set 分割画面表示の場合、ディスプレイの左側にマップを表示します。 - Experimental mode + Experimental Mode diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index 9409f82a1d..0bbae22517 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -967,7 +967,7 @@ location set 운전자 카메라에서 데이터를 업로드하고 운전자 모니터링 알고리즘을 개선합니다. - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control openpilot 롱컨트롤 (실험적) @@ -979,7 +979,7 @@ location set openpilot 롱컨트롤을 활성화합니다. (실험적) - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal 가속페달 조작시 해제 @@ -1003,7 +1003,7 @@ location set 분할 화면 보기에서 지도를 왼쪽에 표시합니다. - Experimental mode + Experimental Mode 실험 모드 diff --git a/selfdrive/ui/translations/main_nl.ts b/selfdrive/ui/translations/main_nl.ts index 24d2031f31..10651a4160 100644 --- a/selfdrive/ui/translations/main_nl.ts +++ b/selfdrive/ui/translations/main_nl.ts @@ -1007,7 +1007,7 @@ ingesteld Upload gegevens van de bestuurders camera en help het algoritme voor het monitoren van de bestuurder te verbeteren. - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal Deactiveren Met Gaspedaal @@ -1043,7 +1043,7 @@ ingesteld - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control diff --git a/selfdrive/ui/translations/main_pl.ts b/selfdrive/ui/translations/main_pl.ts index bdce181375..4f8b03ef50 100644 --- a/selfdrive/ui/translations/main_pl.ts +++ b/selfdrive/ui/translations/main_pl.ts @@ -1011,7 +1011,7 @@ nie zostało ustawione Prześlij dane z kamery skierowanej na kierowcę i pomóż poprawiać algorytm monitorowania kierowcy. - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal Odłącz poprzez naciśnięcie gazu @@ -1047,7 +1047,7 @@ nie zostało ustawione - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 55ae75d20e..702702a8be 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -971,7 +971,7 @@ trabalho definido Upload dados da câmera voltada para o motorista e ajude a melhorar o algoritmo de monitoramentor. - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control Controle longitudinal experimental openpilot @@ -983,7 +983,7 @@ trabalho definido Habilite o controle longitudinal experimental para habilitar isso. - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal Desacionar Com Pedal Do Acelerador @@ -1007,7 +1007,7 @@ trabalho definido Exibir mapa do lado esquerdo quando a tela for dividida. - Experimental mode + Experimental Mode Modo Experimental diff --git a/selfdrive/ui/translations/main_th.ts b/selfdrive/ui/translations/main_th.ts index 95880e69c9..0de0ba5f9a 100644 --- a/selfdrive/ui/translations/main_th.ts +++ b/selfdrive/ui/translations/main_th.ts @@ -951,7 +951,7 @@ location set อัปโหลดข้อมูลจากกล้องที่หันหน้าไปทางคนขับ และช่วยปรับปรุงอัลกอริธึมการตรวจสอบผู้ขับขี่ - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal ยกเลิกระบบช่วยขับเมื่อเหยียบคันเร่ง @@ -979,7 +979,7 @@ location set 🌮 ควบคุมเร่ง/เบรคแบบ End-to-end (อยู่ขั้นพัฒนา) 🌮 - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control ทดลองใช้ระบบควบคุมการเร่ง/เบรคโดย openpilot diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 165aacfa5a..558a6cec4f 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -965,7 +965,7 @@ location set 上传驾驶员摄像头的数据,帮助改进驾驶员监控算法。 - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control @@ -977,7 +977,7 @@ location set - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal 踩油门时取消控制 @@ -1001,7 +1001,7 @@ location set 在分屏模式中,将地图置于屏幕左侧。 - Experimental mode + Experimental Mode diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index e3cd908d18..0f6bc981cf 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -967,7 +967,7 @@ location set 上傳駕駛監控的錄像來協助我們提升駕駛監控的準確率。 - Experimental openpilot longitudinal control + Experimental openpilot Longitudinal Control 使用 openpilot 縱向控制(實驗) @@ -979,7 +979,7 @@ location set 打開縱向控制(實驗)以啟用此功能。 - Disengage On Accelerator Pedal + Disengage on Accelerator Pedal 油門取消控車 @@ -1003,7 +1003,7 @@ location set 進入分割畫面後,地圖將會顯示在畫面的左側。 - Experimental mode + Experimental Mode From 5eaf525c18becad63205fd3add4bfe540f70b01a Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Wed, 9 Nov 2022 21:49:24 -0800 Subject: [PATCH 52/54] camerad: fix OX flicker (#26439) --- system/camerad/cameras/camera_qcom2.cc | 28 +++++++++++--------------- system/camerad/cameras/camera_qcom2.h | 3 ++- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/system/camerad/cameras/camera_qcom2.cc b/system/camerad/cameras/camera_qcom2.cc index 78848af5be..2ee06e372a 100644 --- a/system/camerad/cameras/camera_qcom2.cc +++ b/system/camerad/cameras/camera_qcom2.cc @@ -80,30 +80,26 @@ const float sensor_analog_gains_AR0231[] = { 7.0/2.0, 8.0/2.0, 8.0/1.0}; // 12, 13, 14, 15 = bypass const float sensor_analog_gains_OX03C10[] = { - 1.0, 1.125, 1.25, 1.3125, 1.5625, - 1.6875, 2.0, 2.25, 2.625, 3.125, - 3.625, 4.0, 4.5, 5.0, 5.5, - 6.0, 6.5, 7.0, 7.5, 8.0, - 8.5, 9.0, 9.5, 10.0, 10.5, - 11.0, 11.5, 12.0, 12.5, 13.0, - 13.5, 14.0, 14.5, 15.0, 15.5}; + 1.0, 1.0625, 1.125, 1.1875, 1.25, 1.3125, 1.375, 1.4375, 1.5, 1.5625, 1.6875, + 1.8125, 1.9375, 2.0, 2.125, 2.25, 2.375, 2.5, 2.625, 2.75, 2.875, 3.0, + 3.125, 3.375, 3.625, 3.875, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, + 5.75, 6.0, 6.25, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, + 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5, 15.0, 15.5}; const uint32_t ox03c10_analog_gains_reg[] = { - 0x100, 0x120, 0x140, 0x150, 0x190, - 0x1B0, 0x200, 0x240, 0x2A0, 0x320, - 0x3A0, 0x400, 0x480, 0x500, 0x580, - 0x600, 0x680, 0x700, 0x780, 0x800, - 0x880, 0x900, 0x980, 0xA00, 0xA80, - 0xB00, 0xB80, 0xC00, 0xC80, 0xD00, - 0xD80, 0xE00, 0xE80, 0xF00, 0xF80}; + 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1B0, + 0x1D0, 0x1F0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300, + 0x320, 0x360, 0x3A0, 0x3E0, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580, + 0x5C0, 0x600, 0x640, 0x680, 0x700, 0x780, 0x800, 0x880, 0x900, 0x980, 0xA00, + 0xA80, 0xB00, 0xB80, 0xC00, 0xC80, 0xD00, 0xD80, 0xE00, 0xE80, 0xF00, 0xF80}; const int ANALOG_GAIN_MIN_IDX_AR0231 = 0x1; // 0.25x const int ANALOG_GAIN_REC_IDX_AR0231 = 0x6; // 0.8x const int ANALOG_GAIN_MAX_IDX_AR0231 = 0xD; // 4.0x const int ANALOG_GAIN_MIN_IDX_OX03C10 = 0x0; -const int ANALOG_GAIN_REC_IDX_OX03C10 = 0x6; // 2x -const int ANALOG_GAIN_MAX_IDX_OX03C10 = 0x22; +const int ANALOG_GAIN_REC_IDX_OX03C10 = 0x11; // 2.5x +const int ANALOG_GAIN_MAX_IDX_OX03C10 = 0x36; const int EXPOSURE_TIME_MIN_AR0231 = 2; // with HDR, fastest ss const int EXPOSURE_TIME_MAX_AR0231 = 0x0855; // with HDR, slowest ss, 40ms diff --git a/system/camerad/cameras/camera_qcom2.h b/system/camerad/cameras/camera_qcom2.h index 5023c82458..1e25e605c5 100644 --- a/system/camerad/cameras/camera_qcom2.h +++ b/system/camerad/cameras/camera_qcom2.h @@ -12,6 +12,7 @@ #include "common/util.h" #define FRAME_BUF_COUNT 4 +#define ANALOG_GAIN_MAX_CNT 55 class CameraState { public: @@ -36,7 +37,7 @@ public: float dc_gain_on_grey; float dc_gain_off_grey; - float sensor_analog_gains[35]; + float sensor_analog_gains[ANALOG_GAIN_MAX_CNT]; int analog_gain_min_idx; int analog_gain_max_idx; int analog_gain_rec_idx; From 737408066895452f31f08144c129551b94e64662 Mon Sep 17 00:00:00 2001 From: YassineYousfi Date: Wed, 9 Nov 2022 22:04:57 -0800 Subject: [PATCH 53/54] min lane change speed 20mph (#26434) --- selfdrive/controls/lib/desire_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/controls/lib/desire_helper.py b/selfdrive/controls/lib/desire_helper.py index d41d6780e3..4790b8f0eb 100644 --- a/selfdrive/controls/lib/desire_helper.py +++ b/selfdrive/controls/lib/desire_helper.py @@ -5,7 +5,7 @@ from common.realtime import DT_MDL LaneChangeState = log.LateralPlan.LaneChangeState LaneChangeDirection = log.LateralPlan.LaneChangeDirection -LANE_CHANGE_SPEED_MIN = 15 * CV.MPH_TO_MS +LANE_CHANGE_SPEED_MIN = 20 * CV.MPH_TO_MS LANE_CHANGE_TIME_MAX = 10. DESIRES = { From b320ac6c237eb0d31ab54227066e8ea6ba0f4dec Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Thu, 10 Nov 2022 14:05:18 +0800 Subject: [PATCH 54/54] Cabana: improve the BinaryView & fix known issues (#26409) * fix flipping issue * dragging up to create little endian signal * transform between little & big endian * complete selection functions * scroll to top after msg updated * remove empty line * cleanup code * remove extra semicolon * fix indentation * minmax * dont select hex column * create msg if not existed --- tools/cabana/binaryview.cc | 153 +++++++++++++++++------------------ tools/cabana/binaryview.h | 14 ++-- tools/cabana/dbcmanager.cc | 6 +- tools/cabana/dbcmanager.h | 2 +- tools/cabana/detailwidget.cc | 42 ++++++---- tools/cabana/detailwidget.h | 2 +- tools/cabana/signaledit.cc | 14 +++- 7 files changed, 127 insertions(+), 106 deletions(-) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index ba50b101fc..678fe5f876 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -13,6 +13,10 @@ const int CELL_HEIGHT = 26; +inline int get_bit_index(const QModelIndex &index, bool little_endian) { + return index.row() * 8 + (little_endian ? 7 - index.column() : index.column()); +} + BinaryView::BinaryView(QWidget *parent) : QTableView(parent) { model = new BinaryViewModel(this); setModel(model); @@ -37,31 +41,49 @@ void BinaryView::highlight(const Signal *sig) { } void BinaryView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) { - QModelIndex tl = indexAt({qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom())}); - QModelIndex br = indexAt({qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom())}); - if (!tl.isValid() || !br.isValid()) + auto index = indexAt(viewport()->mapFromGlobal(QCursor::pos())); + if (!anchor_index.isValid() || !index.isValid()) return; - if (tl < anchor_index) { - br = anchor_index; - } else if (anchor_index < br) { - tl = anchor_index; - } QItemSelection selection; - for (int row = tl.row(); row <= br.row(); ++row) { - int left_col = (row == tl.row()) ? tl.column() : 0; - int right_col = (row == br.row()) ? br.column() : 7; - selection.merge({model->index(row, left_col), model->index(row, right_col)}, flags); + auto [tl, br] = std::minmax(anchor_index, index); + if ((resize_sig && resize_sig->is_little_endian) || (!resize_sig && index < anchor_index)) { + // little_endian selection + if (tl.row() == br.row()) { + selection.merge({model->index(tl.row(), tl.column()), model->index(tl.row(), br.column())}, flags); + } else { + for (int row = tl.row(); row <= br.row(); ++row) { + int left_col = (row == br.row()) ? br.column() : 0; + int right_col = (row == tl.row()) ? tl.column() : 7; + selection.merge({model->index(row, left_col), model->index(row, right_col)}, flags); + } + } + } else { + // big endian selection + for (int row = tl.row(); row <= br.row(); ++row) { + int left_col = (row == tl.row()) ? tl.column() : 0; + int right_col = (row == br.row()) ? br.column() : 7; + selection.merge({model->index(row, left_col), model->index(row, right_col)}, flags); + } } selectionModel()->select(selection, flags); } void BinaryView::mousePressEvent(QMouseEvent *event) { delegate->setSelectionColor(style()->standardPalette().color(QPalette::Active, QPalette::Highlight)); - anchor_index = indexAt(event->pos()); - if (getResizingSignal() != nullptr) { + if (auto index = indexAt(event->pos()); index.isValid() && index.column() != 8) { + anchor_index = index; auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer(); - delegate->setSelectionColor(item->bg_color); + if (item && item->sigs.size() > 0) { + int bit_idx = get_bit_index(anchor_index, true); + for (auto s : item->sigs) { + if (bit_idx == s->lsb || bit_idx == s->msb) { + resize_sig = s; + delegate->setSelectionColor(item->bg_color); + break; + } + } + } } QTableView::mousePressEvent(event); } @@ -80,23 +102,35 @@ void BinaryView::mouseMoveEvent(QMouseEvent *event) { void BinaryView::mouseReleaseEvent(QMouseEvent *event) { QTableView::mouseReleaseEvent(event); - if (auto indexes = selectedIndexes(); !indexes.isEmpty()) { - int from = indexes.first().row() * 8 + indexes.first().column(); - int to = indexes.back().row() * 8 + indexes.back().column(); - if (auto sig = getResizingSignal()) { - auto [sig_from, sig_to] = getSignalRange(sig); - if (from >= sig_from && to <= sig_to) { // reduce size - emit(from == sig_from ? resizeSignal(sig, std::min(to + 1, sig_to), sig_to) - : resizeSignal(sig, sig_from, std::max(from - 1, sig_from))); - } else { // increase size - emit resizeSignal(sig, std::min(from, sig_from), std::max(to, sig_to)); + auto release_index = indexAt(event->pos()); + if (release_index.isValid() && anchor_index.isValid()) { + if (release_index.column() == 8) { + release_index = model->index(release_index.row(), 7); + } + bool little_endian = (resize_sig && resize_sig->is_little_endian) || (!resize_sig && release_index < anchor_index); + int release_bit_idx = get_bit_index(release_index, little_endian); + int archor_bit_idx = get_bit_index(anchor_index, little_endian); + if (resize_sig) { + auto [sig_from, sig_to] = getSignalRange(resize_sig); + int start_bit, end_bit; + if (archor_bit_idx == sig_from) { + std::tie(start_bit, end_bit) = std::minmax(release_bit_idx, sig_to); + if (start_bit >= sig_from && start_bit <= sig_to) + start_bit = std::min(start_bit + 1, sig_to); + } else { + std::tie(start_bit, end_bit) = std::minmax(release_bit_idx, sig_from); + if (end_bit >= sig_from && end_bit <= sig_to) + end_bit = std::max(end_bit - 1, sig_from); } + emit resizeSignal(resize_sig, start_bit, end_bit - start_bit + 1); } else { - emit addSignal(from, to); + auto [sart_bit, end_bit] = std::minmax(archor_bit_idx, release_bit_idx); + emit addSignal(sart_bit, end_bit - sart_bit + 1, little_endian); } - clearSelection(); } + clearSelection(); anchor_index = QModelIndex(); + resize_sig = nullptr; } void BinaryView::leaveEvent(QEvent *event) { @@ -107,34 +141,17 @@ void BinaryView::leaveEvent(QEvent *event) { void BinaryView::setMessage(const QString &message_id) { model->setMessage(message_id); clearSelection(); + anchor_index = QModelIndex(); + resize_sig = nullptr; + hovered_sig = nullptr; updateState(); } -const Signal *BinaryView::getResizingSignal() const { - if (anchor_index.isValid()) { - auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer(); - if (item && item->sigs.size() > 0) { - int archor_pos = anchor_index.row() * 8 + anchor_index.column(); - for (auto s : item->sigs) { - auto [sig_from, sig_to] = getSignalRange(s); - if (archor_pos == sig_from || archor_pos == sig_to) - return s; - } - } - } - return nullptr; -} - QSet BinaryView::getOverlappingSignals() const { QSet overlapping; - for (int i = 0; i < model->rowCount(); ++i) { - for (int j = 0; j < model->columnCount() - 1; ++j) { - auto item = (const BinaryViewModel::Item *)model->index(i, j).internalPointer(); - if (item && item->sigs.size() > 1) { - for (auto s : item->sigs) - overlapping.insert(s); - } - } + for (auto &item : model->items) { + if (item.sigs.size() > 1) + for (auto s : item.sigs) overlapping += s; } return overlapping; } @@ -142,53 +159,37 @@ QSet BinaryView::getOverlappingSignals() const { // BinaryViewModel void BinaryViewModel::setMessage(const QString &message_id) { - msg_id = message_id; - beginResetModel(); + msg_id = message_id; items.clear(); - row_count = 0; - - dbc_msg = dbc()->msg(msg_id); - if (dbc_msg) { + if ((dbc_msg = dbc()->msg(msg_id))) { row_count = dbc_msg->size; items.resize(row_count * column_count); for (int i = 0; i < dbc_msg->sigs.size(); ++i) { const auto &sig = dbc_msg->sigs[i]; auto [start, end] = getSignalRange(&sig); for (int j = start; j <= end; ++j) { - int idx = column_count * (j / 8) + j % 8; + int bit_index = sig.is_little_endian ? bigEndianBitIndex(j) : j; + int idx = column_count * (bit_index / 8) + bit_index % 8; if (idx >= items.size()) { qWarning() << "signal " << sig.name.c_str() << "out of bounds.start_bit:" << sig.start_bit << "size:" << sig.size; break; } - if (j == start) { - sig.is_little_endian ? items[idx].is_lsb = true : items[idx].is_msb = true; - } else if (j == end) { - sig.is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true; - } + if (j == start) sig.is_little_endian ? items[idx].is_lsb = true : items[idx].is_msb = true; + if (j == end) sig.is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true; items[idx].bg_color = getColor(i); - items[idx].sigs.push_back(&dbc_msg->sigs[i]); + items[idx].sigs.push_back(&sig); } } } else { row_count = can->lastMessage(msg_id).dat.size(); items.resize(row_count * column_count); } - endResetModel(); } -QModelIndex BinaryViewModel::index(int row, int column, const QModelIndex &parent) const { - return createIndex(row, column, (void *)&items[row * column_count + column]); -} - -Qt::ItemFlags BinaryViewModel::flags(const QModelIndex &index) const { - return (index.column() == column_count - 1) ? Qt::ItemIsEnabled : Qt::ItemIsEnabled | Qt::ItemIsSelectable; -} - void BinaryViewModel::updateState() { auto prev_items = items; - const auto &binary = can->lastMessage(msg_id).dat; // data size may changed. if (!dbc_msg && binary.size() != row_count) { @@ -198,7 +199,6 @@ void BinaryViewModel::updateState() { items.resize(row_count * column_count); endResetModel(); } - char hex[3] = {'\0'}; for (int i = 0; i < std::min(binary.size(), row_count); ++i) { for (int j = 0; j < column_count - 1; ++j) { @@ -248,9 +248,8 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op BinaryView *bin_view = (BinaryView *)parent(); painter->save(); - bool hover = std::find_if(item->sigs.begin(), item->sigs.end(), [=](auto s) { return s == bin_view->hoveredSignal(); }) != - item->sigs.end(); // background + bool hover = item->sigs.contains(bin_view->hoveredSignal()); QColor bg_color = hover ? hoverColor(item->bg_color) : item->bg_color; if (option.state & QStyle::State_Selected) { bg_color = selection_color; @@ -258,7 +257,7 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op painter->fillRect(option.rect, bg_color); // text - if (index.column() == 8) { // hex column + if (index.column() == 8) { // hex column painter->setFont(hex_font); } else if (hover) { painter->setPen(Qt::white); diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index a907a673bf..05bfe7e79f 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -28,12 +28,16 @@ public: BinaryViewModel(QObject *parent) : QAbstractTableModel(parent) {} void setMessage(const QString &message_id); void updateState(); - Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const { return {}; } int rowCount(const QModelIndex &parent = QModelIndex()) const override { return row_count; } int columnCount(const QModelIndex &parent = QModelIndex()) const override { return column_count; } + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override { + return createIndex(row, column, (void *)&items[row * column_count + column]); + } + Qt::ItemFlags flags(const QModelIndex &index) const override { + return (index.column() == column_count - 1) ? Qt::ItemIsEnabled : Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } struct Item { QColor bg_color = QColor(Qt::white); @@ -42,13 +46,13 @@ public: QString val = "0"; QList sigs; }; + std::vector items; private: QString msg_id; const Msg *dbc_msg; int row_count = 0; const int column_count = 9; - std::vector items; }; class BinaryView : public QTableView { @@ -64,7 +68,7 @@ public: signals: void signalHovered(const Signal *sig); - void addSignal(int from, int size); + void addSignal(int start_bit, int size, bool little_endian); void resizeSignal(const Signal *sig, int from, int size); private: @@ -73,10 +77,10 @@ private: void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void leaveEvent(QEvent *event) override; - const Signal *getResizingSignal() const; QModelIndex anchor_index; BinaryViewModel *model; BinaryItemDelegate *delegate; + const Signal *resize_sig = nullptr; const Signal *hovered_sig = nullptr; }; diff --git a/tools/cabana/dbcmanager.cc b/tools/cabana/dbcmanager.cc index 184fab38eb..abdd9a08df 100644 --- a/tools/cabana/dbcmanager.cc +++ b/tools/cabana/dbcmanager.cc @@ -147,9 +147,9 @@ double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig) { return value; } -void updateSigSizeParamsFromRange(Signal &s, int from, int to) { - s.start_bit = s.is_little_endian ? from : bigEndianBitIndex(from); - s.size = to - from + 1; +void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size) { + s.start_bit = s.is_little_endian ? start_bit : bigEndianBitIndex(start_bit); + s.size = size; if (s.is_little_endian) { s.lsb = s.start_bit; s.msb = s.start_bit + s.size - 1; diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index 2b6aca41d7..81c723a20d 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -49,7 +49,7 @@ private: double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig); int bigEndianStartBitsIndex(int start_bit); int bigEndianBitIndex(int index); -void updateSigSizeParamsFromRange(Signal &s, int from, int to); +void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size); std::pair getSignalRange(const Signal *s); DBCManager *dbc(); inline QString msgName(const QString &id, const char *def = "untitled") { diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 287c75a617..f96b60847b 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -130,15 +130,13 @@ void DetailWidget::setMessage(const QString &message_id) { break; } } + msg_id = message_id; if (index == -1) { index = tabbar->addTab(message_id); tabbar->setTabToolTip(index, msgName(message_id)); } tabbar->setCurrentIndex(index); - msg_id = message_id; dbcMsgChanged(); - - scroll->verticalScrollBar()->setValue(0); } void DetailWidget::dbcMsgChanged(int show_form_idx) { @@ -187,6 +185,7 @@ void DetailWidget::dbcMsgChanged(int show_form_idx) { warning_label->setText(warnings.join('\n')); warning_widget->setVisible(!warnings.isEmpty()); setUpdatesEnabled(true); + scroll->verticalScrollBar()->setValue(0); } void DetailWidget::updateState() { @@ -232,24 +231,34 @@ void DetailWidget::removeMsg() { } } -void DetailWidget::addSignal(int from, int to) { - if (auto msg = dbc()->msg(msg_id)) { - Signal sig = {}; +void DetailWidget::addSignal(int start_bit, int size, bool little_endian) { + auto msg = dbc()->msg(msg_id); + if (!msg) { for (int i = 1; /**/; ++i) { - sig.name = "NEW_SIGNAL_" + std::to_string(i); - auto it = std::find_if(msg->sigs.begin(), msg->sigs.end(), [&](auto &s) { return sig.name == s.name; }); - if (it == msg->sigs.end()) break; + std::string name = "NEW_MSG_" + std::to_string(i); + auto it = std::find_if(dbc()->getDBC()->msgs.begin(), dbc()->getDBC()->msgs.end(), [&](auto &m) { return m.name == name; }); + if (it == dbc()->getDBC()->msgs.end()) { + dbc()->updateMsg(msg_id, name.c_str(), can->lastMessage(msg_id).dat.size()); + msg = dbc()->msg(msg_id); + break; + } } - sig.is_little_endian = false, - updateSigSizeParamsFromRange(sig, from, to); - dbc()->addSignal(msg_id, sig); - dbcMsgChanged(msg->sigs.size() - 1); } + Signal sig = {}; + for (int i = 1; /**/; ++i) { + sig.name = "NEW_SIGNAL_" + std::to_string(i); + auto it = std::find_if(msg->sigs.begin(), msg->sigs.end(), [&](auto &s) { return sig.name == s.name; }); + if (it == msg->sigs.end()) break; + } + sig.is_little_endian = little_endian; + updateSigSizeParamsFromRange(sig, start_bit, size); + dbc()->addSignal(msg_id, sig); + dbcMsgChanged(msg->sigs.size() - 1); } -void DetailWidget::resizeSignal(const Signal *sig, int from, int to) { +void DetailWidget::resizeSignal(const Signal *sig, int start_bit, int size) { Signal s = *sig; - updateSigSizeParamsFromRange(s, from, to); + updateSigSizeParamsFromRange(s, start_bit, size); saveSignal(sig, s); } @@ -272,8 +281,7 @@ void DetailWidget::saveSignal(const Signal *sig, const Signal &new_sig) { } dbc()->updateSignal(msg_id, sig->name.c_str(), new_sig); - // update binary view and history log - updateState(); + dbcMsgChanged(); } void DetailWidget::removeSignal(const Signal *sig) { diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index 7cb3a505ee..915e0bde60 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -30,7 +30,7 @@ public: private: void updateChartState(const QString &id, const Signal *sig, bool opened); void showTabBarContextMenu(const QPoint &pt); - void addSignal(int start_bit, int to); + void addSignal(int start_bit, int size, bool little_endian); void resizeSignal(const Signal *sig, int from, int to); void saveSignal(const Signal *sig, const Signal &new_sig); void removeSignal(const Signal *sig); diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index ee91887d0a..99365294b8 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -28,7 +28,6 @@ SignalForm::SignalForm(QWidget *parent) : QWidget(parent) { endianness->addItems({"Little", "Big"}); form_layout->addRow(tr("Endianness"), endianness); - ; form_layout->addRow(tr("lsb"), lsb = new QLabel()); form_layout->addRow(tr("msb"), msb = new QLabel()); @@ -130,7 +129,18 @@ void SignalEdit::saveSignal() { s.offset = form->offset->text().toDouble(); s.factor = form->factor->text().toDouble(); s.is_signed = form->sign->currentIndex() == 0; - s.is_little_endian = form->endianness->currentIndex() == 0; + bool little_endian = form->endianness->currentIndex() == 0; + if (little_endian != s.is_little_endian) { + int start = std::floor(s.start_bit / 8); + if (little_endian) { + int end = std::floor((s.start_bit - s.size + 1) / 8); + s.start_bit = start == end ? s.start_bit - s.size + 1 : bigEndianStartBitsIndex(s.start_bit); + } else { + int end = std::floor((s.start_bit + s.size - 1) / 8); + s.start_bit = start == end ? s.start_bit + s.size - 1 : bigEndianBitIndex(s.start_bit); + } + s.is_little_endian = little_endian; + } if (s.is_little_endian) { s.lsb = s.start_bit; s.msb = s.start_bit + s.size - 1;