dragonpilot - 基於 openpilot 的開源駕駛輔助系統
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

181 lines
4.8 KiB

#include "tools/cabana/parser.h"
#include <QDebug>
#include "cereal/messaging/messaging.h"
Parser *parser = nullptr;
static bool event_filter(const Event *e, void *opaque) {
Parser *p = (Parser*)opaque;
return p->eventFilter(e);
}
Parser::Parser(QObject *parent) : QObject(parent) {
parser = this;
qRegisterMetaType<std::vector<CanData>>();
QObject::connect(this, &Parser::received, this, &Parser::process, Qt::QueuedConnection);
}
Parser::~Parser() {
replay->stop();
}
bool Parser::loadRoute(const QString &route, const QString &data_dir, bool use_qcam) {
replay = new Replay(route, {"can", "roadEncodeIdx"}, {}, nullptr, use_qcam ? REPLAY_FLAG_QCAMERA : 0, data_dir, this);
replay->installEventFilter(event_filter, this);
QObject::connect(replay, &Replay::segmentsMerged, this, &Parser::segmentsMerged);
if (replay->load()) {
replay->start();
return true;
}
return false;
}
void Parser::openDBC(const QString &name) {
dbc_name = name;
dbc = const_cast<DBC *>(dbc_lookup(name.toStdString()));
counters.clear();
msg_map.clear();
for (auto &msg : dbc->msgs) {
msg_map[msg.address] = &msg;
}
}
void Parser::process(std::vector<CanData> msgs) {
static double prev_update_ts = 0;
for (const auto &can_data : msgs) {
can_msgs[can_data.id] = can_data;
++counters[can_data.id];
if (can_data.id == current_msg_id) {
while (history_log.size() >= LOG_SIZE) {
history_log.pop_back();
}
history_log.push_front(can_data);
}
}
double now = millis_since_boot();
if ((now - prev_update_ts) > 1000.0 / FPS) {
prev_update_ts = now;
emit updated();
}
if (current_sec < begin_sec || current_sec > end_sec) {
// loop replay in selected range.
seekTo(begin_sec);
}
}
bool Parser::eventFilter(const Event *event) {
// drop packets when the GUI thread is calling seekTo. to make sure the current_sec is accurate.
if (!seeking && event->which == cereal::Event::Which::CAN) {
current_sec = (event->mono_time - replay->routeStartTime()) / (double)1e9;
auto can = event->event.getCan();
msgs_buf.clear();
msgs_buf.reserve(can.size());
for (const auto &c : can) {
CanData &data = msgs_buf.emplace_back();
data.address = c.getAddress();
data.bus_time = c.getBusTime();
data.source = c.getSrc();
data.dat.append((char *)c.getDat().begin(), c.getDat().size());
data.id = QString("%1:%2").arg(data.source).arg(data.address, 1, 16);
data.ts = current_sec;
}
emit received(msgs_buf);
}
return true;
}
void Parser::seekTo(double ts) {
seeking = true;
replay->seekTo(ts, false);
seeking = false;
}
void Parser::addNewMsg(const Msg &msg) {
dbc->msgs.push_back(msg);
msg_map[dbc->msgs.back().address] = &dbc->msgs.back();
}
void Parser::removeSignal(const QString &id, const QString &sig_name) {
Msg *msg = const_cast<Msg *>(getMsg(id));
if (!msg) return;
auto it = std::find_if(msg->sigs.begin(), msg->sigs.end(), [=](auto &sig) { return sig_name == sig.name.c_str(); });
if (it != msg->sigs.end()) {
msg->sigs.erase(it);
emit signalRemoved(id, sig_name);
}
}
uint32_t Parser::addressFromId(const QString &id) {
return id.mid(id.indexOf(':') + 1).toUInt(nullptr, 16);
}
const Signal *Parser::getSig(const QString &id, const QString &sig_name) {
if (auto msg = getMsg(id)) {
auto it = std::find_if(msg->sigs.begin(), msg->sigs.end(), [&](auto &s) { return sig_name == s.name.c_str(); });
if (it != msg->sigs.end()) {
return &(*it);
}
}
return nullptr;
}
void Parser::setRange(double min, double max) {
if (begin_sec != min || end_sec != max) {
begin_sec = min;
end_sec = max;
is_zoomed = begin_sec != event_begin_sec || end_sec != event_end_sec;
emit rangeChanged(min, max);
}
}
void Parser::segmentsMerged() {
auto events = replay->events();
if (!events || events->empty()) return;
auto it = std::find_if(events->begin(), events->end(), [=](const Event *e) { return e->which == cereal::Event::Which::CAN; });
event_begin_sec = it == events->end() ? 0 : ((*it)->mono_time - replay->routeStartTime()) / (double)1e9;
event_end_sec = double(events->back()->mono_time - replay->routeStartTime()) / 1e9;
if (!is_zoomed) {
begin_sec = event_begin_sec;
end_sec = event_end_sec;
}
emit eventsMerged();
}
void Parser::resetRange() {
setRange(event_begin_sec, event_end_sec);
}
void Parser::setCurrentMsg(const QString &id) {
current_msg_id = id;
history_log.clear();
}
// helper functions
static QVector<int> BIG_ENDIAN_START_BITS = []() {
QVector<int> ret;
for (int i = 0; i < 64; i++) {
for (int j = 7; j >= 0; j--) {
ret.push_back(j + i * 8);
}
}
return ret;
}();
int bigEndianStartBitsIndex(int start_bit) {
return BIG_ENDIAN_START_BITS[start_bit];
}
int bigEndianBitIndex(int index) {
return BIG_ENDIAN_START_BITS.indexOf(index);
}