From ebdd072e57774ad4c1d0198c0c4794dede979cd6 Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Sat, 24 May 2014 16:11:30 +0200 Subject: [PATCH 01/13] Fix up threading of UAS object, WIP --- qgroundcontrol.pro | 6 ++++-- src/uas/QGCMAVLinkUASFactory.cc | 3 ++- src/uas/QGCUASWorker.cc | 12 ++++++++++++ src/uas/QGCUASWorker.h | 15 +++++++++++++++ src/uas/UAS.cc | 12 ++++++------ 5 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 src/uas/QGCUASWorker.cc create mode 100644 src/uas/QGCUASWorker.h diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 135006d..f52faf0 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -562,7 +562,8 @@ HEADERS += \ src/ui/designer/QGCXYPlot.h \ src/ui/menuactionhelper.h \ src/uas/UASManagerInterface.h \ - src/uas/QGCUASParamManagerInterface.h + src/uas/QGCUASParamManagerInterface.h \ + src/uas/QGCUASWorker.h SOURCES += \ src/main.cc \ @@ -745,4 +746,5 @@ SOURCES += \ src/ui/px4_configuration/QGCPX4MulticopterConfig.cc \ src/ui/px4_configuration/QGCPX4SensorCalibration.cc \ src/ui/designer/QGCXYPlot.cc \ - src/ui/menuactionhelper.cpp + src/ui/menuactionhelper.cpp \ + src/uas/QGCUASWorker.cc diff --git a/src/uas/QGCMAVLinkUASFactory.cc b/src/uas/QGCMAVLinkUASFactory.cc index b7658ae..c55648c 100644 --- a/src/uas/QGCMAVLinkUASFactory.cc +++ b/src/uas/QGCMAVLinkUASFactory.cc @@ -1,5 +1,6 @@ #include "QGCMAVLinkUASFactory.h" #include "UASManager.h" +#include "QGCUASWorker.h" QGCMAVLinkUASFactory::QGCMAVLinkUASFactory(QObject *parent) : QObject(parent) @@ -21,7 +22,7 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte UASInterface* uas; - QThread* worker = new QThread(); + QGCUASWorker* worker = new QGCUASWorker(); switch (heartbeat->autopilot) { diff --git a/src/uas/QGCUASWorker.cc b/src/uas/QGCUASWorker.cc new file mode 100644 index 0000000..6fb74b1 --- /dev/null +++ b/src/uas/QGCUASWorker.cc @@ -0,0 +1,12 @@ +#include "QGCUASWorker.h" + +#include + +QGCUASWorker::QGCUASWorker() : QThread() +{ +} + +void QGCUASWorker::run() +{ + QGC::SLEEP::msleep(100); +} diff --git a/src/uas/QGCUASWorker.h b/src/uas/QGCUASWorker.h new file mode 100644 index 0000000..a486728 --- /dev/null +++ b/src/uas/QGCUASWorker.h @@ -0,0 +1,15 @@ +#ifndef QGCUASWORKER_H +#define QGCUASWORKER_H + +#include + +class QGCUASWorker : public QThread +{ +public: + QGCUASWorker(); + +protected: + void run(); +}; + +#endif // QGCUASWORKER_H diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index 0ff565d..fbc4bb3 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -51,7 +51,7 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), commStatus(COMM_DISCONNECTED), receiveDropRate(0), sendDropRate(0), - statusTimeout(new QTimer(this)), + statusTimeout(new QTimer()), name(""), type(MAV_TYPE_GENERIC), @@ -138,7 +138,7 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), airSpeed(std::numeric_limits::quiet_NaN()), groundSpeed(std::numeric_limits::quiet_NaN()), - waypointManager(this), + waypointManager(), attitudeKnown(false), attitudeStamped(false), @@ -153,7 +153,7 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), paramsOnceRequested(false), - paramMgr(this), + paramMgr(), simulation(0), // The protected members. @@ -180,17 +180,17 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), // Store a list of available actions for this UAS. // Basically everything exposed as a SLOT with no return value or arguments. - QAction* newAction = new QAction(tr("Arm"), this); + QAction* newAction = new QAction(tr("Arm"), thread); newAction->setToolTip(tr("Enable the UAS so that all actuators are online")); connect(newAction, SIGNAL(triggered()), this, SLOT(armSystem())); actions.append(newAction); - newAction = new QAction(tr("Disarm"), this); + newAction = new QAction(tr("Disarm"), thread); newAction->setToolTip(tr("Disable the UAS so that all actuators are offline")); connect(newAction, SIGNAL(triggered()), this, SLOT(disarmSystem())); actions.append(newAction); - newAction = new QAction(tr("Toggle armed"), this); + newAction = new QAction(tr("Toggle armed"), thread); newAction->setToolTip(tr("Toggle between armed and disarmed")); connect(newAction, SIGNAL(triggered()), this, SLOT(toggleAutonomy())); actions.append(newAction); From faab2eb21fbe0ebc949593da7422851f59b55c09 Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Sat, 24 May 2014 17:42:39 +0200 Subject: [PATCH 02/13] threading fixes, still wip in some aspects --- src/comm/MAVLinkProtocol.cc | 30 +++++++++++++++++++++--------- src/comm/MAVLinkProtocol.h | 4 +++- src/comm/QGCXPlaneLink.cc | 10 +++++++--- src/comm/QGCXPlaneLink.h | 1 + src/configuration.h | 2 +- src/uas/QGCMAVLinkUASFactory.cc | 15 ++++----------- src/uas/QGCUASWorker.cc | 16 ++++++++++++++-- src/uas/QGCUASWorker.h | 5 +++++ src/uas/UAS.cc | 17 +++++++++++------ src/uas/UAS.h | 3 ++- src/ui/QGCHilXPlaneConfiguration.cc | 3 ++- 11 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/comm/MAVLinkProtocol.cc b/src/comm/MAVLinkProtocol.cc index a9f6548..450f45c 100644 --- a/src/comm/MAVLinkProtocol.cc +++ b/src/comm/MAVLinkProtocol.cc @@ -44,7 +44,7 @@ Q_DECLARE_METATYPE(mavlink_message_t) * the MAVLINK_HEARTBEAT_DEFAULT_RATE to all connected links. */ MAVLinkProtocol::MAVLinkProtocol() : - heartbeatTimer(), + heartbeatTimer(NULL), heartbeatRate(MAVLINK_HEARTBEAT_DEFAULT_RATE), m_heartbeatsEnabled(true), m_multiplexingEnabled(false), @@ -58,17 +58,14 @@ MAVLinkProtocol::MAVLinkProtocol() : m_actionGuardEnabled(false), m_actionRetransmissionTimeout(100), versionMismatchIgnore(false), - systemId(QGC::defaultSystemId) + systemId(QGC::defaultSystemId), + _should_exit(false) { qRegisterMetaType("mavlink_message_t"); m_authKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; loadSettings(); moveToThread(this); - heartbeatTimer.moveToThread(this); - // Start heartbeat timer, emitting a heartbeat at the configured rate - connect(&heartbeatTimer, SIGNAL(timeout()), this, SLOT(sendHeartbeat())); - heartbeatTimer.start(1000/heartbeatRate); // All the *Counter variables are not initialized here, as they should be initialized // on a per-link basis before those links are used. @see resetMetadataForLink(). @@ -171,7 +168,7 @@ MAVLinkProtocol::~MAVLinkProtocol() } // Tell the thread to exit - quit(); + _should_exit = true; // Wait for it to exit wait(); } @@ -182,7 +179,22 @@ MAVLinkProtocol::~MAVLinkProtocol() **/ void MAVLinkProtocol::run() { - exec(); + heartbeatTimer = new QTimer(); + heartbeatTimer->moveToThread(this); + // Start heartbeat timer, emitting a heartbeat at the configured rate + connect(heartbeatTimer, SIGNAL(timeout()), this, SLOT(sendHeartbeat())); + heartbeatTimer->start(1000/heartbeatRate); + + while(!_should_exit) { + + if (isFinished()) { + qDebug() << "MAVLINK WORKER DONE!"; + return; + } + + QCoreApplication::processEvents(); + QGC::SLEEP::msleep(2); + } } QString MAVLinkProtocol::getLogfileName() @@ -782,7 +794,7 @@ void MAVLinkProtocol::enableVersionCheck(bool enabled) void MAVLinkProtocol::setHeartbeatRate(int rate) { heartbeatRate = rate; - heartbeatTimer.setInterval(1000/heartbeatRate); + heartbeatTimer->setInterval(1000/heartbeatRate); } /** @return heartbeat rate in Hertz */ diff --git a/src/comm/MAVLinkProtocol.h b/src/comm/MAVLinkProtocol.h index a2e1063..158890d 100644 --- a/src/comm/MAVLinkProtocol.h +++ b/src/comm/MAVLinkProtocol.h @@ -214,7 +214,7 @@ public slots: void storeSettings(); protected: - QTimer heartbeatTimer; ///< Timer to emit heartbeats + QTimer *heartbeatTimer; ///< Timer to emit heartbeats int heartbeatRate; ///< Heartbeat rate, controls the timer interval bool m_heartbeatsEnabled; ///< Enabled/disable heartbeat emission bool m_multiplexingEnabled; ///< Enable/disable packet multiplexing @@ -237,6 +237,8 @@ protected: int currLossCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< Lost messages during this sample time window. Used for calculating loss %. bool versionMismatchIgnore; int systemId; + bool _should_exit; + #if defined(QGC_PROTOBUF_ENABLED) && defined(QGC_USE_PIXHAWK_MESSAGES) mavlink::ProtobufManager protobufManager; #endif diff --git a/src/comm/QGCXPlaneLink.cc b/src/comm/QGCXPlaneLink.cc index e7bd679..b30b521 100644 --- a/src/comm/QGCXPlaneLink.cc +++ b/src/comm/QGCXPlaneLink.cc @@ -57,7 +57,8 @@ QGCXPlaneLink::QGCXPlaneLink(UASInterface* mav, QString remoteHost, QHostAddress simUpdateLastText(QGC::groundTimeMilliseconds()), simUpdateLastGroundTruth(QGC::groundTimeMilliseconds()), simUpdateHz(0), - _sensorHilEnabled(true) + _sensorHilEnabled(true), + _should_exit(false) { // We're doing it wrong - because the Qt folks got the API wrong: // http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ @@ -75,7 +76,7 @@ QGCXPlaneLink::~QGCXPlaneLink() { storeSettings(); // Tell the thread to exit - quit(); + _should_exit = true; // Wait for it to exit wait(); @@ -216,7 +217,10 @@ void QGCXPlaneLink::run() writeBytes((const char*)&ip, sizeof(ip)); - exec(); + while(!_should_exit) { + QCoreApplication::processEvents(); + QGC::SLEEP::msleep(5); + } } void QGCXPlaneLink::setPort(int localPort) diff --git a/src/comm/QGCXPlaneLink.h b/src/comm/QGCXPlaneLink.h index c5506db..ae44974 100644 --- a/src/comm/QGCXPlaneLink.h +++ b/src/comm/QGCXPlaneLink.h @@ -210,6 +210,7 @@ protected: quint64 simUpdateLastGroundTruth; float simUpdateHz; bool _sensorHilEnabled; + bool _should_exit; void setName(QString name); }; diff --git a/src/configuration.h b/src/configuration.h index 607af7d..bbfa865 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -4,7 +4,7 @@ #include /** @brief Polling interval in ms */ -#define SERIAL_POLL_INTERVAL 5 +#define SERIAL_POLL_INTERVAL 4 /** @brief Heartbeat emission rate, in Hertz (times per second) */ #define MAVLINK_HEARTBEAT_DEFAULT_RATE 1 diff --git a/src/uas/QGCMAVLinkUASFactory.cc b/src/uas/QGCMAVLinkUASFactory.cc index c55648c..5a607c8 100644 --- a/src/uas/QGCMAVLinkUASFactory.cc +++ b/src/uas/QGCMAVLinkUASFactory.cc @@ -32,8 +32,6 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte // Set the system type mav->setSystemType((int)heartbeat->type); - mav->moveToThread(worker); - // Connect this robot to the UAS object connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t))); #ifdef QGC_PROTOBUF_ENABLED @@ -48,8 +46,6 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte // Set the system type mav->setSystemType((int)heartbeat->type); - mav->moveToThread(worker); - // Connect this robot to the UAS object // it is IMPORTANT here to use the right object type, // else the slot of the parent object is called (and thus the special @@ -67,8 +63,6 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte // Set the system type mav->setSystemType((int)heartbeat->type); - mav->moveToThread(worker); - // Connect this robot to the UAS object // it is IMPORTANT here to use the right object type, // else the slot of the parent object is called (and thus the special @@ -83,8 +77,6 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte // Set the system type mav->setSystemType((int)heartbeat->type); - mav->moveToThread(worker); - // Connect this robot to the UAS object // it is IMPORTANT here to use the right object type, // else the slot of the parent object is called (and thus the special @@ -121,6 +113,10 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte break; } + // Get the UAS ready + worker->start(QThread::HighPriority); + connect(uas, SIGNAL(destroyed()), worker, SLOT(quit())); + // Set the autopilot type uas->setAutopilotType((int)heartbeat->autopilot); @@ -130,8 +126,5 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte // Now add UAS to "official" list, which makes the whole application aware of it UASManager::instance()->addUAS(uas); - worker->start(QThread::HighPriority); - connect(uas, SIGNAL(destroyed()), worker, SLOT(quit())); - return uas; } diff --git a/src/uas/QGCUASWorker.cc b/src/uas/QGCUASWorker.cc index 6fb74b1..b726e12 100644 --- a/src/uas/QGCUASWorker.cc +++ b/src/uas/QGCUASWorker.cc @@ -1,12 +1,24 @@ #include "QGCUASWorker.h" #include +#include +#include -QGCUASWorker::QGCUASWorker() : QThread() +QGCUASWorker::QGCUASWorker() : QThread(), + _should_exit(false) { } +void QGCUASWorker::quit() +{ + _should_exit = true; +} + void QGCUASWorker::run() { - QGC::SLEEP::msleep(100); + while(!_should_exit) { + + QCoreApplication::processEvents(); + QGC::SLEEP::msleep(2); + } } diff --git a/src/uas/QGCUASWorker.h b/src/uas/QGCUASWorker.h index a486728..39ea5f0 100644 --- a/src/uas/QGCUASWorker.h +++ b/src/uas/QGCUASWorker.h @@ -8,8 +8,13 @@ class QGCUASWorker : public QThread public: QGCUASWorker(); +public slots: + void quit(); + protected: void run(); + + bool _should_exit; }; #endif // QGCUASWORKER_H diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index fbc4bb3..c018e4f 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -51,7 +51,7 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), commStatus(COMM_DISCONNECTED), receiveDropRate(0), sendDropRate(0), - statusTimeout(new QTimer()), + statusTimeout(thread), name(""), type(MAV_TYPE_GENERIC), @@ -164,12 +164,13 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), hilEnabled(false), sensorHil(false), lastSendTimeGPS(0), - lastSendTimeSensors(0) + lastSendTimeSensors(0), + _thread(thread) { moveToThread(thread); waypointManager.moveToThread(thread); paramMgr.moveToThread(thread); - statusTimeout->moveToThread(thread); + statusTimeout.moveToThread(thread); for (unsigned int i = 0; i<255;++i) { @@ -237,9 +238,9 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), color = UASInterface::getNextColor(); setBatterySpecs(QString("")); - connect(statusTimeout, SIGNAL(timeout()), this, SLOT(updateState())); + connect(&statusTimeout, SIGNAL(timeout()), this, SLOT(updateState())); connect(this, SIGNAL(systemSpecsChanged(int)), this, SLOT(writeSettings())); - statusTimeout->start(500); + statusTimeout.start(500); readSettings(); //need to init paramMgr after readSettings have been loaded, to properly set autopilot and so forth paramMgr.initWithUAS(this); @@ -255,8 +256,11 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), UAS::~UAS() { writeSettings(); + + _thread->quit(); + _thread->wait(); + delete links; - delete statusTimeout; delete simulation; } @@ -369,6 +373,7 @@ void UAS::updateState() GAudioOutput::instance()->notifyNegative(); } } + qDebug() << "UPDATE STATE:" << (heartbeatInterval / 1000) << "milliseconds, LOST:" << connectionLost; } /** diff --git a/src/uas/UAS.h b/src/uas/UAS.h index 6c4c45c..6b57f9c 100644 --- a/src/uas/UAS.h +++ b/src/uas/UAS.h @@ -382,7 +382,7 @@ protected: //COMMENTS FOR TEST UNIT float receiveDropRate; ///< Percentage of packets that were dropped on the MAV's receiving link (from GCS and other MAVs) float sendDropRate; ///< Percentage of packets that were not received from the MAV by the GCS quint64 lastHeartbeat; ///< Time of the last heartbeat message - QTimer* statusTimeout; ///< Timer for various status timeouts + QTimer statusTimeout; ///< Timer for various status timeouts /// BASIC UAS TYPE, NAME AND STATE QString name; ///< Human-friendly name of the vehicle, e.g. bravo @@ -526,6 +526,7 @@ protected: //COMMENTS FOR TEST UNIT /// SIMULATION QGCHilLink* simulation; ///< Hardware in the loop simulation link + QThread* _thread; public: /** @brief Set the current battery type */ diff --git a/src/ui/QGCHilXPlaneConfiguration.cc b/src/ui/QGCHilXPlaneConfiguration.cc index 4166d7e..dc1cd52 100644 --- a/src/ui/QGCHilXPlaneConfiguration.cc +++ b/src/ui/QGCHilXPlaneConfiguration.cc @@ -25,8 +25,9 @@ QGCHilXPlaneConfiguration::QGCHilXPlaneConfiguration(QGCHilLink* link, QWidget * { // connect(ui->randomAttitudeButton, SIGNAL(clicked()), link, SLOT(setRandomAttitude())); // connect(ui->randomPositionButton, SIGNAL(clicked()), link, SLOT(setRandomPosition())); - connect(ui->airframeComboBox, SIGNAL(activated(QString)), link, SLOT(selectAirframe(QString))); + ui->airframeComboBox->setCurrentIndex(link->getAirFrameIndex()); + connect(ui->airframeComboBox, SIGNAL(activated(QString)), link, SLOT(selectAirframe(QString))); // XXX not implemented yet ui->airframeComboBox->hide(); ui->sensorHilCheckBox->setChecked(xplane->sensorHilEnabled()); From 6ba529958d572d0a59449a4141df27f2ab726917 Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Sat, 24 May 2014 18:50:41 +0200 Subject: [PATCH 03/13] Threading fixes --- src/uas/UAS.cc | 24 ++++++++++-------------- src/ui/MainWindow.cc | 3 ++- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index c018e4f..a338d43 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -138,7 +138,7 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), airSpeed(std::numeric_limits::quiet_NaN()), groundSpeed(std::numeric_limits::quiet_NaN()), - waypointManager(), + waypointManager(this), attitudeKnown(false), attitudeStamped(false), @@ -153,7 +153,7 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), paramsOnceRequested(false), - paramMgr(), + paramMgr(this), simulation(0), // The protected members. @@ -168,9 +168,6 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), _thread(thread) { moveToThread(thread); - waypointManager.moveToThread(thread); - paramMgr.moveToThread(thread); - statusTimeout.moveToThread(thread); for (unsigned int i = 0; i<255;++i) { @@ -196,42 +193,42 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), connect(newAction, SIGNAL(triggered()), this, SLOT(toggleAutonomy())); actions.append(newAction); - newAction = new QAction(tr("Go home"), this); + newAction = new QAction(tr("Go home"), thread); newAction->setToolTip(tr("Command the UAS to return to its home position")); connect(newAction, SIGNAL(triggered()), this, SLOT(home())); actions.append(newAction); - newAction = new QAction(tr("Land"), this); + newAction = new QAction(tr("Land"), thread); newAction->setToolTip(tr("Command the UAS to land")); connect(newAction, SIGNAL(triggered()), this, SLOT(land())); actions.append(newAction); - newAction = new QAction(tr("Launch"), this); + newAction = new QAction(tr("Launch"), thread); newAction->setToolTip(tr("Command the UAS to launch itself and begin its mission")); connect(newAction, SIGNAL(triggered()), this, SLOT(launch())); actions.append(newAction); - newAction = new QAction(tr("Resume"), this); + newAction = new QAction(tr("Resume"), thread); newAction->setToolTip(tr("Command the UAS to continue its mission")); connect(newAction, SIGNAL(triggered()), this, SLOT(go())); actions.append(newAction); - newAction = new QAction(tr("Stop"), this); + newAction = new QAction(tr("Stop"), thread); newAction->setToolTip(tr("Command the UAS to halt and hold position")); connect(newAction, SIGNAL(triggered()), this, SLOT(halt())); actions.append(newAction); - newAction = new QAction(tr("Go autonomous"), this); + newAction = new QAction(tr("Go autonomous"), thread); newAction->setToolTip(tr("Set the UAS into an autonomous control mode")); connect(newAction, SIGNAL(triggered()), this, SLOT(goAutonomous())); actions.append(newAction); - newAction = new QAction(tr("Go manual"), this); + newAction = new QAction(tr("Go manual"), thread); newAction->setToolTip(tr("Set the UAS into a manual control mode")); connect(newAction, SIGNAL(triggered()), this, SLOT(goManual())); actions.append(newAction); - newAction = new QAction(tr("Toggle autonomy"), this); + newAction = new QAction(tr("Toggle autonomy"), thread); newAction->setToolTip(tr("Toggle between manual and full-autonomy")); connect(newAction, SIGNAL(triggered()), this, SLOT(toggleAutonomy())); actions.append(newAction); @@ -373,7 +370,6 @@ void UAS::updateState() GAudioOutput::instance()->notifyNegative(); } } - qDebug() << "UPDATE STATE:" << (heartbeatInterval / 1000) << "milliseconds, LOST:" << connectionLost; } /** diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 70a7e9a..da0a849 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -760,6 +760,7 @@ void MainWindow::loadDockWidget(const QString& name) { if(menuActionHelper->containsDockWidget(currentView, name)) return; + if (name.startsWith("HIL_CONFIG")) { //It's a HIL widget. @@ -826,7 +827,7 @@ void MainWindow::loadDockWidget(const QString& name) } else if (name == "HEAD_UP_DISPLAY_DOCKWIDGET") { - createDockWidget(centerStack->currentWidget(),new HUD(320,240,this),tr("Head Up Display"),"HEAD_UP_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); + createDockWidget(centerStack->currentWidget(),new HUD(320,240,this),tr("Video Downlink"),"HEAD_UP_DISPLAY_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); } else if (name == "UAS_INFO_QUICKVIEW_DOCKWIDGET") { From b46887832003177b88c2fba8cf73cedcae91f502 Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Sat, 24 May 2014 18:51:23 +0200 Subject: [PATCH 04/13] Do not allow the PFD to turn QGC into a CPU hog --- src/ui/PrimaryFlightDisplay.cc | 61 +++++++++++++++++++++++++++++++++++++++--- src/ui/PrimaryFlightDisplay.h | 6 +++++ 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/ui/PrimaryFlightDisplay.cc b/src/ui/PrimaryFlightDisplay.cc index 35063a3..7997a1d 100644 --- a/src/ui/PrimaryFlightDisplay.cc +++ b/src/ui/PrimaryFlightDisplay.cc @@ -141,7 +141,9 @@ PrimaryFlightDisplay::PrimaryFlightDisplay(int width, int height, QWidget *paren instrumentOpagueBackground(QColor::fromHsvF(0, 0, 0.3, 1.0)), font("Bitstream Vera Sans"), - refreshTimer(new QTimer(this)) + refreshTimer(new QTimer(this)), + _valuesChanged(false), + _valuesLastPainted(QGC::groundTimeMilliseconds()) { Q_UNUSED(width); Q_UNUSED(height); @@ -159,7 +161,7 @@ PrimaryFlightDisplay::PrimaryFlightDisplay(int width, int height, QWidget *paren // Refresh timer refreshTimer->setInterval(updateInterval); // connect(refreshTimer, SIGNAL(timeout()), this, SLOT(paintHUD())); - connect(refreshTimer, SIGNAL(timeout()), this, SLOT(update())); + connect(refreshTimer, SIGNAL(timeout()), this, SLOT(checkUpdate())); } PrimaryFlightDisplay::~PrimaryFlightDisplay() @@ -224,6 +226,15 @@ void PrimaryFlightDisplay::paintEvent(QPaintEvent *event) doPaint(); } +void PrimaryFlightDisplay::checkUpdate() +{ + if (uas && (_valuesChanged || (QGC::groundTimeMilliseconds() - _valuesLastPainted) > 260)) { + update(); + _valuesChanged = false; + _valuesLastPainted = QGC::groundTimeMilliseconds(); + } +} + ///* // * Interface towards qgroundcontrol // */ @@ -280,24 +291,45 @@ void PrimaryFlightDisplay::updateAttitude(UASInterface* uas, double roll, double { Q_UNUSED(uas); Q_UNUSED(timestamp); + // Called from UAS.cc l. 616 if (isinf(roll)) { this->roll = std::numeric_limits::quiet_NaN(); } else { - this->roll = roll * (180.0 / M_PI); + + float rolldeg = roll * (180.0 / M_PI); + + if (fabsf(roll - rolldeg) > 2.5f) { + _valuesChanged = true; + } + + this->roll = rolldeg; } if (isinf(pitch)) { this->pitch = std::numeric_limits::quiet_NaN(); } else { - this->pitch = pitch * (180.0 / M_PI); + + float pitchdeg = pitch * (180.0 / M_PI); + + if (fabsf(pitch - pitchdeg) > 2.5f) { + _valuesChanged = true; + } + + this->pitch = pitchdeg; } if (isinf(yaw)) { this->heading = std::numeric_limits::quiet_NaN(); } else { + yaw = yaw * (180.0 / M_PI); if (yaw<0) yaw+=360; + + if (fabsf(heading - yaw) > 10.0f) { + _valuesChanged = true; + } + this->heading = yaw; } @@ -314,6 +346,14 @@ void PrimaryFlightDisplay::updateSpeed(UASInterface* uas, double _groundSpeed, d Q_UNUSED(uas); Q_UNUSED(timestamp); + if (fabsf(groundSpeed - _groundSpeed) > 0.5f) { + _valuesChanged = true; + } + + if (fabsf(airSpeed - _airSpeed) > 1.0f) { + _valuesChanged = true; + } + groundSpeed = _groundSpeed; airSpeed = _airSpeed; } @@ -321,6 +361,19 @@ void PrimaryFlightDisplay::updateSpeed(UASInterface* uas, double _groundSpeed, d void PrimaryFlightDisplay::updateAltitude(UASInterface* uas, double _altitudeAMSL, double _altitudeRelative, double _climbRate, quint64 timestamp) { Q_UNUSED(uas); Q_UNUSED(timestamp); + + if (fabsf(altitudeAMSL - _altitudeAMSL) > 0.5f) { + _valuesChanged = true; + } + + if (fabsf(altitudeRelative - _altitudeRelative) > 0.5f) { + _valuesChanged = true; + } + + if (fabsf(climbRate - _climbRate) > 0.5f) { + _valuesChanged = true; + } + altitudeAMSL = _altitudeAMSL; altitudeRelative = _altitudeRelative; climbRate = _climbRate; diff --git a/src/ui/PrimaryFlightDisplay.h b/src/ui/PrimaryFlightDisplay.h index 9dfb8c3..b4236e3 100644 --- a/src/ui/PrimaryFlightDisplay.h +++ b/src/ui/PrimaryFlightDisplay.h @@ -27,7 +27,13 @@ public slots: void forgetUAS(UASInterface* uas); void setActiveUAS(UASInterface* uas); + void checkUpdate(); + protected: + + bool _valuesChanged; + quint64 _valuesLastPainted; + enum Layout { COMPASS_INTEGRATED, COMPASS_SEPARATED // For a very high container. Feature panels are at bottom. From 74736dbb55d666c5233bcb76e4bef24c57f0708f Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Sat, 24 May 2014 21:43:50 +0200 Subject: [PATCH 05/13] Fix warning / error due to comment on line --- QGCExternalLibs.pri | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/QGCExternalLibs.pri b/QGCExternalLibs.pri index 0a2edba..eaea693 100644 --- a/QGCExternalLibs.pri +++ b/QGCExternalLibs.pri @@ -416,9 +416,10 @@ contains(DEFINES, DISABLE_3DMOUSE) { exists(/usr/local/lib/libxdrvlib.so) { message("Including support for 3DConnexion mice") - DEFINES += + DEFINES += \ QGC_MOUSE_ENABLED_LINUX \ - ParameterCheck # Hack: Has to be defined for magellan usage + ParameterCheck + # Hack: Has to be defined for magellan usage HEADERS += src/input/Mouse6dofInput.h SOURCES += src/input/Mouse6dofInput.cpp From fe6ee5b33a31dfbb175a556673e0ac190a33de3a Mon Sep 17 00:00:00 2001 From: Lorenz Meier Date: Sat, 24 May 2014 21:44:16 +0200 Subject: [PATCH 06/13] Unit test fixes --- src/comm/LinkInterface.h | 2 ++ src/qgcunittest/UASUnitTest.cc | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/comm/LinkInterface.h b/src/comm/LinkInterface.h index 833a804..3335677 100644 --- a/src/comm/LinkInterface.h +++ b/src/comm/LinkInterface.h @@ -36,6 +36,7 @@ along with PIXHAWK. If not, see . #include #include #include +#include /** * The link interface defines the interface for all links used to communicate @@ -62,6 +63,7 @@ public: outDataWriteTimes[i] = 0; } + qRegisterMetaType("LinkInterface*"); } virtual ~LinkInterface() { diff --git a/src/qgcunittest/UASUnitTest.cc b/src/qgcunittest/UASUnitTest.cc index 2fc948c..7167579 100644 --- a/src/qgcunittest/UASUnitTest.cc +++ b/src/qgcunittest/UASUnitTest.cc @@ -1,6 +1,8 @@ #include "UASUnitTest.h" #include #include +#include + UASUnitTest::UASUnitTest() { } @@ -8,7 +10,7 @@ UASUnitTest::UASUnitTest() void UASUnitTest::init() { mav = new MAVLinkProtocol(); - uas = new UAS(mav, UASID); + uas = new UAS(mav, QThread::currentThread(), UASID); uas->deleteSettings(); } //this function is called after every test @@ -24,7 +26,7 @@ void UASUnitTest::cleanup() void UASUnitTest::getUASID_test() { // Test a default ID of zero is assigned - UAS* uas2 = new UAS(mav); + UAS* uas2 = new UAS(mav, QThread::currentThread()); QCOMPARE(uas2->getUASID(), 0); delete uas2; @@ -49,7 +51,7 @@ void UASUnitTest::getUASName_test() void UASUnitTest::getUpTime_test() { - UAS* uas2 = new UAS(mav); + UAS* uas2 = new UAS(mav, QThread::currentThread()); // Test that the uptime starts at zero to a // precision of seconds QCOMPARE(floor(uas2->getUptime()/1000.0), 0.0); @@ -281,7 +283,7 @@ void UASUnitTest::signalWayPoint_test() delete uas;// delete(destroyed) uas for validating uas = NULL; QCOMPARE(spyDestroyed.count(), 1);// count destroyed uas should are 1 - uas = new UAS(mav,UASID); + uas = new UAS(mav, QThread::currentThread(), UASID); QSignalSpy spy2(uas->getWaypointManager(), SIGNAL(waypointEditableListChanged())); QCOMPARE(spy2.count(), 0); Waypoint* wp2 = new Waypoint(0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah"); From 00b48cfea2719712e564f64f877a3c394a51651a Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 24 May 2014 16:14:11 -0700 Subject: [PATCH 07/13] Temporary removal of UAS and TCPLink unit test Recent threading changes have broken both of these. They will be fixed in a separate pull request. Also added new CmdLineOptParser.cc/h --- qgroundcontrol.pro | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index f52faf0..2634903 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -182,21 +182,17 @@ DebugBuild { HEADERS += \ src/qgcunittest/AutoTest.h \ - src/qgcunittest/UASUnitTest.h \ src/qgcunittest/MockUASManager.h \ src/qgcunittest/MockUAS.h \ src/qgcunittest/MockQGCUASParamManager.h \ src/qgcunittest/MultiSignalSpy.h \ - src/qgcunittest/TCPLinkTest.h \ src/qgcunittest/FlightModeConfigTest.h SOURCES += \ - src/qgcunittest/UASUnitTest.cc \ src/qgcunittest/MockUASManager.cc \ src/qgcunittest/MockUAS.cc \ src/qgcunittest/MockQGCUASParamManager.cc \ src/qgcunittest/MultiSignalSpy.cc \ - src/qgcunittest/TCPLinkTest.cc \ src/qgcunittest/FlightModeConfigTest.cc } @@ -563,7 +559,8 @@ HEADERS += \ src/ui/menuactionhelper.h \ src/uas/UASManagerInterface.h \ src/uas/QGCUASParamManagerInterface.h \ - src/uas/QGCUASWorker.h + src/uas/QGCUASWorker.h \ + src/CmdLineOptParser.h SOURCES += \ src/main.cc \ @@ -747,4 +744,5 @@ SOURCES += \ src/ui/px4_configuration/QGCPX4SensorCalibration.cc \ src/ui/designer/QGCXYPlot.cc \ src/ui/menuactionhelper.cpp \ - src/uas/QGCUASWorker.cc + src/uas/QGCUASWorker.cc \ + src/CmdLineOptParser.cc From 900c88fe976fe62e103bb78ca720cec818ee98fb Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 24 May 2014 16:14:23 -0700 Subject: [PATCH 08/13] Simple command line option parser --- src/CmdLineOptParser.cc | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ src/CmdLineOptParser.h | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/CmdLineOptParser.cc create mode 100644 src/CmdLineOptParser.h diff --git a/src/CmdLineOptParser.cc b/src/CmdLineOptParser.cc new file mode 100644 index 0000000..5e237a7 --- /dev/null +++ b/src/CmdLineOptParser.cc @@ -0,0 +1,59 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + + ======================================================================*/ + +/// @file +/// @brief Command line option parser +/// +/// @author Don Gagne + +#include "CmdLineOptParser.h" + +#include + +/// @brief Implements a simple command line parser which sets booleans to true if the option is found. +void ParseCmdLineOptions(int& argc, ///< count of arguments in argv + char* argv[], ///< command line arguments + CmdLineOpt_t* prgOpts, ///< command line options + size_t cOpts, ///< count of command line options + bool removeParsedOptions) ///< true: remove parsed option from argc/argv +{ + // Start with all options off + for (size_t iOption=0; iOption + + This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + QGROUNDCONTROL is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QGROUNDCONTROL. If not, see . + + ======================================================================*/ + +/// @file +/// @brief Command line option parser +/// +/// @author Don Gagne + +#ifndef CMDLINEOPTPARSER_H +#define CMDLINEOPTPARSER_H + +#include + +/// @brief Structure used to pass command line options to the ParseCmdLineOptions function. +typedef struct { + const char* optionStr; ///< command line option, for example "--foo" + bool* flag; ///< if option is found this variable will be set to true +} CmdLineOpt_t; + +void ParseCmdLineOptions(int& argc, + char* argv[], + CmdLineOpt_t* prgOpts, + size_t cOpts, + bool removeParsedOptions); + +#endif From 6b2dc5d64a0c0dbe5226e16588ee07c9c4e5d19d Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 24 May 2014 16:15:16 -0700 Subject: [PATCH 09/13] Added --no-windows-assert-ui command line option This disables Windows C Runtime assert dialogs from popping up. --- src/main.cc | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/main.cc b/src/main.cc index 1b0e884..76b278d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -36,6 +36,10 @@ This file is part of the QGROUNDCONTROL project #include "TCPLink.h" #ifdef QT_DEBUG #include "AutoTest.h" +#include "CmdLineOptParser.h" +#ifdef Q_OS_WIN +#include +#endif #endif /* SDL does ugly things to main() */ @@ -44,10 +48,10 @@ This file is part of the QGROUNDCONTROL project #endif -// Install a message handler so you do not need -// the MSFT debug tools installed to se -// qDebug(), qWarning(), qCritical and qAbort #ifdef Q_OS_WIN + +/// @brief Message handler which is installed using qInstallMsgHandler so you do not need +/// the MSFT debug tools installed to see qDebug(), qWarning(), qCritical and qAbort void msgHandler( QtMsgType type, const char* msg ) { const char symbols[] = { 'I', 'E', '!', 'X' }; @@ -56,6 +60,17 @@ void msgHandler( QtMsgType type, const char* msg ) if( type == QtFatalMsg ) abort(); } +/// @brief CRT Report Hook installed using _CrtSetReportHook. We install this hook when +/// we don't want asserts to pop a dialog on windows. +int WindowsCrtReportHook(int reportType, char* message, int* returnValue) +{ + Q_UNUSED(reportType); + + std::cerr << message << std::endl; // Output message to stderr + *returnValue = 0; // Don't break into debugger + return true; // We handled this fully ourselves +} + #endif /** @@ -81,13 +96,27 @@ int main(int argc, char *argv[]) qRegisterMetaType(); #ifdef QT_DEBUG - if (argc > 1 && QString(argv[1]).compare("--unittest", Qt::CaseInsensitive) == 0) { - // Strip off extra command line args so QTest doesn't complain - for (int i=1; i Date: Sat, 24 May 2014 16:15:42 -0700 Subject: [PATCH 10/13] Added --clear-settings command line option Clears the persisted settings for the QGC --- src/QGCCore.cc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/QGCCore.cc b/src/QGCCore.cc index ac09084..375f3c0 100644 --- a/src/QGCCore.cc +++ b/src/QGCCore.cc @@ -47,6 +47,7 @@ This file is part of the QGROUNDCONTROL project #include "MainWindow.h" #include "QGCWelcomeMainWindow.h" #include "GAudioOutput.h" +#include "CmdLineOptParser.h" #ifdef QGC_RTLAB_ENABLED #include "OpalLink.h" @@ -82,12 +83,25 @@ QGCCore::QGCCore(bool firstStart, int &argc, char* argv[]) : QApplication(argc, // Set settings format QSettings::setDefaultFormat(QSettings::IniFormat); - - // Check application settings - // clear them if they mismatch - // QGC then falls back to default + + // Parse command line options + + bool fClearSettingsOptions = false; // Clear stored settings + + CmdLineOpt_t rgCmdLineOptions[] = { + { "--clear-settings", &fClearSettingsOptions }, + // Add additional command line option flags here + }; + + ParseCmdLineOptions(argc, argv, rgCmdLineOptions, sizeof(rgCmdLineOptions)/sizeof(rgCmdLineOptions[0]), false); + QSettings settings; + if (fClearSettingsOptions) { + // User requested settings to be cleared on command line + settings.clear(); + } + // Show user an upgrade message if QGC got upgraded (see code below, after splash screen) bool upgraded = false; enum MainWindow::CUSTOM_MODE mode = MainWindow::CUSTOM_MODE_NONE; @@ -98,7 +112,7 @@ QGCCore::QGCCore(bool firstStart, int &argc, char* argv[]) : QApplication(argc, if (qgcVersion != QGC_APPLICATION_VERSION) { lastApplicationVersion = qgcVersion; - settings.clear(); + settings.clear(); // Clear settings from different version // Write current application version settings.setValue("QGC_APPLICATION_VERSION", QGC_APPLICATION_VERSION); upgraded = true; From f83b07b27b6b7cf4fe7a85ef08e54be9e5f3638a Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 24 May 2014 16:16:01 -0700 Subject: [PATCH 11/13] Fix constructor ordering warnings --- src/uas/UAS.cc | 4 ++-- src/ui/PrimaryFlightDisplay.cc | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index a338d43..3a6e076 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -155,6 +155,7 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), paramsOnceRequested(false), paramMgr(this), simulation(0), + _thread(thread), // The protected members. connectionLost(false), @@ -164,8 +165,7 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(), hilEnabled(false), sensorHil(false), lastSendTimeGPS(0), - lastSendTimeSensors(0), - _thread(thread) + lastSendTimeSensors(0) { moveToThread(thread); diff --git a/src/ui/PrimaryFlightDisplay.cc b/src/ui/PrimaryFlightDisplay.cc index 7997a1d..c22fbf3 100644 --- a/src/ui/PrimaryFlightDisplay.cc +++ b/src/ui/PrimaryFlightDisplay.cc @@ -110,6 +110,9 @@ const QString PrimaryFlightDisplay::compassWindNames[] = { PrimaryFlightDisplay::PrimaryFlightDisplay(int width, int height, QWidget *parent) : QWidget(parent), + _valuesChanged(false), + _valuesLastPainted(QGC::groundTimeMilliseconds()), + uas(NULL), roll(0), @@ -141,9 +144,7 @@ PrimaryFlightDisplay::PrimaryFlightDisplay(int width, int height, QWidget *paren instrumentOpagueBackground(QColor::fromHsvF(0, 0, 0.3, 1.0)), font("Bitstream Vera Sans"), - refreshTimer(new QTimer(this)), - _valuesChanged(false), - _valuesLastPainted(QGC::groundTimeMilliseconds()) + refreshTimer(new QTimer(this)) { Q_UNUSED(width); Q_UNUSED(height); From 8378ee034132135cac0162567dec4c72a8869520 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 24 May 2014 16:16:20 -0700 Subject: [PATCH 12/13] Temp hack for Issue #647 --- src/ui/QGCMAVLinkLogPlayer.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/QGCMAVLinkLogPlayer.cc b/src/ui/QGCMAVLinkLogPlayer.cc index dd2085e..3e7aa2f 100644 --- a/src/ui/QGCMAVLinkLogPlayer.cc +++ b/src/ui/QGCMAVLinkLogPlayer.cc @@ -575,6 +575,7 @@ void QGCMAVLinkLogPlayer::logLoop() // have at least 3ms until the next one. int nextExecutionTime = 0; mavlink_message_t msg; + msg.len = 0; // FIXME: Hack, remove once Issue #647 is fixed while (nextExecutionTime < 3) { // Now we're sitting at the start of a MAVLink message, so read it all into a byte array for feeding to our parser. From 3b43cf6dd3769e990e4770c77f0b354d3670071d Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sun, 25 May 2014 10:46:18 -0700 Subject: [PATCH 13/13] UAS unit test back on --- qgroundcontrol.pro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 2634903..6475dc5 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -182,6 +182,7 @@ DebugBuild { HEADERS += \ src/qgcunittest/AutoTest.h \ + src/qgcunittest/UASUnitTest.h \ src/qgcunittest/MockUASManager.h \ src/qgcunittest/MockUAS.h \ src/qgcunittest/MockQGCUASParamManager.h \ @@ -189,6 +190,7 @@ DebugBuild { src/qgcunittest/FlightModeConfigTest.h SOURCES += \ + src/qgcunittest/UASUnitTest.cc \ src/qgcunittest/MockUASManager.cc \ src/qgcunittest/MockUAS.cc \ src/qgcunittest/MockQGCUASParamManager.cc \