cabana: improve dbc parsing (#28321)

pull/28322/head
Dean Lee 2 years ago committed by GitHub
parent 376faefec2
commit 2a6458b44e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      tools/cabana/dbc/dbc.cc
  2. 2
      tools/cabana/dbc/dbc.h
  3. 64
      tools/cabana/dbc/dbcfile.cc
  4. 2
      tools/cabana/historylog.cc
  5. 14
      tools/cabana/signalview.cc
  6. 4
      tools/cabana/tools/findsignal.cc
  7. 8
      tools/cabana/util.cc
  8. 8
      tools/cabana/util.h

@ -40,7 +40,7 @@ void cabana::Signal::updatePrecision() {
QString cabana::Signal::formatValue(double value) const { QString cabana::Signal::formatValue(double value) const {
// Show enum string // Show enum string
for (auto &[val, desc] : val_desc) { for (auto &[val, desc] : val_desc) {
if (std::abs(value - val.toInt()) < 1e-6) { if (std::abs(value - val) < 1e-6) {
return desc; return desc;
} }
} }

@ -42,7 +42,7 @@ struct std::hash<MessageId> {
std::size_t operator()(const MessageId &k) const noexcept { return qHash(k); } std::size_t operator()(const MessageId &k) const noexcept { return qHash(k); }
}; };
typedef QList<std::pair<QString, QString>> ValueDescription; typedef QList<std::pair<double, QString>> ValueDescription;
namespace cabana { namespace cabana {
struct Signal { struct Signal {

@ -196,7 +196,13 @@ void DBCFile::parseExtraInfo(const QString &content) {
static QRegularExpression sgm_regexp(R"(^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); static QRegularExpression sgm_regexp(R"(^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))");
static QRegularExpression msg_comment_regexp(R"(^CM_ BO_ *(\w+) *\"(.*)\";)"); static QRegularExpression msg_comment_regexp(R"(^CM_ BO_ *(\w+) *\"(.*)\";)");
static QRegularExpression sg_comment_regexp(R"(^CM_ SG_ *(\w+) *(\w+) *\"(.*)\";)"); static QRegularExpression sg_comment_regexp(R"(^CM_ SG_ *(\w+) *(\w+) *\"(.*)\";)");
static QRegularExpression val_regexp(R"(VAL_ (\w+) (\w+) (.*);)"); static QRegularExpression val_regexp(R"(VAL_ (\w+) (\w+) (\s*[-+]?[0-9]+\s+\".+?\"[^;]*))");
int line_num = 0;
QString line;
auto dbc_assert = [&line_num, &line, this](bool condition) {
if (!condition) throw std::runtime_error(QString("[%1:%2]: %3").arg(filename).arg(line_num).arg(line).toStdString());
};
auto get_sig = [this](uint32_t address, const QString &name) -> cabana::Signal * { auto get_sig = [this](uint32_t address, const QString &name) -> cabana::Signal * {
auto m = (cabana::Msg *)msg(address); auto m = (cabana::Msg *)msg(address);
return m ? (cabana::Signal *)m->sig(name) : nullptr; return m ? (cabana::Signal *)m->sig(name) : nullptr;
@ -205,11 +211,12 @@ void DBCFile::parseExtraInfo(const QString &content) {
QTextStream stream((QString *)&content); QTextStream stream((QString *)&content);
uint32_t address = 0; uint32_t address = 0;
while (!stream.atEnd()) { while (!stream.atEnd()) {
QString line = stream.readLine().trimmed(); ++line_num;
line = stream.readLine().trimmed();
if (line.startsWith("BO_ ")) { if (line.startsWith("BO_ ")) {
if (auto match = bo_regexp.match(line); match.hasMatch()) { auto match = bo_regexp.match(line);
address = match.captured(1).toUInt(); dbc_assert(match.hasMatch());
} address = match.captured(1).toUInt();
} else if (line.startsWith("SG_ ")) { } else if (line.startsWith("SG_ ")) {
int offset = 0; int offset = 0;
auto match = sg_regexp.match(line); auto match = sg_regexp.match(line);
@ -217,37 +224,36 @@ void DBCFile::parseExtraInfo(const QString &content) {
match = sgm_regexp.match(line); match = sgm_regexp.match(line);
offset = 1; offset = 1;
} }
if (match.hasMatch()) { dbc_assert(match.hasMatch());
if (auto s = get_sig(address, match.captured(1))) { if (auto s = get_sig(address, match.captured(1))) {
s->min = match.captured(8 + offset).toDouble(); s->min = match.captured(8 + offset).toDouble();
s->max = match.captured(9 + offset).toDouble(); s->max = match.captured(9 + offset).toDouble();
s->unit = match.captured(10 + offset); s->unit = match.captured(10 + offset);
}
} }
} else if (line.startsWith("VAL_ ")) { } else if (line.startsWith("VAL_ ")) {
if (auto match = val_regexp.match(line); match.hasMatch()) { auto match = val_regexp.match(line);
if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) { dbc_assert(match.hasMatch());
QStringList desc_list = match.captured(3).trimmed().split('"'); if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) {
for (int i = 0; i < desc_list.size(); i += 2) { QStringList desc_list = match.captured(3).trimmed().split('"');
auto val = desc_list[i].trimmed(); for (int i = 0; i < desc_list.size(); i += 2) {
if (!val.isEmpty() && (i + 1) < desc_list.size()) { auto val = desc_list[i].trimmed();
auto desc = desc_list[i+1].trimmed(); if (!val.isEmpty() && (i + 1) < desc_list.size()) {
s->val_desc.push_back({val, desc}); auto desc = desc_list[i + 1].trimmed();
} s->val_desc.push_back({val.toDouble(), desc});
} }
} }
} }
} else if (line.startsWith("CM_ BO_")) { } else if (line.startsWith("CM_ BO_")) {
if (auto match = msg_comment_regexp.match(line); match.hasMatch()) { auto match = msg_comment_regexp.match(line);
if (auto m = (cabana::Msg *)msg(match.captured(1).toUInt())) { dbc_assert(match.hasMatch());
m->comment = match.captured(2).trimmed(); if (auto m = (cabana::Msg *)msg(match.captured(1).toUInt())) {
} m->comment = match.captured(2).trimmed();
} }
} else if (line.startsWith("CM_ SG_ ")) { } else if (line.startsWith("CM_ SG_ ")) {
if (auto match = sg_comment_regexp.match(line); match.hasMatch()) { auto match = sg_comment_regexp.match(line);
if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) { dbc_assert(match.hasMatch());
s->comment = match.captured(3).trimmed(); if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) {
} s->comment = match.captured(3).trimmed();
} }
} }
} }
@ -278,7 +284,7 @@ QString DBCFile::generateDBC() {
if (!sig->val_desc.isEmpty()) { if (!sig->val_desc.isEmpty()) {
QStringList text; QStringList text;
for (auto &[val, desc] : sig->val_desc) { for (auto &[val, desc] : sig->val_desc) {
text << QString("%1 \"%2\"").arg(val, desc); text << QString("%1 \"%2\"").arg(val).arg(desc);
} }
val_desc += QString("VAL_ %1 %2 %3;\n").arg(address).arg(sig->name).arg(text.join(" ")); val_desc += QString("VAL_ %1 %2 %3;\n").arg(address).arg(sig->name).arg(text.join(" "));
} }

@ -224,7 +224,7 @@ LogsWidget::LogsWidget(QWidget *parent) : QFrame(parent) {
display_type_cb->setToolTip(tr("Display signal value or raw hex value")); display_type_cb->setToolTip(tr("Display signal value or raw hex value"));
comp_box->addItems({">", "=", "!=", "<"}); comp_box->addItems({">", "=", "!=", "<"});
value_edit->setClearButtonEnabled(true); value_edit->setClearButtonEnabled(true);
value_edit->setValidator(new QDoubleValidator(-500000, 500000, 6, this)); value_edit->setValidator(new DoubleValidator(this));
dynamic_mode->setChecked(true); dynamic_mode->setChecked(true);
dynamic_mode->setEnabled(!can->liveStreaming()); dynamic_mode->setEnabled(!can->liveStreaming());

@ -133,7 +133,7 @@ QVariant SignalModel::data(const QModelIndex &index, int role) const {
case Item::Desc: { case Item::Desc: {
QStringList val_desc; QStringList val_desc;
for (auto &[val, desc] : item->sig->val_desc) { for (auto &[val, desc] : item->sig->val_desc) {
val_desc << QString("%1 \"%2\"").arg(val, desc); val_desc << QString("%1 \"%2\"").arg(val).arg(desc);
} }
return val_desc.join(" "); return val_desc.join(" ");
} }
@ -284,11 +284,7 @@ void SignalModel::handleSignalRemoved(const cabana::Signal *sig) {
SignalItemDelegate::SignalItemDelegate(QObject *parent) : QStyledItemDelegate(parent) { SignalItemDelegate::SignalItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {
name_validator = new NameValidator(this); name_validator = new NameValidator(this);
double_validator = new DoubleValidator(this);
QLocale locale(QLocale::C);
locale.setNumberOptions(QLocale::RejectGroupSeparator);
double_validator = new QDoubleValidator(this);
double_validator->setLocale(locale); // Match locale of QString::toDouble() instead of system
label_font.setPointSize(8); label_font.setPointSize(8);
minmax_font.setPixelSize(10); minmax_font.setPixelSize(10);
@ -666,7 +662,7 @@ ValueDescriptionDlg::ValueDescriptionDlg(const ValueDescription &descriptions, Q
int row = 0; int row = 0;
for (auto &[val, desc] : descriptions) { for (auto &[val, desc] : descriptions) {
table->setItem(row, 0, new QTableWidgetItem(val)); table->setItem(row, 0, new QTableWidgetItem(QString::number(val)));
table->setItem(row, 1, new QTableWidgetItem(desc)); table->setItem(row, 1, new QTableWidgetItem(desc));
++row; ++row;
} }
@ -696,7 +692,7 @@ void ValueDescriptionDlg::save() {
QString val = table->item(i, 0)->text().trimmed(); QString val = table->item(i, 0)->text().trimmed();
QString desc = table->item(i, 1)->text().trimmed(); QString desc = table->item(i, 1)->text().trimmed();
if (!val.isEmpty() && !desc.isEmpty()) { if (!val.isEmpty() && !desc.isEmpty()) {
val_desc.push_back({val, desc}); val_desc.push_back({val.toDouble(), desc});
} }
} }
QDialog::accept(); QDialog::accept();
@ -706,7 +702,7 @@ QWidget *ValueDescriptionDlg::Delegate::createEditor(QWidget *parent, const QSty
QLineEdit *edit = new QLineEdit(parent); QLineEdit *edit = new QLineEdit(parent);
edit->setFrame(false); edit->setFrame(false);
if (index.column() == 0) { if (index.column() == 0) {
edit->setValidator(new QIntValidator(edit)); edit->setValidator(new DoubleValidator(parent));
} }
return edit; return edit;
} }

@ -1,6 +1,5 @@
#include "tools/cabana/tools/findsignal.h" #include "tools/cabana/tools/findsignal.h"
#include <QDoubleValidator>
#include <QFormLayout> #include <QFormLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
@ -138,8 +137,7 @@ FindSignalDlg::FindSignalDlg(QWidget *parent) : QDialog(parent, Qt::WindowFlags(
undo_btn->setEnabled(false); undo_btn->setEnabled(false);
reset_btn->setEnabled(false); reset_btn->setEnabled(false);
auto double_validator = new QDoubleValidator(this); auto double_validator = new DoubleValidator(this);
double_validator->setLocale(QLocale::C);
for (auto edit : {value1, value2, factor_edit, offset_edit, first_time_edit, last_time_edit}) { for (auto edit : {value1, value2, factor_edit, offset_edit, first_time_edit, last_time_edit}) {
edit->setValidator(double_validator); edit->setValidator(double_validator);
} }

@ -2,6 +2,7 @@
#include <QFontDatabase> #include <QFontDatabase>
#include <QHelpEvent> #include <QHelpEvent>
#include <QLocale>
#include <QPainter> #include <QPainter>
#include <QPixmapCache> #include <QPixmapCache>
#include <QToolTip> #include <QToolTip>
@ -161,6 +162,13 @@ QValidator::State NameValidator::validate(QString &input, int &pos) const {
return QRegExpValidator::validate(input, pos); return QRegExpValidator::validate(input, pos);
} }
DoubleValidator::DoubleValidator(QObject *parent) : QDoubleValidator(parent) {
// Match locale of QString::toDouble() instead of system
QLocale locale(QLocale::C);
locale.setNumberOptions(QLocale::RejectGroupSeparator);
setLocale(locale);
}
namespace utils { namespace utils {
QPixmap icon(const QString &id) { QPixmap icon(const QString &id) {
bool dark_theme = settings.theme == DARK_THEME; bool dark_theme = settings.theme == DARK_THEME;

@ -6,6 +6,7 @@
#include <QApplication> #include <QApplication>
#include <QByteArray> #include <QByteArray>
#include <QDateTime> #include <QDateTime>
#include <QDoubleValidator>
#include <QColor> #include <QColor>
#include <QFont> #include <QFont>
#include <QRegExpValidator> #include <QRegExpValidator>
@ -84,12 +85,17 @@ QColor getColor(const cabana::Signal *sig);
class NameValidator : public QRegExpValidator { class NameValidator : public QRegExpValidator {
Q_OBJECT Q_OBJECT
public: public:
NameValidator(QObject *parent=nullptr); NameValidator(QObject *parent=nullptr);
QValidator::State validate(QString &input, int &pos) const override; QValidator::State validate(QString &input, int &pos) const override;
}; };
class DoubleValidator : public QDoubleValidator {
Q_OBJECT
public:
DoubleValidator(QObject *parent = nullptr);
};
namespace utils { namespace utils {
QPixmap icon(const QString &id); QPixmap icon(const QString &id);
void setTheme(int theme); void setTheme(int theme);

Loading…
Cancel
Save