Commit aaed8c2d authored by Don Gagne's avatar Don Gagne

Auto connect support

- Pervasive change to automatically connect to known board types
- Lots of additional changes along with this:
- More exposure of objects/properties to Qml
- Much restructuring in LinkManager and LinkManager clients
parent ee06661a
......@@ -270,7 +270,6 @@ HEADERS += \
src/QmlControls/QGCQGeoCoordinate.h \
src/QmlControls/QGroundControlQmlGlobal.h \
src/QmlControls/QmlObjectListModel.h \
src/SerialPortIds.h \
src/uas/FileManager.h \
src/uas/UAS.h \
src/uas/UASInterface.h \
......
......@@ -28,7 +28,6 @@
<file alias="PowerComponent.qml">src/AutoPilotPlugins/PX4/PowerComponent.qml</file>
<file alias="PowerComponentSummary.qml">src/AutoPilotPlugins/PX4/PowerComponentSummary.qml</file>
<file alias="PX4FlowSensor.qml">src/VehicleSetup/PX4FlowSensor.qml</file>
<file alias="QGroundControl/Controls/ClickableColor.qml">src/QmlControls/ClickableColor.qml</file>
<file alias="QGroundControl/Controls/DropButton.qml">src/QmlControls/DropButton.qml</file>
<file alias="QGroundControl/Controls/ExclusiveGroupItem.qml">src/QmlControls/ExclusiveGroupItem.qml</file>
......@@ -42,7 +41,6 @@
<file alias="QGroundControl/Controls/ParameterEditor.qml">src/QmlControls/ParameterEditor.qml</file>
<file alias="QGroundControl/Controls/ParameterEditorDialog.qml">src/QmlControls/ParameterEditorDialog.qml</file>
<file alias="QGroundControl/Controls/QGCButton.qml">src/QmlControls/QGCButton.qml</file>
<file alias="QGroundControl/Controls/QGCCanvas.qml">src/QmlControls/QGCCanvas.qml</file>
<file alias="QGroundControl/Controls/QGCCheckBox.qml">src/QmlControls/QGCCheckBox.qml</file>
<file alias="QGroundControl/Controls/QGCColoredImage.qml">src/QmlControls/QGCColoredImage.qml</file>
<file alias="QGroundControl/Controls/QGCComboBox.qml">src/QmlControls/QGCComboBox.qml</file>
......@@ -62,20 +60,17 @@
<file alias="QGroundControl/Controls/VehicleRotationCal.qml">src/QmlControls/VehicleRotationCal.qml</file>
<file alias="QGroundControl/Controls/VehicleSummaryRow.qml">src/QmlControls/VehicleSummaryRow.qml</file>
<file alias="QGroundControl/Controls/ViewWidget.qml">src/ViewWidgets/ViewWidget.qml</file>
<file alias="QGroundControl/FactControls/FactCheckBox.qml">src/FactSystem/FactControls/FactCheckBox.qml</file>
<file alias="QGroundControl/FactControls/FactComboBox.qml">src/FactSystem/FactControls/FactComboBox.qml</file>
<file alias="QGroundControl/FactControls/FactLabel.qml">src/FactSystem/FactControls/FactLabel.qml</file>
<file alias="QGroundControl/FactControls/FactPanel.qml">src/FactSystem/FactControls/FactPanel.qml</file>
<file alias="QGroundControl/FactControls/FactTextField.qml">src/FactSystem/FactControls/FactTextField.qml</file>
<file alias="QGroundControl/FactControls/qmldir">src/FactSystem/FactControls/qmldir</file>
<file alias="QGroundControl/FlightDisplay/FlightDisplayView.qml">src/FlightDisplay/FlightDisplayView.qml</file>
<file alias="QGroundControl/FlightDisplay/FlightDisplayViewMap.qml">src/FlightDisplay/FlightDisplayViewMap.qml</file>
<file alias="QGroundControl/FlightDisplay/FlightDisplayViewVideo.qml">src/FlightDisplay/FlightDisplayViewVideo.qml</file>
<file alias="QGroundControl/FlightDisplay/FlightDisplayViewWidgets.qml">src/FlightDisplay/FlightDisplayViewWidgets.qml</file>
<file alias="QGroundControl/FlightDisplay/qmldir">src/FlightDisplay/qmldir</file>
<file alias="QGroundControl/FlightMap/FlightMap.qml">src/FlightMap/FlightMap.qml</file>
<file alias="QGroundControl/FlightMap/MissionItemIndicator.qml">src/FlightMap/MapItems/MissionItemIndicator.qml</file>
<file alias="QGroundControl/FlightMap/MissionItemView.qml">src/FlightMap/MapItems/MissionItemView.qml</file>
......@@ -90,10 +85,8 @@
<file alias="QGroundControl/FlightMap/QGCVideoBackground.qml">src/FlightMap/QGCVideoBackground.qml</file>
<file alias="QGroundControl/FlightMap/qmldir">src/FlightMap/qmldir</file>
<file alias="QGroundControl/FlightMap/VehicleMapItem.qml">src/FlightMap/MapItems/VehicleMapItem.qml</file>
<file alias="QGroundControl/ScreenTools/qmldir">src/QmlControls/QGroundControl.ScreenTools.qmldir</file>
<file alias="QGroundControl/ScreenTools/ScreenTools.qml">src/QmlControls/ScreenTools.qml</file>
<file alias="QmlTest.qml">src/QmlControls/QmlTest.qml</file>
<file alias="RadioComponent.qml">src/AutoPilotPlugins/PX4/RadioComponent.qml</file>
<file alias="RadioComponentSummary.qml">src/AutoPilotPlugins/PX4/RadioComponentSummary.qml</file>
......
......@@ -139,7 +139,7 @@ void AirframeComponentController::_rebootAfterStackUnwind(void)
QGC::SLEEP::usleep(500);
qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
}
qgcApp()->toolbox()->linkManager()->disconnectAll();
qgcApp()->toolbox()->linkManager()->disconnectAll(false /* disconnectAutoconnectLink */);
qgcApp()->restoreOverrideCursor();
}
......
......@@ -50,14 +50,13 @@ HomePositionManager::HomePositionManager(QGCApplication* app)
, homeLon(8.549444)
, homeAlt(470.0)
{
qmlRegisterUncreatableType<HomePositionManager> ("QGroundControl", 1, 0, "HomePositionManager", "Reference only");
}
void HomePositionManager::setToolbox(QGCToolbox *toolbox)
{
QGCTool::setToolbox(toolbox);
qmlRegisterUncreatableType<HomePositionManager> ("QGroundControl", 1, 0, "HomePositionManager", "Reference only");
_loadSettings();
}
......
......@@ -184,7 +184,7 @@ Item {
id: dropDownItem
visible: checked
QGCCanvas {
Canvas {
id: arrowCanvas
anchors.fill: parent
......
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
/// Canvas has some sort of bug in it which can cause it to not paint when top level Views
/// are switched. In order to fix this we ahve a signal hacked into ScreenTools to force
/// a repaint.
Canvas {
id: _root
Connections {
target: ScreenTools
onRepaintRequested: _root.requestPaint()
}
}
......@@ -9,7 +9,6 @@ QGCComboBox 1.0 QGCComboBox.qml
QGCColoredImage 1.0 QGCColoredImage.qml
QGCToolBarButton 1.0 QGCToolBarButton.qml
QGCMovableItem 1.0 QGCMovableItem.qml
QGCCanvas 1.0 QGCCanvas.qml
SubMenuButton 1.0 SubMenuButton.qml
IndicatorButton 1.0 IndicatorButton.qml
......
......@@ -33,6 +33,8 @@ static const char* kQmlGlobalKeyName = "QGCQml";
QGroundControlQmlGlobal::QGroundControlQmlGlobal(QGCToolbox* toolbox, QObject* parent)
: QObject(parent)
, _multiVehicleManager(toolbox->multiVehicleManager())
, _linkManager(toolbox->linkManager())
, _homePositionManager(toolbox->homePositionManager())
, _flightMapSettings(toolbox->flightMapSettings())
{
......@@ -70,25 +72,25 @@ bool QGroundControlQmlGlobal::loadBoolGlobalSetting (const QString& key, bool de
#ifdef QT_DEBUG
void QGroundControlQmlGlobal::_startMockLink(MockConfiguration* mockConfig)
{
MockLink* mockLink = new MockLink(mockConfig);
LinkManager* linkManager = qgcApp()->toolbox()->linkManager();
linkManager->_addLink(mockLink);
linkManager->connectLink(mockLink);
mockConfig->setDynamic(true);
linkManager->linkConfigurations()->append(mockConfig);
linkManager->createConnectedLink(mockConfig, false /* autoconnectLink */);
}
#endif
void QGroundControlQmlGlobal::startPX4MockLink(bool sendStatusText)
{
#ifdef QT_DEBUG
MockConfiguration mockConfig("PX4 MockLink");
MockConfiguration* mockConfig = new MockConfiguration("PX4 MockLink");
mockConfig.setFirmwareType(MAV_AUTOPILOT_PX4);
mockConfig.setVehicleType(MAV_TYPE_QUADROTOR);
mockConfig.setSendStatusText(sendStatusText);
mockConfig->setFirmwareType(MAV_AUTOPILOT_PX4);
mockConfig->setVehicleType(MAV_TYPE_QUADROTOR);
mockConfig->setSendStatusText(sendStatusText);
_startMockLink(&mockConfig);
_startMockLink(mockConfig);
#else
Q_UNUSED(sendStatusText);
#endif
......@@ -97,13 +99,13 @@ void QGroundControlQmlGlobal::startPX4MockLink(bool sendStatusText)
void QGroundControlQmlGlobal::startGenericMockLink(bool sendStatusText)
{
#ifdef QT_DEBUG
MockConfiguration mockConfig("Generic MockLink");
MockConfiguration* mockConfig = new MockConfiguration("Generic MockLink");
mockConfig.setFirmwareType(MAV_AUTOPILOT_GENERIC);
mockConfig.setVehicleType(MAV_TYPE_QUADROTOR);
mockConfig.setSendStatusText(sendStatusText);
mockConfig->setFirmwareType(MAV_AUTOPILOT_GENERIC);
mockConfig->setVehicleType(MAV_TYPE_QUADROTOR);
mockConfig->setSendStatusText(sendStatusText);
_startMockLink(&mockConfig);
_startMockLink(mockConfig);
#else
Q_UNUSED(sendStatusText);
#endif
......@@ -112,13 +114,13 @@ void QGroundControlQmlGlobal::startGenericMockLink(bool sendStatusText)
void QGroundControlQmlGlobal::startAPMArduCopterMockLink(bool sendStatusText)
{
#ifdef QT_DEBUG
MockConfiguration mockConfig("APM ArduCopter MockLink");
MockConfiguration* mockConfig = new MockConfiguration("APM ArduCopter MockLink");
mockConfig.setFirmwareType(MAV_AUTOPILOT_ARDUPILOTMEGA);
mockConfig.setVehicleType(MAV_TYPE_QUADROTOR);
mockConfig.setSendStatusText(sendStatusText);
mockConfig->setFirmwareType(MAV_AUTOPILOT_ARDUPILOTMEGA);
mockConfig->setVehicleType(MAV_TYPE_QUADROTOR);
mockConfig->setSendStatusText(sendStatusText);
_startMockLink(&mockConfig);
_startMockLink(mockConfig);
#else
Q_UNUSED(sendStatusText);
#endif
......@@ -127,13 +129,13 @@ void QGroundControlQmlGlobal::startAPMArduCopterMockLink(bool sendStatusText)
void QGroundControlQmlGlobal::startAPMArduPlaneMockLink(bool sendStatusText)
{
#ifdef QT_DEBUG
MockConfiguration mockConfig("APM ArduPlane MockLink");
MockConfiguration* mockConfig = new MockConfiguration("APM ArduPlane MockLink");
mockConfig.setFirmwareType(MAV_AUTOPILOT_ARDUPILOTMEGA);
mockConfig.setVehicleType(MAV_TYPE_FIXED_WING);
mockConfig.setSendStatusText(sendStatusText);
mockConfig->setFirmwareType(MAV_AUTOPILOT_ARDUPILOTMEGA);
mockConfig->setVehicleType(MAV_TYPE_FIXED_WING);
mockConfig->setSendStatusText(sendStatusText);
_startMockLink(&mockConfig);
_startMockLink(mockConfig);
#else
Q_UNUSED(sendStatusText);
#endif
......@@ -144,12 +146,12 @@ void QGroundControlQmlGlobal::stopAllMockLinks(void)
#ifdef QT_DEBUG
LinkManager* linkManager = qgcApp()->toolbox()->linkManager();
QList<LinkInterface*> links = linkManager->getLinks();
for (int i=0; i<links.count(); i++) {
LinkInterface* link = links[i];
for (int i=0; i<linkManager->links()->count(); i++) {
LinkInterface* link = linkManager->links()->value<LinkInterface*>(i);
MockLink* mockLink = qobject_cast<MockLink*>(link);
if (mockLink) {
linkManager->disconnectLink(mockLink);
linkManager->disconnectLink(mockLink, false /* disconnectAutoconnectLink */);
}
}
#endif
......
......@@ -31,6 +31,7 @@
#include "QGCApplication.h"
#include "MainWindow.h"
#include "LinkManager.h"
#include "HomePositionManager.h"
#include "FlightMapSettings.h"
......@@ -47,6 +48,8 @@ class QGroundControlQmlGlobal : public QObject
public:
QGroundControlQmlGlobal(QGCToolbox* toolbox, QObject* parent = NULL);
Q_PROPERTY(LinkManager* linkManager READ linkManager CONSTANT)
Q_PROPERTY(MultiVehicleManager* multiVehicleManager READ multiVehicleManager CONSTANT)
Q_PROPERTY(HomePositionManager* homePositionManager READ homePositionManager CONSTANT)
Q_PROPERTY(FlightMapSettings* flightMapSettings READ flightMapSettings CONSTANT)
......@@ -70,6 +73,8 @@ public:
// Property accesors
LinkManager* linkManager () { return _linkManager; }
MultiVehicleManager* multiVehicleManager () { return _multiVehicleManager; }
HomePositionManager* homePositionManager () { return _homePositionManager; }
FlightMapSettings* flightMapSettings () { return _flightMapSettings; }
......@@ -137,6 +142,8 @@ private:
void _startMockLink(MockConfiguration* mockConfig);
#endif
MultiVehicleManager* _multiVehicleManager;
LinkManager* _linkManager;
HomePositionManager* _homePositionManager;
FlightMapSettings* _flightMapSettings;
};
......
......@@ -197,11 +197,6 @@ int QmlObjectListModel::count(void) const
return rowCount();
}
QObject* QmlObjectListModel::get(int index)
{
return _objectList[index];
}
void QmlObjectListModel::setDirty(bool dirty)
{
_dirty = dirty;
......
......@@ -34,14 +34,14 @@ public:
QmlObjectListModel(QObject* parent = NULL);
~QmlObjectListModel();
Q_INVOKABLE QObject* get(int index);
Q_PROPERTY(int count READ count NOTIFY countChanged)
/// Returns true if any of the items in the list are dirty. Requires each object to have
/// a dirty property and dirtyChanged signal.
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
Q_INVOKABLE QObject* get(int index) { return _objectList[index]; }
// Property accessors
int count(void) const;
......@@ -52,13 +52,14 @@ public:
void append(QObject* object);
void clear(void);
QObject* removeAt(int i);
QObject* removeOne(QObject* object) { return removeAt(indexOf(object)); }
void insert(int i, QObject* object);
QObject* operator[](int i);
const QObject* operator[](int i) const;
template <class T>
const QList<T*>& list(void) { return *((QList<T*>*)((void*)(&_objectList))); }
bool contains(QObject* object) { return _objectList.indexOf(object) != -1; }
int indexOf(QObject* object) { return _objectList.indexOf(object); }
template<class T> T value(int index) { return qobject_cast<T>(_objectList[index]); }
signals:
void countChanged(int count);
void dirtyChanged(bool dirtyChanged);
......
......@@ -47,9 +47,4 @@ Item {
property real fontWidth: contentWidth * (ScreenToolsController.testHighDPI ? 2 : 1)
property real fontHeight: contentHeight * (ScreenToolsController.testHighDPI ? 2 : 1)
}
Connections {
target: ScreenToolsController
onRepaintRequested: repaintRequested()
}
}
......@@ -43,15 +43,5 @@ const double ScreenToolsController::_largeFontPixelSizeRatio = 1.66;
ScreenToolsController::ScreenToolsController()
{
MainWindow* mainWindow = MainWindow::instance();
// Unit tests can run Qml without MainWindow
if (mainWindow) {
connect(mainWindow, &MainWindow::repaintCanvas, this, &ScreenToolsController::_updateCanvas);
}
}
void ScreenToolsController::_updateCanvas()
{
emit repaintRequested();
}
......@@ -114,12 +114,6 @@ public:
bool testHighDPI () { return false; }
#endif
signals:
void repaintRequested();
private slots:
void _updateCanvas();
private:
static const double _defaultFontPixelSizeRatio;
static const double _smallFontPixelSizeRatio;
......
......@@ -57,33 +57,26 @@ void MultiVehicleManager::setToolbox(QGCToolbox *toolbox)
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
qmlRegisterUncreatableType<MultiVehicleManager>("QGroundControl.MultiVehicleManager", 1, 0, "MultiVehicleManager", "Reference only");
connect(_toolbox->linkManager(), &LinkManager::linkActive, this, &MultiVehicleManager::_linkActive);
}
bool MultiVehicleManager::notifyHeartbeatInfo(LinkInterface* link, int vehicleId, mavlink_heartbeat_t& heartbeat)
void MultiVehicleManager::_linkActive(LinkInterface* link, int vehicleId, int vehicleFirmwareType, int vehicleType)
{
if (!getVehicleById(vehicleId) && !_ignoreVehicleIds.contains(vehicleId)) {
if (vehicleId == _mavlinkProtocol->getSystemId()) {
_app->showToolBarMessage(QString("Warning: A vehicle is using the same system id as QGroundControl: %1").arg(vehicleId));
}
QSettings settings;
bool mavlinkVersionCheck = settings.value("VERSION_CHECK_ENABLED", true).toBool();
if (mavlinkVersionCheck && heartbeat.mavlink_version != MAVLINK_VERSION) {
_ignoreVehicleIds += vehicleId;
_app->showToolBarMessage(QString("The MAVLink protocol version on vehicle #%1 and QGroundControl differ! "
"It is unsafe to use different MAVLink versions. "
"QGroundControl therefore refuses to connect to vehicle #%1, which sends MAVLink version %2 (QGroundControl uses version %3).").arg(vehicleId).arg(heartbeat.mavlink_version).arg(MAVLINK_VERSION));
return false;
}
if (!getVehicleById(vehicleId)) {
qCDebug(MultiVehicleManagerLog) << "Adding new vehicle linkName:vehicleId:vehicleFirmwareType:vehicleType"
<< link->getName()
<< vehicleId
<< vehicleFirmwareType
<< vehicleType;
Vehicle* vehicle = new Vehicle(link, vehicleId, (MAV_AUTOPILOT)heartbeat.autopilot, (MAV_TYPE)heartbeat.type, _firmwarePluginManager, _autopilotPluginManager, _joystickManager);
Vehicle* vehicle = new Vehicle(link, vehicleId, (MAV_AUTOPILOT)vehicleFirmwareType, (MAV_TYPE)vehicleType, _firmwarePluginManager, _autopilotPluginManager, _joystickManager);
if (!vehicle) {
qWarning() << "New Vehicle allocation failed";
return false;
return;
}
connect(vehicle, &Vehicle::allLinksDisconnected, this, &MultiVehicleManager::_deleteVehiclePhase1);
connect(vehicle, &Vehicle::allLinksInactive, this, &MultiVehicleManager::_deleteVehiclePhase1);
connect(vehicle->autopilotPlugin(), &AutoPilotPlugin::parametersReadyChanged, this, &MultiVehicleManager::_autopilotParametersReadyChanged);
_vehicles.append(vehicle);
......@@ -92,22 +85,20 @@ bool MultiVehicleManager::notifyHeartbeatInfo(LinkInterface* link, int vehicleId
setActiveVehicle(vehicle);
}
return true;
}
/// This slot is connected to the Vehicle::allLinksDestroyed signal such that the Vehicle is deleted
/// and all other right things happen when the Vehicle goes away.
void MultiVehicleManager::_deleteVehiclePhase1(Vehicle* vehicle)
{
qCDebug(MultiVehicleManagerLog) << "_deleteVehiclePhase1";
qCDebug(MultiVehicleManagerLog) << "_deleteVehiclePhase1" << vehicle;
_vehicleBeingDeleted = vehicle;
_vehiclesBeingDeleted << vehicle;
// Remove from map
bool found = false;
for (int i=0; i<_vehicles.count(); i++) {
if (_vehicles[i] == _vehicleBeingDeleted) {
if (_vehicles[i] == vehicle) {
_vehicles.removeAt(i);
found = true;
break;
......@@ -136,9 +127,9 @@ void MultiVehicleManager::_deleteVehiclePhase1(Vehicle* vehicle)
QTimer::singleShot(20, this, &MultiVehicleManager::_deleteVehiclePhase2);
}
void MultiVehicleManager::_deleteVehiclePhase2 (void)
void MultiVehicleManager::_deleteVehiclePhase2(void)
{
qCDebug(MultiVehicleManagerLog) << "_deleteVehiclePhase2";
qCDebug(MultiVehicleManagerLog) << "_deleteVehiclePhase2" << _vehiclesBeingDeleted[0];
/// Qml has been notified of vehicle about to go away and should be disconnected from it by now.
/// This means we can now clear the active vehicle property and delete the Vehicle for real.
......@@ -159,7 +150,8 @@ void MultiVehicleManager::_deleteVehiclePhase2 (void)
}
}
_vehicleBeingDeleted->deleteLater();
delete _vehiclesBeingDeleted[0];
_vehiclesBeingDeleted.removeAt(0);
}
void MultiVehicleManager::setActiveVehicle(Vehicle* vehicle)
......@@ -189,7 +181,7 @@ void MultiVehicleManager::setActiveVehicle(Vehicle* vehicle)
void MultiVehicleManager::_setActiveVehiclePhase2(void)
{
qCDebug(MultiVehicleManagerLog) << "_setActiveVehiclePhase2";
qCDebug(MultiVehicleManagerLog) << "_setActiveVehiclePhase2 _vehicleBeingSetActive" << _vehicleBeingSetActive;
// Now we signal the new active vehicle
_activeVehicle = _vehicleBeingSetActive;
......
......@@ -58,14 +58,6 @@ public:
// Methods
/// Called to notify that a heartbeat was received with the specified information. MultiVehicleManager
/// will create/update Vehicles as necessary.
/// @param link Heartbeat came through on this link
/// @param vehicleId Mavlink system id for vehicle
/// @param heartbeat Mavlink heartbeat message
/// @return true: continue further processing of this message, false: disregard this message
bool notifyHeartbeatInfo(LinkInterface* link, int vehicleId, mavlink_heartbeat_t& heartbeat);
Q_INVOKABLE Vehicle* getVehicleById(int vehicleId);
UAS* activeUas(void) { return _activeVehicle ? _activeVehicle->uas() : NULL; }
......@@ -98,6 +90,7 @@ private slots:
void _deleteVehiclePhase2(void);
void _setActiveVehiclePhase2(void);
void _autopilotParametersReadyChanged(bool parametersReady);
void _linkActive(LinkInterface* link, int vehicleId, int vehicleFirmwareType, int vehicleType);
private:
bool _vehicleExists(int vehicleId);
......@@ -106,8 +99,8 @@ private:
bool _parameterReadyVehicleAvailable; ///< true: An active vehicle with ready parameters is available
Vehicle* _activeVehicle; ///< Currently active vehicle from a ui perspective
Vehicle* _vehicleBeingDeleted; ///< Vehicle being deleted in queued phases
Vehicle* _vehicleBeingSetActive; ///< Vehicle being set active in queued phases
QList<Vehicle*> _vehiclesBeingDeleted; ///< List of Vehicles being deleted in queued phases
Vehicle* _vehicleBeingSetActive; ///< Vehicle being set active in queued phases
QList<int> _ignoreVehicleIds; ///< List of vehicle id for which we ignore further communication
......
......@@ -94,6 +94,8 @@ Vehicle::Vehicle(LinkInterface* link,
, _satelliteCount(-1)
, _satelliteLock(0)
, _updateCount(0)
, _rcRSSI(0)
, _rcRSSIstore(100.0)
, _missionManager(NULL)
, _missionManagerInitialRequestComplete(false)
, _parameterLoader(NULL)
......@@ -106,6 +108,7 @@ Vehicle::Vehicle(LinkInterface* link,
, _autopilotPluginManager(autopilotPluginManager)
, _joystickManager(joystickManager)
, _flowImageIndex(0)
, _allLinksInactiveSent(false)
{
_addLink(link);
......@@ -119,9 +122,10 @@ Vehicle::Vehicle(LinkInterface* link,
setLatitude(_uas->getLatitude());
setLongitude(_uas->getLongitude());
connect(_uas, &UAS::latitudeChanged, this, &Vehicle::setLatitude);
connect(_uas, &UAS::longitudeChanged, this, &Vehicle::setLongitude);
connect(_uas, &UAS::imageReady, this, &Vehicle::_imageReady);
connect(_uas, &UAS::latitudeChanged, this, &Vehicle::setLatitude);
connect(_uas, &UAS::longitudeChanged, this, &Vehicle::setLongitude);
connect(_uas, &UAS::imageReady, this, &Vehicle::_imageReady);
connect(_uas, &UAS::remoteControlRSSIChanged, this, &Vehicle::_remoteControlRSSIChanged);
_firmwarePlugin = _firmwarePluginManager->firmwarePluginForAutopilot(_firmwareType, _vehicleType);
_autopilotPlugin = _autopilotPluginManager->newAutopilotPluginForVehicle(this);
......@@ -186,6 +190,8 @@ Vehicle::Vehicle(LinkInterface* link,
Vehicle::~Vehicle()
{
qCDebug(VehicleLog) << "~Vehicle" << this;
delete _missionManager;
_missionManager = NULL;
......@@ -285,38 +291,29 @@ void Vehicle::_handleHeartbeat(mavlink_message_t& message)
bool Vehicle::_containsLink(LinkInterface* link)
{
foreach (SharedLinkInterface sharedLink, _links) {
if (sharedLink.data() == link) {
return true;
}
}
return false;
return _links.contains(link);
}
void Vehicle::_addLink(LinkInterface* link)
{
if (!_containsLink(link)) {
_links += qgcApp()->toolbox()->linkManager()->sharedPointerForLink(link);
_links += link;
qCDebug(VehicleLog) << "_addLink:" << QString("%1").arg((ulong)link, 0, 16);
connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkDisconnected, this, &Vehicle::_linkDisconnected);
connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkInactive, this, &Vehicle::_linkInactiveOrDeleted);
connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkDeleted, this, &Vehicle::_linkInactiveOrDeleted);
}
}
void Vehicle::_linkDisconnected(LinkInterface* link)
void Vehicle::_linkInactiveOrDeleted(LinkInterface* link)
{
qCDebug(VehicleLog) << "_linkDisconnected:" << link->getName();
qCDebug(VehicleLog) << "link count:" << _links.count();
qCDebug(VehicleLog) << "_linkInactiveOrDeleted linkCount" << _links.count();
for (int i=0; i<_links.count(); i++) {
if (_links[i].data() == link) {
_links.removeAt(i);
break;
}
}
_links.removeOne(link);
if (_links.count() == 0) {
emit allLinksDisconnected(this);
if (_links.count() == 0 && !_allLinksInactiveSent) {
// Make sure to not send this more than one time
_allLinksInactiveSent = true;
emit allLinksInactive(this);
}
}
......@@ -328,10 +325,7 @@ void Vehicle::sendMessage(mavlink_message_t message)
void Vehicle::_sendMessage(mavlink_message_t message)
{
// Emit message on all links that are currently connected
foreach (SharedLinkInterface sharedLink, _links) {
LinkInterface* link = sharedLink.data();
Q_ASSERT(link);
foreach (LinkInterface* link, _links) {
if (link->isConnected()) {
MAVLinkProtocol* mavlink = _mavlink;
......@@ -350,17 +344,6 @@ void Vehicle::_sendMessage(mavlink_message_t message)
}
}
QList<LinkInterface*> Vehicle::links(void)
{
QList<LinkInterface*> list;
foreach (SharedLinkInterface sharedLink, _links) {
list += sharedLink.data();
}
return list;
}
void Vehicle::setLatitude(double latitude)
{
_coordinate.setLatitude(latitude);
......@@ -1035,11 +1018,11 @@ void Vehicle::_parametersReady(bool parametersReady)
void Vehicle::_communicationInactivityTimedOut(void)
{
// Vechile is no longer communicating with us, disconnect all links
// Vehicle is no longer communicating with us, disconnect all links inactive
LinkManager* linkMgr = qgcApp()->toolbox()->linkManager();
for (int i=0; i<_links.count(); i++) {
linkMgr->disconnectLink(_links[i].data());
linkMgr->disconnectLink(_links[i], false /* disconnectAutoconnectLink */);
}
}
......@@ -1058,3 +1041,17 @@ void Vehicle::_imageReady(UASInterface*)
emit flowImageIndexChanged();
}
}
void Vehicle::_remoteControlRSSIChanged(uint8_t rssi)
{
// Low pass to git rid of jitter
_rcRSSIstore = (_rcRSSIstore * 0.9f) + ((float)rssi * 0.1);
uint8_t filteredRSSI = (uint8_t)ceil(_rcRSSIstore);
if(_rcRSSIstore < 0.1) {
filteredRSSI = 0;
}
if(_rcRSSI != filteredRSSI) {
_rcRSSI = filteredRSSI;
emit rcRSSIChanged(_rcRSSI);
}
}
......@@ -107,6 +107,7 @@ public:
Q_PROPERTY(bool joystickEnabled READ joystickEnabled WRITE setJoystickEnabled NOTIFY joystickEnabledChanged)
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(int flowImageIndex READ flowImageIndex NOTIFY flowImageIndexChanged)
Q_PROPERTY(int rcRSSI READ rcRSSI NOTIFY rcRSSIChanged)
/// Returns the number of buttons which are reserved for firmware use in the MANUAL_CONTROL mavlink
/// message. For example PX4 Flight Stack reserves the first 8 buttons to simulate rc switches.
......@@ -166,8 +167,6 @@ public:
/// Provides access to the Firmware Plugin for this Vehicle
FirmwarePlugin* firmwarePlugin(void) { return _firmwarePlugin; }
QList<LinkInterface*> links(void);
int manualControlReservedButtonCount(void);
MissionManager* missionManager(void) { return _missionManager; }
......@@ -245,6 +244,7 @@ public:
QString currentState () { return _currentState; }
int satelliteLock () { return _satelliteLock; }
unsigned int heartbeatTimeout () { return _currentHeartbeatTimeout; }
int rcRSSI () { return _rcRSSI; }
ParameterLoader* getParameterLoader(void);
......@@ -253,7 +253,7 @@ public slots:
void setLongitude(double longitude);
signals:
void allLinksDisconnected(Vehicle* vehicle);
void allLinksInactive(Vehicle* vehicle);
void coordinateChanged(QGeoCoordinate coordinate);
void coordinateValidChanged(bool coordinateValid);
void joystickModeChanged(int mode);
......@@ -293,15 +293,17 @@ signals:
void currentStateChanged ();
void satelliteLockChanged ();
void flowImageIndexChanged ();
void rcRSSIChanged (int rcRSSI);
private slots:
void _mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message);
void _linkDisconnected(LinkInterface* link);
void _linkInactiveOrDeleted(LinkInterface* link);
void _sendMessage(mavlink_message_t message);
void _sendMessageMultipleNext(void);
void _addNewMapTrajectoryPoint(void);
void _parametersReady(bool parametersReady);
void _communicationInactivityTimedOut(void);
void _remoteControlRSSIChanged(uint8_t rssi);
void _handleTextMessage (int newCount);
/** @brief Attitude from main autopilot / system state */
......@@ -347,10 +349,7 @@ private:
AutoPilotPlugin* _autopilotPlugin;
MAVLinkProtocol* _mavlink;
/// List of all links associated with this vehicle. We keep SharedLinkInterface objects
/// which are QSharedPointer's in order to maintain reference counts across threads.
/// This way Link deletion works correctly.