cabana: increase replay's segment cache limit & add setting dialog (#26019)

* increase replay's segment cache limit

* todo

* add settings dialog

blank line

typo
pull/26057/head
Dean Lee 3 years ago committed by GitHub
parent 8809116a26
commit b31932382d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      tools/cabana/.gitignore
  2. 36
      tools/cabana/canmessages.cc
  3. 19
      tools/cabana/canmessages.h
  4. 54
      tools/cabana/mainwin.cc
  5. 12
      tools/cabana/mainwin.h
  6. 4
      tools/replay/replay.cc
  7. 5
      tools/replay/replay.h

@ -2,3 +2,4 @@ moc_*
*.moc *.moc
_cabana _cabana
settings

@ -1,9 +1,11 @@
#include "tools/cabana/canmessages.h" #include "tools/cabana/canmessages.h"
#include <QDebug> #include <QDebug>
#include <QSettings>
Q_DECLARE_METATYPE(std::vector<CanData>); Q_DECLARE_METATYPE(std::vector<CanData>);
Settings settings;
CANMessages *can = nullptr; CANMessages *can = nullptr;
CANMessages::CANMessages(QObject *parent) : QObject(parent) { CANMessages::CANMessages(QObject *parent) : QObject(parent) {
@ -11,6 +13,7 @@ CANMessages::CANMessages(QObject *parent) : QObject(parent) {
qRegisterMetaType<std::vector<CanData>>(); qRegisterMetaType<std::vector<CanData>>();
QObject::connect(this, &CANMessages::received, this, &CANMessages::process, Qt::QueuedConnection); QObject::connect(this, &CANMessages::received, this, &CANMessages::process, Qt::QueuedConnection);
QObject::connect(&settings, &Settings::changed, this, &CANMessages::settingChanged);
} }
CANMessages::~CANMessages() { CANMessages::~CANMessages() {
@ -24,6 +27,7 @@ static bool event_filter(const Event *e, void *opaque) {
bool CANMessages::loadRoute(const QString &route, const QString &data_dir, bool use_qcam) { bool CANMessages::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 = new Replay(route, {"can", "roadEncodeIdx"}, {}, nullptr, use_qcam ? REPLAY_FLAG_QCAMERA : 0, data_dir, this);
replay->setSegmentCacheLimit(settings.cached_segment_limit);
replay->installEventFilter(event_filter, this); replay->installEventFilter(event_filter, this);
QObject::connect(replay, &Replay::segmentsMerged, this, &CANMessages::segmentsMerged); QObject::connect(replay, &Replay::segmentsMerged, this, &CANMessages::segmentsMerged);
if (replay->load()) { if (replay->load()) {
@ -38,11 +42,11 @@ void CANMessages::process(QHash<QString, std::deque<CanData>> *messages) {
++counters[it.key()]; ++counters[it.key()];
auto &msgs = can_msgs[it.key()]; auto &msgs = can_msgs[it.key()];
const auto &new_msgs = it.value(); const auto &new_msgs = it.value();
if (msgs.size() == CAN_MSG_LOG_SIZE || can_msgs[it.key()].size() == 0) { if (new_msgs.size() == settings.can_msg_log_size || msgs.empty()) {
msgs = std::move(new_msgs); msgs = std::move(new_msgs);
} else { } else {
msgs.insert(msgs.begin(), std::make_move_iterator(new_msgs.begin()), std::make_move_iterator(new_msgs.end())); msgs.insert(msgs.begin(), std::make_move_iterator(new_msgs.begin()), std::make_move_iterator(new_msgs.end()));
while (msgs.size() >= CAN_MSG_LOG_SIZE) { while (msgs.size() >= settings.can_msg_log_size) {
msgs.pop_back(); msgs.pop_back();
} }
} }
@ -71,7 +75,7 @@ bool CANMessages::eventFilter(const Event *event) {
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);
auto &list = (*received_msgs)[id]; auto &list = (*received_msgs)[id];
while (list.size() >= CAN_MSG_LOG_SIZE) { while (list.size() >= settings.can_msg_log_size) {
list.pop_back(); list.pop_back();
} }
CanData &data = list.emplace_front(); CanData &data = list.emplace_front();
@ -80,7 +84,7 @@ bool CANMessages::eventFilter(const Event *event) {
data.dat.append((char *)c.getDat().begin(), c.getDat().size()); data.dat.append((char *)c.getDat().begin(), c.getDat().size());
} }
if (current_sec < prev_update_sec || (current_sec - prev_update_sec) > 1.0 / FPS) { if (current_sec < prev_update_sec || (current_sec - prev_update_sec) > 1.0 / settings.fps) {
prev_update_sec = current_sec; prev_update_sec = current_sec;
// use pointer to avoid data copy in queued connection. // use pointer to avoid data copy in queued connection.
emit received(received_msgs.release()); emit received(received_msgs.release());
@ -121,3 +125,27 @@ void CANMessages::segmentsMerged() {
void CANMessages::resetRange() { void CANMessages::resetRange() {
setRange(event_begin_sec, event_end_sec); setRange(event_begin_sec, event_end_sec);
} }
void CANMessages::settingChanged() {
replay->setSegmentCacheLimit(settings.cached_segment_limit);
}
// Settings
Settings::Settings() {
load();
}
void Settings::save() {
QSettings s("settings", QSettings::IniFormat);
s.setValue("fps", fps);
s.setValue("log_size", can_msg_log_size);
s.setValue("cached_segment", cached_segment_limit);
}
void Settings::load() {
QSettings s("settings", QSettings::IniFormat);
fps = s.value("fps", 10).toInt();
can_msg_log_size = s.value("log_size", 100).toInt();
cached_segment_limit = s.value("cached_segment", 3.).toInt();
}

@ -8,8 +8,21 @@
#include "tools/replay/replay.h" #include "tools/replay/replay.h"
const int FPS = 10; class Settings : public QObject {
const int CAN_MSG_LOG_SIZE = 100; Q_OBJECT
public:
Settings();
void save();
void load();
int fps = 10;
int can_msg_log_size = 100;
int cached_segment_limit = 3;
signals:
void changed();
};
struct CanData { struct CanData {
double ts; double ts;
@ -57,6 +70,7 @@ public:
protected: protected:
void process(QHash<QString, std::deque<CanData>> *); void process(QHash<QString, std::deque<CanData>> *);
void segmentsMerged(); void segmentsMerged();
void settingChanged();
std::atomic<double> current_sec = 0.; std::atomic<double> current_sec = 0.;
std::atomic<bool> seeking = false; std::atomic<bool> seeking = false;
@ -82,3 +96,4 @@ inline const QString &getColor(int i) {
// A global pointer referring to the unique CANMessages object // A global pointer referring to the unique CANMessages object
extern CANMessages *can; extern CANMessages *can;
extern Settings settings;

@ -1,7 +1,9 @@
#include "tools/cabana/mainwin.h" #include "tools/cabana/mainwin.h"
#include <QApplication> #include <QApplication>
#include <QDialogButtonBox>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QFormLayout>
#include <QScreen> #include <QScreen>
#include <QVBoxLayout> #include <QVBoxLayout>
@ -23,6 +25,9 @@ MainWindow::MainWindow() : QWidget() {
right_container->setFixedWidth(640); right_container->setFixedWidth(640);
r_layout = new QVBoxLayout(right_container); r_layout = new QVBoxLayout(right_container);
QPushButton *settings_btn = new QPushButton("Settings");
r_layout->addWidget(settings_btn, 0, Qt::AlignRight);
video_widget = new VideoWidget(this); video_widget = new VideoWidget(this);
r_layout->addWidget(video_widget, 0, Qt::AlignTop); r_layout->addWidget(video_widget, 0, Qt::AlignTop);
@ -34,6 +39,7 @@ MainWindow::MainWindow() : QWidget() {
QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, detail_widget, &DetailWidget::setMessage); QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, detail_widget, &DetailWidget::setMessage);
QObject::connect(detail_widget, &DetailWidget::showChart, charts_widget, &ChartsWidget::addChart); QObject::connect(detail_widget, &DetailWidget::showChart, charts_widget, &ChartsWidget::addChart);
QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts); QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts);
QObject::connect(settings_btn, &QPushButton::clicked, this, &MainWindow::setOption);
} }
void MainWindow::dockCharts(bool dock) { void MainWindow::dockCharts(bool dock) {
@ -59,3 +65,51 @@ void MainWindow::closeEvent(QCloseEvent *event) {
floating_window->deleteLater(); floating_window->deleteLater();
QWidget::closeEvent(event); QWidget::closeEvent(event);
} }
void MainWindow::setOption() {
SettingsDlg dlg(this);
dlg.exec();
}
// SettingsDlg
SettingsDlg::SettingsDlg(QWidget *parent) : QDialog(parent) {
setWindowTitle(tr("Settings"));
QVBoxLayout *main_layout = new QVBoxLayout(this);
QFormLayout *form_layout = new QFormLayout();
fps = new QSpinBox(this);
fps->setRange(10, 100);
fps->setSingleStep(10);
fps->setValue(settings.fps);
form_layout->addRow("FPS", fps);
log_size = new QSpinBox(this);
log_size->setRange(50, 500);
log_size->setSingleStep(10);
log_size->setValue(settings.can_msg_log_size);
form_layout->addRow(tr("Log size"), log_size);
cached_segment = new QSpinBox(this);
cached_segment->setRange(3, 60);
cached_segment->setSingleStep(1);
cached_segment->setValue(settings.cached_segment_limit);
form_layout->addRow(tr("Cached segments limit"), cached_segment);
main_layout->addLayout(form_layout);
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
main_layout->addWidget(buttonBox);
setFixedWidth(360);
connect(buttonBox, &QDialogButtonBox::accepted, this, &SettingsDlg::save);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
void SettingsDlg::save() {
settings.fps = fps->value();
settings.can_msg_log_size = log_size->value();
settings.cached_segment_limit = cached_segment->value();
settings.save();
accept();
}

@ -14,6 +14,7 @@ public:
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
void setOption();
VideoWidget *video_widget; VideoWidget *video_widget;
MessagesWidget *messages_widget; MessagesWidget *messages_widget;
@ -22,3 +23,14 @@ protected:
QWidget *floating_window = nullptr; QWidget *floating_window = nullptr;
QVBoxLayout *r_layout; QVBoxLayout *r_layout;
}; };
class SettingsDlg : public QDialog {
Q_OBJECT
public:
SettingsDlg(QWidget *parent);
void save();
QSpinBox *fps;
QSpinBox *log_size ;
QSpinBox *cached_segment;
};

@ -211,7 +211,7 @@ void Replay::queueSegment() {
SegmentMap::iterator cur, end; SegmentMap::iterator cur, end;
cur = end = segments_.lower_bound(std::min(current_segment_.load(), segments_.rbegin()->first)); cur = end = segments_.lower_bound(std::min(current_segment_.load(), segments_.rbegin()->first));
for (int i = 0; end != segments_.end() && i <= FORWARD_SEGS; ++i) { for (int i = 0; end != segments_.end() && i <= segment_cache_limit + FORWARD_FETCH_SEGS; ++i) {
++end; ++end;
} }
// load one segment at a time // load one segment at a time
@ -250,7 +250,7 @@ void Replay::mergeSegments(const SegmentMap::iterator &begin, const SegmentMap::
// merge 3 segments in sequence. // merge 3 segments in sequence.
std::vector<int> segments_need_merge; std::vector<int> segments_need_merge;
size_t new_events_size = 0; size_t new_events_size = 0;
for (auto it = begin; it != end && it->second && it->second->isLoaded() && segments_need_merge.size() < 3; ++it) { for (auto it = begin; it != end && it->second && it->second->isLoaded() && segments_need_merge.size() < segment_cache_limit; ++it) {
segments_need_merge.push_back(it->first); segments_need_merge.push_back(it->first);
new_events_size += it->second->log->events.size(); new_events_size += it->second->log->events.size();
} }

@ -10,7 +10,7 @@
const QString DEMO_ROUTE = "4cf7a6ad03080c90|2021-09-29--13-46-36"; const QString DEMO_ROUTE = "4cf7a6ad03080c90|2021-09-29--13-46-36";
// one segment uses about 100M of memory // one segment uses about 100M of memory
constexpr int FORWARD_SEGS = 5; constexpr int FORWARD_FETCH_SEGS = 3;
enum REPLAY_FLAGS { enum REPLAY_FLAGS {
REPLAY_FLAG_NONE = 0x0000, REPLAY_FLAG_NONE = 0x0000,
@ -57,6 +57,8 @@ public:
filter_opaque = opaque; filter_opaque = opaque;
event_filter = filter; event_filter = filter;
} }
inline int segmentCacheLimit() const { return segment_cache_limit; }
inline void setSegmentCacheLimit(int n) { segment_cache_limit = std::max(3, n); }
inline bool hasFlag(REPLAY_FLAGS flag) const { return flags_ & flag; } inline bool hasFlag(REPLAY_FLAGS flag) const { return flags_ & flag; }
inline void addFlag(REPLAY_FLAGS flag) { flags_ |= flag; } inline void addFlag(REPLAY_FLAGS flag) { flags_ |= flag; }
inline void removeFlag(REPLAY_FLAGS flag) { flags_ &= ~flag; } inline void removeFlag(REPLAY_FLAGS flag) { flags_ &= ~flag; }
@ -131,4 +133,5 @@ protected:
float speed_ = 1.0; float speed_ = 1.0;
replayEventFilter event_filter = nullptr; replayEventFilter event_filter = nullptr;
void *filter_opaque = nullptr; void *filter_opaque = nullptr;
int segment_cache_limit = 3;
}; };

Loading…
Cancel
Save