cabana: fix panda stream issues (#32537)

fix segfault
pull/32584/head
Dean Lee 11 months ago committed by GitHub
parent 521ee46c47
commit 6b3d2b5a80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      tools/cabana/streams/abstractstream.h
  2. 9
      tools/cabana/streams/livestream.cc
  3. 1
      tools/cabana/streams/livestream.h
  4. 31
      tools/cabana/streams/pandastream.cc
  5. 5
      tools/cabana/streams/pandastream.h
  6. 1
      tools/cabana/streams/socketcanstream.h
  7. 5
      tools/cabana/streamselector.cc
  8. 2
      tools/cabana/streamselector.h

@ -64,6 +64,7 @@ public:
AbstractStream(QObject *parent); AbstractStream(QObject *parent);
virtual ~AbstractStream() {} virtual ~AbstractStream() {}
virtual void start() = 0; virtual void start() = 0;
virtual void stop() {}
virtual bool liveStreaming() const { return true; } virtual bool liveStreaming() const { return true; }
virtual void seekTo(double ts) {} virtual void seekTo(double ts) {}
virtual QString routeName() const = 0; virtual QString routeName() const = 0;
@ -128,11 +129,15 @@ private:
}; };
class AbstractOpenStreamWidget : public QWidget { class AbstractOpenStreamWidget : public QWidget {
Q_OBJECT
public: public:
AbstractOpenStreamWidget(AbstractStream **stream, QWidget *parent = nullptr) : stream(stream), QWidget(parent) {} AbstractOpenStreamWidget(AbstractStream **stream, QWidget *parent = nullptr) : stream(stream), QWidget(parent) {}
virtual bool open() = 0; virtual bool open() = 0;
virtual QString title() = 0; virtual QString title() = 0;
signals:
void enableOpenButton(bool);
protected: protected:
AbstractStream **stream = nullptr; AbstractStream **stream = nullptr;
}; };

@ -42,6 +42,10 @@ LiveStream::LiveStream(QObject *parent) : AbstractStream(parent) {
QObject::connect(stream_thread, &QThread::finished, stream_thread, &QThread::deleteLater); QObject::connect(stream_thread, &QThread::finished, stream_thread, &QThread::deleteLater);
} }
LiveStream::~LiveStream() {
stop();
}
void LiveStream::startUpdateTimer() { void LiveStream::startUpdateTimer() {
update_timer.stop(); update_timer.stop();
update_timer.start(1000.0 / settings.fps, this); update_timer.start(1000.0 / settings.fps, this);
@ -55,11 +59,14 @@ void LiveStream::start() {
begin_date_time = QDateTime::currentDateTime(); begin_date_time = QDateTime::currentDateTime();
} }
LiveStream::~LiveStream() { void LiveStream::stop() {
if (!stream_thread) return;
update_timer.stop(); update_timer.stop();
stream_thread->requestInterruption(); stream_thread->requestInterruption();
stream_thread->quit(); stream_thread->quit();
stream_thread->wait(); stream_thread->wait();
stream_thread = nullptr;
} }
// called in streamThread // called in streamThread

@ -14,6 +14,7 @@ public:
LiveStream(QObject *parent); LiveStream(QObject *parent);
virtual ~LiveStream(); virtual ~LiveStream();
void start() override; void start() override;
void stop() override;
inline QDateTime beginDateTime() const { return begin_date_time; } inline QDateTime beginDateTime() const { return begin_date_time; }
inline double routeStartTime() const override { return begin_event_ts / 1e9; } inline double routeStartTime() const override { return begin_event_ts / 1e9; }
void setSpeed(float speed) override { speed_ = speed; } void setSpeed(float speed) override { speed_ = speed; }

@ -6,12 +6,17 @@
#include <QMessageBox> #include <QMessageBox>
#include <QPushButton> #include <QPushButton>
#include <QThread> #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() { bool PandaStream::connect() {
try { try {
qDebug() << "Connecting to panda with serial" << config.serial; qDebug() << "Connecting to panda " << config.serial;
panda.reset(new Panda(config.serial.toStdString())); panda.reset(new Panda(config.serial.toStdString()));
config.bus_config.resize(3); config.bus_config.resize(3);
qDebug() << "Connected"; qDebug() << "Connected";
@ -80,6 +85,13 @@ AbstractOpenStreamWidget *PandaStream::widget(AbstractStream **stream) {
OpenPandaWidget::OpenPandaWidget(AbstractStream **stream) : AbstractOpenStreamWidget(stream) { OpenPandaWidget::OpenPandaWidget(AbstractStream **stream) : AbstractOpenStreamWidget(stream) {
form_layout = new QFormLayout(this); 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(); QHBoxLayout *serial_layout = new QHBoxLayout();
serial_layout->addWidget(serial_edit = new QComboBox()); serial_layout->addWidget(serial_edit = new QComboBox());
@ -116,6 +128,7 @@ void OpenPandaWidget::buildConfigForm() {
Panda panda(serial.toStdString()); Panda panda(serial.toStdString());
has_fd = (panda.hw_type == cereal::PandaState::PandaType::RED_PANDA) || (panda.hw_type == cereal::PandaState::PandaType::RED_PANDA_V2); has_fd = (panda.hw_type == cereal::PandaState::PandaType::RED_PANDA) || (panda.hw_type == cereal::PandaState::PandaType::RED_PANDA_V2);
} catch (const std::exception& e) { } catch (const std::exception& e) {
qDebug() << "failed to open panda" << serial;
has_panda = false; has_panda = false;
} }
} }
@ -170,13 +183,11 @@ void OpenPandaWidget::buildConfigForm() {
} }
bool OpenPandaWidget::open() { bool OpenPandaWidget::open() {
if (!config.serial.isEmpty()) { try {
auto panda_stream = std::make_unique<PandaStream>(qApp, config); *stream = new PandaStream(qApp, config);
if (panda_stream->connect()) { return true;
*stream = panda_stream.release(); } catch (std::exception &e) {
return true; 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 Q_OBJECT
public: public:
PandaStream(QObject *parent, PandaStreamConfig config_ = {}); PandaStream(QObject *parent, PandaStreamConfig config_ = {});
bool connect(); ~PandaStream() { stop(); }
static AbstractOpenStreamWidget *widget(AbstractStream **stream); static AbstractOpenStreamWidget *widget(AbstractStream **stream);
inline QString routeName() const override { inline QString routeName() const override {
return QString("Live Streaming From Panda %1").arg(config.serial); return QString("Panda: %1").arg(config.serial);
} }
protected: protected:
bool connect();
void streamThread() override; void streamThread() override;
std::unique_ptr<Panda> panda; std::unique_ptr<Panda> panda;

@ -17,6 +17,7 @@ class SocketCanStream : public LiveStream {
Q_OBJECT Q_OBJECT
public: public:
SocketCanStream(QObject *parent, SocketCanStreamConfig config_ = {}); SocketCanStream(QObject *parent, SocketCanStreamConfig config_ = {});
~SocketCanStream() { stop(); }
static AbstractOpenStreamWidget *widget(AbstractStream **stream); static AbstractOpenStreamWidget *widget(AbstractStream **stream);
static bool available(); static bool available();

@ -1,6 +1,5 @@
#include "tools/cabana/streamselector.h" #include "tools/cabana/streamselector.h"
#include <QDialogButtonBox>
#include <QFileDialog> #include <QFileDialog>
#include <QLabel> #include <QLabel>
#include <QPushButton> #include <QPushButton>
@ -31,7 +30,7 @@ StreamSelector::StreamSelector(AbstractStream **stream, QWidget *parent) : QDial
line->setFrameStyle(QFrame::HLine | QFrame::Sunken); line->setFrameStyle(QFrame::HLine | QFrame::Sunken);
layout->addWidget(line); layout->addWidget(line);
auto btn_box = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel); btn_box = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel);
layout->addWidget(btn_box); layout->addWidget(btn_box);
addStreamWidget(ReplayStream::widget(stream)); addStreamWidget(ReplayStream::widget(stream));
@ -60,4 +59,6 @@ StreamSelector::StreamSelector(AbstractStream **stream, QWidget *parent) : QDial
void StreamSelector::addStreamWidget(AbstractOpenStreamWidget *w) { void StreamSelector::addStreamWidget(AbstractOpenStreamWidget *w) {
tab->addTab(w, w->title()); 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 #pragma once
#include <QDialogButtonBox>
#include <QDialog> #include <QDialog>
#include <QLineEdit> #include <QLineEdit>
#include <QTabWidget> #include <QTabWidget>
@ -17,4 +18,5 @@ public:
private: private:
QLineEdit *dbc_file; QLineEdit *dbc_file;
QTabWidget *tab; QTabWidget *tab;
QDialogButtonBox *btn_box;
}; };

Loading…
Cancel
Save