diff --git a/SConstruct b/SConstruct index 17d7975e47..f20ee17848 100644 --- a/SConstruct +++ b/SConstruct @@ -175,7 +175,7 @@ env = Environment( CCFLAGS=[ "-g", "-fPIC", - "-O2", + "-O0", #"-Wunused", "-Werror", "-Wshadow", diff --git a/settings b/settings new file mode 100644 index 0000000000..c70289de40 --- /dev/null +++ b/settings @@ -0,0 +1,14 @@ +[General] +chart_column_count=1 +chart_height=200 +chart_range=905 +chart_series_type=0 +fps=10 +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\a\x80\0\0\0\x17\0\0\x11\x7f\0\0\x5o\0\0\a\x80\0\0\0\x17\0\0\x11\x7f\0\0\x5o\0\0\0\0\0\0\0\0\x19\0\0\0\a\x80\0\0\0\x17\0\0\x11\x7f\0\0\x5o) +last_dir=/home/justin/openpilot/opendbc +last_route_dir=/home/justin +max_cached_minutes=30 +message_header_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1\xf4\0\0\0\x6\0\x1\x1\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x84\0\0\0\0\0\0\0\x6\0\0\0\x96\0\0\0\x1\0\0\0\0\0\0\0\x32\0\0\0\x1\0\0\0\0\0\0\0\x32\0\0\0\x1\0\0\0\0\0\0\0\x32\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64) +recent_files=/home/justin/openpilot/opendbc/subaru_global_2017_generated.dbc, /home/justin/openpilot/opendbc/chrysler_ram_dt_generated.dbc +video_splitter_state=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\x1\x44\0\0\x3\xd4\x1\xff\xff\xff\xff\x1\0\0\0\x2\0) +window_state=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x2\0\0\0\0\0\0\x1\x93\0\0\x5/\xfc\x2\0\0\0\x1\xfb\0\0\0\x1a\0M\0\x65\0s\0s\0\x61\0g\0\x65\0s\0P\0\x61\0n\0\x65\0l\x1\0\0\0\x14\0\0\x5/\0\0\0\x93\0\xff\xff\xff\0\0\0\x1\0\0\x5\x46\0\0\x5/\xfc\x2\0\0\0\x1\xfb\0\0\0\x14\0V\0i\0\x64\0\x65\0o\0P\0\x61\0n\0\x65\0l\x1\0\0\0\x14\0\0\x5/\0\0\x1-\0\xff\xff\xff\0\0\x3\x1f\0\0\x5/\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\0) diff --git a/tools/cabana/dbc/dbcmanager.h b/tools/cabana/dbc/dbcmanager.h index 31183e8199..2f833a9429 100644 --- a/tools/cabana/dbc/dbcmanager.h +++ b/tools/cabana/dbc/dbcmanager.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include diff --git a/tools/cabana/tools/search.cc b/tools/cabana/tools/search.cc index f8913758ea..879ed75f12 100644 --- a/tools/cabana/tools/search.cc +++ b/tools/cabana/tools/search.cc @@ -2,8 +2,24 @@ #include -#include "tools/cabana/dbc/dbcmanager.h" -#include "tools/cabana/streams/abstractstream.h" +std::map scanTypeToDisplayName { + {ExactValue, "Exact value"}, + {BiggerThan, "Bigger than..."}, + {SmallerThan, "Smaller than..."}, + {BiggerThan, "Bigger than..."}, + {ValueBetween, "Value between..."}, + {IncreasedValue, "Increased value"}, + {IncreaseValueBy, "Increased value by..."}, + {DecreasedValue, "Decreased value"}, + {DecreasedValueBy, "Decreased value by..."}, + {ChangedValue, "Changed value"}, + {UnchangedValue, "Unchanged value"}, + {UnknownInitialValue, "Unknown initial value"}, +}; + +uint64_t getBitValue(uint64_t val, int offset, int size){ + return (((1 << size) - 1) & (val >> (offset - 1))); +} SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Search")); @@ -13,9 +29,12 @@ SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) { QHBoxLayout *scan_button_layout = new QHBoxLayout(); - QPushButton *first_scan_button = new QPushButton(QString("First Scan"), this); - QPushButton *next_scan_button = new QPushButton(QString("Next Scan"), this); - QPushButton *undo_scan_button = new QPushButton(QString("Undo Scan"), this); + first_scan_button = new QPushButton(QString("..."), this); + next_scan_button = new QPushButton(QString("Next Scan"), this); + undo_scan_button = new QPushButton(QString("Undo Scan"), this); + + undo_scan_button->setEnabled(false); + next_scan_button->setEnabled(false); QObject::connect(first_scan_button, &QPushButton::clicked, [=]() { firstScan(); }); QObject::connect(next_scan_button, &QPushButton::clicked, [=]() { nextScan(); }); @@ -27,13 +46,14 @@ SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) { QVBoxLayout *search_parameters_layout = new QVBoxLayout(); - QLineEdit *value_box = new QLineEdit(); - value_box->setValidator( new QIntValidator(this) ); + QLineEdit *value_box1 = new QLineEdit(); + value_box1->setValidator( new QIntValidator(this) ); + + QObject::connect(value_box1, &QLineEdit::textChanged, [=](QString value) { scan_value1 = value.toInt(); }); - QObject::connect(value_box, &QLineEdit::textChanged, [=](QString value) { scan_value = value.toInt(); }); + scan_type = new QComboBox(); - QComboBox *scan_type = new QComboBox(); - scan_type->addItem(QString("Exact Value")); + QObject::connect(scan_type, qOverload(&QComboBox::currentIndexChanged), [=](int index) { selectedScanType = (ScanType)(scan_type->itemData(index).toInt()); }); QHBoxLayout *bits_min_max_layout = new QHBoxLayout(); @@ -45,42 +65,103 @@ SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) { bits_max->setRange(1,32); bits_max->setValue(scan_bits_range_max); - QObject::connect(bits_min, qOverload(&QSpinBox::valueChanged), [=](int value) { scan_bits_range_min=value; }); + QObject::connect(bits_min, qOverload(&QSpinBox::valueChanged), [=](int value) { scan_bits_range_min=value; }); QObject::connect(bits_max, qOverload(&QSpinBox::valueChanged), [=](int value) { scan_bits_range_max=value; }); bits_min_max_layout->addWidget(bits_min); bits_min_max_layout->addWidget(bits_max); - search_parameters_layout->addWidget(value_box); + search_parameters_layout->addWidget(value_box1); + search_parameters_layout->addWidget(scan_type); search_parameters_layout->addLayout(bits_min_max_layout); + QVBoxLayout *search_results_layout = new QVBoxLayout(); + + numberOfSigsLabel = new QLabel(QString("Found: 0")); + search_results_layout->addWidget(numberOfSigsLabel); + + data_table = new QTableWidget(); + data_table->setRowCount(1); + data_table->setColumnCount(6); + + search_results_layout->addWidget(data_table); + main_layout->addLayout(scan_button_layout); main_layout->addLayout(search_parameters_layout); + main_layout->addLayout(search_results_layout); + + update(); + + QObject::connect(can, &AbstractStream::received, this, &SearchDlg::updateRowData); + QObject::connect(can, &AbstractStream::seekedTo, this, &SearchDlg::updateRowData); } -uint64_t getBitValue(uint64_t val, int offset, int size){ - return (((1 << size) - 1) & (val >> (offset - 1))); +void SearchDlg::setRowData(int row, QString msgID, QString bitRange, QString currentValue, QString previousValue){ + QTableWidgetItem *msg_id = new QTableWidgetItem(msgID); + data_table->setItem(row, 0, msg_id); + + QTableWidgetItem *bit_range = new QTableWidgetItem(bitRange); + data_table->setItem(row, 1, bit_range); + + QTableWidgetItem *current_value = new QTableWidgetItem(currentValue); + data_table->setItem(row, 2, current_value); + + QTableWidgetItem *previous_value = new QTableWidgetItem(previousValue); + data_table->setItem(row, 3, previous_value); } -class Sig { - public: - Sig(MessageId _messageID, int _offset, int _size) : messageID(_messageID), offset(_offset), size(_size) {} +void SearchDlg::updateRowData(){ + data_table->clear(); + data_table->setRowCount(0); - MessageId messageID; - size_t offset; - size_t size; - - uint64_t getValue(){ - auto msg = can->can_msgs[messageID]; - uint64_t* data = (uint64_t*)(msg.dat.data()); - return getBitValue(*data, offset, size); + if(filteredSignals.size() < 1000){ + data_table->setRowCount(filteredSignals.size() + 1); + + setRowData(0, QString("Message ID"), QString("Bit Range"), QString("Current Value"), QString("Previous Value")); + + int row=1; + for(auto &sig : filteredSignals){ + setRowData(row, sig.messageID.toString(), QString("%1:%2").arg(sig.offset).arg(sig.offset+sig.size), QString::number(sig.getValue()), QString::number(sig.previousValue)); + row++; } -}; + } +} + +void SearchDlg::update(){ + first_scan_button->setText(scanningStarted ? "New Scan" : "First Scan"); + numberOfSigsLabel->setText(QString("Found: ") + QString::number(filteredSignals.size())); + + ScanType selectedValue = (ScanType)(scan_type->currentData().toInt()); + + next_scan_button->setEnabled(scanningStarted); + undo_scan_button->setEnabled(false); + + scan_type->clear(); + + int selectedIndex = -1; + int i = 0; + + for(auto scanType : enabledScanTypes()){ + if(scanType == selectedValue) selectedIndex = i; + scan_type->addItem(QString::fromStdString(scanTypeToDisplayName[scanType]), QVariant(scanType)); + i++; + } + + if(selectedIndex != -1){ + scan_type->setCurrentIndex(selectedIndex); + } + + updateRowData(); + + for(auto &sig : filteredSignals){ + sig.previousValue = sig.getValue(); + } +} std::vector getAllPossibleSignals(int bits_min, int bits_max){ std::vector ret; - for(auto msg_id : can->can_msgs.keys()) { + for(auto msg_id : can->last_msgs.keys()) { for(int i = bits_min; i < bits_max+1; i++) { for(int j = 0; j < 64 - i; j++) { ret.push_back(Sig(msg_id, j, i)); @@ -91,23 +172,81 @@ std::vector getAllPossibleSignals(int bits_min, int bits_max){ return ret; } +std::vector SearchDlg::enabledScanTypes(){ + if(!scanningStarted){ + return std::vector { + ExactValue, + BiggerThan, + SmallerThan, + ValueBetween, + UnknownInitialValue + }; + } + else{ + return std::vector { + ExactValue, + BiggerThan, + SmallerThan, + ValueBetween, + IncreasedValue, + IncreaseValueBy, + DecreasedValue, + DecreasedValueBy, + ChangedValue, + UnchangedValue + }; + } +} + void SearchDlg::firstScan(){ - std::cout << scan_bits_range_min << " " << scan_bits_range_max << " " << scan_value << std::endl; + if(scanningStarted){ + filteredSignals.clear(); + scanningStarted = false; + } + else{ + filteredSignals = getAllPossibleSignals(scan_bits_range_min, scan_bits_range_max); + scanningStarted = true; - std::vector allPossibleValues = getAllPossibleSignals(scan_bits_range_min, scan_bits_range_max); + nextScan(); + } + update(); +} - std::cout << allPossibleValues.size() << std::endl; +SignalFilterer* SearchDlg::getCurrentFilterer() { + if(selectedScanType == ExactValue){ + return new ExactValueSignalFilterer(scan_value1); + } + if(selectedScanType == BiggerThan){ + return new BiggerThanSignalFilterer(scan_value1); + } + if(selectedScanType == SmallerThan){ + return new SmallerThanSignalFilterer(scan_value1); + } + if(selectedScanType == UnknownInitialValue){ + return new UnknownInitialValueSignalFilter(); + } + if(selectedScanType == UnchangedValue){ + return new UnchangedValueSignalFilter(); + } + if(selectedScanType == ChangedValue){ + return new ChangedValueSignalFilter(); + } + if(selectedScanType == IncreasedValue){ + return new IncreasedValueSignalFilter(); + } + if(selectedScanType == DecreasedValue){ + return new DecreasedValueSignalFilter(); + } - std::vector filteredValues; - std::copy_if(allPossibleValues.begin(), allPossibleValues.end(), std::back_inserter(filteredValues), [=](Sig i) { - return i.getValue() == scan_value; - }); - - std::cout << filteredValues.size() << std::endl; + return nullptr; } void SearchDlg::nextScan(){ + auto filterer = getCurrentFilterer(); + + filteredSignals = filterer->filter(filteredSignals); + update(); } void SearchDlg::undoScan(){ diff --git a/tools/cabana/tools/search.h b/tools/cabana/tools/search.h index 7d529e7c42..449bdd4a75 100644 --- a/tools/cabana/tools/search.h +++ b/tools/cabana/tools/search.h @@ -8,7 +8,150 @@ #include #include #include +#include +#include +#include +#include + +#include "tools/cabana/dbc/dbcmanager.h" +#include "tools/cabana/streams/abstractstream.h" + +uint64_t getBitValue(uint64_t val, int offset, int size); + +enum ScanType { + ExactValue, + BiggerThan, + SmallerThan, + ValueBetween, + IncreasedValue, + IncreaseValueBy, + DecreasedValue, + DecreasedValueBy, + ChangedValue, + UnchangedValue, + UnknownInitialValue +}; + +class Sig { + public: + Sig(MessageId _messageID, int _offset, int _size) : messageID(_messageID), offset(_offset), size(_size) {} + + MessageId messageID; + size_t offset; + size_t size; + + uint64_t previousValue; + + uint64_t getValue(){ + auto msg = can->last_msgs[messageID]; + uint64_t* data = (uint64_t*)(msg.dat.data()); + return getBitValue(*data, offset, size); + } +}; + +class SignalFilterer { + public: + virtual bool signalMatches(Sig sig) = 0; + + std::vector filter(std::vector in) { + std::vector ret; + + std::copy_if(in.begin(), in.end(), std::back_inserter(ret), [=] (Sig sig) { return signalMatches(sig); }); + + return ret; + } +}; + +class ZeroInputSignalFilterer : public SignalFilterer { + public: + ZeroInputSignalFilterer(){ + + } +}; + +class SingleInputSignalFilterer : public SignalFilterer { + public: + SingleInputSignalFilterer(uint64_t _value) : value(_value){ + + } + protected: + uint64_t value; +}; + +class DoubleInputSignalFilterer : public SignalFilterer { + public: + DoubleInputSignalFilterer(uint64_t _value1, uint64_t _value2) : value1(_value1), value2(_value2){ + + } + protected: + uint64_t value1; + uint64_t value2; +}; + +class ExactValueSignalFilterer : public SingleInputSignalFilterer { + using SingleInputSignalFilterer::SingleInputSignalFilterer; + + bool signalMatches(Sig sig) { + return sig.getValue() == value; + } +}; + +class BiggerThanSignalFilterer : public SingleInputSignalFilterer { + using SingleInputSignalFilterer::SingleInputSignalFilterer; + + bool signalMatches(Sig sig) { + return sig.getValue() > value; + } +}; + +class SmallerThanSignalFilterer : public SingleInputSignalFilterer { + using SingleInputSignalFilterer::SingleInputSignalFilterer; + + bool signalMatches(Sig sig) { + return sig.getValue() < value; + } +}; + +class UnknownInitialValueSignalFilter : public ZeroInputSignalFilterer { + using ZeroInputSignalFilterer::ZeroInputSignalFilterer; + + bool signalMatches(Sig sig) { + return true; + } +}; + +class IncreasedValueSignalFilter : public ZeroInputSignalFilterer { + using ZeroInputSignalFilterer::ZeroInputSignalFilterer; + + bool signalMatches(Sig sig) { + return sig.getValue() > sig.previousValue; + } +}; + +class DecreasedValueSignalFilter : public ZeroInputSignalFilterer { + using ZeroInputSignalFilterer::ZeroInputSignalFilterer; + + bool signalMatches(Sig sig) { + return sig.getValue() < sig.previousValue; + } +}; + +class ChangedValueSignalFilter : public ZeroInputSignalFilterer { + using ZeroInputSignalFilterer::ZeroInputSignalFilterer; + + bool signalMatches(Sig sig) { + return sig.getValue() != sig.previousValue; + } +}; + +class UnchangedValueSignalFilter : public ZeroInputSignalFilterer { + using ZeroInputSignalFilterer::ZeroInputSignalFilterer; + + bool signalMatches(Sig sig) { + return sig.getValue() == sig.previousValue; + } +}; class SearchDlg : public QDialog { Q_OBJECT @@ -21,8 +164,31 @@ private: void nextScan(); void undoScan(); + void update(); + void updateRowData(); + void setRowData(int row, QString msgID, QString bitRange, QString currentValue, QString previousValue); + + std::vector enabledScanTypes(); + + SignalFilterer* getCurrentFilterer(); + + bool scanningStarted = false; + uint32_t scan_bits_range_min = 1; uint32_t scan_bits_range_max = 32; - uint64_t scan_value = 0; + uint64_t scan_value1 = 0; + uint64_t scan_value2 = 0; + + std::vector filteredSignals; + + ScanType selectedScanType; + + QLabel* numberOfSigsLabel; + QComboBox *scan_type; + QPushButton *first_scan_button; + QPushButton *next_scan_button; + QPushButton *undo_scan_button; + + QTableWidget *data_table; }; \ No newline at end of file diff --git a/tools/cabana/videowidget.cc b/tools/cabana/videowidget.cc index 0e9714994e..36880f5e56 100644 --- a/tools/cabana/videowidget.cc +++ b/tools/cabana/videowidget.cc @@ -188,15 +188,36 @@ void Slider::sliderChange(QAbstractSlider::SliderChange change) { } } +bool sortTimelineBasedOnEventPriority(std::tuple left, std::tuple right){ + std::map timelinePriority = { + { TimelineType::None, 0 }, + { TimelineType::Engaged, 10 }, + { TimelineType::AlertInfo, 20 }, + { TimelineType::AlertWarning, 30 }, + { TimelineType::AlertCritical, 40 }, + { TimelineType::UserFlag, 35 } + }; + + return timelinePriority[std::get<2>(left)] < timelinePriority[std::get<2>(right)]; +} + void Slider::paintEvent(QPaintEvent *ev) { QPainter p(this); QRect r = rect().adjusted(0, 4, 0, -4); p.fillRect(r, timeline_colors[(int)TimelineType::None]); double min = minimum() / 1000.0; double max = maximum() / 1000.0; - for (auto [begin, end, type] : timeline) { - if (begin > max || end < min) + + std::vector> sortedTimeline; + + std::copy(timeline.begin(), timeline.end(), std::back_inserter(sortedTimeline)); + + std::sort(sortedTimeline.begin(), sortedTimeline.end(), sortTimelineBasedOnEventPriority); + + for (auto [begin, end, type] : sortedTimeline) { + if (begin > max || end < min) continue; + r.setLeft(((std::max(min, (double)begin) - min) / (max - min)) * width()); r.setRight(((std::min(max, (double)end) - min) / (max - min)) * width()); p.fillRect(r, timeline_colors[(int)type]);