pull/27829/head
Justin Newberry 2 years ago
commit 145ba15763
  1. 2
      SConstruct
  2. 14
      settings
  3. 1
      tools/cabana/dbc/dbcmanager.h
  4. 207
      tools/cabana/tools/search.cc
  5. 168
      tools/cabana/tools/search.h
  6. 23
      tools/cabana/videowidget.cc

@ -175,7 +175,7 @@ env = Environment(
CCFLAGS=[ CCFLAGS=[
"-g", "-g",
"-fPIC", "-fPIC",
"-O2", "-O0",
#"-Wunused", #"-Wunused",
"-Werror", "-Werror",
"-Wshadow", "-Wshadow",

@ -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)

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <map> #include <map>
#include <optional>
#include <QList> #include <QList>
#include <QMetaType> #include <QMetaType>
#include <QObject> #include <QObject>

@ -2,8 +2,24 @@
#include <iostream> #include <iostream>
#include "tools/cabana/dbc/dbcmanager.h" std::map<ScanType, std::string> scanTypeToDisplayName {
#include "tools/cabana/streams/abstractstream.h" {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) { SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) {
setWindowTitle(tr("Search")); setWindowTitle(tr("Search"));
@ -13,9 +29,12 @@ SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) {
QHBoxLayout *scan_button_layout = new QHBoxLayout(); QHBoxLayout *scan_button_layout = new QHBoxLayout();
QPushButton *first_scan_button = new QPushButton(QString("First Scan"), this); first_scan_button = new QPushButton(QString("..."), this);
QPushButton *next_scan_button = new QPushButton(QString("Next Scan"), this); next_scan_button = new QPushButton(QString("Next Scan"), this);
QPushButton *undo_scan_button = new QPushButton(QString("Undo 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(first_scan_button, &QPushButton::clicked, [=]() { firstScan(); });
QObject::connect(next_scan_button, &QPushButton::clicked, [=]() { nextScan(); }); QObject::connect(next_scan_button, &QPushButton::clicked, [=]() { nextScan(); });
@ -27,13 +46,14 @@ SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) {
QVBoxLayout *search_parameters_layout = new QVBoxLayout(); QVBoxLayout *search_parameters_layout = new QVBoxLayout();
QLineEdit *value_box = new QLineEdit(); QLineEdit *value_box1 = new QLineEdit();
value_box->setValidator( new QIntValidator(this) ); 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(); QObject::connect(scan_type, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) { selectedScanType = (ScanType)(scan_type->itemData(index).toInt()); });
scan_type->addItem(QString("Exact Value"));
QHBoxLayout *bits_min_max_layout = new QHBoxLayout(); QHBoxLayout *bits_min_max_layout = new QHBoxLayout();
@ -51,36 +71,97 @@ SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) {
bits_min_max_layout->addWidget(bits_min); bits_min_max_layout->addWidget(bits_min);
bits_min_max_layout->addWidget(bits_max); 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); 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(scan_button_layout);
main_layout->addLayout(search_parameters_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){ void SearchDlg::setRowData(int row, QString msgID, QString bitRange, QString currentValue, QString previousValue){
return (((1 << size) - 1) & (val >> (offset - 1))); 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 { void SearchDlg::updateRowData(){
public: data_table->clear();
Sig(MessageId _messageID, int _offset, int _size) : messageID(_messageID), offset(_offset), size(_size) {} data_table->setRowCount(0);
MessageId messageID; if(filteredSignals.size() < 1000){
size_t offset; data_table->setRowCount(filteredSignals.size() + 1);
size_t size;
uint64_t getValue(){ setRowData(0, QString("Message ID"), QString("Bit Range"), QString("Current Value"), QString("Previous Value"));
auto msg = can->can_msgs[messageID];
uint64_t* data = (uint64_t*)(msg.dat.data()); int row=1;
return getBitValue(*data, offset, size); 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<Sig> getAllPossibleSignals(int bits_min, int bits_max){ std::vector<Sig> getAllPossibleSignals(int bits_min, int bits_max){
std::vector<Sig> ret; std::vector<Sig> 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 i = bits_min; i < bits_max+1; i++) {
for(int j = 0; j < 64 - i; j++) { for(int j = 0; j < 64 - i; j++) {
ret.push_back(Sig(msg_id, j, i)); ret.push_back(Sig(msg_id, j, i));
@ -91,23 +172,81 @@ std::vector<Sig> getAllPossibleSignals(int bits_min, int bits_max){
return ret; return ret;
} }
void SearchDlg::firstScan(){ std::vector<ScanType> SearchDlg::enabledScanTypes(){
std::cout << scan_bits_range_min << " " << scan_bits_range_max << " " << scan_value << std::endl; if(!scanningStarted){
return std::vector<ScanType> {
ExactValue,
BiggerThan,
SmallerThan,
ValueBetween,
UnknownInitialValue
};
}
else{
return std::vector<ScanType> {
ExactValue,
BiggerThan,
SmallerThan,
ValueBetween,
IncreasedValue,
IncreaseValueBy,
DecreasedValue,
DecreasedValueBy,
ChangedValue,
UnchangedValue
};
}
}
std::vector<Sig> allPossibleValues = getAllPossibleSignals(scan_bits_range_min, scan_bits_range_max); void SearchDlg::firstScan(){
if(scanningStarted){
filteredSignals.clear();
scanningStarted = false;
}
else{
filteredSignals = getAllPossibleSignals(scan_bits_range_min, scan_bits_range_max);
scanningStarted = true;
std::cout << allPossibleValues.size() << std::endl; nextScan();
}
update();
}
std::vector<Sig> filteredValues; SignalFilterer* SearchDlg::getCurrentFilterer() {
std::copy_if(allPossibleValues.begin(), allPossibleValues.end(), std::back_inserter(filteredValues), [=](Sig i) { if(selectedScanType == ExactValue){
return i.getValue() == scan_value; 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::cout << filteredValues.size() << std::endl; return nullptr;
} }
void SearchDlg::nextScan(){ void SearchDlg::nextScan(){
auto filterer = getCurrentFilterer();
filteredSignals = filterer->filter(filteredSignals);
update();
} }
void SearchDlg::undoScan(){ void SearchDlg::undoScan(){

@ -8,7 +8,150 @@
#include <QDoubleValidator> #include <QDoubleValidator>
#include <QComboBox> #include <QComboBox>
#include <QSpinBox> #include <QSpinBox>
#include <QLabel>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <iostream>
#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<Sig> filter(std::vector<Sig> in) {
std::vector<Sig> 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 { class SearchDlg : public QDialog {
Q_OBJECT Q_OBJECT
@ -21,8 +164,31 @@ private:
void nextScan(); void nextScan();
void undoScan(); void undoScan();
void update();
void updateRowData();
void setRowData(int row, QString msgID, QString bitRange, QString currentValue, QString previousValue);
std::vector<ScanType> enabledScanTypes();
SignalFilterer* getCurrentFilterer();
bool scanningStarted = false;
uint32_t scan_bits_range_min = 1; uint32_t scan_bits_range_min = 1;
uint32_t scan_bits_range_max = 32; uint32_t scan_bits_range_max = 32;
uint64_t scan_value = 0; uint64_t scan_value1 = 0;
uint64_t scan_value2 = 0;
std::vector<Sig> filteredSignals;
ScanType selectedScanType;
QLabel* numberOfSigsLabel;
QComboBox *scan_type;
QPushButton *first_scan_button;
QPushButton *next_scan_button;
QPushButton *undo_scan_button;
QTableWidget *data_table;
}; };

@ -188,15 +188,36 @@ void Slider::sliderChange(QAbstractSlider::SliderChange change) {
} }
} }
bool sortTimelineBasedOnEventPriority(std::tuple<int, int, TimelineType> left, std::tuple<int, int, TimelineType> right){
std::map<TimelineType, int> 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) { void Slider::paintEvent(QPaintEvent *ev) {
QPainter p(this); QPainter p(this);
QRect r = rect().adjusted(0, 4, 0, -4); QRect r = rect().adjusted(0, 4, 0, -4);
p.fillRect(r, timeline_colors[(int)TimelineType::None]); p.fillRect(r, timeline_colors[(int)TimelineType::None]);
double min = minimum() / 1000.0; double min = minimum() / 1000.0;
double max = maximum() / 1000.0; double max = maximum() / 1000.0;
for (auto [begin, end, type] : timeline) {
std::vector<std::tuple<int, int, TimelineType>> 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) if (begin > max || end < min)
continue; continue;
r.setLeft(((std::max(min, (double)begin) - min) / (max - min)) * width()); r.setLeft(((std::max(min, (double)begin) - min) / (max - min)) * width());
r.setRight(((std::min(max, (double)end) - min) / (max - min)) * width()); r.setRight(((std::min(max, (double)end) - min) / (max - min)) * width());
p.fillRect(r, timeline_colors[(int)type]); p.fillRect(r, timeline_colors[(int)type]);

Loading…
Cancel
Save