Skip to content

Commit

Permalink
cabana: support suppress highlighted bits (commaai#30336)
Browse files Browse the repository at this point in the history
* support suppress highlighted bits

d

* faster filtering and sorting

* improve livestream

* specify the context in the connections

* remove inline
  • Loading branch information
deanlee authored Oct 30, 2023
1 parent 61288df commit 0161012
Show file tree
Hide file tree
Showing 35 changed files with 464 additions and 516 deletions.
16 changes: 6 additions & 10 deletions tools/cabana/binaryview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <algorithm>

#include <QDebug>
#include <QFontDatabase>
#include <QHeaderView>
#include <QMouseEvent>
Expand Down Expand Up @@ -273,7 +274,7 @@ void BinaryViewModel::refresh() {
row_count = can->lastMessage(msg_id).dat.size();
items.resize(row_count * column_count);
}
int valid_rows = std::min(can->lastMessage(msg_id).dat.size(), row_count);
int valid_rows = std::min<int>(can->lastMessage(msg_id).dat.size(), row_count);
for (int i = 0; i < valid_rows * column_count; ++i) {
items[i].valid = true;
}
Expand Down Expand Up @@ -311,7 +312,7 @@ void BinaryViewModel::updateState() {
int val = ((binary[i] >> (7 - j)) & 1) != 0 ? 1 : 0;
// Bit update frequency based highlighting
double offset = !item.sigs.empty() ? 50 : 0;
auto n = last_msg.bit_change_counts[i][7 - j];
auto n = last_msg.last_changes[i].bit_change_counts[j];
double min_f = n == 0 ? offset : offset + 25;
double alpha = std::clamp(offset + log2(1.0 + factor * (double)n / (double)last_msg.count) * scaler, min_f, max_f);
auto color = item.bg_color;
Expand All @@ -334,13 +335,8 @@ QVariant BinaryViewModel::headerData(int section, Qt::Orientation orientation, i
}

QVariant BinaryViewModel::data(const QModelIndex &index, int role) const {
if (role == Qt::ToolTipRole) {
auto item = (const BinaryViewModel::Item *)index.internalPointer();
if (item && !item->sigs.empty()) {
return signalToolTip(item->sigs.back());
}
}
return {};
auto item = (const BinaryViewModel::Item *)index.internalPointer();
return role == Qt::ToolTipRole && item && !item->sigs.empty() ? signalToolTip(item->sigs.back()) : QVariant();
}

// BinaryItemDelegate
Expand Down Expand Up @@ -388,7 +384,7 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
drawSignalCell(painter, option, index, s);
}
}
} else if (item->valid) {
} else if (item->valid && item->bg_color.alpha() > 0) {
painter->fillRect(option.rect, item->bg_color);
}
auto color_role = item->sigs.contains(bin_view->hovered_sig) ? QPalette::BrightText : QPalette::Text;
Expand Down
4 changes: 2 additions & 2 deletions tools/cabana/chart/chartswidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : align_timer(this), auto_scroll_tim
QObject::connect(&auto_scroll_timer, &QTimer::timeout, this, &ChartsWidget::doAutoScroll);
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &ChartsWidget::removeAll);
QObject::connect(can, &AbstractStream::eventsMerged, this, &ChartsWidget::eventsMerged);
QObject::connect(can, &AbstractStream::updated, this, &ChartsWidget::updateState);
QObject::connect(can, &AbstractStream::msgsReceived, this, &ChartsWidget::updateState);
QObject::connect(range_slider, &QSlider::valueChanged, this, &ChartsWidget::setMaxChartRange);
QObject::connect(new_plot_btn, &QToolButton::clicked, this, &ChartsWidget::newChart);
QObject::connect(remove_all_btn, &QToolButton::clicked, this, &ChartsWidget::removeAll);
Expand Down Expand Up @@ -324,7 +324,7 @@ void ChartsWidget::updateLayout(bool force) {
charts_layout->addWidget(current_charts[i], i / n, i % n);
if (current_charts[i]->sigs.empty()) {
// the chart will be resized after add signal. delay setVisible to reduce flicker.
QTimer::singleShot(0, [c = current_charts[i]]() { c->setVisible(true); });
QTimer::singleShot(0, current_charts[i], [c = current_charts[i]]() { c->setVisible(true); });
} else {
current_charts[i]->setVisible(true);
}
Expand Down
6 changes: 3 additions & 3 deletions tools/cabana/chart/signalselector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ SignalSelector::SignalSelector(QString title, QWidget *parent) : QDialog(parent)
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
main_layout->addWidget(buttonBox, 3, 2);

for (auto it = can->last_msgs.cbegin(); it != can->last_msgs.cend(); ++it) {
if (auto m = dbc()->msg(it.key())) {
msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(it.key().toString()), QVariant::fromValue(it.key()));
for (const auto &[id, _] : can->lastMessages()) {
if (auto m = dbc()->msg(id)) {
msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(id.toString()), QVariant::fromValue(id));
}
}
msgs_combo->model()->sort(0);
Expand Down
6 changes: 2 additions & 4 deletions tools/cabana/dbc/dbcfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
#include <QFileInfo>
#include <QRegularExpression>
#include <QTextStream>
#include <numeric>
#include <sstream>

DBCFile::DBCFile(const QString &dbc_file_name, QObject *parent) : QObject(parent) {
DBCFile::DBCFile(const QString &dbc_file_name) {
QFile file(dbc_file_name);
if (file.open(QIODevice::ReadOnly)) {
name_ = QFileInfo(dbc_file_name).baseName();
Expand All @@ -22,7 +20,7 @@ DBCFile::DBCFile(const QString &dbc_file_name, QObject *parent) : QObject(parent
}
}

DBCFile::DBCFile(const QString &name, const QString &content, QObject *parent) : QObject(parent), name_(name), filename("") {
DBCFile::DBCFile(const QString &name, const QString &content) : name_(name), filename("") {
// Open from clipboard
parse(content);
}
Expand Down
9 changes: 3 additions & 6 deletions tools/cabana/dbc/dbcfile.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
#pragma once

#include <map>
#include <QObject>

#include "tools/cabana/dbc/dbc.h"

const QString AUTO_SAVE_EXTENSION = ".tmp";

class DBCFile : public QObject {
Q_OBJECT

class DBCFile {
public:
DBCFile(const QString &dbc_file_name, QObject *parent=nullptr);
DBCFile(const QString &name, const QString &content, QObject *parent=nullptr);
DBCFile(const QString &dbc_file_name);
DBCFile(const QString &name, const QString &content);
~DBCFile() {}

bool save();
Expand Down
11 changes: 9 additions & 2 deletions tools/cabana/dbc/dbcmanager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ bool DBCManager::open(const SourceSet &sources, const QString &dbc_file_name, QS
try {
auto it = std::find_if(dbc_files.begin(), dbc_files.end(),
[&](auto &f) { return f.second && f.second->filename == dbc_file_name; });
auto file = (it != dbc_files.end()) ? it->second : std::make_shared<DBCFile>(dbc_file_name, this);
auto file = (it != dbc_files.end()) ? it->second : std::make_shared<DBCFile>(dbc_file_name);
for (auto s : sources) {
dbc_files[s] = file;
}
Expand All @@ -22,7 +22,7 @@ bool DBCManager::open(const SourceSet &sources, const QString &dbc_file_name, QS

bool DBCManager::open(const SourceSet &sources, const QString &name, const QString &content, QString *error) {
try {
auto file = std::make_shared<DBCFile>(name, content, this);
auto file = std::make_shared<DBCFile>(name, content);
for (auto s : sources) {
dbc_files[s] = file;
}
Expand Down Expand Up @@ -189,6 +189,13 @@ const SourceSet DBCManager::sources(const DBCFile *dbc_file) const {
return sources;
}

QString toString(const SourceSet &ss) {
return std::accumulate(ss.cbegin(), ss.cend(), QString(), [](QString str, int source) {
if (!str.isEmpty()) str += ", ";
return str + (source == -1 ? QStringLiteral("all") : QString::number(source));
});
}

DBCManager *dbc() {
static DBCManager dbc_manager(nullptr);
return &dbc_manager;
Expand Down
10 changes: 2 additions & 8 deletions tools/cabana/dbc/dbcmanager.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <QObject>
#include <memory>
#include <map>
#include <set>
Expand Down Expand Up @@ -66,15 +67,8 @@ class DBCManager : public QObject {

DBCManager *dbc();

QString toString(const SourceSet &ss);
inline QString msgName(const MessageId &id) {
auto msg = dbc()->msg(id);
return msg ? msg->name : UNTITLED;
}

inline QString toString(const SourceSet &ss) {
QStringList ret;
for (auto s : ss) {
ret << (s == -1 ? QString("all") : QString::number(s));
}
return ret.join(", ");
}
4 changes: 2 additions & 2 deletions tools/cabana/detailwidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ void DetailWidget::refresh() {
warning_widget->setVisible(!warnings.isEmpty());
}

void DetailWidget::updateState(const QHash<MessageId, CanData> *msgs) {
if ((msgs && !msgs->contains(msg_id)))
void DetailWidget::updateState(const std::set<MessageId> *msgs) {
if ((msgs && !msgs->count(msg_id)))
return;

if (tab_widget->currentIndex() == 0)
Expand Down
4 changes: 2 additions & 2 deletions tools/cabana/detailwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
#include <QSplitter>
#include <QTabWidget>
#include <QTextEdit>
#include <set>

#include "selfdrive/ui/qt/widgets/controls.h"
#include "tools/cabana/binaryview.h"
#include "tools/cabana/chart/chartswidget.h"
#include "tools/cabana/historylog.h"
#include "tools/cabana/signalview.h"

class MainWindow;
class EditMessageDialog : public QDialog {
public:
EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent);
Expand Down Expand Up @@ -39,7 +39,7 @@ class DetailWidget : public QWidget {
void showTabBarContextMenu(const QPoint &pt);
void editMsg();
void removeMsg();
void updateState(const QHash<MessageId, CanData> * msgs = nullptr);
void updateState(const std::set<MessageId> *msgs = nullptr);

MessageId msg_id;
QLabel *warning_icon, *warning_label;
Expand Down
22 changes: 11 additions & 11 deletions tools/cabana/historylog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include <QVBoxLayout>

#include "tools/cabana/commands.h"
// HistoryLogModel

QVariant HistoryLogModel::data(const QModelIndex &index, int role) const {
const bool show_signals = display_signals_mode && sigs.size() > 0;
Expand All @@ -17,11 +16,11 @@ QVariant HistoryLogModel::data(const QModelIndex &index, int role) const {
return QString::number((m.mono_time / (double)1e9) - can->routeStartTime(), 'f', 2);
}
int i = index.column() - 1;
return show_signals ? QString::number(m.sig_values[i], 'f', sigs[i]->precision) : toHex(m.data);
return show_signals ? QString::number(m.sig_values[i], 'f', sigs[i]->precision) : QString();
} else if (role == ColorsRole) {
return QVariant::fromValue(m.colors);
return QVariant::fromValue((void *)(&m.colors));
} else if (role == BytesRole) {
return m.data;
return QVariant::fromValue((void *)(&m.data));
} else if (role == Qt::TextAlignmentRole) {
return (uint32_t)(Qt::AlignRight | Qt::AlignVCenter);
}
Expand Down Expand Up @@ -123,7 +122,7 @@ void HistoryLogModel::fetchMore(const QModelIndex &parent) {
template <class InputIt>
std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(InputIt first, InputIt last, uint64_t min_time) {
std::deque<HistoryLogModel::Message> msgs;
QVector<double> values(sigs.size());
std::vector<double> values(sigs.size());
for (; first != last && (*first)->mono_time > min_time; ++first) {
const CanEvent *e = *first;
for (int i = 0; i < sigs.size(); ++i) {
Expand All @@ -132,7 +131,7 @@ std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(InputIt first, I
if (!filter_cmp || filter_cmp(values[filter_sig_idx], filter_value)) {
auto &m = msgs.emplace_back();
m.mono_time = e->mono_time;
m.data = QByteArray((const char *)e->dat, e->size);
m.data.assign(e->dat, e->dat + e->size);
m.sig_values = values;
if (msgs.size() >= batch_size && min_time == 0) {
return msgs;
Expand All @@ -146,7 +145,7 @@ std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(uint64_t from_ti
const auto &events = can->events(msg_id);
const auto freq = can->lastMessage(msg_id).freq;
const bool update_colors = !display_signals_mode || sigs.empty();

const std::vector<uint8_t> no_mask;
const auto speed = can->getSpeed();
if (dynamic_mode) {
auto first = std::upper_bound(events.rbegin(), events.rend(), from_time, [](uint64_t ts, auto e) {
Expand All @@ -155,7 +154,7 @@ std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(uint64_t from_ti
auto msgs = fetchData(first, events.rend(), min_time);
if (update_colors && (min_time > 0 || messages.empty())) {
for (auto it = msgs.rbegin(); it != msgs.rend(); ++it) {
hex_colors.compute(msg_id, it->data.data(), it->data.size(), it->mono_time / (double)1e9, speed, nullptr, freq);
hex_colors.compute(msg_id, it->data.data(), it->data.size(), it->mono_time / (double)1e9, speed, no_mask, freq);
it->colors = hex_colors.colors;
}
}
Expand All @@ -166,7 +165,7 @@ std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(uint64_t from_ti
auto msgs = fetchData(first, events.cend(), 0);
if (update_colors) {
for (auto it = msgs.begin(); it != msgs.end(); ++it) {
hex_colors.compute(msg_id, it->data.data(), it->data.size(), it->mono_time / (double)1e9, speed, nullptr, freq);
hex_colors.compute(msg_id, it->data.data(), it->data.size(), it->mono_time / (double)1e9, speed, no_mask, freq);
it->colors = hex_colors.colors;
}
}
Expand All @@ -177,7 +176,7 @@ std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(uint64_t from_ti
// HeaderView

QSize HeaderView::sectionSizeFromContents(int logicalIndex) const {
static QSize time_col_size = fontMetrics().boundingRect({0, 0, 200, 200}, defaultAlignment(), "000000.000").size() + QSize(10, 6);
static const QSize time_col_size = fontMetrics().boundingRect({0, 0, 200, 200}, defaultAlignment(), "000000.000").size() + QSize(10, 6);
if (logicalIndex == 0) {
return time_col_size;
} else {
Expand Down Expand Up @@ -237,10 +236,11 @@ LogsWidget::LogsWidget(QWidget *parent) : QFrame(parent) {
main_layout->addWidget(logs = new QTableView(this));
logs->setModel(model = new HistoryLogModel(this));
delegate = new MessageBytesDelegate(this);
logs->setItemDelegateForColumn(1, new MessageBytesDelegate(this));
logs->setHorizontalHeader(new HeaderView(Qt::Horizontal, this));
logs->horizontalHeader()->setDefaultAlignment(Qt::AlignRight | (Qt::Alignment)Qt::TextWordWrap);
logs->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
logs->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
logs->verticalHeader()->setDefaultSectionSize(delegate->sizeForBytes(8).height());
logs->verticalHeader()->setVisible(false);
logs->setFrameShape(QFrame::NoFrame);

Expand Down
6 changes: 3 additions & 3 deletions tools/cabana/historylog.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ public slots:
public:
struct Message {
uint64_t mono_time = 0;
QVector<double> sig_values;
QByteArray data;
QVector<QColor> colors;
std::vector<double> sig_values;
std::vector<uint8_t> data;
std::vector<QColor> colors;
};

template <class InputIt>
Expand Down
27 changes: 10 additions & 17 deletions tools/cabana/mainwin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "tools/cabana/commands.h"
#include "tools/cabana/streamselector.h"
#include "tools/cabana/tools/findsignal.h"
#include "tools/replay/replay.h"

MainWindow::MainWindow() : QMainWindow() {
createDockWindows();
Expand Down Expand Up @@ -84,8 +85,8 @@ void MainWindow::createActions() {
close_stream_act->setEnabled(false);
file_menu->addSeparator();

file_menu->addAction(tr("New DBC File"), [this]() { newFile(); })->setShortcuts(QKeySequence::New);
file_menu->addAction(tr("Open DBC File..."), [this]() { openFile(); })->setShortcuts(QKeySequence::Open);
file_menu->addAction(tr("New DBC File"), [this]() { newFile(); }, QKeySequence::New);
file_menu->addAction(tr("Open DBC File..."), [this]() { openFile(); }, QKeySequence::Open);

manage_dbcs_menu = file_menu->addMenu(tr("Manage &DBC Files"));

Expand All @@ -111,19 +112,15 @@ void MainWindow::createActions() {
file_menu->addAction(tr("Load DBC From Clipboard"), [=]() { loadFromClipboard(); });

file_menu->addSeparator();
save_dbc = file_menu->addAction(tr("Save DBC..."), this, &MainWindow::save);
save_dbc->setShortcuts(QKeySequence::Save);

save_dbc_as = file_menu->addAction(tr("Save DBC As..."), this, &MainWindow::saveAs);
save_dbc_as->setShortcuts(QKeySequence::SaveAs);

save_dbc = file_menu->addAction(tr("Save DBC..."), this, &MainWindow::save, QKeySequence::Save);
save_dbc_as = file_menu->addAction(tr("Save DBC As..."), this, &MainWindow::saveAs, QKeySequence::SaveAs);
copy_dbc_to_clipboard = file_menu->addAction(tr("Copy DBC To Clipboard"), this, &MainWindow::saveToClipboard);

file_menu->addSeparator();
file_menu->addAction(tr("Settings..."), this, &MainWindow::setOption)->setShortcuts(QKeySequence::Preferences);
file_menu->addAction(tr("Settings..."), this, &MainWindow::setOption, QKeySequence::Preferences);

file_menu->addSeparator();
file_menu->addAction(tr("E&xit"), qApp, &QApplication::closeAllWindows)->setShortcuts(QKeySequence::Quit);
file_menu->addAction(tr("E&xit"), qApp, &QApplication::closeAllWindows, QKeySequence::Quit);

// Edit Menu
QMenu *edit_menu = menuBar()->addMenu(tr("&Edit"));
Expand Down Expand Up @@ -157,7 +154,7 @@ void MainWindow::createActions() {

// Help Menu
QMenu *help_menu = menuBar()->addMenu(tr("&Help"));
help_menu->addAction(tr("Help"), this, &MainWindow::onlineHelp)->setShortcuts(QKeySequence::HelpContents);
help_menu->addAction(tr("Help"), this, &MainWindow::onlineHelp, QKeySequence::HelpContents);
help_menu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
}

Expand Down Expand Up @@ -374,7 +371,7 @@ void MainWindow::eventsMerged() {
auto dbc_name = fingerprint_to_dbc[car_fingerprint];
if (dbc_name != QJsonValue::Undefined) {
// Prevent dialog that load autosaved file from blocking replay->start().
QTimer::singleShot(0, [dbc_name, this]() { loadDBCFromOpendbc(dbc_name.toString()); });
QTimer::singleShot(0, this, [dbc_name, this]() { loadDBCFromOpendbc(dbc_name.toString()); });
}
}
}
Expand Down Expand Up @@ -471,11 +468,7 @@ void MainWindow::saveFileToClipboard(DBCFile *dbc_file) {

void MainWindow::updateLoadSaveMenus() {
int cnt = dbc()->nonEmptyDBCCount();
if (cnt > 1) {
save_dbc->setText(tr("Save %1 DBCs...").arg(dbc()->dbcCount()));
} else {
save_dbc->setText(tr("Save DBC..."));
}
save_dbc->setText(cnt > 1 ? tr("Save %1 DBCs...").arg(cnt) : tr("Save DBC..."));
save_dbc->setEnabled(cnt > 0);
save_dbc_as->setEnabled(cnt == 1);

Expand Down
Loading

0 comments on commit 0161012

Please sign in to comment.