|
|
@ -1,7 +1,4 @@ |
|
|
|
#include "tools/cabana/canmessages.h" |
|
|
|
#include "tools/cabana/canmessages.h" |
|
|
|
|
|
|
|
|
|
|
|
#include <QSettings> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "tools/cabana/dbcmanager.h" |
|
|
|
#include "tools/cabana/dbcmanager.h" |
|
|
|
|
|
|
|
|
|
|
|
CANMessages *can = nullptr; |
|
|
|
CANMessages *can = nullptr; |
|
|
@ -25,6 +22,7 @@ bool CANMessages::loadRoute(const QString &route, const QString &data_dir, uint3 |
|
|
|
replay = new Replay(route, {"can", "roadEncodeIdx", "wideRoadEncodeIdx", "carParams"}, {}, nullptr, replay_flags, data_dir, this); |
|
|
|
replay = new Replay(route, {"can", "roadEncodeIdx", "wideRoadEncodeIdx", "carParams"}, {}, nullptr, replay_flags, data_dir, this); |
|
|
|
replay->setSegmentCacheLimit(settings.cached_segment_limit); |
|
|
|
replay->setSegmentCacheLimit(settings.cached_segment_limit); |
|
|
|
replay->installEventFilter(event_filter, this); |
|
|
|
replay->installEventFilter(event_filter, this); |
|
|
|
|
|
|
|
QObject::connect(replay, &Replay::seekedTo, this, &CANMessages::seekedTo); |
|
|
|
QObject::connect(replay, &Replay::segmentsMerged, this, &CANMessages::eventsMerged); |
|
|
|
QObject::connect(replay, &Replay::segmentsMerged, this, &CANMessages::eventsMerged); |
|
|
|
QObject::connect(replay, &Replay::streamStarted, this, &CANMessages::streamStarted); |
|
|
|
QObject::connect(replay, &Replay::streamStarted, this, &CANMessages::streamStarted); |
|
|
|
if (replay->load()) { |
|
|
|
if (replay->load()) { |
|
|
@ -69,17 +67,13 @@ void CANMessages::process(QHash<QString, CanData> *messages) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CANMessages::eventFilter(const Event *event) { |
|
|
|
bool CANMessages::eventFilter(const Event *event) { |
|
|
|
static std::unique_ptr<QHash<QString, CanData>> new_msgs; |
|
|
|
static std::unique_ptr new_msgs = std::make_unique<QHash<QString, CanData>>(); |
|
|
|
static double prev_update_ts = 0; |
|
|
|
static double prev_update_ts = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (event->which == cereal::Event::Which::CAN) { |
|
|
|
if (event->which == cereal::Event::Which::CAN) { |
|
|
|
if (!new_msgs) { |
|
|
|
|
|
|
|
new_msgs.reset(new QHash<QString, CanData>); |
|
|
|
|
|
|
|
new_msgs->reserve(1000); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double current_sec = replay->currentSeconds(); |
|
|
|
double current_sec = replay->currentSeconds(); |
|
|
|
if (counters_begin_sec == 0 || counters_begin_sec >= current_sec) { |
|
|
|
if (counters_begin_sec == 0 || counters_begin_sec >= current_sec) { |
|
|
|
|
|
|
|
new_msgs->clear(); |
|
|
|
counters.clear(); |
|
|
|
counters.clear(); |
|
|
|
counters_begin_sec = current_sec; |
|
|
|
counters_begin_sec = current_sec; |
|
|
|
} |
|
|
|
} |
|
|
@ -87,40 +81,29 @@ bool CANMessages::eventFilter(const Event *event) { |
|
|
|
auto can_events = event->event.getCan(); |
|
|
|
auto can_events = event->event.getCan(); |
|
|
|
for (const auto &c : can_events) { |
|
|
|
for (const auto &c : can_events) { |
|
|
|
QString id = QString("%1:%2").arg(c.getSrc()).arg(c.getAddress(), 1, 16); |
|
|
|
QString id = QString("%1:%2").arg(c.getSrc()).arg(c.getAddress(), 1, 16); |
|
|
|
|
|
|
|
CanData &data = (*new_msgs)[id]; |
|
|
|
std::lock_guard lk(lock); |
|
|
|
|
|
|
|
auto &list = received_msgs[id]; |
|
|
|
|
|
|
|
while (list.size() > settings.can_msg_log_size) { |
|
|
|
|
|
|
|
list.pop_back(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
CanData &data = list.emplace_front(); |
|
|
|
|
|
|
|
data.ts = current_sec; |
|
|
|
data.ts = current_sec; |
|
|
|
data.dat.append((char *)c.getDat().begin(), c.getDat().size()); |
|
|
|
data.dat = QByteArray((char *)c.getDat().begin(), c.getDat().size()); |
|
|
|
|
|
|
|
|
|
|
|
data.count = ++counters[id]; |
|
|
|
data.count = ++counters[id]; |
|
|
|
if (double delta = (current_sec - counters_begin_sec); delta > 0) { |
|
|
|
if (double delta = (current_sec - counters_begin_sec); delta > 0) { |
|
|
|
data.freq = data.count / delta; |
|
|
|
data.freq = data.count / delta; |
|
|
|
} |
|
|
|
} |
|
|
|
(*new_msgs)[id] = data; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
double ts = millis_since_boot(); |
|
|
|
double ts = millis_since_boot(); |
|
|
|
if ((ts - prev_update_ts) > (1000.0 / settings.fps) && !processing) { |
|
|
|
if ((ts - prev_update_ts) > (1000.0 / settings.fps) && !processing && !new_msgs->isEmpty()) { |
|
|
|
// delay posting CAN message if UI thread is busy
|
|
|
|
// delay posting CAN message if UI thread is busy
|
|
|
|
processing = true; |
|
|
|
processing = true; |
|
|
|
prev_update_ts = ts; |
|
|
|
prev_update_ts = ts; |
|
|
|
// use pointer to avoid data copy in queued connection.
|
|
|
|
// use pointer to avoid data copy in queued connection.
|
|
|
|
emit received(new_msgs.release()); |
|
|
|
emit received(new_msgs.release()); |
|
|
|
|
|
|
|
new_msgs.reset(new QHash<QString, CanData>); |
|
|
|
|
|
|
|
new_msgs->reserve(100); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const std::deque<CanData> CANMessages::messages(const QString &id) { |
|
|
|
|
|
|
|
std::lock_guard lk(lock); |
|
|
|
|
|
|
|
return received_msgs[id]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CANMessages::seekTo(double ts) { |
|
|
|
void CANMessages::seekTo(double ts) { |
|
|
|
replay->seekTo(std::max(double(0), ts), false); |
|
|
|
replay->seekTo(std::max(double(0), ts), false); |
|
|
|
counters_begin_sec = 0; |
|
|
|
counters_begin_sec = 0; |
|
|
|