Commit fc493d75 authored by Don Gagne's avatar Don Gagne

Move UAS and MAVLinkProtocol back to main thread

Plus a large number of other changes to allow for orderly shutdown of
objects without crashes or asserts. This is need for unit tests to
create/delete global state around every test.
parent 3b328f36
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
======================================================================*/ ======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef AUTOPILOTPLUGIN_H #ifndef AUTOPILOTPLUGIN_H
#define AUTOPILOTPLUGIN_H #define AUTOPILOTPLUGIN_H
...@@ -33,12 +36,12 @@ ...@@ -33,12 +36,12 @@
#include "VehicleComponent.h" #include "VehicleComponent.h"
#include "FactSystem.h" #include "FactSystem.h"
/// @file /// This is the base class for AutoPilot plugins
/// @brief The AutoPilotPlugin class is an abstract base class which represent the methods and objects ///
/// which are specific to a certain AutoPilot. This is the only place where AutoPilot specific /// The AutoPilotPlugin class is an abstract base class which represent the methods and objects
/// code should reside in QGroundControl. The remainder of the QGroundControl source is /// which are specific to a certain AutoPilot. This is the only place where AutoPilot specific
/// generic to a common mavlink implementation. /// code should reside in QGroundControl. The remainder of the QGroundControl source is
/// @author Don Gagne <don@thegagnes.com> /// generic to a common mavlink implementation.
class AutoPilotPlugin : public QObject class AutoPilotPlugin : public QObject
{ {
...@@ -46,21 +49,28 @@ class AutoPilotPlugin : public QObject ...@@ -46,21 +49,28 @@ class AutoPilotPlugin : public QObject
public: public:
/// @brief Returns the list of VehicleComponent objects associated with the AutoPilot. /// @brief Returns the list of VehicleComponent objects associated with the AutoPilot.
virtual QList<VehicleComponent*> getVehicleComponents(UASInterface* uas) const = 0; virtual QList<VehicleComponent*> getVehicleComponents(void) const = 0;
/// Returns the parameter facts for the specified UAS.
///
/// Access to parameter properties is done through QObject::property or the full
/// QMetaObject methods. The property name is the parameter name. You should not
/// request parameter facts until the plugin reports that it is ready.
virtual QObject* parameterFacts(void) const = 0;
typedef struct { /// Adds the FactSystem properties to the Qml context. You should not call
uint8_t baseMode; /// this method until the plugin reports that it is ready.
uint32_t customMode; virtual void addFactsToQmlContext(QQmlContext* context) const = 0;
} FullMode_t;
/// @brief Returns the list of modes which are available for this AutoPilot. /// Returns true if the plugin is ready for use
virtual QList<FullMode_t> getModes(void) const = 0; virtual bool pluginIsReady(void) const = 0;
/// @brief Returns a human readable short description for the specified mode. /// FIXME: Kind of hacky
virtual QString getShortModeText(uint8_t baseMode, uint32_t customMode) const = 0; static void clearStaticData(void);
/// @brief Adds the FactSystem properties associated with this AutoPilot to the Qml context. signals:
virtual void addFactsToQmlContext(QQmlContext* context, UASInterface* uas) const = 0; /// Signalled when plugin is ready for use
void pluginReady(void);
protected: protected:
// All access to AutoPilotPugin objects is through getInstanceForAutoPilotPlugin // All access to AutoPilotPugin objects is through getInstanceForAutoPilotPlugin
......
...@@ -28,29 +28,109 @@ ...@@ -28,29 +28,109 @@
#include "PX4/PX4AutoPilotPlugin.h" #include "PX4/PX4AutoPilotPlugin.h"
#include "Generic/GenericAutoPilotPlugin.h" #include "Generic/GenericAutoPilotPlugin.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#include "UASManager.h"
IMPLEMENT_QGC_SINGLETON(AutoPilotPluginManager, AutoPilotPluginManager) IMPLEMENT_QGC_SINGLETON(AutoPilotPluginManager, AutoPilotPluginManager)
AutoPilotPluginManager::AutoPilotPluginManager(QObject* parent) : AutoPilotPluginManager::AutoPilotPluginManager(QObject* parent) :
QGCSingleton(parent) QGCSingleton(parent)
{ {
// All plugins are constructed here so that they end up on the correct thread UASManagerInterface* uasMgr = UASManager::instance();
_pluginMap[MAV_AUTOPILOT_PX4] = new PX4AutoPilotPlugin(this); Q_ASSERT(uasMgr);
Q_ASSERT(_pluginMap.contains(MAV_AUTOPILOT_PX4));
// We need to track uas coming and going so that we can instantiate plugins for each uas
connect(uasMgr, &UASManagerInterface::UASCreated, this, &AutoPilotPluginManager::_uasCreated);
connect(uasMgr, &UASManagerInterface::UASDeleted, this, &AutoPilotPluginManager::_uasDeleted);
}
_pluginMap[MAV_AUTOPILOT_GENERIC] = new GenericAutoPilotPlugin(this); AutoPilotPluginManager::~AutoPilotPluginManager()
Q_ASSERT(_pluginMap.contains(MAV_AUTOPILOT_GENERIC)); {
#ifdef QT_DEBUG
foreach(MAV_AUTOPILOT mavType, _pluginMap.keys()) {
Q_ASSERT_X(_pluginMap[mavType].count() == 0, "AutoPilotPluginManager", "LinkManager::_shutdown should have already closed all uas");
}
#endif
_pluginMap.clear();
PX4AutoPilotPlugin::clearStaticData();
GenericAutoPilotPlugin::clearStaticData();
}
/// Create the plugin for this uas
void AutoPilotPluginManager::_uasCreated(UASInterface* uas)
{
Q_ASSERT(uas);
MAV_AUTOPILOT autopilotType = static_cast<MAV_AUTOPILOT>(uas->getAutopilotType());
int uasId = uas->getUASID();
Q_ASSERT(uasId != 0);
if (_pluginMap.contains(autopilotType)) {
Q_ASSERT_X(!_pluginMap[autopilotType].contains(uasId), "AutoPilotPluginManager", "Either we have duplicate UAS ids, or a UAS was not removed correctly.");
}
AutoPilotPlugin* plugin;
switch (autopilotType) {
case MAV_AUTOPILOT_PX4:
plugin = new PX4AutoPilotPlugin(uas, this);
Q_CHECK_PTR(plugin);
_pluginMap[MAV_AUTOPILOT_PX4][uasId] = plugin;
break;
case MAV_AUTOPILOT_GENERIC:
default:
plugin = new GenericAutoPilotPlugin(uas, this);
Q_CHECK_PTR(plugin);
_pluginMap[MAV_AUTOPILOT_GENERIC][uasId] = plugin;
}
}
/// Destroy the plugin associated with this uas
void AutoPilotPluginManager::_uasDeleted(UASInterface* uas)
{
Q_ASSERT(uas);
MAV_AUTOPILOT autopilotType = static_cast<MAV_AUTOPILOT>(uas->getAutopilotType());
int uasId = uas->getUASID();
Q_ASSERT(uasId != 0);
Q_ASSERT(_pluginMap.contains(autopilotType));
Q_ASSERT(_pluginMap[autopilotType].contains(uasId));
delete _pluginMap[autopilotType][uasId];
_pluginMap[autopilotType].remove(uasId);
}
AutoPilotPlugin* AutoPilotPluginManager::getInstanceForAutoPilotPlugin(UASInterface* uas)
{
Q_ASSERT(uas);
MAV_AUTOPILOT autopilotType = static_cast<MAV_AUTOPILOT>(uas->getAutopilotType());
int uasId = uas->getUASID();
Q_ASSERT(uasId != 0);
Q_ASSERT(_pluginMap.contains(autopilotType));
Q_ASSERT(_pluginMap[autopilotType].contains(uasId));
return _pluginMap[autopilotType][uasId];
}
QList<AutoPilotPluginManager::FullMode_t> AutoPilotPluginManager::getModes(int autopilotType) const
{
switch (autopilotType) {
case MAV_AUTOPILOT_PX4:
return PX4AutoPilotPlugin::getModes();
case MAV_AUTOPILOT_GENERIC:
default:
return GenericAutoPilotPlugin::getModes();
}
} }
AutoPilotPlugin* AutoPilotPluginManager::getInstanceForAutoPilotPlugin(int autopilotType) QString AutoPilotPluginManager::getShortModeText(uint8_t baseMode, uint32_t customMode, int autopilotType) const
{ {
switch (autopilotType) { switch (autopilotType) {
case MAV_AUTOPILOT_PX4: case MAV_AUTOPILOT_PX4:
Q_ASSERT(_pluginMap.contains(MAV_AUTOPILOT_PX4)); return PX4AutoPilotPlugin::getShortModeText(baseMode, customMode);
return _pluginMap[MAV_AUTOPILOT_PX4]; case MAV_AUTOPILOT_GENERIC:
default: default:
Q_ASSERT(_pluginMap.contains(MAV_AUTOPILOT_GENERIC)); return GenericAutoPilotPlugin::getShortModeText(baseMode, customMode);
return _pluginMap[MAV_AUTOPILOT_GENERIC];
} }
} }
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
======================================================================*/ ======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef AUTOPILOTPLUGINMANAGER_H #ifndef AUTOPILOTPLUGINMANAGER_H
#define AUTOPILOTPLUGINMANAGER_H #define AUTOPILOTPLUGINMANAGER_H
...@@ -32,11 +35,10 @@ ...@@ -32,11 +35,10 @@
#include "VehicleComponent.h" #include "VehicleComponent.h"
#include "AutoPilotPlugin.h" #include "AutoPilotPlugin.h"
#include "QGCSingleton.h" #include "QGCSingleton.h"
#include "QGCMAVLink.h"
/// @file
/// @brief The AutoPilotPlugin manager is a singleton which maintains the list of AutoPilotPlugin objects. /// AutoPilotPlugin manager is a singleton which maintains the list of AutoPilotPlugin objects.
///
/// @author Don Gagne <don@thegagnes.com>
class AutoPilotPluginManager : public QGCSingleton class AutoPilotPluginManager : public QGCSingleton
{ {
...@@ -45,15 +47,31 @@ class AutoPilotPluginManager : public QGCSingleton ...@@ -45,15 +47,31 @@ class AutoPilotPluginManager : public QGCSingleton
DECLARE_QGC_SINGLETON(AutoPilotPluginManager, AutoPilotPluginManager) DECLARE_QGC_SINGLETON(AutoPilotPluginManager, AutoPilotPluginManager)
public: public:
/// @brief Returns the singleton AutoPilot instance for the specified auto pilot type. /// Returns the singleton AutoPilotPlugin instance for the specified uas.
/// @param autopilotType Specified using the MAV_AUTOPILOT_* values. /// @param uas Uas to get plugin for
AutoPilotPlugin* getInstanceForAutoPilotPlugin(int autopilotType); AutoPilotPlugin* getInstanceForAutoPilotPlugin(UASInterface* uas);
typedef struct {
uint8_t baseMode;
uint32_t customMode;
} FullMode_t;
/// Returns the list of modes which are available for the specified autopilot type.
QList<FullMode_t> getModes(int autopilotType) const;
/// @brief Returns a human readable short description for the specified mode.
QString getShortModeText(uint8_t baseMode, uint32_t customMode, int autopilotType) const;
private slots:
void _uasCreated(UASInterface* uas);
void _uasDeleted(UASInterface* uas);
private: private:
/// All access to singleton is through AutoPilotPluginManager::instance /// All access to singleton is through AutoPilotPluginManager::instance
AutoPilotPluginManager(QObject* parent = NULL); AutoPilotPluginManager(QObject* parent = NULL);
~AutoPilotPluginManager();
QMap<int, AutoPilotPlugin*> _pluginMap; QMap<MAV_AUTOPILOT, QMap<int, AutoPilotPlugin*> > _pluginMap; ///< Map of AutoPilot plugins _pluginMap[MAV_TYPE][UASid]
}; };
#endif #endif
...@@ -26,24 +26,22 @@ ...@@ -26,24 +26,22 @@
#include "GenericAutoPilotPlugin.h" #include "GenericAutoPilotPlugin.h"
GenericAutoPilotPlugin::GenericAutoPilotPlugin(QObject* parent) : GenericAutoPilotPlugin::GenericAutoPilotPlugin(UASInterface* uas, QObject* parent) :
AutoPilotPlugin(parent) AutoPilotPlugin(parent)
{ {
Q_UNUSED(uas);
} }
QList<VehicleComponent*> GenericAutoPilotPlugin::getVehicleComponents(UASInterface* uas) const QList<VehicleComponent*> GenericAutoPilotPlugin::getVehicleComponents(void) const
{ {
Q_UNUSED(uas);
// Generic autopilot has no configurable components // Generic autopilot has no configurable components
return QList<VehicleComponent*>(); return QList<VehicleComponent*>();
} }
QList<AutoPilotPlugin::FullMode_t> GenericAutoPilotPlugin::getModes(void) const QList<AutoPilotPluginManager::FullMode_t> GenericAutoPilotPlugin::getModes(void)
{ {
QList<FullMode_t> modeList; AutoPilotPluginManager::FullMode_t fullMode;
FullMode_t fullMode; QList<AutoPilotPluginManager::FullMode_t> modeList;
fullMode.customMode = 0; fullMode.customMode = 0;
...@@ -62,7 +60,7 @@ QList<AutoPilotPlugin::FullMode_t> GenericAutoPilotPlugin::getModes(void) const ...@@ -62,7 +60,7 @@ QList<AutoPilotPlugin::FullMode_t> GenericAutoPilotPlugin::getModes(void) const
return modeList; return modeList;
} }
QString GenericAutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t customMode) const QString GenericAutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t customMode)
{ {
Q_UNUSED(customMode); Q_UNUSED(customMode);
...@@ -85,11 +83,20 @@ QString GenericAutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t cust ...@@ -85,11 +83,20 @@ QString GenericAutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t cust
return mode; return mode;
} }
void GenericAutoPilotPlugin::addFactsToQmlContext(QQmlContext* context, UASInterface* uas) const void GenericAutoPilotPlugin::addFactsToQmlContext(QQmlContext* context) const
{ {
Q_UNUSED(context); Q_UNUSED(context);
Q_UNUSED(uas);
// Qml not yet supported for Generic // Qml not yet supported for Generic
Q_ASSERT(false); Q_ASSERT(false);
} }
QObject* GenericAutoPilotPlugin::parameterFacts(void) const
{
return NULL;
}
void GenericAutoPilotPlugin::clearStaticData(void)
{
// No Static data yet
}
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define GENERICAUTOPILOT_H #define GENERICAUTOPILOT_H
#include "AutoPilotPlugin.h" #include "AutoPilotPlugin.h"
#include "AutoPilotPluginManager.h"
/// @file /// @file
/// @brief This is the generic implementation of the AutoPilotPlugin class for mavs /// @brief This is the generic implementation of the AutoPilotPlugin class for mavs
...@@ -36,13 +37,17 @@ class GenericAutoPilotPlugin : public AutoPilotPlugin ...@@ -36,13 +37,17 @@ class GenericAutoPilotPlugin : public AutoPilotPlugin
Q_OBJECT Q_OBJECT
public: public:
GenericAutoPilotPlugin(QObject* parent = NULL); GenericAutoPilotPlugin(UASInterface* uas, QObject* parent = NULL);
// Overrides from AutoPilotPlugin // Overrides from AutoPilotPlugin
virtual QList<VehicleComponent*> getVehicleComponents(UASInterface* uas) const ; virtual QList<VehicleComponent*> getVehicleComponents(void) const ;
virtual QList<FullMode_t> getModes(void) const; virtual void addFactsToQmlContext(QQmlContext* context) const;
virtual QString getShortModeText(uint8_t baseMode, uint32_t customMode) const; virtual QObject* parameterFacts(void) const;
virtual void addFactsToQmlContext(QQmlContext* context, UASInterface* uas) const; virtual bool pluginIsReady(void) const { return true; }
static QList<AutoPilotPluginManager::FullMode_t> getModes(void);
static QString getShortModeText(uint8_t baseMode, uint32_t customMode);
static void clearStaticData(void);
}; };
#endif #endif
...@@ -65,59 +65,59 @@ union px4_custom_mode { ...@@ -65,59 +65,59 @@ union px4_custom_mode {
float data_float; float data_float;
}; };
PX4AutoPilotPlugin::PX4AutoPilotPlugin(QObject* parent) : PX4AutoPilotPlugin::PX4AutoPilotPlugin(UASInterface* uas, QObject* parent) :
AutoPilotPlugin(parent) AutoPilotPlugin(parent),
_uas(uas),
_parameterFacts(NULL)
{ {
UASManagerInterface* uasMgr = UASManager::instance(); Q_ASSERT(uas);
Q_ASSERT(uasMgr);
_parameterFacts = new PX4ParameterFacts(uas, this);
Q_CHECK_PTR(_parameterFacts);
// We need to track uas coming and going so that we can create PX4ParameterFacts instances for each uas connect(_parameterFacts, &PX4ParameterFacts::factsReady, this, &PX4AutoPilotPlugin::pluginReady);
connect(uasMgr, &UASManagerInterface::UASCreated, this, &PX4AutoPilotPlugin::_uasCreated);
connect(uasMgr, &UASManagerInterface::UASDeleted, this, &PX4AutoPilotPlugin::_uasDeleted);
PX4ParameterFacts::loadParameterFactMetaData(); PX4ParameterFacts::loadParameterFactMetaData();
} }
PX4AutoPilotPlugin::~PX4AutoPilotPlugin() PX4AutoPilotPlugin::~PX4AutoPilotPlugin()
{ {
delete _parameterFacts;
PX4ParameterFacts::deleteParameterFactMetaData(); PX4ParameterFacts::deleteParameterFactMetaData();
foreach(UASInterface* uas, _mapUas2ParameterFacts.keys()) {
delete _mapUas2ParameterFacts[uas];
}
_mapUas2ParameterFacts.clear();
} }
QList<VehicleComponent*> PX4AutoPilotPlugin::getVehicleComponents(UASInterface* uas) const QList<VehicleComponent*> PX4AutoPilotPlugin::getVehicleComponents(void) const
{ {
Q_ASSERT(_uas);
QList<VehicleComponent*> components; QList<VehicleComponent*> components;
VehicleComponent* component; VehicleComponent* component;
component = new AirframeComponent(uas); component = new AirframeComponent(_uas);
Q_CHECK_PTR(component); Q_CHECK_PTR(component);
components.append(component); components.append(component);
component = new RadioComponent(uas); component = new RadioComponent(_uas);
Q_CHECK_PTR(component); Q_CHECK_PTR(component);
components.append(component); components.append(component);
component = new FlightModesComponent(uas); component = new FlightModesComponent(_uas);
Q_CHECK_PTR(component); Q_CHECK_PTR(component);
components.append(component); components.append(component);
component = new SensorsComponent(uas); component = new SensorsComponent(_uas);
Q_CHECK_PTR(component); Q_CHECK_PTR(component);
components.append(component); components.append(component);
return components; return components;
} }
QList<AutoPilotPlugin::FullMode_t> PX4AutoPilotPlugin::getModes(void) const QList<AutoPilotPluginManager::FullMode_t> PX4AutoPilotPlugin::getModes(void)
{ {
QList<FullMode_t> modeList; union px4_custom_mode px4_cm;
FullMode_t fullMode; AutoPilotPluginManager::FullMode_t fullMode;
union px4_custom_mode px4_cm; QList<AutoPilotPluginManager::FullMode_t> modeList;
px4_cm.data = 0; px4_cm.data = 0;
px4_cm.main_mode = PX4_CUSTOM_MAIN_MODE_MANUAL; px4_cm.main_mode = PX4_CUSTOM_MAIN_MODE_MANUAL;
...@@ -152,7 +152,7 @@ QList<AutoPilotPlugin::FullMode_t> PX4AutoPilotPlugin::getModes(void) const ...@@ -152,7 +152,7 @@ QList<AutoPilotPlugin::FullMode_t> PX4AutoPilotPlugin::getModes(void) const
return modeList; return modeList;
} }
QString PX4AutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t customMode) const QString PX4AutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t customMode)
{ {
QString mode; QString mode;
...@@ -187,51 +187,40 @@ QString PX4AutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t customMo ...@@ -187,51 +187,40 @@ QString PX4AutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t customMo
mode = "|OFFBOARD"; mode = "|OFFBOARD";
} }
} else { } else {
mode = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(MAV_AUTOPILOT_GENERIC)->getShortModeText(baseMode, customMode); // use base_mode - not autopilot-specific
if (baseMode == 0) {
mode = "|PREFLIGHT";
} else if (baseMode & MAV_MODE_FLAG_DECODE_POSITION_AUTO) {
mode = "|AUTO";
} else if (baseMode & MAV_MODE_FLAG_DECODE_POSITION_MANUAL) {
mode = "|MANUAL";
if (baseMode & MAV_MODE_FLAG_DECODE_POSITION_GUIDED) {
mode += "|GUIDED";
} else if (baseMode & MAV_MODE_FLAG_DECODE_POSITION_STABILIZE) {
mode += "|STABILIZED";
}
}
} }
return mode; return mode;
} }
void PX4AutoPilotPlugin::addFactsToQmlContext(QQmlContext* context, UASInterface* uas) const void PX4AutoPilotPlugin::addFactsToQmlContext(QQmlContext* context) const
{ {
Q_ASSERT(context); Q_ASSERT(context);
Q_ASSERT(uas);
QGCUASParamManagerInterface* paramMgr = uas->getParamManager();
Q_UNUSED(paramMgr);
Q_ASSERT(paramMgr);
Q_ASSERT(paramMgr->parametersReady());
PX4ParameterFacts* facts = _parameterFactsForUas(uas); Q_ASSERT(_parameterFacts->factsAreReady());
Q_ASSERT(facts);
context->setContextProperty("parameterFacts", facts); context->setContextProperty("parameterFacts", _parameterFacts);
} }
/// @brief When a new uas is create we add a new set of parameter facts for it void PX4AutoPilotPlugin::clearStaticData(void)
void PX4AutoPilotPlugin::_uasCreated(UASInterface* uas)
{ {
Q_ASSERT(uas); PX4ParameterFacts::clearStaticData();
Q_ASSERT(!_mapUas2ParameterFacts.contains(uas));
// Each uas has it's own set of parameter facts
PX4ParameterFacts* facts = new PX4ParameterFacts(uas, this);
Q_CHECK_PTR(facts);
_mapUas2ParameterFacts[uas] = facts;
} }
/// @brief When the uas is deleted we remove the parameter facts for it from the system bool PX4AutoPilotPlugin::pluginIsReady(void) const
void PX4AutoPilotPlugin::_uasDeleted(UASInterface* uas)
{ {
delete _parameterFactsForUas(uas); return _parameterFacts->factsAreReady();
_mapUas2ParameterFacts.remove(uas);
}
PX4ParameterFacts* PX4AutoPilotPlugin::_parameterFactsForUas(UASInterface* uas) const
{
Q_ASSERT(uas);
Q_ASSERT(_mapUas2ParameterFacts.contains(uas));
return _mapUas2ParameterFacts[uas];
} }
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define PX4AUTOPILOT_H #define PX4AUTOPILOT_H
#include "AutoPilotPlugin.h" #include "AutoPilotPlugin.h"
#include "AutoPilotPluginManager.h"
#include "UASInterface.h" #include "UASInterface.h"
#include "PX4ParameterFacts.h" #include "PX4ParameterFacts.h"
...@@ -37,23 +38,23 @@ class PX4AutoPilotPlugin : public AutoPilotPlugin ...@@ -37,23 +38,23 @@ class PX4AutoPilotPlugin : public AutoPilotPlugin
Q_OBJECT Q_OBJECT
public: public:
PX4AutoPilotPlugin(QObject* parent); PX4AutoPilotPlugin(UASInterface* uas, QObject* parent);
~PX4AutoPilotPlugin(); ~PX4AutoPilotPlugin();
// Overrides from AutoPilotPlugin // Overrides from AutoPilotPlugin
virtual QList<VehicleComponent*> getVehicleComponents(UASInterface* uas) const ; virtual QList<VehicleComponent*> getVehicleComponents(void) const ;
virtual QList<FullMode_t> getModes(void) const; virtual void addFactsToQmlContext(QQmlContext* context) const;
virtual QString getShortModeText(uint8_t baseMode, uint32_t customMode) const; virtual QObject* parameterFacts(void) const { return _parameterFacts; }
virtual void addFactsToQmlContext(QQmlContext* context, UASInterface* uas) const; virtual bool pluginIsReady(void) const;
private slots: static QList<AutoPilotPluginManager::FullMode_t> getModes(void);
void _uasCreated(UASInterface* uas); static QString getShortModeText(uint8_t baseMode, uint32_t customMode);
void _uasDeleted(UASInterface* uas); static void clearStaticData(void);
private: private:
PX4ParameterFacts* _parameterFactsForUas(UASInterface* uas) const; UASInterface* _uas;
PX4ParameterFacts* _parameterFacts;
QMap<UASInterface*, PX4ParameterFacts*> _mapUas2ParameterFacts; bool _pluginReady;
}; };
#endif #endif
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
#include "PX4ParameterFacts.h" #include "PX4ParameterFacts.h"
#include "QGCApplication.h"
#include <QFile> #include <QFile>
#include <QDebug> #include <QDebug>
...@@ -32,12 +33,14 @@ ...@@ -32,12 +33,14 @@
Q_LOGGING_CATEGORY(PX4ParameterFactsLog, "PX4ParameterFactsLog") Q_LOGGING_CATEGORY(PX4ParameterFactsLog, "PX4ParameterFactsLog")
Q_LOGGING_CATEGORY(PX4ParameterFactsMetaDataLog, "PX4ParameterFactsMetaDataLog") Q_LOGGING_CATEGORY(PX4ParameterFactsMetaDataLog, "PX4ParameterFactsMetaDataLog")
bool PX4ParameterFacts::_parameterMetaDataLoaded = false;
QMap<QString, FactMetaData*> PX4ParameterFacts::_mapParameterName2FactMetaData; QMap<QString, FactMetaData*> PX4ParameterFacts::_mapParameterName2FactMetaData;
PX4ParameterFacts::PX4ParameterFacts(UASInterface* uas, QObject* parent) : PX4ParameterFacts::PX4ParameterFacts(UASInterface* uas, QObject* parent) :
QObject(parent), QObject(parent),
_lastSeenComponent(-1), _lastSeenComponent(-1),
_paramMgr(NULL) _paramMgr(NULL),
_factsReady(false)
{ {
Q_ASSERT(uas); Q_ASSERT(uas);
...@@ -46,11 +49,14 @@ PX4ParameterFacts::PX4ParameterFacts(UASInterface* uas, QObject* parent) : ...@@ -46,11 +49,14 @@ PX4ParameterFacts::PX4ParameterFacts(UASInterface* uas, QObject* parent) :
_paramMgr = uas->getParamManager(); _paramMgr = uas->getParamManager();
Q_ASSERT(_paramMgr); Q_ASSERT(_paramMgr);
// We need to be initialized before param mgr starts sending parameters so we catch each one
Q_ASSERT(!_paramMgr->parametersReady());
// We need to know when the param mgr is done sending the initial set of paramters
connect(_paramMgr, SIGNAL(parameterListUpToDate()), this, SLOT(_paramMgrParameterListUpToDate()));
// UASInterface::parameterChanged has multiple overrides so we need to use SIGNAL/SLOT style connect // UASInterface::parameterChanged has multiple overrides so we need to use SIGNAL/SLOT style connect
connect(uas, SIGNAL(parameterChanged(int, int, QString, QVariant)), this, SLOT(_parameterChanged(int, int, QString, QVariant))); connect(uas, SIGNAL(parameterChanged(int, int, QString, QVariant)), this, SLOT(_parameterChanged(int, int, QString, QVariant)));
// Fact meta data should already be loaded
Q_ASSERT(_mapParameterName2FactMetaData.count() != 0);
} }
PX4ParameterFacts::~PX4ParameterFacts() PX4ParameterFacts::~PX4ParameterFacts()
...@@ -90,7 +96,7 @@ void PX4ParameterFacts::_parameterChanged(int uas, int component, QString parame ...@@ -90,7 +96,7 @@ void PX4ParameterFacts::_parameterChanged(int uas, int component, QString parame
// If we don't have meta data for the parameter it can't be part of the FactSystem // If we don't have meta data for the parameter it can't be part of the FactSystem
if (!_mapParameterName2FactMetaData.contains(parameterName)) { if (!_mapParameterName2FactMetaData.contains(parameterName)) {
// FIXME: Debug or Warning. Warning will fail TC // FIXME: Debug or Warning. Warning will fail TC
qCDebug(PX4ParameterFactsLog) << "FactSystem meta data out of date. Missing parameter:" << parameterName; qDebug() << "FactSystem meta data out of date. Missing parameter:" << parameterName;
return; return;
} }
...@@ -99,19 +105,22 @@ void PX4ParameterFacts::_parameterChanged(int uas, int component, QString parame ...@@ -99,19 +105,22 @@ void PX4ParameterFacts::_parameterChanged(int uas, int component, QString parame
fact->setMetaData(_mapParameterName2FactMetaData[parameterName]); fact->setMetaData(_mapParameterName2FactMetaData[parameterName]);
// We need to know when the fact changes so that we can send the new value to the parameter managers
connect(fact, &Fact::valueUpdated, this, &PX4ParameterFacts::_valueUpdated);
_mapParameterName2Fact[parameterName] = fact; _mapParameterName2Fact[parameterName] = fact;
_mapFact2ParameterName[fact] = parameterName; _mapFact2ParameterName[fact] = parameterName;
// We need to know when the fact changes so that we can send the new value to the parameter manager
connect(fact, &Fact::_containerValueChanged, this, &PX4ParameterFacts::_valueUpdated);
//qDebug() << "Adding new fact" << parameterName;
} }
_mapParameterName2Fact[parameterName]->updateValue(value); //qDebug() << "Updating fact value" << parameterName << value;
_mapParameterName2Fact[parameterName]->_containerSetValue(value);
} }
/// Connected to Fact::valueUpdated /// Connected to Fact::valueUpdated
/// ///
/// Sets the new value into the Parameter Manager. Paramter is persisted after send. /// Sets the new value into the Parameter Manager. Paramter is persisted after send.
void PX4ParameterFacts::_valueUpdated(QVariant& value) void PX4ParameterFacts::_valueUpdated(QVariant value)
{ {
Fact* fact = qobject_cast<Fact*>(sender()); Fact* fact = qobject_cast<Fact*>(sender());
Q_ASSERT(fact); Q_ASSERT(fact);
...@@ -285,6 +294,11 @@ QVariant PX4ParameterFacts::_stringToTypedVariant(const QString& string, FactMet ...@@ -285,6 +294,11 @@ QVariant PX4ParameterFacts::_stringToTypedVariant(const QString& string, FactMet
/// The meta data comes from firmware parameters.xml file. /// The meta data comes from firmware parameters.xml file.
void PX4ParameterFacts::loadParameterFactMetaData(void) void PX4ParameterFacts::loadParameterFactMetaData(void)
{ {
if (_parameterMetaDataLoaded) {
return;
}
_parameterMetaDataLoaded = true;
qCDebug(PX4ParameterFactsMetaDataLog) << "Loading PX4 parameter fact meta data"; qCDebug(PX4ParameterFactsMetaDataLog) << "Loading PX4 parameter fact meta data";
Q_ASSERT(_mapParameterName2FactMetaData.count() == 0); Q_ASSERT(_mapParameterName2FactMetaData.count() == 0);
...@@ -347,3 +361,29 @@ void PX4ParameterFacts::loadParameterFactMetaData(void) ...@@ -347,3 +361,29 @@ void PX4ParameterFacts::loadParameterFactMetaData(void)
xml.readNext(); xml.readNext();
} }
} }
// Called when param mgr list is up to date
void PX4ParameterFacts::_paramMgrParameterListUpToDate(void)
{
if (!_factsReady) {
_factsReady = true;
// We don't need this any more
disconnect(_paramMgr, SIGNAL(parameterListUpToDate()), this, SLOT(_paramMgrParameterListUpToDate()));
// There may be parameterUpdated signals still in our queue. Flush them out.
qgcApp()->processEvents();
// We should have all paramters now so we can signal ready
emit factsReady();
}
}
void PX4ParameterFacts::clearStaticData(void)
{
foreach(QString parameterName, _mapParameterName2FactMetaData.keys()) {
delete _mapParameterName2FactMetaData[parameterName];
}
_mapParameterName2FactMetaData.clear();
_parameterMetaDataLoaded = false;
}
\ No newline at end of file
...@@ -487,6 +487,7 @@ class PX4ParameterFacts : public QObject ...@@ -487,6 +487,7 @@ class PX4ParameterFacts : public QObject
Q_PROPERTY(Fact* UAVCAN_BITRATE READ getUAVCAN_BITRATE CONSTANT) Fact* getUAVCAN_BITRATE(void) { return _mapParameterName2Fact["UAVCAN_BITRATE"]; } Q_PROPERTY(Fact* UAVCAN_BITRATE READ getUAVCAN_BITRATE CONSTANT) Fact* getUAVCAN_BITRATE(void) { return _mapParameterName2Fact["UAVCAN_BITRATE"]; }
Q_PROPERTY(Fact* UAVCAN_ENABLE READ getUAVCAN_ENABLE CONSTANT) Fact* getUAVCAN_ENABLE(void) { return _mapParameterName2Fact["UAVCAN_ENABLE"]; } Q_PROPERTY(Fact* UAVCAN_ENABLE READ getUAVCAN_ENABLE CONSTANT) Fact* getUAVCAN_ENABLE(void) { return _mapParameterName2Fact["UAVCAN_ENABLE"]; }
Q_PROPERTY(Fact* UAVCAN_NODE_ID READ getUAVCAN_NODE_ID CONSTANT) Fact* getUAVCAN_NODE_ID(void) { return _mapParameterName2Fact["UAVCAN_NODE_ID"]; } Q_PROPERTY(Fact* UAVCAN_NODE_ID READ getUAVCAN_NODE_ID CONSTANT) Fact* getUAVCAN_NODE_ID(void) { return _mapParameterName2Fact["UAVCAN_NODE_ID"]; }
Q_PROPERTY(QString testString READ getTestString CONSTANT)
public: public:
/// @param uas Uas which this set of facts is associated with /// @param uas Uas which this set of facts is associated with
...@@ -496,13 +497,20 @@ public: ...@@ -496,13 +497,20 @@ public:
static void loadParameterFactMetaData(void); static void loadParameterFactMetaData(void);
static void deleteParameterFactMetaData(void); static void deleteParameterFactMetaData(void);
static void clearStaticData(void);
/// Returns true if the full set of facts are ready
bool factsAreReady(void) { return _factsReady; }
signals:
/// Signalled when the full set of facts are ready
void factsReady(void);
private slots: private slots:
/// Connected to UASInterface::parameterChanged
void _parameterChanged(int uas, int component, QString parameterName, QVariant value); void _parameterChanged(int uas, int component, QString parameterName, QVariant value);
void _valueUpdated(QVariant value);
/// Signalled from Fact to indicate value was changed through the property write accessor void _paramMgrParameterListUpToDate(void);
void _valueUpdated(QVariant& value); QString getTestString(void) { return QString("foo"); }
private: private:
static FactMetaData* _parseParameter(QXmlStreamReader& xml, const QString& group); static FactMetaData* _parseParameter(QXmlStreamReader& xml, const QString& group);
...@@ -512,12 +520,15 @@ private: ...@@ -512,12 +520,15 @@ private:
QMap<QString, Fact*> _mapParameterName2Fact; ///< Maps from a parameter name to a Fact QMap<QString, Fact*> _mapParameterName2Fact; ///< Maps from a parameter name to a Fact
QMap<Fact*, QString> _mapFact2ParameterName; ///< Maps from a Fact to a parameter name QMap<Fact*, QString> _mapFact2ParameterName; ///< Maps from a Fact to a parameter name
static bool _parameterMetaDataLoaded; ///< true: parameter meta data already loaded
static QMap<QString, FactMetaData*> _mapParameterName2FactMetaData; ///< Maps from a parameter name to FactMetaData static QMap<QString, FactMetaData*> _mapParameterName2FactMetaData; ///< Maps from a parameter name to FactMetaData
int _uasId; ///< Id for uas which this set of Facts are associated with int _uasId; ///< Id for uas which this set of Facts are associated with
int _lastSeenComponent; int _lastSeenComponent;
QGCUASParamManagerInterface* _paramMgr; QGCUASParamManagerInterface* _paramMgr;
bool _factsReady; ///< All facts received from param mgr
}; };
#endif #endif
\ No newline at end of file
...@@ -34,14 +34,15 @@ Fact::Fact(QObject* parent) : ...@@ -34,14 +34,15 @@ Fact::Fact(QObject* parent) :
} }
void Fact::setValue(QVariant& value) void Fact::setValue(const QVariant& value)
{ {
_value = value; _value = value;
emit valueUpdated(value); emit valueChanged(_value);
emit _containerValueChanged(_value);
} }
void Fact::updateValue(QVariant& value) void Fact::_containerSetValue(const QVariant& value)
{ {
_value = value; _value = value;
emit valueChanged(value); emit valueChanged(_value);
} }
...@@ -62,7 +62,7 @@ public: ...@@ -62,7 +62,7 @@ public:
QVariant value(void) const { return _value; } QVariant value(void) const { return _value; }
/// Write accessor for value property /// Write accessor for value property
void setValue(QVariant& value); void setValue(const QVariant& value);
/// Read accesor for defaultValue property /// Read accesor for defaultValue property
QVariant defaultValue(void) { return _metaData->defaultValue; } QVariant defaultValue(void) { return _metaData->defaultValue; }
...@@ -85,24 +85,21 @@ public: ...@@ -85,24 +85,21 @@ public:
/// Read accesor for max property /// Read accesor for max property
QVariant max(void) { return _metaData->max; } QVariant max(void) { return _metaData->max; }
/// Used to update the value property from C++ code.
///
/// The setValue method is only for use by the QObject Property system. It should not be called directly by C++ app code.
void updateValue(QVariant& value);
/// Sets the meta data associated with the Fact. /// Sets the meta data associated with the Fact.
void setMetaData(FactMetaData* metaData) { _metaData = metaData; } void setMetaData(FactMetaData* metaData) { _metaData = metaData; }
void _containerSetValue(const QVariant& value);
signals: signals:
/// QObject Property System signal for value property changes /// QObject Property System signal for value property changes
/// ///
/// This signal is only meant for use by the QT property system. It should not be connected to by client code. /// This signal is only meant for use by the QT property system. It should not be connected to by client code.
void valueChanged(QVariant& value); void valueChanged(QVariant value);
/// Signalled when property has been changed by a call to the property write accessor /// Signalled when property has been changed by a call to the property write accessor
/// ///
/// This signal is meant for use by client code. /// This signal is meant for use by Fact container implementations.
void valueUpdated(QVariant& value); void _containerValueChanged(QVariant& value);
private: private:
QVariant _value; ///< Fact value QVariant _value; ///< Fact value
......
...@@ -50,7 +50,6 @@ class FactSystem : public QGCSingleton ...@@ -50,7 +50,6 @@ class FactSystem : public QGCSingleton
private: private:
/// All access to FactSystem is through FactSystem::instance, so constructor is private /// All access to FactSystem is through FactSystem::instance, so constructor is private
FactSystem(QObject* parent = NULL); FactSystem(QObject* parent = NULL);
~FactSystem(); ~FactSystem();
static const char* _factSystemQmlUri; ///< URI for FactSystem QML imports static const char* _factSystemQmlUri; ///< URI for FactSystem QML imports
......
...@@ -32,37 +32,22 @@ This file is part of the QGROUNDCONTROL project ...@@ -32,37 +32,22 @@ This file is part of the QGROUNDCONTROL project
#include <QApplication> #include <QApplication>
#include <QSettings> #include <QSettings>
#include "GAudioOutput.h"
#include <QDebug> #include <QDebug>
#include <QGC.h>
/** #include "GAudioOutput.h"
* This class follows the singleton design pattern #include "QGCApplication.h"
* @see http://en.wikipedia.org/wiki/Singleton_pattern #include "QGC.h"
* A call to this function thus returns the only instance of this object
* the call can occur at any place in the code, no reference to the
* GAudioOutput object has to be passed.
*/
GAudioOutput *GAudioOutput::instance()
{
static GAudioOutput *_instance = 0;
if (_instance == 0)
{
_instance = new GAudioOutput();
// Set the application as parent to ensure that this object
// will be destroyed when the main application exits
_instance->setParent(qApp);
}
return _instance; IMPLEMENT_QGC_SINGLETON(GAudioOutput, GAudioOutput)
}
GAudioOutput::GAudioOutput(QObject *parent) : QObject(parent), GAudioOutput::GAudioOutput(QObject *parent) :
QGCSingleton(parent),
muted(false), muted(false),
thread(new QThread()), thread(new QThread()),
worker(new QGCAudioWorker()) worker(new QGCAudioWorker())
{ {
muted = qgcApp()->runningUnitTests();
worker->moveToThread(thread); worker->moveToThread(thread);
connect(this, SIGNAL(textToSpeak(QString,int)), worker, SLOT(say(QString,int))); connect(this, SIGNAL(textToSpeak(QString,int)), worker, SLOT(say(QString,int)));
connect(this, SIGNAL(beepOnce()), worker, SLOT(beep())); connect(this, SIGNAL(beepOnce()), worker, SLOT(beep()));
...@@ -72,9 +57,8 @@ GAudioOutput::GAudioOutput(QObject *parent) : QObject(parent), ...@@ -72,9 +57,8 @@ GAudioOutput::GAudioOutput(QObject *parent) : QObject(parent),
GAudioOutput::~GAudioOutput() GAudioOutput::~GAudioOutput()
{ {
thread->quit(); thread->quit();
while (thread->isRunning()) { thread->wait();
QGC::SLEEP::usleep(100);
}
delete worker; delete worker;
delete thread; delete thread;
} }
...@@ -82,19 +66,19 @@ GAudioOutput::~GAudioOutput() ...@@ -82,19 +66,19 @@ GAudioOutput::~GAudioOutput()
void GAudioOutput::mute(bool mute) void GAudioOutput::mute(bool mute)
{ {
// XXX handle muting muted = mute;
Q_UNUSED(mute);
} }
bool GAudioOutput::isMuted() bool GAudioOutput::isMuted()
{ {
// XXX return right stuff return muted;
return false;
} }
bool GAudioOutput::say(QString text, int severity) bool GAudioOutput::say(QString text, int severity)
{ {
emit textToSpeak(text, severity); if (!muted) {
emit textToSpeak(text, severity);
}
return true; return true;
} }
...@@ -103,7 +87,9 @@ bool GAudioOutput::say(QString text, int severity) ...@@ -103,7 +87,9 @@ bool GAudioOutput::say(QString text, int severity)
*/ */
bool GAudioOutput::alert(QString text) bool GAudioOutput::alert(QString text)
{ {
emit textToSpeak(text, 1); if (!muted) {
emit textToSpeak(text, 1);
}
return true; return true;
} }
...@@ -172,5 +158,7 @@ bool GAudioOutput::stopEmergency() ...@@ -172,5 +158,7 @@ bool GAudioOutput::stopEmergency()
void GAudioOutput::beep() void GAudioOutput::beep()
{ {
emit beepOnce(); if (!muted) {
emit beepOnce();
}
} }
...@@ -37,19 +37,21 @@ This file is part of the PIXHAWK project ...@@ -37,19 +37,21 @@ This file is part of the PIXHAWK project
#include <QThread> #include <QThread>
#include <QStringList> #include <QStringList>
#include <QGCAudioWorker.h> #include "QGCAudioWorker.h"
#include "QGCSingleton.h"
/** /**
* @brief Audio Output (speech synthesizer and "beep" output) * @brief Audio Output (speech synthesizer and "beep" output)
* This class follows the singleton design pattern * This class follows the singleton design pattern
* @see http://en.wikipedia.org/wiki/Singleton_pattern * @see http://en.wikipedia.org/wiki/Singleton_pattern
*/ */
class GAudioOutput : public QObject class GAudioOutput : public QGCSingleton
{ {
Q_OBJECT Q_OBJECT
DECLARE_QGC_SINGLETON(GAudioOutput, GAudioOutput)
public: public:
/** @brief Get the singleton instance */
static GAudioOutput *instance();
/** @brief List available voices */ /** @brief List available voices */
QStringList listVoices(void); QStringList listVoices(void);
enum enum
...@@ -104,6 +106,7 @@ protected: ...@@ -104,6 +106,7 @@ protected:
bool muted; bool muted;
QThread* thread; QThread* thread;
QGCAudioWorker* worker; QGCAudioWorker* worker;
private: private:
GAudioOutput(QObject *parent = NULL); GAudioOutput(QObject *parent = NULL);
~GAudioOutput(); ~GAudioOutput();
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <QFile> #include <QFile>
#include <QFlags> #include <QFlags>
#include <QThread>
#include <QSplashScreen> #include <QSplashScreen>
#include <QPixmap> #include <QPixmap>
#include <QDesktopWidget> #include <QDesktopWidget>
...@@ -182,8 +181,6 @@ void QGCApplication::_initCommon(void) ...@@ -182,8 +181,6 @@ void QGCApplication::_initCommon(void)
{ {
QSettings settings; QSettings settings;
_createSingletons();
// Show user an upgrade message if the settings version has been bumped up // Show user an upgrade message if the settings version has been bumped up
bool settingsUpgraded = false; bool settingsUpgraded = false;
if (settings.contains(_settingsVersionKey)) { if (settings.contains(_settingsVersionKey)) {
...@@ -244,6 +241,8 @@ bool QGCApplication::_initForNormalAppBoot(void) ...@@ -244,6 +241,8 @@ bool QGCApplication::_initForNormalAppBoot(void)
{ {
QSettings settings; QSettings settings;
_createSingletons();
enum MainWindow::CUSTOM_MODE mode = (enum MainWindow::CUSTOM_MODE) settings.value("QGC_CUSTOM_MODE", (int)MainWindow::CUSTOM_MODE_PX4).toInt(); enum MainWindow::CUSTOM_MODE mode = (enum MainWindow::CUSTOM_MODE) settings.value("QGC_CUSTOM_MODE", (int)MainWindow::CUSTOM_MODE_PX4).toInt();
// Show splash screen // Show splash screen
...@@ -425,6 +424,11 @@ QGCApplication* qgcApp(void) ...@@ -425,6 +424,11 @@ QGCApplication* qgcApp(void)
void QGCApplication::_createSingletons(void) void QGCApplication::_createSingletons(void)
{ {
// The order here is important since the singletons reference each other // The order here is important since the singletons reference each other
GAudioOutput* audio = GAudioOutput::_createSingleton();
Q_UNUSED(audio);
Q_ASSERT(audio);
LinkManager* linkManager = LinkManager::_createSingleton(); LinkManager* linkManager = LinkManager::_createSingleton();
Q_UNUSED(linkManager); Q_UNUSED(linkManager);
Q_ASSERT(linkManager); Q_ASSERT(linkManager);
...@@ -443,14 +447,34 @@ void QGCApplication::_createSingletons(void) ...@@ -443,14 +447,34 @@ void QGCApplication::_createSingletons(void)
FactSystem* factSystem = FactSystem::_createSingleton(); FactSystem* factSystem = FactSystem::_createSingleton();
Q_UNUSED(factSystem); Q_UNUSED(factSystem);
Q_ASSERT(factSystem); Q_ASSERT(factSystem);
// Needs everything!
MAVLinkProtocol* mavlink = MAVLinkProtocol::_createSingleton();
Q_UNUSED(mavlink);
Q_ASSERT(mavlink);
} }
void QGCApplication::_destroySingletons(void) void QGCApplication::_destroySingletons(void)
{ {
if (LinkManager::instance(true /* nullOk */)) {
// This will close/delete all connections
LinkManager::instance()->_shutdown();
}
if (UASManager::instance(true /* nullOk */)) {
// This will delete all uas from the system
UASManager::instance()->_shutdown();
}
// Let the signals flow through the main thread
processEvents(QEventLoop::ExcludeUserInputEvents);
// Take down singletons in reverse order of creation // Take down singletons in reverse order of creation
MAVLinkProtocol::_deleteSingleton();
FactSystem::_deleteSingleton(); FactSystem::_deleteSingleton();
AutoPilotPluginManager::_deleteSingleton(); AutoPilotPluginManager::_deleteSingleton();
UASManager::_deleteSingleton(); UASManager::_deleteSingleton();
LinkManager::_deleteSingleton(); LinkManager::_deleteSingleton();
GAudioOutput::_deleteSingleton();
} }
...@@ -43,9 +43,7 @@ QGCQuickWidget::QGCQuickWidget(QWidget* parent) : ...@@ -43,9 +43,7 @@ QGCQuickWidget::QGCQuickWidget(QWidget* parent) :
UASInterface* uas = uasMgr->getActiveUAS(); UASInterface* uas = uasMgr->getActiveUAS();
Q_ASSERT(uas); Q_ASSERT(uas);
AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(uas->getAutopilotType())->addFactsToQmlContext(rootContext(), uas);
rootContext()->engine()->addImportPath("qrc:/qml"); rootContext()->engine()->addImportPath("qrc:/qml");
setSource(QUrl::fromLocalFile("/Users/Don/repos/qgroundcontrol/test.qml")); AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(uas)->addFactsToQmlContext(rootContext());
} }
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
/// For example DECLARE_QGC_SINGLETON(UASManager, UASManagerInterface) /// For example DECLARE_QGC_SINGLETON(UASManager, UASManagerInterface)
#define DECLARE_QGC_SINGLETON(className, interfaceName) \ #define DECLARE_QGC_SINGLETON(className, interfaceName) \
public: \ public: \
static interfaceName* instance(void); \ static interfaceName* instance(bool nullOk = false); \
static void setMockInstance(interfaceName* mock); \ static void setMockInstance(interfaceName* mock); \
private: \ private: \
static interfaceName* _createSingleton(void); \ static interfaceName* _createSingleton(void); \
...@@ -75,9 +75,11 @@ ...@@ -75,9 +75,11 @@
} \ } \
} \ } \
\ \
interfaceName* className::instance(void) \ interfaceName* className::instance(bool nullOk) \
{ \ { \
Q_ASSERT_X(_instance, "QGCSingleton", "If you hit this, then you have run into a startup or shutdown sequence bug."); \ if (!nullOk) { \
Q_ASSERT_X(_instance, "QGCSingleton", "If you hit this, then you have run into a startup or shutdown sequence bug."); \
} \
return _instance; \ return _instance; \
} \ } \
\ \
......
...@@ -208,7 +208,7 @@ void SetupView::_parametersReady(void) ...@@ -208,7 +208,7 @@ void SetupView::_parametersReady(void)
_ui->summaryButton->setVisible(true); _ui->summaryButton->setVisible(true);
_components = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(_uasCurrent->getAutopilotType())->getVehicleComponents(_uasCurrent); _components = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(_uasCurrent)->getVehicleComponents();
foreach(VehicleComponent* component, _components) { foreach(VehicleComponent* component, _components) {
VehicleComponentButton* button = new VehicleComponentButton(component, _ui->navBarWidget); VehicleComponentButton* button = new VehicleComponentButton(component, _ui->navBarWidget);
......
...@@ -76,21 +76,17 @@ void QGCAudioWorker::init() ...@@ -76,21 +76,17 @@ void QGCAudioWorker::init()
} }
#endif #endif
// Prepare regular emergency signal, will be fired off on calling startEmergency()
emergencyTimer = new QTimer();
connect(emergencyTimer, SIGNAL(timeout()), this, SLOT(beep()));
} }
QGCAudioWorker::~QGCAudioWorker() QGCAudioWorker::~QGCAudioWorker()
{ {
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED #if defined _MSC_VER && defined QGC_SPEECH_ENABLED
pVoice->Release(); if (pVoice) {
pVoice = NULL; pVoice->Release();
pVoice = NULL;
}
::CoUninitialize(); ::CoUninitialize();
#endif #endif
delete emergencyTimer;
} }
void QGCAudioWorker::say(QString text, int severity) void QGCAudioWorker::say(QString text, int severity)
......
...@@ -47,27 +47,14 @@ IMPLEMENT_QGC_SINGLETON(LinkManager, LinkManager) ...@@ -47,27 +47,14 @@ IMPLEMENT_QGC_SINGLETON(LinkManager, LinkManager)
**/ **/
LinkManager::LinkManager(QObject* parent) : LinkManager::LinkManager(QObject* parent) :
QGCSingleton(parent), QGCSingleton(parent),
_connectionsSuspended(false), _connectionsSuspended(false)
_mavlink(NULL)
{ {
_mavlink = new MAVLinkProtocol(this);
Q_CHECK_PTR(_mavlink);
} }
LinkManager::~LinkManager() LinkManager::~LinkManager()
{ {
disconnectAll(); Q_ASSERT_X(_links.count() == 0, "LinkManager", "LinkManager::_shutdown should have been called previously");
foreach (LinkInterface* link, _links) {
Q_ASSERT(link);
deleteLink(link);
}
_links.clear();
// Clear out the queue so disconnects make it all the way through threads
qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
delete _mavlink;
} }
void LinkManager::addLink(LinkInterface* link) void LinkManager::addLink(LinkInterface* link)
...@@ -92,10 +79,11 @@ void LinkManager::addLink(LinkInterface* link) ...@@ -92,10 +79,11 @@ void LinkManager::addLink(LinkInterface* link)
connect(link, SIGNAL(communicationError(QString,QString)), MainWindow::instance(), SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection); connect(link, SIGNAL(communicationError(QString,QString)), MainWindow::instance(), SLOT(showCriticalMessage(QString,QString)), Qt::QueuedConnection);
} }
connect(link, &LinkInterface::bytesReceived, _mavlink, &MAVLinkProtocol::receiveBytes); MAVLinkProtocol* mavlink = MAVLinkProtocol::instance();
connect(link, &LinkInterface::connected, _mavlink, &MAVLinkProtocol::linkConnected); connect(link, &LinkInterface::bytesReceived, mavlink, &MAVLinkProtocol::receiveBytes);
connect(link, &LinkInterface::disconnected, _mavlink, &MAVLinkProtocol::linkDisconnected); connect(link, &LinkInterface::connected, mavlink, &MAVLinkProtocol::linkConnected);
_mavlink->resetMetadataForLink(link); connect(link, &LinkInterface::disconnected, mavlink, &MAVLinkProtocol::linkDisconnected);
mavlink->resetMetadataForLink(link);
} }
bool LinkManager::connectAll() bool LinkManager::connectAll()
...@@ -221,3 +209,12 @@ void LinkManager::setConnectionsSuspended(QString reason) ...@@ -221,3 +209,12 @@ void LinkManager::setConnectionsSuspended(QString reason)
_connectionsSuspendedReason = reason; _connectionsSuspendedReason = reason;
Q_ASSERT(!reason.isEmpty()); Q_ASSERT(!reason.isEmpty());
} }
void LinkManager::_shutdown(void)
{
QList<LinkInterface*> links = _links;
foreach(LinkInterface* link, links) {
disconnectLink(link);
deleteLink(link);
}
}
...@@ -27,7 +27,6 @@ This file is part of the PIXHAWK project ...@@ -27,7 +27,6 @@ This file is part of the PIXHAWK project
#ifndef _LINKMANAGER_H_ #ifndef _LINKMANAGER_H_
#define _LINKMANAGER_H_ #define _LINKMANAGER_H_
#include <QThread>
#include <QList> #include <QList>
#include <QMultiMap> #include <QMultiMap>
#include <QMutex> #include <QMutex>
...@@ -89,9 +88,6 @@ public: ...@@ -89,9 +88,6 @@ public:
/// Disconnect the specified link /// Disconnect the specified link
bool disconnectLink(LinkInterface* link); bool disconnectLink(LinkInterface* link);
/// Returns the one mavlink protocol object in the system
MAVLinkProtocol* mavlink(void) { return _mavlink; }
signals: signals:
void newLink(LinkInterface* link); void newLink(LinkInterface* link);
void linkDeleted(LinkInterface* link); void linkDeleted(LinkInterface* link);
...@@ -99,8 +95,9 @@ signals: ...@@ -99,8 +95,9 @@ signals:
private: private:
/// All access to LinkManager is through LinkManager::instance /// All access to LinkManager is through LinkManager::instance
LinkManager(QObject* parent = NULL); LinkManager(QObject* parent = NULL);
~LinkManager(); ~LinkManager();
virtual void _shutdown(void);
bool _connectionsSuspendedMsg(void); bool _connectionsSuspendedMsg(void);
...@@ -109,8 +106,6 @@ private: ...@@ -109,8 +106,6 @@ private:
bool _connectionsSuspended; ///< true: all new connections should not be allowed bool _connectionsSuspended; ///< true: all new connections should not be allowed
QString _connectionsSuspendedReason; ///< User visible reason for suspension QString _connectionsSuspendedReason; ///< User visible reason for suspension
MAVLinkProtocol* _mavlink; ///< The one and only mavlink protocol
}; };
#endif #endif
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include "QGCApplication.h" #include "QGCApplication.h"
Q_DECLARE_METATYPE(mavlink_message_t) Q_DECLARE_METATYPE(mavlink_message_t)
IMPLEMENT_QGC_SINGLETON(MAVLinkProtocol, MAVLinkProtocol)
Q_LOGGING_CATEGORY(MAVLinkProtocolLog, "MAVLinkProtocolLog")
const char* MAVLinkProtocol::_tempLogFileTemplate = "FlightDataXXXXXX"; ///< Template for temporary log file const char* MAVLinkProtocol::_tempLogFileTemplate = "FlightDataXXXXXX"; ///< Template for temporary log file
const char* MAVLinkProtocol::_logFileExtension = "mavlink"; ///< Extension for log files const char* MAVLinkProtocol::_logFileExtension = "mavlink"; ///< Extension for log files
...@@ -39,10 +41,8 @@ const char* MAVLinkProtocol::_logFileExtension = "mavlink"; ///< Ext ...@@ -39,10 +41,8 @@ const char* MAVLinkProtocol::_logFileExtension = "mavlink"; ///< Ext
* The default constructor will create a new MAVLink object sending heartbeats at * The default constructor will create a new MAVLink object sending heartbeats at
* the MAVLINK_HEARTBEAT_DEFAULT_RATE to all connected links. * the MAVLINK_HEARTBEAT_DEFAULT_RATE to all connected links.
*/ */
MAVLinkProtocol::MAVLinkProtocol(LinkManager* linkMgr) : MAVLinkProtocol::MAVLinkProtocol(QObject* parent) :
heartbeatTimer(NULL), QGCSingleton(parent),
heartbeatRate(MAVLINK_HEARTBEAT_DEFAULT_RATE),
m_heartbeatsEnabled(true),
m_multiplexingEnabled(false), m_multiplexingEnabled(false),
m_authEnabled(false), m_authEnabled(false),
m_enable_version_check(true), m_enable_version_check(true),
...@@ -53,19 +53,19 @@ MAVLinkProtocol::MAVLinkProtocol(LinkManager* linkMgr) : ...@@ -53,19 +53,19 @@ MAVLinkProtocol::MAVLinkProtocol(LinkManager* linkMgr) :
m_actionRetransmissionTimeout(100), m_actionRetransmissionTimeout(100),
versionMismatchIgnore(false), versionMismatchIgnore(false),
systemId(QGC::defaultSystemId), systemId(QGC::defaultSystemId),
_should_exit(false),
_logSuspendError(false), _logSuspendError(false),
_logSuspendReplay(false), _logSuspendReplay(false),
_tempLogFile(QString("%2.%3").arg(_tempLogFileTemplate).arg(_logFileExtension)), _tempLogFile(QString("%2.%3").arg(_tempLogFileTemplate).arg(_logFileExtension)),
_protocolStatusMessageConnected(false), _protocolStatusMessageConnected(false),
_saveTempFlightDataLogConnected(false), _saveTempFlightDataLogConnected(false),
_linkMgr(linkMgr) _linkMgr(LinkManager::instance()),
_heartbeatRate(MAVLINK_HEARTBEAT_DEFAULT_RATE),
_heartbeatsEnabled(true)
{ {
qRegisterMetaType<mavlink_message_t>("mavlink_message_t"); qRegisterMetaType<mavlink_message_t>("mavlink_message_t");
m_authKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; m_authKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
loadSettings(); loadSettings();
moveToThread(this);
// All the *Counter variables are not initialized here, as they should be initialized // 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(). // on a per-link basis before those links are used. @see resetMetadataForLink().
...@@ -78,18 +78,27 @@ MAVLinkProtocol::MAVLinkProtocol(LinkManager* linkMgr) : ...@@ -78,18 +78,27 @@ MAVLinkProtocol::MAVLinkProtocol(LinkManager* linkMgr) :
lastIndex[i][j] = -1; lastIndex[i][j] = -1;
} }
} }
start(QThread::HighPriority); // Start heartbeat timer, emitting a heartbeat at the configured rate
connect(&_heartbeatTimer, &QTimer::timeout, this, &MAVLinkProtocol::sendHeartbeat);
_heartbeatTimer.start(1000/_heartbeatRate);
emit versionCheckChanged(m_enable_version_check); emit versionCheckChanged(m_enable_version_check);
} }
MAVLinkProtocol::~MAVLinkProtocol()
{
storeSettings();
_closeLogFile();
}
void MAVLinkProtocol::loadSettings() void MAVLinkProtocol::loadSettings()
{ {
// Load defaults from settings // Load defaults from settings
QSettings settings; QSettings settings;
settings.beginGroup("QGC_MAVLINK_PROTOCOL"); settings.beginGroup("QGC_MAVLINK_PROTOCOL");
enableHeartbeats(settings.value("HEARTBEATS_ENABLED", m_heartbeatsEnabled).toBool()); enableHeartbeats(settings.value("HEARTBEATS_ENABLED", _heartbeatsEnabled).toBool());
enableVersionCheck(settings.value("VERSION_CHECK_ENABLED", m_enable_version_check).toBool()); enableVersionCheck(settings.value("VERSION_CHECK_ENABLED", m_enable_version_check).toBool());
enableMultiplexing(settings.value("MULTIPLEXING_ENABLED", m_multiplexingEnabled).toBool()); enableMultiplexing(settings.value("MULTIPLEXING_ENABLED", m_multiplexingEnabled).toBool());
...@@ -119,7 +128,7 @@ void MAVLinkProtocol::storeSettings() ...@@ -119,7 +128,7 @@ void MAVLinkProtocol::storeSettings()
// Store settings // Store settings
QSettings settings; QSettings settings;
settings.beginGroup("QGC_MAVLINK_PROTOCOL"); settings.beginGroup("QGC_MAVLINK_PROTOCOL");
settings.setValue("HEARTBEATS_ENABLED", m_heartbeatsEnabled); settings.setValue("HEARTBEATS_ENABLED", _heartbeatsEnabled);
settings.setValue("VERSION_CHECK_ENABLED", m_enable_version_check); settings.setValue("VERSION_CHECK_ENABLED", m_enable_version_check);
settings.setValue("MULTIPLEXING_ENABLED", m_multiplexingEnabled); settings.setValue("MULTIPLEXING_ENABLED", m_multiplexingEnabled);
settings.setValue("GCS_SYSTEM_ID", systemId); settings.setValue("GCS_SYSTEM_ID", systemId);
...@@ -132,43 +141,6 @@ void MAVLinkProtocol::storeSettings() ...@@ -132,43 +141,6 @@ void MAVLinkProtocol::storeSettings()
settings.endGroup(); settings.endGroup();
} }
MAVLinkProtocol::~MAVLinkProtocol()
{
storeSettings();
_closeLogFile();
// Tell the thread to exit
_should_exit = true;
// Wait for it to exit
wait();
}
/**
* @brief Runs the thread
*
**/
void MAVLinkProtocol::run()
{
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()) {
delete heartbeatTimer;
qDebug() << "MAVLINK WORKER DONE!";
return;
}
QCoreApplication::processEvents();
QGC::SLEEP::msleep(2);
}
}
void MAVLinkProtocol::resetMetadataForLink(const LinkInterface *link) void MAVLinkProtocol::resetMetadataForLink(const LinkInterface *link)
{ {
int linkId = link->getId(); int linkId = link->getId();
...@@ -197,6 +169,7 @@ void MAVLinkProtocol::linkDisconnected(void) ...@@ -197,6 +169,7 @@ void MAVLinkProtocol::linkDisconnected(void)
void MAVLinkProtocol::_linkStatusChanged(LinkInterface* link, bool connected) void MAVLinkProtocol::_linkStatusChanged(LinkInterface* link, bool connected)
{ {
qCDebug(MAVLinkProtocolLog) << "_linkStatusChanged" << QString("%1").arg((long)link, 0, 16) << connected;
Q_ASSERT(link); Q_ASSERT(link);
if (connected) { if (connected) {
...@@ -559,7 +532,7 @@ void MAVLinkProtocol::sendMessage(LinkInterface* link, mavlink_message_t message ...@@ -559,7 +532,7 @@ void MAVLinkProtocol::sendMessage(LinkInterface* link, mavlink_message_t message
*/ */
void MAVLinkProtocol::sendHeartbeat() void MAVLinkProtocol::sendHeartbeat()
{ {
if (m_heartbeatsEnabled) if (_heartbeatsEnabled)
{ {
mavlink_message_t beat; mavlink_message_t beat;
mavlink_msg_heartbeat_pack(getSystemId(), getComponentId(),&beat, MAV_TYPE_GCS, MAV_AUTOPILOT_INVALID, MAV_MODE_MANUAL_ARMED, 0, MAV_STATE_ACTIVE); mavlink_msg_heartbeat_pack(getSystemId(), getComponentId(),&beat, MAV_TYPE_GCS, MAV_AUTOPILOT_INVALID, MAV_MODE_MANUAL_ARMED, 0, MAV_STATE_ACTIVE);
...@@ -576,10 +549,10 @@ void MAVLinkProtocol::sendHeartbeat() ...@@ -576,10 +549,10 @@ void MAVLinkProtocol::sendHeartbeat()
} }
} }
/** @param enabled true to enable heartbeats emission at heartbeatRate, false to disable */ /** @param enabled true to enable heartbeats emission at _heartbeatRate, false to disable */
void MAVLinkProtocol::enableHeartbeats(bool enabled) void MAVLinkProtocol::enableHeartbeats(bool enabled)
{ {
m_heartbeatsEnabled = enabled; _heartbeatsEnabled = enabled;
emit heartbeatChanged(enabled); emit heartbeatChanged(enabled);
} }
...@@ -655,14 +628,14 @@ void MAVLinkProtocol::enableVersionCheck(bool enabled) ...@@ -655,14 +628,14 @@ void MAVLinkProtocol::enableVersionCheck(bool enabled)
*/ */
void MAVLinkProtocol::setHeartbeatRate(int rate) void MAVLinkProtocol::setHeartbeatRate(int rate)
{ {
heartbeatRate = rate; _heartbeatRate = rate;
heartbeatTimer->setInterval(1000/heartbeatRate); _heartbeatTimer.setInterval(1000/_heartbeatRate);
} }
/** @return heartbeat rate in Hertz */ /** @return heartbeat rate in Hertz */
int MAVLinkProtocol::getHeartbeatRate() int MAVLinkProtocol::getHeartbeatRate()
{ {
return heartbeatRate; return _heartbeatRate;
} }
/// @brief Closes the log file if it is open /// @brief Closes the log file if it is open
...@@ -705,7 +678,8 @@ void MAVLinkProtocol::_startLogging(void) ...@@ -705,7 +678,8 @@ void MAVLinkProtocol::_startLogging(void)
void MAVLinkProtocol::_stopLogging(void) void MAVLinkProtocol::_stopLogging(void)
{ {
if (_closeLogFile()) { if (_closeLogFile()) {
if (qgcApp()->promptFlightDataSave()) { // If the signals are not connected it means we are running a unit test. In that case just delete log files
if (_protocolStatusMessageConnected && _saveTempFlightDataLogConnected && qgcApp()->promptFlightDataSave()) {
emit saveTempFlightDataLog(_tempLogFile.fileName()); emit saveTempFlightDataLog(_tempLogFile.fileName());
} else { } else {
QFile::remove(_tempLogFile.fileName()); QFile::remove(_tempLogFile.fileName());
...@@ -761,11 +735,6 @@ void MAVLinkProtocol::_checkLostLogFiles(void) ...@@ -761,11 +735,6 @@ void MAVLinkProtocol::_checkLostLogFiles(void)
void MAVLinkProtocol::suspendLogForReplay(bool suspend) void MAVLinkProtocol::suspendLogForReplay(bool suspend)
{ {
// This must come through a slot so that we handle this on the right thread. This will
// also cause the signal to be queued behind any bytesReady signals which must be flushed
// out of the queue before we change suspend state.
Q_ASSERT(QThread::currentThread() == this);
_logSuspendReplay = suspend; _logSuspendReplay = suspend;
} }
......
...@@ -37,14 +37,18 @@ This file is part of the QGROUNDCONTROL project ...@@ -37,14 +37,18 @@ This file is part of the QGROUNDCONTROL project
#include <QFile> #include <QFile>
#include <QMap> #include <QMap>
#include <QByteArray> #include <QByteArray>
#include <QLoggingCategory>
#include "LinkInterface.h" #include "LinkInterface.h"
#include "QGCMAVLink.h" #include "QGCMAVLink.h"
#include "QGC.h" #include "QGC.h"
#include "QGCTemporaryFile.h" #include "QGCTemporaryFile.h"
#include "QGCSingleton.h"
class LinkManager; class LinkManager;
Q_DECLARE_LOGGING_CATEGORY(MAVLinkProtocolLog)
/** /**
* @brief MAVLink micro air vehicle protocol reference implementation. * @brief MAVLink micro air vehicle protocol reference implementation.
* *
...@@ -52,14 +56,13 @@ class LinkManager; ...@@ -52,14 +56,13 @@ class LinkManager;
* for more information, please see the official website. * for more information, please see the official website.
* @ref http://pixhawk.ethz.ch/software/mavlink/ * @ref http://pixhawk.ethz.ch/software/mavlink/
**/ **/
class MAVLinkProtocol : public QThread class MAVLinkProtocol : public QGCSingleton
{ {
Q_OBJECT Q_OBJECT
public: DECLARE_QGC_SINGLETON(MAVLinkProtocol, MAVLinkProtocol)
MAVLinkProtocol(LinkManager *linkMgr);
~MAVLinkProtocol();
public:
/** @brief Get the human-friendly name of this protocol */ /** @brief Get the human-friendly name of this protocol */
QString getName(); QString getName();
/** @brief Get the system id of this application */ /** @brief Get the system id of this application */
...@@ -70,7 +73,7 @@ public: ...@@ -70,7 +73,7 @@ public:
int getHeartbeatRate(); int getHeartbeatRate();
/** @brief Get heartbeat state */ /** @brief Get heartbeat state */
bool heartbeatsEnabled() const { bool heartbeatsEnabled() const {
return m_heartbeatsEnabled; return _heartbeatsEnabled;
} }
/** @brief Get protocol version check state */ /** @brief Get protocol version check state */
...@@ -139,7 +142,8 @@ public: ...@@ -139,7 +142,8 @@ public:
*/ */
virtual void resetMetadataForLink(const LinkInterface *link); virtual void resetMetadataForLink(const LinkInterface *link);
void run(); /// Suspend/Restart logging during replay.
void suspendLogForReplay(bool suspend);
public slots: public slots:
/** @brief Receive bytes from a communication interface */ /** @brief Receive bytes from a communication interface */
...@@ -199,11 +203,6 @@ public slots: ...@@ -199,11 +203,6 @@ public slots:
/** @brief Store protocol settings */ /** @brief Store protocol settings */
void storeSettings(); void storeSettings();
/// @brief Suspend/Restart logging during replay. This must be emitted as a signal
/// and not called directly in order to synchronize with the bytesReady signal
/// which may be ahead of it in the signal queue.
void suspendLogForReplay(bool suspend);
/// @brief Deletes any log files which are in the temp directory /// @brief Deletes any log files which are in the temp directory
static void deleteTempLogFiles(void); static void deleteTempLogFiles(void);
...@@ -211,9 +210,6 @@ protected: ...@@ -211,9 +210,6 @@ protected:
// Override from QObject // Override from QObject
virtual void connectNotify(const QMetaMethod& signal); virtual void connectNotify(const QMetaMethod& signal);
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 bool m_multiplexingEnabled; ///< Enable/disable packet multiplexing
bool m_authEnabled; ///< Enable authentication token broadcast bool m_authEnabled; ///< Enable authentication token broadcast
QString m_authKey; ///< Authentication key QString m_authKey; ///< Authentication key
...@@ -232,7 +228,6 @@ protected: ...@@ -232,7 +228,6 @@ protected:
int currLossCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< Lost messages during this sample time window. Used for calculating loss %. int currLossCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< Lost messages during this sample time window. Used for calculating loss %.
bool versionMismatchIgnore; bool versionMismatchIgnore;
int systemId; int systemId;
bool _should_exit;
signals: signals:
/** @brief Message received and directly copied via signal */ /** @brief Message received and directly copied via signal */
...@@ -282,6 +277,9 @@ signals: ...@@ -282,6 +277,9 @@ signals:
void saveTempFlightDataLog(QString tempLogfile); void saveTempFlightDataLog(QString tempLogfile);
private: private:
MAVLinkProtocol(QObject* parent = NULL);
~MAVLinkProtocol();
void _linkStatusChanged(LinkInterface* link, bool connected); void _linkStatusChanged(LinkInterface* link, bool connected);
bool _closeLogFile(void); bool _closeLogFile(void);
void _startLogging(void); void _startLogging(void);
...@@ -301,6 +299,10 @@ private: ...@@ -301,6 +299,10 @@ private:
bool _saveTempFlightDataLogConnected; ///< true: saveTempFlightDataLog signal has been connected bool _saveTempFlightDataLogConnected; ///< true: saveTempFlightDataLog signal has been connected
LinkManager* _linkMgr; LinkManager* _linkMgr;
QTimer _heartbeatTimer; ///< Timer to emit heartbeats
int _heartbeatRate; ///< Heartbeat rate, controls the timer interval
bool _heartbeatsEnabled; ///< Enabled/disable heartbeat emission
}; };
#endif // MAVLINKPROTOCOL_H_ #endif // MAVLINKPROTOCOL_H_
...@@ -238,8 +238,6 @@ void SerialLink::run() ...@@ -238,8 +238,6 @@ void SerialLink::run()
m_port->close(); m_port->close();
delete m_port; delete m_port;
m_port = NULL; m_port = NULL;
emit disconnected();
} }
QGC::SLEEP::msleep(500); QGC::SLEEP::msleep(500);
...@@ -337,8 +335,6 @@ void SerialLink::run() ...@@ -337,8 +335,6 @@ void SerialLink::run()
m_port->close(); m_port->close();
delete m_port; delete m_port;
m_port = NULL; m_port = NULL;
emit disconnected();
} }
} }
...@@ -474,7 +470,9 @@ bool SerialLink::hardwareConnect(QString &type) ...@@ -474,7 +470,9 @@ bool SerialLink::hardwareConnect(QString &type)
return false; // couldn't create serial port. return false; // couldn't create serial port.
} }
QObject::connect(m_port,SIGNAL(aboutToClose()),this,SIGNAL(disconnected())); // We need to catch this signal and then emit disconnected. You can't connect
// signal to signal otherwise disonnected will have the wrong QObject::Sender
QObject::connect(m_port, SIGNAL(aboutToClose()), this, SLOT(_rerouteDisconnected()));
QObject::connect(m_port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(linkError(QSerialPort::SerialPortError))); QObject::connect(m_port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(linkError(QSerialPort::SerialPortError)));
checkIfCDC(); checkIfCDC();
...@@ -899,3 +897,8 @@ bool SerialLink::setStopBitsType(int stopBits) ...@@ -899,3 +897,8 @@ bool SerialLink::setStopBitsType(int stopBits)
} }
return accepted; return accepted;
} }
void SerialLink::_rerouteDisconnected(void)
{
emit disconnected();
}
...@@ -162,6 +162,9 @@ protected: ...@@ -162,6 +162,9 @@ protected:
QMutex m_writeMutex; // Mutex for accessing the m_transmitBuffer. QMutex m_writeMutex; // Mutex for accessing the m_transmitBuffer.
QString type; QString type;
bool m_is_cdc; bool m_is_cdc;
private slots:
void _rerouteDisconnected(void);
private: private:
// From LinkInterface // From LinkInterface
......
...@@ -118,7 +118,7 @@ int main(int argc, char *argv[]) ...@@ -118,7 +118,7 @@ int main(int argc, char *argv[])
// Add additional command line option flags here // Add additional command line option flags here
}; };
ParseCmdLineOptions(argc, argv, rgCmdLineOptions, sizeof(rgCmdLineOptions)/sizeof(rgCmdLineOptions[0]), true); ParseCmdLineOptions(argc, argv, rgCmdLineOptions, sizeof(rgCmdLineOptions)/sizeof(rgCmdLineOptions[0]), false);
if (quietWindowsAsserts) { if (quietWindowsAsserts) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
...@@ -157,7 +157,7 @@ int main(int argc, char *argv[]) ...@@ -157,7 +157,7 @@ int main(int argc, char *argv[])
} }
// Run the test // Run the test
int failures = UnitTest::run(argc-1, argv, rgCmdLineOptions[0].optionArg); int failures = UnitTest::run(rgCmdLineOptions[0].optionArg);
if (failures == 0) { if (failures == 0) {
qDebug() << "ALL TESTS PASSED"; qDebug() << "ALL TESTS PASSED";
} else { } else {
......
...@@ -60,6 +60,8 @@ void LinkManagerTest::cleanup(void) ...@@ -60,6 +60,8 @@ void LinkManagerTest::cleanup(void)
Q_ASSERT(_linkMgr); Q_ASSERT(_linkMgr);
Q_ASSERT(_multiSpy); Q_ASSERT(_multiSpy);
_linkMgr->_shutdown();
delete _linkMgr; delete _linkMgr;
delete _multiSpy; delete _multiSpy;
......
This diff is collapsed.
...@@ -25,10 +25,13 @@ ...@@ -25,10 +25,13 @@
#define MOCKLINK_H #define MOCKLINK_H
#include <QMap> #include <QMap>
#include <QLoggingCategory>
#include "MockLinkMissionItemHandler.h" #include "MockLinkMissionItemHandler.h"
#include "LinkInterface.h" #include "LinkInterface.h"
#include "mavlink.h" #include "QGCMAVLink.h"
Q_DECLARE_LOGGING_CATEGORY(MockLinkLog)
/// @file /// @file
/// @brief Mock implementation of a Link. /// @brief Mock implementation of a Link.
...@@ -57,8 +60,6 @@ public: ...@@ -57,8 +60,6 @@ public:
bool disconnect(void); bool disconnect(void);
signals: signals:
void error(const QString& errorMsg);
/// @brief Used internally to move data to the thread. /// @brief Used internally to move data to the thread.
void _incomingBytes(const QByteArray bytes); void _incomingBytes(const QByteArray bytes);
...@@ -88,7 +89,6 @@ private: ...@@ -88,7 +89,6 @@ private:
void _handleIncomingNSHBytes(const char* bytes, int cBytes); void _handleIncomingNSHBytes(const char* bytes, int cBytes);
void _handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes); void _handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes);
void _loadParams(void); void _loadParams(void);
void _errorInvalidTargetSystem(int targetId);
void _emitMavlinkMessage(const mavlink_message_t& msg); void _emitMavlinkMessage(const mavlink_message_t& msg);
void _handleHeartBeat(const mavlink_message_t& msg); void _handleHeartBeat(const mavlink_message_t& msg);
void _handleSetMode(const mavlink_message_t& msg); void _handleSetMode(const mavlink_message_t& msg);
...@@ -98,7 +98,9 @@ private: ...@@ -98,7 +98,9 @@ private:
void _handleMissionRequestList(const mavlink_message_t& msg); void _handleMissionRequestList(const mavlink_message_t& msg);
void _handleMissionRequest(const mavlink_message_t& msg); void _handleMissionRequest(const mavlink_message_t& msg);
void _handleMissionItem(const mavlink_message_t& msg); void _handleMissionItem(const mavlink_message_t& msg);
float _floatUnionForParam(const QString& paramName);
void _setParamFloatUnionIntoMap(const QString& paramName, float paramFloat);
MockLinkMissionItemHandler* _missionItemHandler; MockLinkMissionItemHandler* _missionItemHandler;
int _linkId; int _linkId;
...@@ -111,9 +113,8 @@ private: ...@@ -111,9 +113,8 @@ private:
bool _inNSH; bool _inNSH;
bool _mavlinkStarted; bool _mavlinkStarted;
typedef QMap<QString, QVariant> ParamMap_t; QMap<QString, QVariant> _mapParamName2Value;
ParamMap_t _parameters; QMap<QString, MAV_PARAM_TYPE> _mapParamName2MavParamType;
uint16_t _cParameters;
typedef QMap<uint16_t, mavlink_mission_item_t> MissionList_t; typedef QMap<uint16_t, mavlink_mission_item_t> MissionList_t;
MissionList_t _missionItems; MissionList_t _missionItems;
......
...@@ -81,7 +81,7 @@ public: ...@@ -81,7 +81,7 @@ public:
virtual QString getUASName() const { Q_ASSERT(false); return _bogusString; }; virtual QString getUASName() const { Q_ASSERT(false); return _bogusString; };
virtual const QString& getShortState() const { Q_ASSERT(false); return _bogusString; }; virtual const QString& getShortState() const { Q_ASSERT(false); return _bogusString; };
virtual const QString& getShortMode() const { Q_ASSERT(false); return _bogusString; }; virtual const QString& getShortMode() const { Q_ASSERT(false); return _bogusString; };
static QString getShortModeTextFor(int id) { Q_UNUSED(id); Q_ASSERT(false); return _bogusStaticString; }; virtual QString getShortModeTextFor(uint8_t base_mode, uint32_t custom_mode) const { Q_UNUSED(base_mode); Q_UNUSED(custom_mode); Q_ASSERT(false); return _bogusStaticString; };
virtual quint64 getUptime() const { Q_ASSERT(false); return 0; }; virtual quint64 getUptime() const { Q_ASSERT(false); return 0; };
virtual int getCommunicationStatus() const { Q_ASSERT(false); return 0; }; virtual int getCommunicationStatus() const { Q_ASSERT(false); return 0; };
virtual double getLocalX() const { Q_ASSERT(false); return std::numeric_limits<double>::quiet_NaN(); }; virtual double getLocalX() const { Q_ASSERT(false); return std::numeric_limits<double>::quiet_NaN(); };
...@@ -100,7 +100,7 @@ public: ...@@ -100,7 +100,7 @@ public:
virtual bool isArmed() const { Q_ASSERT(false); return false; }; virtual bool isArmed() const { Q_ASSERT(false); return false; };
virtual int getAirframe() const { Q_ASSERT(false); return 0; }; virtual int getAirframe() const { Q_ASSERT(false); return 0; };
virtual UASWaypointManager* getWaypointManager(void) { Q_ASSERT(false); return NULL; }; virtual UASWaypointManager* getWaypointManager(void) { Q_ASSERT(false); return NULL; };
virtual QList<LinkInterface*>* getLinks() { Q_ASSERT(false); return NULL; }; virtual QList<LinkInterface*> getLinks() { Q_ASSERT(false); return QList<LinkInterface*>(); };
virtual bool systemCanReverse() const { Q_ASSERT(false); return false; }; virtual bool systemCanReverse() const { Q_ASSERT(false); return false; };
virtual QString getSystemTypeName() { Q_ASSERT(false); return _bogusString; }; virtual QString getSystemTypeName() { Q_ASSERT(false); return _bogusString; };
virtual int getAutopilotType() { return MAV_AUTOPILOT_PX4; }; virtual int getAutopilotType() { return MAV_AUTOPILOT_PX4; };
......
...@@ -106,6 +106,7 @@ public slots: ...@@ -106,6 +106,7 @@ public slots:
{ Q_ASSERT(false); Q_UNUSED(uav); Q_UNUSED(lat); Q_UNUSED(lon); Q_UNUSED(alt); } { Q_ASSERT(false); Q_UNUSED(uav); Q_UNUSED(lat); Q_UNUSED(lon); Q_UNUSED(alt); }
virtual void loadSettings() { Q_ASSERT(false); } virtual void loadSettings() { Q_ASSERT(false); }
virtual void storeSettings() { Q_ASSERT(false); } virtual void storeSettings() { Q_ASSERT(false); }
virtual void _shutdown(void) { Q_ASSERT(false); }
private: private:
MockUAS* _mockUAS; MockUAS* _mockUAS;
......
#include "UASUnitTest.h" #include "UASUnitTest.h"
#include <stdio.h> #include <stdio.h>
#include <QObject> #include <QObject>
#include <QThread>
UT_REGISTER_TEST(UASUnitTest) UT_REGISTER_TEST(UASUnitTest)
...@@ -14,7 +13,7 @@ void UASUnitTest::init() ...@@ -14,7 +13,7 @@ void UASUnitTest::init()
UnitTest::init(); UnitTest::init();
_mavlink = new MAVLinkProtocol(); _mavlink = new MAVLinkProtocol();
_uas = new UAS(_mavlink, QThread::currentThread(), UASID); _uas = new UAS(_mavlink, UASID);
_uas->deleteSettings(); _uas->deleteSettings();
} }
//this function is called after every test //this function is called after every test
...@@ -32,7 +31,7 @@ void UASUnitTest::cleanup() ...@@ -32,7 +31,7 @@ void UASUnitTest::cleanup()
void UASUnitTest::getUASID_test() void UASUnitTest::getUASID_test()
{ {
// Test a default ID of zero is assigned // Test a default ID of zero is assigned
UAS* uas2 = new UAS(_mavlink, QThread::currentThread()); UAS* uas2 = new UAS(_mavlink);
QCOMPARE(uas2->getUASID(), 0); QCOMPARE(uas2->getUASID(), 0);
delete uas2; delete uas2;
...@@ -57,7 +56,7 @@ void UASUnitTest::getUASName_test() ...@@ -57,7 +56,7 @@ void UASUnitTest::getUASName_test()
void UASUnitTest::getUpTime_test() void UASUnitTest::getUpTime_test()
{ {
UAS* uas2 = new UAS(_mavlink, QThread::currentThread()); UAS* uas2 = new UAS(_mavlink);
// Test that the uptime starts at zero to a // Test that the uptime starts at zero to a
// precision of seconds // precision of seconds
QCOMPARE(floor(uas2->getUptime()/1000.0), 0.0); QCOMPARE(floor(uas2->getUptime()/1000.0), 0.0);
...@@ -289,7 +288,7 @@ void UASUnitTest::signalWayPoint_test() ...@@ -289,7 +288,7 @@ void UASUnitTest::signalWayPoint_test()
delete _uas;// delete(destroyed) _uas for validating delete _uas;// delete(destroyed) _uas for validating
_uas = NULL; _uas = NULL;
QCOMPARE(spyDestroyed.count(), 1);// count destroyed _uas should are 1 QCOMPARE(spyDestroyed.count(), 1);// count destroyed _uas should are 1
_uas = new UAS(_mavlink, QThread::currentThread(), UASID); _uas = new UAS(_mavlink, UASID);
QSignalSpy spy2(_uas->getWaypointManager(), SIGNAL(waypointEditableListChanged())); QSignalSpy spy2(_uas->getWaypointManager(), SIGNAL(waypointEditableListChanged()));
QCOMPARE(spy2.count(), 0); 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"); 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");
......
...@@ -81,13 +81,15 @@ QList<QObject*>& UnitTest::_testList(void) ...@@ -81,13 +81,15 @@ QList<QObject*>& UnitTest::_testList(void)
return tests; return tests;
} }
int UnitTest::run(int argc, char *argv[], QString& singleTest) int UnitTest::run(QString& singleTest)
{ {
int ret = 0; int ret = 0;
foreach (QObject* test, _testList()) { foreach (QObject* test, _testList()) {
if (singleTest.isEmpty() || singleTest == test->objectName()) { if (singleTest.isEmpty() || singleTest == test->objectName()) {
ret += QTest::qExec(test, argc, argv); QStringList args;
args << "*" << "-maxwarnings" << "0";
ret += QTest::qExec(test, args);
} }
} }
......
...@@ -49,10 +49,8 @@ public: ...@@ -49,10 +49,8 @@ public:
virtual ~UnitTest(void); virtual ~UnitTest(void);
/// @brief Called to run all the registered unit tests /// @brief Called to run all the registered unit tests
/// @param argc argc from main
/// @param argv argv from main
/// @param singleTest Name of test to just run a single test /// @param singleTest Name of test to just run a single test
static int run(int argc, char *argv[], QString& singleTest); static int run(QString& singleTest);
/// @brief Sets up for an expected QGCMessageBox /// @brief Sets up for an expected QGCMessageBox
/// @param response Response to take on message box /// @param response Response to take on message box
...@@ -103,18 +101,6 @@ protected slots: ...@@ -103,18 +101,6 @@ protected slots:
virtual void cleanup(void); virtual void cleanup(void);
protected: protected:
/// @brief Must be called first by derived class implementation
void _initTestCase(void);
/// @brief Must be called first by derived class implementation
void _cleanupTestCase(void);
/// @brief Must be called first by derived class implementation
void _init(void);
/// @brief Must be called first by derived class implementation
void _cleanup(void);
bool _expectMissedFileDialog; // true: expect a missed file dialog, used for internal testing bool _expectMissedFileDialog; // true: expect a missed file dialog, used for internal testing
bool _expectMissedMessageBox; // true: expect a missed message box, used for internal testing bool _expectMissedMessageBox; // true: expect a missed message box, used for internal testing
......
#include "QGCMAVLinkUASFactory.h" #include "QGCMAVLinkUASFactory.h"
#include "UASManager.h" #include "UASManager.h"
#include "QGCUASWorker.h"
#include "QGXPX4UAS.h" #include "QGXPX4UAS.h"
QGCMAVLinkUASFactory::QGCMAVLinkUASFactory(QObject *parent) : QGCMAVLinkUASFactory::QGCMAVLinkUASFactory(QObject *parent) :
...@@ -23,13 +22,11 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte ...@@ -23,13 +22,11 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte
UASInterface* uas; UASInterface* uas;
QGCUASWorker* worker = new QGCUASWorker();
switch (heartbeat->autopilot) switch (heartbeat->autopilot)
{ {
case MAV_AUTOPILOT_GENERIC: case MAV_AUTOPILOT_GENERIC:
{ {
UAS* mav = new UAS(mavlink, worker, sysid); UAS* mav = new UAS(mavlink, sysid);
// Set the system type // Set the system type
mav->setSystemType((int)heartbeat->type); mav->setSystemType((int)heartbeat->type);
...@@ -41,7 +38,7 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte ...@@ -41,7 +38,7 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte
break; break;
case MAV_AUTOPILOT_PX4: case MAV_AUTOPILOT_PX4:
{ {
QGXPX4UAS* px4 = new QGXPX4UAS(mavlink, worker, sysid); QGXPX4UAS* px4 = new QGXPX4UAS(mavlink, sysid);
// Set the system type // Set the system type
px4->setSystemType((int)heartbeat->type); px4->setSystemType((int)heartbeat->type);
...@@ -55,7 +52,7 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte ...@@ -55,7 +52,7 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte
break; break;
default: default:
{ {
UAS* mav = new UAS(mavlink, worker, sysid); UAS* mav = new UAS(mavlink, sysid);
mav->setSystemType((int)heartbeat->type); mav->setSystemType((int)heartbeat->type);
// Connect this robot to the UAS object // Connect this robot to the UAS object
...@@ -68,10 +65,6 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte ...@@ -68,10 +65,6 @@ UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInte
break; break;
} }
// Get the UAS ready
worker->start(QThread::HighPriority);
connect(uas, SIGNAL(destroyed()), worker, SLOT(quit()));
// Set the autopilot type // Set the autopilot type
uas->setAutopilotType((int)heartbeat->autopilot); uas->setAutopilotType((int)heartbeat->autopilot);
......
...@@ -481,7 +481,7 @@ void QGCUASFileManager::_sendRequest(Request* request) ...@@ -481,7 +481,7 @@ void QGCUASFileManager::_sendRequest(Request* request)
request->hdr.seqNumber = _lastOutgoingSeqNumber; request->hdr.seqNumber = _lastOutgoingSeqNumber;
if (_systemIdQGC == 0) { if (_systemIdQGC == 0) {
_systemIdQGC = LinkManager::instance()->mavlink()->getSystemId(); _systemIdQGC = MAVLinkProtocol::instance()->getSystemId();
} }
Q_ASSERT(_mav); Q_ASSERT(_mav);
......
...@@ -217,7 +217,7 @@ void QGCUASParamManager::requestRcCalibrationParamsUpdate() { ...@@ -217,7 +217,7 @@ void QGCUASParamManager::requestRcCalibrationParamsUpdate() {
void QGCUASParamManager::_parameterListUpToDate(void) void QGCUASParamManager::_parameterListUpToDate(void)
{ {
qDebug() << "Emitting parameters ready, count:" << paramDataModel.countOnboardParams(); //qDebug() << "Emitting parameters ready, count:" << paramDataModel.countOnboardParams();
_parametersReady = true; _parametersReady = true;
emit parameterListUpToDate(); emit parameterListUpToDate();
......
#include "QGCUASWorker.h"
#include <QGC.h>
#include <QCoreApplication>
#include <QDebug>
QGCUASWorker::QGCUASWorker() : QThread(),
_should_exit(false)
{
}
void QGCUASWorker::quit()
{
_should_exit = true;
}
void QGCUASWorker::run()
{
while(!_should_exit) {
QCoreApplication::processEvents();
QGC::SLEEP::msleep(2);
}
}
#ifndef QGCUASWORKER_H
#define QGCUASWORKER_H
#include <QThread>
class QGCUASWorker : public QThread
{
public:
QGCUASWorker();
public slots:
void quit();
protected:
void run();
bool _should_exit;
};
#endif // QGCUASWORKER_H
#include "QGXPX4UAS.h" #include "QGXPX4UAS.h"
QGXPX4UAS::QGXPX4UAS(MAVLinkProtocol* mavlink, QThread* thread, int id) : QGXPX4UAS::QGXPX4UAS(MAVLinkProtocol* mavlink, int id) :
UAS(mavlink, thread, id) UAS(mavlink, id)
{ {
} }
......
...@@ -8,7 +8,7 @@ class QGXPX4UAS : public UAS ...@@ -8,7 +8,7 @@ class QGXPX4UAS : public UAS
Q_OBJECT Q_OBJECT
Q_INTERFACES(UASInterface) Q_INTERFACES(UASInterface)
public: public:
QGXPX4UAS(MAVLinkProtocol* mavlink, QThread* thread, int id); QGXPX4UAS(MAVLinkProtocol* mavlink, int id);
public slots: public slots:
/** @brief Receive a MAVLink message from this MAV */ /** @brief Receive a MAVLink message from this MAV */
......
This diff is collapsed.
...@@ -32,7 +32,6 @@ This file is part of the QGROUNDCONTROL project ...@@ -32,7 +32,6 @@ This file is part of the QGROUNDCONTROL project
#ifndef _UAS_H_ #ifndef _UAS_H_
#define _UAS_H_ #define _UAS_H_
#include <QThread>
#include "UASInterface.h" #include "UASInterface.h"
#include <MAVLinkProtocol.h> #include <MAVLinkProtocol.h>
#include <QVector3D> #include <QVector3D>
...@@ -44,6 +43,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -44,6 +43,7 @@ This file is part of the QGROUNDCONTROL project
#include "QGCUASParamManager.h" #include "QGCUASParamManager.h"
#include "QGCUASFileManager.h" #include "QGCUASFileManager.h"
Q_DECLARE_LOGGING_CATEGORY(UASLog)
/** /**
* @brief A generic MAVLINK-connected MAV/UAV * @brief A generic MAVLINK-connected MAV/UAV
...@@ -57,7 +57,7 @@ class UAS : public UASInterface ...@@ -57,7 +57,7 @@ class UAS : public UASInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
UAS(MAVLinkProtocol* protocol, QThread* thread, int id = 0); UAS(MAVLinkProtocol* protocol, int id = 0);
~UAS(); ~UAS();
float lipoFull; ///< 100% charged voltage float lipoFull; ///< 100% charged voltage
...@@ -72,7 +72,7 @@ public: ...@@ -72,7 +72,7 @@ public:
/** @brief Get short mode */ /** @brief Get short mode */
const QString& getShortMode() const; const QString& getShortMode() const;
/** @brief Translate from mode id to text */ /** @brief Translate from mode id to text */
static QString getShortModeTextFor(uint8_t base_mode, uint32_t custom_mode, int autopilot); QString getShortModeTextFor(uint8_t base_mode, uint32_t custom_mode) const;
/** @brief Translate from mode id to audio text */ /** @brief Translate from mode id to audio text */
static QString getAudioModeTextFor(int id); static QString getAudioModeTextFor(int id);
/** @brief Get the unique system id */ /** @brief Get the unique system id */
...@@ -92,7 +92,7 @@ public: ...@@ -92,7 +92,7 @@ public:
/** @brief Add one measurement and get low-passed voltage */ /** @brief Add one measurement and get low-passed voltage */
float filterVoltage(float value) const; float filterVoltage(float value) const;
/** @brief Get the links associated with this robot */ /** @brief Get the links associated with this robot */
QList<LinkInterface*>* getLinks(); QList<LinkInterface*> getLinks();
Q_PROPERTY(double localX READ getLocalX WRITE setLocalX NOTIFY localXChanged) Q_PROPERTY(double localX READ getLocalX WRITE setLocalX NOTIFY localXChanged)
Q_PROPERTY(double localY READ getLocalY WRITE setLocalY NOTIFY localYChanged) Q_PROPERTY(double localY READ getLocalY WRITE setLocalY NOTIFY localYChanged)
...@@ -341,7 +341,7 @@ protected: //COMMENTS FOR TEST UNIT ...@@ -341,7 +341,7 @@ protected: //COMMENTS FOR TEST UNIT
/// LINK ID AND STATUS /// LINK ID AND STATUS
int uasId; ///< Unique system ID int uasId; ///< Unique system ID
QMap<int, QString> components;///< IDs and names of all detected onboard components QMap<int, QString> components;///< IDs and names of all detected onboard components
QList<LinkInterface*>* links; ///< List of links this UAS can be reached by QList<LinkInterface*> links; ///< List of links this UAS can be reached by
QList<int> unknownPackets; ///< Packet IDs which are unknown and have been received QList<int> unknownPackets; ///< Packet IDs which are unknown and have been received
MAVLinkProtocol* mavlink; ///< Reference to the MAVLink instance MAVLinkProtocol* mavlink; ///< Reference to the MAVLink instance
CommStatus commStatus; ///< Communication status CommStatus commStatus; ///< Communication status
...@@ -473,7 +473,6 @@ protected: //COMMENTS FOR TEST UNIT ...@@ -473,7 +473,6 @@ protected: //COMMENTS FOR TEST UNIT
/// SIMULATION /// SIMULATION
QGCHilLink* simulation; ///< Hardware in the loop simulation link QGCHilLink* simulation; ///< Hardware in the loop simulation link
QThread* _thread;
public: public:
/** @brief Set the current battery type */ /** @brief Set the current battery type */
...@@ -952,13 +951,6 @@ protected slots: ...@@ -952,13 +951,6 @@ protected slots:
void writeSettings(); void writeSettings();
/** @brief Read settings from disk */ /** @brief Read settings from disk */
void readSettings(); void readSettings();
// // MESSAGE RECEPTION
// /** @brief Receive a named value message */
// void receiveMessageNamedValue(const mavlink_message_t& message);
private:
// unsigned int mode; ///< The current mode of the MAV
}; };
......
...@@ -103,7 +103,7 @@ public: ...@@ -103,7 +103,7 @@ public:
/** @brief Get short mode */ /** @brief Get short mode */
virtual const QString& getShortMode() const = 0; virtual const QString& getShortMode() const = 0;
/** @brief Translate mode id into text */ /** @brief Translate mode id into text */
static QString getShortModeTextFor(int id); virtual QString getShortModeTextFor(uint8_t base_mode, uint32_t custom_mode) const = 0;
//virtual QColor getColor() = 0; //virtual QColor getColor() = 0;
virtual int getUASID() const = 0; ///< Get the ID of the connected UAS virtual int getUASID() const = 0; ///< Get the ID of the connected UAS
/** @brief The time interval the robot is switched on **/ /** @brief The time interval the robot is switched on **/
...@@ -187,7 +187,7 @@ public: ...@@ -187,7 +187,7 @@ public:
* based on the fact that a message for this robot has been received through that * based on the fact that a message for this robot has been received through that
* interface. The LinkInterface can support multiple protocols. * interface. The LinkInterface can support multiple protocols.
**/ **/
virtual QList<LinkInterface*>* getLinks() = 0; virtual QList<LinkInterface*> getLinks() = 0;
/** /**
* @brief Get the color for this UAS * @brief Get the color for this UAS
......
...@@ -42,10 +42,19 @@ UASManager::UASManager(QObject* parent) : ...@@ -42,10 +42,19 @@ UASManager::UASManager(QObject* parent) :
UASManager::~UASManager() UASManager::~UASManager()
{ {
storeSettings(); storeSettings();
// Delete all systems Q_ASSERT_X(systems.count() == 0, "~UASManager", "_shutdown should have already removed all uas");
foreach (UASInterface* mav, systems) { }
// deleteLater so it ends up on correct thread
mav->deleteLater(); void UASManager::_shutdown(void)
{
QList<UASInterface*> uasList;
foreach(UASInterface* uas, systems) {
uasList.append(uas);
}
foreach(UASInterface* uas, uasList) {
removeUAS(uas);
} }
} }
...@@ -280,7 +289,8 @@ void UASManager::addUAS(UASInterface* uas) ...@@ -280,7 +289,8 @@ void UASManager::addUAS(UASInterface* uas)
if (firstUAS) if (firstUAS)
{ {
setActiveUAS(uas); setActiveUAS(uas);
if (offlineUASWaypointManager->getWaypointEditableList().size() > 0) // Call getActiveUASWaypointManager instead of referencing variable to make sure of creation
if (getActiveUASWaypointManager()->getWaypointEditableList().size() > 0)
{ {
if (QGCMessageBox::question(tr("Question"), tr("Do you want to append the offline waypoints to the ones currently on the UAV?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) if (QGCMessageBox::question(tr("Question"), tr("Do you want to append the offline waypoints to the ones currently on the UAV?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
{ {
......
...@@ -32,7 +32,6 @@ This file is part of the QGROUNDCONTROL project ...@@ -32,7 +32,6 @@ This file is part of the QGROUNDCONTROL project
#define _UASMANAGER_H_ #define _UASMANAGER_H_
#include "UASManagerInterface.h" #include "UASManagerInterface.h"
#include <QThread>
#include <QList> #include <QList>
#include <QMutex> #include <QMutex>
#include <UASInterface.h> #include <UASInterface.h>
...@@ -241,6 +240,8 @@ public slots: ...@@ -241,6 +240,8 @@ public slots:
void loadSettings(); void loadSettings();
/** @brief Store settings */ /** @brief Store settings */
void storeSettings(); void storeSettings();
void _shutdown(void);
protected: protected:
...@@ -262,7 +263,6 @@ protected: ...@@ -262,7 +263,6 @@ protected:
private: private:
/// @brief All access to UASManager singleton is through UASManager::instance /// @brief All access to UASManager singleton is through UASManager::instance
UASManager(QObject* parent = NULL); UASManager(QObject* parent = NULL);
~UASManager(); ~UASManager();
public: public:
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#ifndef _UASMANAGERINTERFACE_H_ #ifndef _UASMANAGERINTERFACE_H_
#define _UASMANAGERINTERFACE_H_ #define _UASMANAGERINTERFACE_H_
#include <QThread>
#include <QList> #include <QList>
#include <QMutex> #include <QMutex>
...@@ -91,6 +90,7 @@ public slots: ...@@ -91,6 +90,7 @@ public slots:
virtual void uavChangedHomePosition(int uav, double lat, double lon, double alt) = 0; virtual void uavChangedHomePosition(int uav, double lat, double lon, double alt) = 0;
virtual void loadSettings() = 0; virtual void loadSettings() = 0;
virtual void storeSettings() = 0; virtual void storeSettings() = 0;
virtual void _shutdown(void) = 0;
signals: signals:
/** A new system was created */ /** A new system was created */
......
...@@ -71,7 +71,7 @@ void UASParameterCommsMgr::loadParamCommsSettings() ...@@ -71,7 +71,7 @@ void UASParameterCommsMgr::loadParamCommsSettings()
void UASParameterCommsMgr::_sendParamRequestListMsg(void) void UASParameterCommsMgr::_sendParamRequestListMsg(void)
{ {
MAVLinkProtocol* mavlink = LinkManager::instance()->mavlink(); MAVLinkProtocol* mavlink = MAVLinkProtocol::instance();
Q_ASSERT(mavlink); Q_ASSERT(mavlink);
mavlink_message_t msg; mavlink_message_t msg;
...@@ -411,7 +411,7 @@ void UASParameterCommsMgr::setParameterStatusMsg(const QString& msg, ParamCommsS ...@@ -411,7 +411,7 @@ void UASParameterCommsMgr::setParameterStatusMsg(const QString& msg, ParamCommsS
void UASParameterCommsMgr::receivedParameterUpdate(int uas, int compId, int paramCount, int paramId, QString paramName, QVariant value) void UASParameterCommsMgr::receivedParameterUpdate(int uas, int compId, int paramCount, int paramId, QString paramName, QVariant value)
{ {
qCDebug(UASParameterCommsMgrLog) << QString("Received parameter update for: name(%1) count(%2) index(%3)").arg(paramName).arg(paramCount).arg(paramId); qCDebug(UASParameterCommsMgrLog) << "Received parameter update for:" << paramName << "count" << paramCount << "index" << paramId << "value" << value;
Q_UNUSED(uas); //this object is assigned to one UAS only Q_UNUSED(uas); //this object is assigned to one UAS only
lastReceiveTime = QGC::groundTimeMilliseconds(); lastReceiveTime = QGC::groundTimeMilliseconds();
......
...@@ -224,7 +224,7 @@ CommConfigurationWindow::CommConfigurationWindow(LinkInterface* link, QWidget *p ...@@ -224,7 +224,7 @@ CommConfigurationWindow::CommConfigurationWindow(LinkInterface* link, QWidget *p
connect(ui.linkType,SIGNAL(currentIndexChanged(int)),this,SLOT(linkCurrentIndexChanged(int))); connect(ui.linkType,SIGNAL(currentIndexChanged(int)),this,SLOT(linkCurrentIndexChanged(int)));
// Open details pane for MAVLink if necessary // Open details pane for MAVLink if necessary
MAVLinkProtocol* mavlink = LinkManager::instance()->mavlink(); MAVLinkProtocol* mavlink = MAVLinkProtocol::instance();
QWidget* conf = new MAVLinkSettingsWidget(mavlink, this); QWidget* conf = new MAVLinkSettingsWidget(mavlink, this);
ui.protocolScrollArea->setWidget(conf); ui.protocolScrollArea->setWidget(conf);
ui.protocolGroupBox->setTitle(mavlink->getName()+" (Global Settings)"); ui.protocolGroupBox->setTitle(mavlink->getName()+" (Global Settings)");
......
...@@ -130,8 +130,8 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE ...@@ -130,8 +130,8 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
this->setAttribute(Qt::WA_DeleteOnClose); this->setAttribute(Qt::WA_DeleteOnClose);
connect(menuActionHelper, SIGNAL(needToShowDockWidget(QString,bool)),SLOT(showDockWidget(QString,bool))); connect(menuActionHelper, SIGNAL(needToShowDockWidget(QString,bool)),SLOT(showDockWidget(QString,bool)));
connect(LinkManager::instance()->mavlink(), SIGNAL(protocolStatusMessage(const QString&, const QString&)), this, SLOT(showCriticalMessage(const QString&, const QString&))); connect(MAVLinkProtocol::instance(), SIGNAL(protocolStatusMessage(const QString&, const QString&)), this, SLOT(showCriticalMessage(const QString&, const QString&)));
connect(LinkManager::instance()->mavlink(), SIGNAL(saveTempFlightDataLog(QString)), this, SLOT(_saveTempFlightDataLog(QString))); connect(MAVLinkProtocol::instance(), SIGNAL(saveTempFlightDataLog(QString)), this, SLOT(_saveTempFlightDataLog(QString)));
loadSettings(); loadSettings();
...@@ -294,7 +294,6 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE ...@@ -294,7 +294,6 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
{ {
// Restore the window geometry // Restore the window geometry
restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray()); restoreGeometry(settings.value(getWindowGeometryKey()).toByteArray());
show();
} }
else else
{ {
...@@ -305,12 +304,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE ...@@ -305,12 +304,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
if (screenWidth < 1500) if (screenWidth < 1500)
{ {
resize(screenWidth, screenHeight - 80); resize(screenWidth, screenHeight - 80);
show();
} }
else else
{ {
resize(screenWidth*0.67f, qMin(screenHeight, (int)(screenWidth*0.67f*0.67f))); resize(screenWidth*0.67f, qMin(screenHeight, (int)(screenWidth*0.67f*0.67f)));
show();
} }
} }
...@@ -358,7 +355,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE ...@@ -358,7 +355,10 @@ MainWindow::MainWindow(QSplashScreen* splashScreen, enum MainWindow::CUSTOM_MODE
connect(&windowNameUpdateTimer, SIGNAL(timeout()), this, SLOT(configureWindowName())); connect(&windowNameUpdateTimer, SIGNAL(timeout()), this, SLOT(configureWindowName()));
windowNameUpdateTimer.start(15000); windowNameUpdateTimer.start(15000);
emit initStatusChanged(tr("Done"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141)); emit initStatusChanged(tr("Done"), Qt::AlignLeft | Qt::AlignBottom, QColor(62, 93, 141));
show();
if (!qgcApp()->runningUnitTests()) {
show();
}
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
...@@ -489,12 +489,12 @@ void MainWindow::buildCustomWidget() ...@@ -489,12 +489,12 @@ void MainWindow::buildCustomWidget()
void MainWindow::buildCommonWidgets() void MainWindow::buildCommonWidgets()
{ {
// Add generic MAVLink decoder // Add generic MAVLink decoder
mavlinkDecoder = new MAVLinkDecoder(LinkManager::instance()->mavlink(), this); mavlinkDecoder = new MAVLinkDecoder(MAVLinkProtocol::instance(), this);
connect(mavlinkDecoder, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)), connect(mavlinkDecoder, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)),
this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64))); this, SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)));
// Log player // Log player
logPlayer = new QGCMAVLinkLogPlayer(LinkManager::instance()->mavlink(), statusBar()); logPlayer = new QGCMAVLinkLogPlayer(MAVLinkProtocol::instance(), statusBar());
statusBar()->addPermanentWidget(logPlayer); statusBar()->addPermanentWidget(logPlayer);
// Initialize all of the views, if they haven't been already, and add their central widgets // Initialize all of the views, if they haven't been already, and add their central widgets
...@@ -581,7 +581,7 @@ void MainWindow::buildCommonWidgets() ...@@ -581,7 +581,7 @@ void MainWindow::buildCommonWidgets()
createDockWidget(simView, new PrimaryFlightDisplay(this), tr("Primary Flight Display"), "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET", VIEW_SIMULATION, Qt::RightDockWidgetArea); createDockWidget(simView, new PrimaryFlightDisplay(this), tr("Primary Flight Display"), "PRIMARY_FLIGHT_DISPLAY_DOCKWIDGET", VIEW_SIMULATION, Qt::RightDockWidgetArea);
// Add dock widgets for the engineering view // Add dock widgets for the engineering view
createDockWidget(engineeringView, new QGCMAVLinkInspector(LinkManager::instance()->mavlink(), this), tr("MAVLink Inspector"), "MAVLINK_INSPECTOR_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea); createDockWidget(engineeringView, new QGCMAVLinkInspector(MAVLinkProtocol::instance(), this), tr("MAVLink Inspector"), "MAVLINK_INSPECTOR_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea);
createDockWidget(engineeringView, new ParameterInterface(this), tr("Onboard Parameters"), "PARAMETER_INTERFACE_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea); createDockWidget(engineeringView, new ParameterInterface(this), tr("Onboard Parameters"), "PARAMETER_INTERFACE_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea);
createDockWidget(engineeringView, new QGCUASFileViewMulti(this), tr("Onboard Files"), "FILE_VIEW_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea); createDockWidget(engineeringView, new QGCUASFileViewMulti(this), tr("Onboard Files"), "FILE_VIEW_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea);
createDockWidget(engineeringView, new HUD(320, 240, this), tr("Video Downlink"), "HEAD_UP_DISPLAY_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea); createDockWidget(engineeringView, new HUD(320, 240, this), tr("Video Downlink"), "HEAD_UP_DISPLAY_DOCKWIDGET", VIEW_ENGINEER, Qt::RightDockWidgetArea);
...@@ -662,7 +662,7 @@ void MainWindow::loadDockWidget(const QString& name) ...@@ -662,7 +662,7 @@ void MainWindow::loadDockWidget(const QString& name)
} }
else if (name == "MAVLINK_INSPECTOR_DOCKWIDGET") else if (name == "MAVLINK_INSPECTOR_DOCKWIDGET")
{ {
createDockWidget(centerStack->currentWidget(),new QGCMAVLinkInspector(LinkManager::instance()->mavlink(),this),tr("MAVLink Inspector"),"MAVLINK_INSPECTOR_DOCKWIDGET",currentView,Qt::RightDockWidgetArea); createDockWidget(centerStack->currentWidget(),new QGCMAVLinkInspector(MAVLinkProtocol::instance(),this),tr("MAVLink Inspector"),"MAVLINK_INSPECTOR_DOCKWIDGET",currentView,Qt::RightDockWidgetArea);
} }
else if (name == "PARAMETER_INTERFACE_DOCKWIDGET") else if (name == "PARAMETER_INTERFACE_DOCKWIDGET")
{ {
...@@ -816,7 +816,7 @@ void MainWindow::connectCommonWidgets() ...@@ -816,7 +816,7 @@ void MainWindow::connectCommonWidgets()
{ {
if (infoDockWidget && infoDockWidget->widget()) if (infoDockWidget && infoDockWidget->widget())
{ {
connect(LinkManager::instance()->mavlink(), SIGNAL(receiveLossChanged(int, float)), connect(MAVLinkProtocol::instance(), SIGNAL(receiveLossChanged(int, float)),
infoDockWidget->widget(), SLOT(updateSendLoss(int, float))); infoDockWidget->widget(), SLOT(updateSendLoss(int, float)));
} }
} }
......
...@@ -15,7 +15,7 @@ OpalLinkConfigurationWindow::OpalLinkConfigurationWindow(OpalLink* link, ...@@ -15,7 +15,7 @@ OpalLinkConfigurationWindow::OpalLinkConfigurationWindow(OpalLink* link,
connect(ui.opalInstIDSpinBox, SIGNAL(valueChanged(int)), link, SLOT(setOpalInstID(int))); connect(ui.opalInstIDSpinBox, SIGNAL(valueChanged(int)), link, SLOT(setOpalInstID(int)));
connect(link, &LinkInterface::connected, this, OpalLinkConfigurationWindow::_linkConnected); connect(link, &LinkInterface::connected, this, OpalLinkConfigurationWindow::_linkConnected);
connect(link, &LinkInterface::disconnected, this, OpalLinkConfigurationWindow::_linkDisConnected); connect(link, &LinkInterface::disconnected, this, OpalLinkConfigurationWindow::_linkDisconnected);
this->show(); this->show();
} }
......
...@@ -43,10 +43,6 @@ QGCMAVLinkLogPlayer::QGCMAVLinkLogPlayer(MAVLinkProtocol* mavlink, QWidget *pare ...@@ -43,10 +43,6 @@ QGCMAVLinkLogPlayer::QGCMAVLinkLogPlayer(MAVLinkProtocol* mavlink, QWidget *pare
connect(ui->positionSlider, &QSlider::valueChanged, this, &QGCMAVLinkLogPlayer::jumpToSliderVal); connect(ui->positionSlider, &QSlider::valueChanged, this, &QGCMAVLinkLogPlayer::jumpToSliderVal);
connect(ui->positionSlider, &QSlider::sliderPressed, this, &QGCMAVLinkLogPlayer::pause); connect(ui->positionSlider, &QSlider::sliderPressed, this, &QGCMAVLinkLogPlayer::pause);
// We use this to queue the signal over to mavlink. This way it will be behind any remaining
// bytesReady signals in the queue.
connect(this, &QGCMAVLinkLogPlayer::suspendLogForReplay, mavlink, &MAVLinkProtocol::suspendLogForReplay);
setAccelerationFactorInt(49); setAccelerationFactorInt(49);
ui->speedSlider->setValue(49); ui->speedSlider->setValue(49);
updatePositionSliderUi(0.0); updatePositionSliderUi(0.0);
...@@ -84,7 +80,7 @@ void QGCMAVLinkLogPlayer::play() ...@@ -84,7 +80,7 @@ void QGCMAVLinkLogPlayer::play()
Q_ASSERT(logFile.isOpen()); Q_ASSERT(logFile.isOpen());
LinkManager::instance()->setConnectionsSuspended(tr("Connect not allowed during Flight Data replay.")); LinkManager::instance()->setConnectionsSuspended(tr("Connect not allowed during Flight Data replay."));
emit suspendLogForReplay(true); mavlink->suspendLogForReplay(true);
// Disable the log file selector button // Disable the log file selector button
ui->selectFileButton->setEnabled(false); ui->selectFileButton->setEnabled(false);
...@@ -122,7 +118,7 @@ void QGCMAVLinkLogPlayer::play() ...@@ -122,7 +118,7 @@ void QGCMAVLinkLogPlayer::play()
void QGCMAVLinkLogPlayer::pause() void QGCMAVLinkLogPlayer::pause()
{ {
LinkManager::instance()->setConnectionsAllowed(); LinkManager::instance()->setConnectionsAllowed();
emit suspendLogForReplay(false); mavlink->suspendLogForReplay(false);
loopTimer.stop(); loopTimer.stop();
isPlaying = false; isPlaying = false;
...@@ -642,7 +638,7 @@ void QGCMAVLinkLogPlayer::_finishPlayback(void) ...@@ -642,7 +638,7 @@ void QGCMAVLinkLogPlayer::_finishPlayback(void)
emit logFileEndReached(); emit logFileEndReached();
emit suspendLogForReplay(false); mavlink->suspendLogForReplay(false);
LinkManager::instance()->setConnectionsAllowed(); LinkManager::instance()->setConnectionsAllowed();
} }
......
...@@ -59,9 +59,6 @@ signals: ...@@ -59,9 +59,6 @@ signals:
/** @brief Send ready bytes */ /** @brief Send ready bytes */
void bytesReady(LinkInterface* link, const QByteArray& bytes); void bytesReady(LinkInterface* link, const QByteArray& bytes);
void logFileEndReached(); void logFileEndReached();
/// @brief Connected to the MAVLinkProtocol::suspendLogForReplay
void suspendLogForReplay(bool suspend);
protected: protected:
quint64 playbackStartTime; ///< The time when the logfile was first played back. This is used to pace out replaying the messages to fix long-term drift/skew. 0 indicates that the player hasn't initiated playback of this log file. In units of milliseconds since epoch UTC. quint64 playbackStartTime; ///< The time when the logfile was first played back. This is used to pace out replaying the messages to fix long-term drift/skew. 0 indicates that the player hasn't initiated playback of this log file. In units of milliseconds since epoch UTC.
......
...@@ -52,7 +52,7 @@ _ui(new Ui::SettingsDialog) ...@@ -52,7 +52,7 @@ _ui(new Ui::SettingsDialog)
// Add the joystick settings pane // Add the joystick settings pane
_ui->tabWidget->addTab(new JoystickWidget(joystick, this), "Controllers"); _ui->tabWidget->addTab(new JoystickWidget(joystick, this), "Controllers");
MAVLinkSettingsWidget* msettings = new MAVLinkSettingsWidget(LinkManager::instance()->mavlink(), this); MAVLinkSettingsWidget* msettings = new MAVLinkSettingsWidget(MAVLinkProtocol::instance(), this);
_ui->tabWidget->addTab(msettings, "MAVLink"); _ui->tabWidget->addTab(msettings, "MAVLink");
this->window()->setWindowTitle(tr("QGroundControl Settings")); this->window()->setWindowTitle(tr("QGroundControl Settings"));
......
...@@ -59,23 +59,19 @@ UASControlWidget::UASControlWidget(QWidget *parent) : QWidget(parent), ...@@ -59,23 +59,19 @@ UASControlWidget::UASControlWidget(QWidget *parent) : QWidget(parent),
void UASControlWidget::updateModesList() void UASControlWidget::updateModesList()
{ {
// Detect autopilot type if (this->uasID == 0) {
int autopilot = MAV_AUTOPILOT_GENERIC; return;
if (this->uasID >= 0) {
UASInterface *uas = UASManager::instance()->getUASForId(this->uasID);
if (uas) {
autopilot = UASManager::instance()->getUASForId(this->uasID)->getAutopilotType();
}
} }
AutoPilotPlugin* autopilotPlugin = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(autopilot); UASInterface*uas = UASManager::instance()->getUASForId(this->uasID);
Q_ASSERT(uas);
_modeList = autopilotPlugin->getModes(); _modeList = AutoPilotPluginManager::instance()->getModes(uas->getAutopilotType());
// Set combobox items // Set combobox items
ui.modeComboBox->clear(); ui.modeComboBox->clear();
foreach (AutoPilotPlugin::FullMode_t fullMode, _modeList) { foreach (AutoPilotPluginManager::FullMode_t fullMode, _modeList) {
ui.modeComboBox->addItem(UAS::getShortModeTextFor(fullMode.baseMode, fullMode.customMode, autopilot).remove(0, 2)); ui.modeComboBox->addItem(uas->getShortModeTextFor(fullMode.baseMode, fullMode.customMode).remove(0, 2));
} }
// Select first mode in list // Select first mode in list
...@@ -197,7 +193,7 @@ void UASControlWidget::transmitMode() ...@@ -197,7 +193,7 @@ void UASControlWidget::transmitMode()
UASInterface* uas_iface = UASManager::instance()->getUASForId(this->uasID); UASInterface* uas_iface = UASManager::instance()->getUASForId(this->uasID);
if (uas_iface) { if (uas_iface) {
if (modeIdx >= 0 && modeIdx < _modeList.count()) { if (modeIdx >= 0 && modeIdx < _modeList.count()) {
AutoPilotPlugin::FullMode_t fullMode = _modeList[modeIdx]; AutoPilotPluginManager::FullMode_t fullMode = _modeList[modeIdx];
// include armed state // include armed state
if (armed) { if (armed) {
fullMode.baseMode |= MAV_MODE_FLAG_SAFETY_ARMED; fullMode.baseMode |= MAV_MODE_FLAG_SAFETY_ARMED;
......
...@@ -38,7 +38,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -38,7 +38,7 @@ This file is part of the QGROUNDCONTROL project
#include <QPushButton> #include <QPushButton>
#include <ui_UASControl.h> #include <ui_UASControl.h>
#include <UASInterface.h> #include <UASInterface.h>
#include "AutoPilotPlugin.h" #include "AutoPilotPluginManager.h"
/** /**
* @brief Widget controlling one MAV * @brief Widget controlling one MAV
...@@ -79,7 +79,7 @@ protected slots: ...@@ -79,7 +79,7 @@ protected slots:
protected: protected:
int uasID; ///< Reference to the current uas int uasID; ///< Reference to the current uas
QList<AutoPilotPlugin::FullMode_t> _modeList; ///< Mode list for the current UAS QList<AutoPilotPluginManager::FullMode_t> _modeList; ///< Mode list for the current UAS
int modeIdx; ///< Current uas mode index int modeIdx; ///< Current uas mode index
bool armed; ///< Engine state bool armed; ///< Engine state
......
...@@ -124,7 +124,7 @@ void UASListWidget::updateStatus() ...@@ -124,7 +124,7 @@ void UASListWidget::updateStatus()
if (!link) if (!link)
continue; continue;
MAVLinkProtocol* mavlink = LinkManager::instance()->mavlink(); MAVLinkProtocol* mavlink = MAVLinkProtocol::instance();
// Build the tooltip out of the protocol parsing data: received, dropped, and parsing errors. // Build the tooltip out of the protocol parsing data: received, dropped, and parsing errors.
QString displayString(""); QString displayString("");
...@@ -167,10 +167,10 @@ void UASListWidget::addUAS(UASInterface* uas) ...@@ -167,10 +167,10 @@ void UASListWidget::addUAS(UASInterface* uas)
if (!uasViews.contains(uas)) if (!uasViews.contains(uas))
{ {
// Only display the UAS in a single link. // Only display the UAS in a single link.
QList<LinkInterface*>* x = uas->getLinks(); QList<LinkInterface*> x = uas->getLinks();
if (x->size()) if (x.size())
{ {
LinkInterface* li = x->first(); LinkInterface* li = x.first();
// Find an existing QGroupBox for this LinkInterface or create a // Find an existing QGroupBox for this LinkInterface or create a
// new one. // new one.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment