Release 260111
This commit is contained in:
120
tools/cabana/dbc/dbc.h
Normal file
120
tools/cabana/dbc/dbc.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <QColor>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
|
||||
const QString UNTITLED = "untitled";
|
||||
const QString DEFAULT_NODE_NAME = "XXX";
|
||||
constexpr int CAN_MAX_DATA_BYTES = 64;
|
||||
|
||||
struct MessageId {
|
||||
uint8_t source = 0;
|
||||
uint32_t address = 0;
|
||||
|
||||
QString toString() const {
|
||||
return QString("%1:%2").arg(source).arg(QString::number(address, 16).toUpper());
|
||||
}
|
||||
|
||||
bool operator==(const MessageId &other) const {
|
||||
return source == other.source && address == other.address;
|
||||
}
|
||||
|
||||
bool operator!=(const MessageId &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool operator<(const MessageId &other) const {
|
||||
return std::tie(source, address) < std::tie(other.source, other.address);
|
||||
}
|
||||
|
||||
bool operator>(const MessageId &other) const {
|
||||
return std::tie(source, address) > std::tie(other.source, other.address);
|
||||
}
|
||||
};
|
||||
|
||||
uint qHash(const MessageId &item);
|
||||
Q_DECLARE_METATYPE(MessageId);
|
||||
|
||||
template <>
|
||||
struct std::hash<MessageId> {
|
||||
std::size_t operator()(const MessageId &k) const noexcept { return qHash(k); }
|
||||
};
|
||||
|
||||
typedef std::vector<std::pair<double, QString>> ValueDescription;
|
||||
|
||||
namespace cabana {
|
||||
|
||||
class Signal {
|
||||
public:
|
||||
Signal() = default;
|
||||
Signal(const Signal &other) = default;
|
||||
void update();
|
||||
bool getValue(const uint8_t *data, size_t data_size, double *val) const;
|
||||
QString formatValue(double value, bool with_unit = true) const;
|
||||
bool operator==(const cabana::Signal &other) const;
|
||||
inline bool operator!=(const cabana::Signal &other) const { return !(*this == other); }
|
||||
|
||||
enum class Type {
|
||||
Normal = 0,
|
||||
Multiplexed,
|
||||
Multiplexor
|
||||
};
|
||||
|
||||
Type type = Type::Normal;
|
||||
QString name;
|
||||
int start_bit, msb, lsb, size;
|
||||
double factor = 1.0;
|
||||
double offset = 0;
|
||||
bool is_signed;
|
||||
bool is_little_endian;
|
||||
double min, max;
|
||||
QString unit;
|
||||
QString comment;
|
||||
QString receiver_name;
|
||||
ValueDescription val_desc;
|
||||
int precision = 0;
|
||||
QColor color;
|
||||
|
||||
// Multiplexed
|
||||
int multiplex_value = 0;
|
||||
Signal *multiplexor = nullptr;
|
||||
};
|
||||
|
||||
class Msg {
|
||||
public:
|
||||
Msg() = default;
|
||||
Msg(const Msg &other) { *this = other; }
|
||||
~Msg();
|
||||
cabana::Signal *addSignal(const cabana::Signal &sig);
|
||||
cabana::Signal *updateSignal(const QString &sig_name, const cabana::Signal &sig);
|
||||
void removeSignal(const QString &sig_name);
|
||||
Msg &operator=(const Msg &other);
|
||||
int indexOf(const cabana::Signal *sig) const;
|
||||
cabana::Signal *sig(const QString &sig_name) const;
|
||||
QString newSignalName();
|
||||
void update();
|
||||
inline const std::vector<cabana::Signal *> &getSignals() const { return sigs; }
|
||||
|
||||
uint32_t address;
|
||||
QString name;
|
||||
uint32_t size;
|
||||
QString comment;
|
||||
QString transmitter;
|
||||
std::vector<cabana::Signal *> sigs;
|
||||
|
||||
std::vector<uint8_t> mask;
|
||||
cabana::Signal *multiplexor = nullptr;
|
||||
};
|
||||
|
||||
} // namespace cabana
|
||||
|
||||
// Helper functions
|
||||
double get_raw_value(const uint8_t *data, size_t data_size, const cabana::Signal &sig);
|
||||
void updateMsbLsb(cabana::Signal &s);
|
||||
inline int flipBitPos(int start_bit) { return 8 * (start_bit / 8) + 7 - start_bit % 8; }
|
||||
inline QString doubleToString(double value) { return QString::number(value, 'g', std::numeric_limits<double>::digits10); }
|
||||
44
tools/cabana/dbc/dbcfile.h
Normal file
44
tools/cabana/dbc/dbcfile.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "tools/cabana/dbc/dbc.h"
|
||||
|
||||
class DBCFile {
|
||||
public:
|
||||
DBCFile(const QString &dbc_file_name);
|
||||
DBCFile(const QString &name, const QString &content);
|
||||
~DBCFile() {}
|
||||
|
||||
bool save();
|
||||
bool saveAs(const QString &new_filename);
|
||||
bool writeContents(const QString &fn);
|
||||
QString generateDBC();
|
||||
|
||||
void updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &node, const QString &comment);
|
||||
inline void removeMsg(const MessageId &id) { msgs.erase(id.address); }
|
||||
|
||||
inline const std::map<uint32_t, cabana::Msg> &getMessages() const { return msgs; }
|
||||
cabana::Msg *msg(uint32_t address);
|
||||
cabana::Msg *msg(const QString &name);
|
||||
inline cabana::Msg *msg(const MessageId &id) { return msg(id.address); }
|
||||
cabana::Signal *signal(uint32_t address, const QString &name);
|
||||
|
||||
inline QString name() const { return name_.isEmpty() ? "untitled" : name_; }
|
||||
inline bool isEmpty() const { return msgs.empty() && name_.isEmpty(); }
|
||||
|
||||
QString filename;
|
||||
|
||||
private:
|
||||
void parse(const QString &content);
|
||||
cabana::Msg *parseBO(const QString &line);
|
||||
void parseSG(const QString &line, cabana::Msg *current_msg, int &multiplexor_cnt);
|
||||
void parseCM_BO(const QString &line, const QString &content, const QString &raw_line, const QTextStream &stream);
|
||||
void parseCM_SG(const QString &line, const QString &content, const QString &raw_line, const QTextStream &stream);
|
||||
void parseVAL(const QString &line);
|
||||
|
||||
QString header;
|
||||
std::map<uint32_t, cabana::Msg> msgs;
|
||||
QString name_;
|
||||
};
|
||||
69
tools/cabana/dbc/dbcmanager.h
Normal file
69
tools/cabana/dbc/dbcmanager.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "tools/cabana/dbc/dbcfile.h"
|
||||
|
||||
typedef std::set<int> SourceSet;
|
||||
const SourceSet SOURCE_ALL = {-1};
|
||||
const int INVALID_SOURCE = 0xff;
|
||||
inline bool operator<(const std::shared_ptr<DBCFile> &l, const std::shared_ptr<DBCFile> &r) { return l.get() < r.get(); }
|
||||
|
||||
class DBCManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DBCManager(QObject *parent) : QObject(parent) {}
|
||||
~DBCManager() {}
|
||||
bool open(const SourceSet &sources, const QString &dbc_file_name, QString *error = nullptr);
|
||||
bool open(const SourceSet &sources, const QString &name, const QString &content, QString *error = nullptr);
|
||||
void close(const SourceSet &sources);
|
||||
void close(DBCFile *dbc_file);
|
||||
void closeAll();
|
||||
|
||||
void addSignal(const MessageId &id, const cabana::Signal &sig);
|
||||
void updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig);
|
||||
void removeSignal(const MessageId &id, const QString &sig_name);
|
||||
|
||||
void updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &node, const QString &comment);
|
||||
void removeMsg(const MessageId &id);
|
||||
|
||||
QString newMsgName(const MessageId &id);
|
||||
QString newSignalName(const MessageId &id);
|
||||
|
||||
const std::map<uint32_t, cabana::Msg> &getMessages(uint8_t source);
|
||||
cabana::Msg *msg(const MessageId &id);
|
||||
cabana::Msg* msg(uint8_t source, const QString &name);
|
||||
|
||||
QStringList signalNames();
|
||||
inline int dbcCount() { return allDBCFiles().size(); }
|
||||
int nonEmptyDBCCount();
|
||||
|
||||
const SourceSet sources(const DBCFile *dbc_file) const;
|
||||
DBCFile *findDBCFile(const uint8_t source);
|
||||
inline DBCFile *findDBCFile(const MessageId &id) { return findDBCFile(id.source); }
|
||||
std::set<DBCFile *> allDBCFiles();
|
||||
|
||||
signals:
|
||||
void signalAdded(MessageId id, const cabana::Signal *sig);
|
||||
void signalRemoved(const cabana::Signal *sig);
|
||||
void signalUpdated(const cabana::Signal *sig);
|
||||
void msgUpdated(MessageId id);
|
||||
void msgRemoved(MessageId id);
|
||||
void DBCFileChanged();
|
||||
void maskUpdated();
|
||||
|
||||
private:
|
||||
std::map<int, std::shared_ptr<DBCFile>> dbc_files;
|
||||
};
|
||||
|
||||
DBCManager *dbc();
|
||||
|
||||
QString toString(const SourceSet &ss);
|
||||
inline QString msgName(const MessageId &id) {
|
||||
auto msg = dbc()->msg(id);
|
||||
return msg ? msg->name : UNTITLED;
|
||||
}
|
||||
39
tools/cabana/dbc/generate_dbc_json.py
Normal file
39
tools/cabana/dbc/generate_dbc_json.py
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
|
||||
from opendbc.car import Bus
|
||||
from opendbc.car.fingerprints import MIGRATION
|
||||
from opendbc.car.values import PLATFORMS
|
||||
|
||||
|
||||
def generate_dbc_dict() -> dict[str, str]:
|
||||
dbc_map = {}
|
||||
for platform in PLATFORMS.values():
|
||||
if platform != "MOCK":
|
||||
if Bus.pt in platform.config.dbc_dict:
|
||||
dbc_map[platform.name] = platform.config.dbc_dict[Bus.pt]
|
||||
elif Bus.main in platform.config.dbc_dict:
|
||||
dbc_map[platform.name] = platform.config.dbc_dict[Bus.main]
|
||||
elif Bus.party in platform.config.dbc_dict:
|
||||
dbc_map[platform.name] = platform.config.dbc_dict[Bus.party]
|
||||
else:
|
||||
raise ValueError("Unknown main type")
|
||||
|
||||
for m in MIGRATION:
|
||||
if MIGRATION[m] in dbc_map:
|
||||
dbc_map[m] = dbc_map[MIGRATION[m]]
|
||||
|
||||
return dbc_map
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate mapping for all car fingerprints to DBC names and outputs json file",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
|
||||
parser.add_argument("--out", required=True, help="Generated json filepath")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.out, 'w') as f:
|
||||
f.write(json.dumps(dict(sorted(generate_dbc_dict().items())), indent=2))
|
||||
print(f"Generated and written to {args.out}")
|
||||
Reference in New Issue
Block a user