Skip to content

Commit 06a73f5

Browse files
cabana: de-Qt, part 1 (#38357)
* cabana: de-Qt, part 1 * lil more
1 parent 60716ed commit 06a73f5

41 files changed

Lines changed: 722 additions & 470 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

openpilot/tools/cabana/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ assets.cc
77
_cabana
88
dbc/car_fingerprint_to_dbc.json
99
tests/test_cabana
10+
tests/test_dbc_core

openpilot/tools/cabana/SConscript

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ cabana_env.Depends(assets_src, str(bootstrap_icons.SVG_PATH))
9797
cabana_env.Depends(assets, Glob('/assets/*', exclude=[assets, assets_src, "assets/assets.o"]))
9898

9999
cabana_srcs = ['mainwin.cc', 'streams/pandastream.cc', 'streams/devicestream.cc', 'streams/livestream.cc', 'streams/abstractstream.cc', 'streams/replaystream.cc', 'binaryview.cc', 'historylog.cc', 'videowidget.cc', 'signalview.cc',
100-
'streams/routes.cc', 'dbc/dbc.cc', 'dbc/dbcfile.cc', 'dbc/dbcmanager.cc',
100+
'streams/routes.cc', 'dbc/dbc.cc', 'dbc/dbcfile.cc', 'dbc/dbcmanager.cc', 'dbc/dbcqt.cc',
101101
'utils/export.cc', 'utils/util.cc', 'utils/elidedlabel.cc',
102102
'chart/chartswidget.cc', 'chart/chart.cc', 'chart/signalselector.cc', 'chart/tiplabel.cc', 'chart/sparkline.cc',
103103
'commands.cc', 'messageswidget.cc', 'streamselector.cc', 'settings.cc', 'panda.cc',
@@ -110,6 +110,19 @@ cabana_env.Program('_cabana', ['cabana.cc', cabana_lib, assets], LIBS=cabana_lib
110110
if GetOption('extras'):
111111
cabana_env.Program('tests/test_cabana', ['tests/test_runner.cc', 'tests/test_cabana.cc', cabana_lib], LIBS=[cabana_libs])
112112

113+
# This target deliberately uses the base environment and links no Qt libraries.
114+
# It prevents Qt dependencies from creeping back into the DBC core.
115+
dbc_core_test_env = env.Clone()
116+
dbc_core_test_env['CXXFLAGS'] += [opendbc_path]
117+
dbc_core_test_objects = [
118+
dbc_core_test_env.Object('tests/dbc_core_test_runner', 'tests/test_runner.cc'),
119+
dbc_core_test_env.Object('tests/dbc_core_tests', 'tests/test_cabana.cc'),
120+
dbc_core_test_env.Object('tests/dbc_core_model', 'dbc/dbc.cc'),
121+
dbc_core_test_env.Object('tests/dbc_core_file', 'dbc/dbcfile.cc'),
122+
dbc_core_test_env.Object('tests/dbc_core_manager', 'dbc/dbcmanager.cc'),
123+
]
124+
dbc_core_test_env.Program('tests/test_dbc_core', dbc_core_test_objects)
125+
113126
output_json_file = 'openpilot/tools/cabana/dbc/car_fingerprint_to_dbc.json'
114127
generate_dbc = cabana_env.Command('#' + output_json_file,
115128
['dbc/generate_dbc_json.py'],

openpilot/tools/cabana/binaryview.cc

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "tools/cabana/binaryview.h"
2+
#include "tools/cabana/dbc/dbcqt.h"
23

34
#include <algorithm>
45

@@ -34,7 +35,7 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) {
3435
setMouseTracking(true);
3536
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3637

37-
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &BinaryView::refresh);
38+
QObject::connect(dbcNotifier(), &QtDBCNotifier::DBCFileChanged, this, &BinaryView::refresh);
3839
QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &BinaryView::refresh);
3940

4041
addShortcuts();
@@ -334,7 +335,7 @@ void BinaryViewModel::updateState() {
334335
color.setAlpha(alpha);
335336
updateItem(i, j, bit_val, color);
336337
}
337-
updateItem(i, 8, binary[i], last_msg.colors[i]);
338+
updateItem(i, 8, binary[i], toQColor(last_msg.colors[i]));
338339
}
339340
}
340341

@@ -421,14 +422,14 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
421422
painter->fillRect(option.rect, item->bg_color);
422423
}
423424
} else if (option.state & QStyle::State_Selected) {
424-
auto color = bin_view->resize_sig ? bin_view->resize_sig->color : option.palette.color(QPalette::Active, QPalette::Highlight);
425+
auto color = bin_view->resize_sig ? toQColor(bin_view->resize_sig->color) : option.palette.color(QPalette::Active, QPalette::Highlight);
425426
painter->fillRect(option.rect, color);
426427
painter->setPen(option.palette.color(QPalette::BrightText));
427428
} else if (!bin_view->selectionModel()->hasSelection() || std::find(item->sigs.begin(), item->sigs.end(), bin_view->resize_sig) == item->sigs.end()) { // not resizing
428429
if (item->sigs.size() > 0) {
429430
for (auto &s : item->sigs) {
430431
if (s == bin_view->hovered_sig) {
431-
painter->fillRect(option.rect, s->color.darker(125)); // 4/5x brightness
432+
painter->fillRect(option.rect, toQColor(s->color.darker(125))); // 4/5x brightness
432433
} else {
433434
drawSignalCell(painter, option, index, s);
434435
}
@@ -483,14 +484,14 @@ void BinaryItemDelegate::drawSignalCell(QPainter *painter, const QStyleOptionVie
483484
painter->setClipRegion(QRegion(rc).subtracted(subtract));
484485

485486
auto item = (const BinaryViewModel::Item *)index.internalPointer();
486-
QColor color = sig->color;
487+
QColor color = toQColor(sig->color);
487488
color.setAlpha(item->bg_color.alpha());
488489
// Mixing the signal color with the Base background color to fade it
489490
painter->fillRect(rc, option.palette.color(QPalette::Base));
490491
painter->fillRect(rc, color);
491492

492493
// Draw edges
493-
color = sig->color.darker(125);
494+
color = toQColor(sig->color.darker(125));
494495
painter->setPen(QPen(color, 1));
495496
if (draw_left) painter->drawLine(rc.topLeft(), rc.bottomLeft());
496497
if (draw_right) painter->drawLine(rc.topRight(), rc.bottomRight());

openpilot/tools/cabana/chart/chart.cc

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "tools/cabana/chart/chart.h"
2+
#include "tools/cabana/dbc/dbcqt.h"
23

34
#include <algorithm>
45
#include <limits>
@@ -52,10 +53,10 @@ ChartView::ChartView(const std::pair<double, double> &x_range, ChartsWidget *par
5253
QObject::connect(axis_y, &QAbstractAxis::titleTextChanged, this, &ChartView::resetChartCache);
5354
QObject::connect(window()->windowHandle(), &QWindow::screenChanged, this, &ChartView::resetChartCache);
5455

55-
QObject::connect(dbc(), &DBCManager::signalRemoved, this, &ChartView::signalRemoved);
56-
QObject::connect(dbc(), &DBCManager::signalUpdated, this, &ChartView::signalUpdated);
57-
QObject::connect(dbc(), &DBCManager::msgRemoved, this, &ChartView::msgRemoved);
58-
QObject::connect(dbc(), &DBCManager::msgUpdated, this, &ChartView::msgUpdated);
56+
QObject::connect(dbcNotifier(), &QtDBCNotifier::signalRemoved, this, &ChartView::signalRemoved);
57+
QObject::connect(dbcNotifier(), &QtDBCNotifier::signalUpdated, this, &ChartView::signalUpdated);
58+
QObject::connect(dbcNotifier(), &QtDBCNotifier::msgRemoved, this, &ChartView::msgRemoved);
59+
QObject::connect(dbcNotifier(), &QtDBCNotifier::msgUpdated, this, &ChartView::msgUpdated);
5960
}
6061

6162
void ChartView::createToolButtons() {
@@ -115,14 +116,14 @@ void ChartView::setTheme(QChart::ChartTheme theme) {
115116
axis_x->setLineVisible(false);
116117
axis_y->setLineVisible(false);
117118
for (auto &s : sigs) {
118-
s.series->setColor(s.sig->color);
119+
s.series->setColor(toQColor(s.sig->color));
119120
}
120121
}
121122

122123
void ChartView::addSignal(const MessageId &msg_id, const cabana::Signal *sig) {
123124
if (hasSignal(msg_id, sig)) return;
124125

125-
QXYSeries *series = createSeries(series_type, sig->color);
126+
QXYSeries *series = createSeries(series_type, toQColor(sig->color));
126127
sigs.push_back({.msg_id = msg_id, .sig = sig, .series = series});
127128
updateSeries(sig);
128129
updateSeriesPoints();
@@ -157,8 +158,8 @@ void ChartView::removeIf(std::function<bool(const SigItem &s)> predicate) {
157158
void ChartView::signalUpdated(const cabana::Signal *sig) {
158159
auto it = std::find_if(sigs.begin(), sigs.end(), [sig](auto &s) { return s.sig == sig; });
159160
if (it != sigs.end()) {
160-
if (it->series->color() != sig->color) {
161-
setSeriesColor(it->series, sig->color);
161+
if (it->series->color() != toQColor(sig->color)) {
162+
setSeriesColor(it->series, toQColor(sig->color));
162163
}
163164
updateTitle();
164165
updateSeries(sig);
@@ -838,7 +839,7 @@ void ChartView::setSeriesType(SeriesType type) {
838839
s.series->deleteLater();
839840
}
840841
for (auto &s : sigs) {
841-
s.series = createSeries(series_type, s.sig->color);
842+
s.series = createSeries(series_type, toQColor(s.sig->color));
842843
const auto &points = series_type == SeriesType::StepLine ? s.step_vals : s.vals;
843844
s.series->replace(QVector<QPointF>(points.cbegin(), points.cend()));
844845
}

openpilot/tools/cabana/chart/chartswidget.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "tools/cabana/chart/chartswidget.h"
2+
#include "tools/cabana/dbc/dbcqt.h"
23

34
#include <algorithm>
45
#include <future>
@@ -115,7 +116,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) {
115116
align_timer->setSingleShot(true);
116117
QObject::connect(align_timer, &QTimer::timeout, this, &ChartsWidget::alignCharts);
117118
QObject::connect(auto_scroll_timer, &QTimer::timeout, this, &ChartsWidget::doAutoScroll);
118-
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &ChartsWidget::removeAll);
119+
QObject::connect(dbcNotifier(), &QtDBCNotifier::DBCFileChanged, this, &ChartsWidget::removeAll);
119120
QObject::connect(can, &AbstractStream::eventsMerged, this, &ChartsWidget::eventsMerged);
120121
QObject::connect(can, &AbstractStream::msgsReceived, this, &ChartsWidget::updateState);
121122
QObject::connect(can, &AbstractStream::seeking, this, &ChartsWidget::updateState);
@@ -309,7 +310,7 @@ void ChartsWidget::splitChart(ChartView *src_chart) {
309310
src_chart->chart()->removeSeries(it->series);
310311

311312
// Restore to the original color
312-
it->series->setColor(it->sig->color);
313+
it->series->setColor(toQColor(it->sig->color));
313314

314315
c->addSeries(it->series);
315316
c->sigs.emplace_back(std::move(*it));

openpilot/tools/cabana/chart/signalselector.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "tools/cabana/chart/signalselector.h"
2+
#include "tools/cabana/dbc/dbcqt.h"
23

34
#include <QCompleter>
45
#include <QDialogButtonBox>
@@ -92,7 +93,7 @@ void SignalSelector::updateAvailableList(int index) {
9293
}
9394

9495
void SignalSelector::addItemToList(QListWidget *parent, const MessageId id, const cabana::Signal *sig, bool show_msg_name) {
95-
QString text = QString("<span style=\"color:%0;\">■ </span> %1").arg(sig->color.name(), QString::fromStdString(sig->name));
96+
QString text = QString("<span style=\"color:%0;\">■ </span> %1").arg(toQColor(sig->color).name(), QString::fromStdString(sig->name));
9697
if (show_msg_name) text += QString(" <font color=\"gray\">%0 %1</font>").arg(QString::fromStdString(msgName(id)), QString::fromStdString(id.toString()));
9798

9899
QLabel *label = new QLabel(text);

openpilot/tools/cabana/chart/sparkline.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ void Sparkline::update(const cabana::Signal *sig, CanEventIter first, CanEventIt
3131
}
3232

3333
freq_ = points_.size() / std::max(points_.back().x() - points_.front().x(), 1.0);
34-
render(sig->color, range, size);
34+
render(toQColor(sig->color), range, size);
3535
}
3636

3737
void Sparkline::render(const QColor &color, int range, QSize size) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
#include <array>
4+
#include <cstdint>
5+
#include <unordered_map>
6+
#include <vector>
7+
8+
#include "tools/cabana/core/color.h"
9+
#include "tools/cabana/core/message_id.h"
10+
11+
struct CanData {
12+
void compute(const MessageId &msg_id, const uint8_t *data, int size, double current_sec,
13+
double playback_speed, const std::vector<uint8_t> &mask, double frequency = 0);
14+
15+
double ts = 0.;
16+
uint32_t count = 0;
17+
double freq = 0;
18+
std::vector<uint8_t> dat;
19+
std::vector<CabanaColor> colors;
20+
21+
struct ByteLastChange {
22+
double ts = 0;
23+
int delta = 0;
24+
int same_delta_counter = 0;
25+
bool suppressed = false;
26+
};
27+
std::vector<ByteLastChange> last_changes;
28+
std::vector<std::array<uint32_t, 8>> bit_flip_counts;
29+
double last_freq_update_ts = 0;
30+
};
31+
32+
struct CanEvent {
33+
uint8_t src;
34+
uint32_t address;
35+
uint64_t mono_time;
36+
uint8_t size;
37+
uint8_t dat[];
38+
};
39+
40+
struct CompareCanEvent {
41+
constexpr bool operator()(const CanEvent *const event, uint64_t ts) const { return event->mono_time < ts; }
42+
constexpr bool operator()(uint64_t ts, const CanEvent *const event) const { return ts < event->mono_time; }
43+
};
44+
45+
using MessageEventsMap = std::unordered_map<MessageId, std::vector<const CanEvent *>>;
46+
using CanEventIter = std::vector<const CanEvent *>::const_iterator;
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#pragma once
2+
3+
#include <algorithm>
4+
#include <cmath>
5+
#include <cstdint>
6+
7+
struct CabanaColor {
8+
uint8_t r = 0;
9+
uint8_t g = 0;
10+
uint8_t b = 0;
11+
uint8_t a = 255;
12+
13+
constexpr CabanaColor() = default;
14+
constexpr CabanaColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255)
15+
: r(red), g(green), b(blue), a(alpha) {}
16+
17+
static CabanaColor fromHsv(float hue, float saturation, float value, float alpha = 1.0f) {
18+
const float h = hue - std::floor(hue);
19+
const float c = value * saturation;
20+
const float x = c * (1.0f - std::fabs(std::fmod(h * 6.0f, 2.0f) - 1.0f));
21+
const float m = value - c;
22+
float red = 0, green = 0, blue = 0;
23+
switch (static_cast<int>(h * 6.0f) % 6) {
24+
case 0: red = c; green = x; break;
25+
case 1: red = x; green = c; break;
26+
case 2: green = c; blue = x; break;
27+
case 3: green = x; blue = c; break;
28+
case 4: red = x; blue = c; break;
29+
default: red = c; blue = x; break;
30+
}
31+
auto channel = [m](float v) { return static_cast<uint8_t>(std::clamp((v + m) * 255.0f, 0.0f, 255.0f) + 0.5f); };
32+
return {channel(red), channel(green), channel(blue),
33+
static_cast<uint8_t>(std::clamp(alpha * 255.0f, 0.0f, 255.0f) + 0.5f)};
34+
}
35+
36+
CabanaColor darker(int factor = 200) const {
37+
if (factor <= 0) return *this;
38+
if (factor < 100) return lighter(10000 / factor);
39+
auto [hue, saturation, value] = hsv();
40+
return fromHsv(hue, saturation, value * 100.0f / factor, a / 255.0f);
41+
}
42+
43+
CabanaColor lighter(int factor = 150) const {
44+
if (factor <= 0) return *this;
45+
if (factor < 100) return darker(10000 / factor);
46+
auto [hue, saturation, value] = hsv();
47+
const float scaled_value = value * factor / 100.0f;
48+
if (scaled_value > 1.0f) saturation = std::max(0.0f, saturation - (scaled_value - 1.0f));
49+
return fromHsv(hue, saturation, std::min(1.0f, scaled_value), a / 255.0f);
50+
}
51+
52+
constexpr int red() const { return r; }
53+
constexpr int green() const { return g; }
54+
constexpr int blue() const { return b; }
55+
constexpr int alpha() const { return a; }
56+
float alphaF() const { return a / 255.0f; }
57+
void setAlphaF(float alpha) { a = static_cast<uint8_t>(std::clamp(alpha * 255.0f, 0.0f, 255.0f) + 0.5f); }
58+
59+
constexpr bool operator==(const CabanaColor &other) const {
60+
return r == other.r && g == other.g && b == other.b && a == other.a;
61+
}
62+
63+
private:
64+
struct Hsv { float hue; float saturation; float value; };
65+
Hsv hsv() const {
66+
const float red = r / 255.0f, green = g / 255.0f, blue = b / 255.0f;
67+
const float maximum = std::max({red, green, blue});
68+
const float minimum = std::min({red, green, blue});
69+
const float delta = maximum - minimum;
70+
float hue = 0;
71+
if (delta > 0) {
72+
if (maximum == red) hue = std::fmod((green - blue) / delta, 6.0f) / 6.0f;
73+
else if (maximum == green) hue = ((blue - red) / delta + 2.0f) / 6.0f;
74+
else hue = ((red - green) / delta + 4.0f) / 6.0f;
75+
if (hue < 0) hue += 1.0f;
76+
}
77+
return {hue, maximum == 0 ? 0 : delta / maximum, maximum};
78+
}
79+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
#include <cstdint>
3+
#include <cstdio>
4+
#include <functional>
5+
#include <string>
6+
#include <tuple>
7+
8+
constexpr int INVALID_SOURCE = 0xff;
9+
10+
struct MessageId {
11+
uint8_t source = 0;
12+
uint32_t address = 0;
13+
std::string toString() const { char b[64]; snprintf(b, sizeof(b), "%u:%X", source, address); return b; }
14+
static MessageId fromString(const std::string &s) {
15+
const auto p = s.find(':');
16+
if (p == std::string::npos) return {};
17+
return {.source = static_cast<uint8_t>(std::stoul(s.substr(0, p))), .address = static_cast<uint32_t>(std::stoul(s.substr(p + 1), nullptr, 16))};
18+
}
19+
bool operator==(const MessageId &o) const { return source == o.source && address == o.address; }
20+
bool operator!=(const MessageId &o) const { return !(*this == o); }
21+
bool operator<(const MessageId &o) const { return std::tie(source, address) < std::tie(o.source, o.address); }
22+
bool operator>(const MessageId &o) const { return o < *this; }
23+
};
24+
25+
template <> struct std::hash<MessageId> {
26+
size_t operator()(const MessageId &id) const noexcept { return std::hash<uint8_t>{}(id.source) ^ (std::hash<uint32_t>{}(id.address) << 1); }
27+
};

0 commit comments

Comments
 (0)