mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-10 11:52:10 +08:00
cabana: fix panda stream issues (#32537)
fix segfault old-commit-hash: 6b3d2b5a80c61e83a925ff28cc2394f9a9c0a996
This commit is contained in:
@@ -64,6 +64,7 @@ public:
|
||||
AbstractStream(QObject *parent);
|
||||
virtual ~AbstractStream() {}
|
||||
virtual void start() = 0;
|
||||
virtual void stop() {}
|
||||
virtual bool liveStreaming() const { return true; }
|
||||
virtual void seekTo(double ts) {}
|
||||
virtual QString routeName() const = 0;
|
||||
@@ -128,11 +129,15 @@ private:
|
||||
};
|
||||
|
||||
class AbstractOpenStreamWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AbstractOpenStreamWidget(AbstractStream **stream, QWidget *parent = nullptr) : stream(stream), QWidget(parent) {}
|
||||
virtual bool open() = 0;
|
||||
virtual QString title() = 0;
|
||||
|
||||
signals:
|
||||
void enableOpenButton(bool);
|
||||
|
||||
protected:
|
||||
AbstractStream **stream = nullptr;
|
||||
};
|
||||
|
||||
@@ -42,6 +42,10 @@ LiveStream::LiveStream(QObject *parent) : AbstractStream(parent) {
|
||||
QObject::connect(stream_thread, &QThread::finished, stream_thread, &QThread::deleteLater);
|
||||
}
|
||||
|
||||
LiveStream::~LiveStream() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void LiveStream::startUpdateTimer() {
|
||||
update_timer.stop();
|
||||
update_timer.start(1000.0 / settings.fps, this);
|
||||
@@ -55,11 +59,14 @@ void LiveStream::start() {
|
||||
begin_date_time = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
LiveStream::~LiveStream() {
|
||||
void LiveStream::stop() {
|
||||
if (!stream_thread) return;
|
||||
|
||||
update_timer.stop();
|
||||
stream_thread->requestInterruption();
|
||||
stream_thread->quit();
|
||||
stream_thread->wait();
|
||||
stream_thread = nullptr;
|
||||
}
|
||||
|
||||
// called in streamThread
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
LiveStream(QObject *parent);
|
||||
virtual ~LiveStream();
|
||||
void start() override;
|
||||
void stop() override;
|
||||
inline QDateTime beginDateTime() const { return begin_date_time; }
|
||||
inline double routeStartTime() const override { return begin_event_ts / 1e9; }
|
||||
void setSpeed(float speed) override { speed_ = speed; }
|
||||
|
||||
@@ -6,12 +6,17 @@
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
PandaStream::PandaStream(QObject *parent, PandaStreamConfig config_) : config(config_), LiveStream(parent) {}
|
||||
PandaStream::PandaStream(QObject *parent, PandaStreamConfig config_) : config(config_), LiveStream(parent) {
|
||||
if (!connect()) {
|
||||
throw std::runtime_error("Failed to connect to panda");
|
||||
}
|
||||
}
|
||||
|
||||
bool PandaStream::connect() {
|
||||
try {
|
||||
qDebug() << "Connecting to panda with serial" << config.serial;
|
||||
qDebug() << "Connecting to panda " << config.serial;
|
||||
panda.reset(new Panda(config.serial.toStdString()));
|
||||
config.bus_config.resize(3);
|
||||
qDebug() << "Connected";
|
||||
@@ -80,6 +85,13 @@ AbstractOpenStreamWidget *PandaStream::widget(AbstractStream **stream) {
|
||||
|
||||
OpenPandaWidget::OpenPandaWidget(AbstractStream **stream) : AbstractOpenStreamWidget(stream) {
|
||||
form_layout = new QFormLayout(this);
|
||||
if (can && dynamic_cast<PandaStream *>(can) != nullptr) {
|
||||
form_layout->addWidget(new QLabel(tr("Already connected to %1.").arg(can->routeName())));
|
||||
form_layout->addWidget(new QLabel("Close the current connection via [File menu -> Close Stream] before connecting to another Panda."));
|
||||
QTimer::singleShot(0, [this]() { emit enableOpenButton(false); });
|
||||
return;
|
||||
}
|
||||
|
||||
QHBoxLayout *serial_layout = new QHBoxLayout();
|
||||
serial_layout->addWidget(serial_edit = new QComboBox());
|
||||
|
||||
@@ -116,6 +128,7 @@ void OpenPandaWidget::buildConfigForm() {
|
||||
Panda panda(serial.toStdString());
|
||||
has_fd = (panda.hw_type == cereal::PandaState::PandaType::RED_PANDA) || (panda.hw_type == cereal::PandaState::PandaType::RED_PANDA_V2);
|
||||
} catch (const std::exception& e) {
|
||||
qDebug() << "failed to open panda" << serial;
|
||||
has_panda = false;
|
||||
}
|
||||
}
|
||||
@@ -170,13 +183,11 @@ void OpenPandaWidget::buildConfigForm() {
|
||||
}
|
||||
|
||||
bool OpenPandaWidget::open() {
|
||||
if (!config.serial.isEmpty()) {
|
||||
auto panda_stream = std::make_unique<PandaStream>(qApp, config);
|
||||
if (panda_stream->connect()) {
|
||||
*stream = panda_stream.release();
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
*stream = new PandaStream(qApp, config);
|
||||
return true;
|
||||
} catch (std::exception &e) {
|
||||
QMessageBox::warning(nullptr, tr("Warning"), tr("Failed to connect to panda: '%1'").arg(e.what()));
|
||||
return false;
|
||||
}
|
||||
QMessageBox::warning(nullptr, tr("Warning"), tr("Failed to connect to panda"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -21,13 +21,14 @@ class PandaStream : public LiveStream {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PandaStream(QObject *parent, PandaStreamConfig config_ = {});
|
||||
bool connect();
|
||||
~PandaStream() { stop(); }
|
||||
static AbstractOpenStreamWidget *widget(AbstractStream **stream);
|
||||
inline QString routeName() const override {
|
||||
return QString("Live Streaming From Panda %1").arg(config.serial);
|
||||
return QString("Panda: %1").arg(config.serial);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool connect();
|
||||
void streamThread() override;
|
||||
|
||||
std::unique_ptr<Panda> panda;
|
||||
|
||||
@@ -17,6 +17,7 @@ class SocketCanStream : public LiveStream {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SocketCanStream(QObject *parent, SocketCanStreamConfig config_ = {});
|
||||
~SocketCanStream() { stop(); }
|
||||
static AbstractOpenStreamWidget *widget(AbstractStream **stream);
|
||||
static bool available();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "tools/cabana/streamselector.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
@@ -31,7 +30,7 @@ StreamSelector::StreamSelector(AbstractStream **stream, QWidget *parent) : QDial
|
||||
line->setFrameStyle(QFrame::HLine | QFrame::Sunken);
|
||||
layout->addWidget(line);
|
||||
|
||||
auto btn_box = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel);
|
||||
btn_box = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel);
|
||||
layout->addWidget(btn_box);
|
||||
|
||||
addStreamWidget(ReplayStream::widget(stream));
|
||||
@@ -60,4 +59,6 @@ StreamSelector::StreamSelector(AbstractStream **stream, QWidget *parent) : QDial
|
||||
|
||||
void StreamSelector::addStreamWidget(AbstractOpenStreamWidget *w) {
|
||||
tab->addTab(w, w->title());
|
||||
auto open_btn = btn_box->button(QDialogButtonBox::Open);
|
||||
QObject::connect(w, &AbstractOpenStreamWidget::enableOpenButton, open_btn, &QPushButton::setEnabled);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QTabWidget>
|
||||
@@ -17,4 +18,5 @@ public:
|
||||
private:
|
||||
QLineEdit *dbc_file;
|
||||
QTabWidget *tab;
|
||||
QDialogButtonBox *btn_box;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user