mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 18:53:55 +08:00
cabana: increase replay's segment cache limit & add setting dialog (#26019)
* increase replay's segment cache limit
* todo
* add settings dialog
blank line
typo
old-commit-hash: b31932382d
This commit is contained in:
1
tools/cabana/.gitignore
vendored
1
tools/cabana/.gitignore
vendored
@@ -2,3 +2,4 @@ moc_*
|
||||
*.moc
|
||||
|
||||
_cabana
|
||||
settings
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "tools/cabana/canmessages.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
|
||||
Q_DECLARE_METATYPE(std::vector<CanData>);
|
||||
|
||||
Settings settings;
|
||||
CANMessages *can = nullptr;
|
||||
|
||||
CANMessages::CANMessages(QObject *parent) : QObject(parent) {
|
||||
@@ -11,6 +13,7 @@ CANMessages::CANMessages(QObject *parent) : QObject(parent) {
|
||||
|
||||
qRegisterMetaType<std::vector<CanData>>();
|
||||
QObject::connect(this, &CANMessages::received, this, &CANMessages::process, Qt::QueuedConnection);
|
||||
QObject::connect(&settings, &Settings::changed, this, &CANMessages::settingChanged);
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
QObject::connect(replay, &Replay::segmentsMerged, this, &CANMessages::segmentsMerged);
|
||||
if (replay->load()) {
|
||||
@@ -38,11 +42,11 @@ void CANMessages::process(QHash<QString, std::deque<CanData>> *messages) {
|
||||
++counters[it.key()];
|
||||
auto &msgs = can_msgs[it.key()];
|
||||
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);
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -71,7 +75,7 @@ bool CANMessages::eventFilter(const Event *event) {
|
||||
for (const auto &c : can_events) {
|
||||
QString id = QString("%1:%2").arg(c.getSrc()).arg(c.getAddress(), 1, 16);
|
||||
auto &list = (*received_msgs)[id];
|
||||
while (list.size() >= CAN_MSG_LOG_SIZE) {
|
||||
while (list.size() >= settings.can_msg_log_size) {
|
||||
list.pop_back();
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
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;
|
||||
// use pointer to avoid data copy in queued connection.
|
||||
emit received(received_msgs.release());
|
||||
@@ -121,3 +125,27 @@ void CANMessages::segmentsMerged() {
|
||||
void CANMessages::resetRange() {
|
||||
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"
|
||||
|
||||
const int FPS = 10;
|
||||
const int CAN_MSG_LOG_SIZE = 100;
|
||||
class Settings : public QObject {
|
||||
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 {
|
||||
double ts;
|
||||
@@ -57,6 +70,7 @@ public:
|
||||
protected:
|
||||
void process(QHash<QString, std::deque<CanData>> *);
|
||||
void segmentsMerged();
|
||||
void settingChanged();
|
||||
|
||||
std::atomic<double> current_sec = 0.;
|
||||
std::atomic<bool> seeking = false;
|
||||
@@ -82,3 +96,4 @@ inline const QString &getColor(int i) {
|
||||
|
||||
// A global pointer referring to the unique CANMessages object
|
||||
extern CANMessages *can;
|
||||
extern Settings settings;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "tools/cabana/mainwin.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QFormLayout>
|
||||
#include <QScreen>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
@@ -23,6 +25,9 @@ MainWindow::MainWindow() : QWidget() {
|
||||
right_container->setFixedWidth(640);
|
||||
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);
|
||||
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(detail_widget, &DetailWidget::showChart, charts_widget, &ChartsWidget::addChart);
|
||||
QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts);
|
||||
QObject::connect(settings_btn, &QPushButton::clicked, this, &MainWindow::setOption);
|
||||
}
|
||||
|
||||
void MainWindow::dockCharts(bool dock) {
|
||||
@@ -59,3 +65,51 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
floating_window->deleteLater();
|
||||
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:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void setOption();
|
||||
|
||||
VideoWidget *video_widget;
|
||||
MessagesWidget *messages_widget;
|
||||
@@ -22,3 +23,14 @@ protected:
|
||||
QWidget *floating_window = nullptr;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
// load one segment at a time
|
||||
@@ -250,7 +250,7 @@ void Replay::mergeSegments(const SegmentMap::iterator &begin, const SegmentMap::
|
||||
// merge 3 segments in sequence.
|
||||
std::vector<int> segments_need_merge;
|
||||
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);
|
||||
new_events_size += it->second->log->events.size();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
const QString DEMO_ROUTE = "4cf7a6ad03080c90|2021-09-29--13-46-36";
|
||||
|
||||
// one segment uses about 100M of memory
|
||||
constexpr int FORWARD_SEGS = 5;
|
||||
constexpr int FORWARD_FETCH_SEGS = 3;
|
||||
|
||||
enum REPLAY_FLAGS {
|
||||
REPLAY_FLAG_NONE = 0x0000,
|
||||
@@ -57,6 +57,8 @@ public:
|
||||
filter_opaque = opaque;
|
||||
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 void addFlag(REPLAY_FLAGS flag) { flags_ |= flag; }
|
||||
inline void removeFlag(REPLAY_FLAGS flag) { flags_ &= ~flag; }
|
||||
@@ -131,4 +133,5 @@ protected:
|
||||
float speed_ = 1.0;
|
||||
replayEventFilter event_filter = nullptr;
|
||||
void *filter_opaque = nullptr;
|
||||
int segment_cache_limit = 3;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user