Commit 18dc3d04 authored by Don Gagne's avatar Don Gagne
Browse files

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 eb13a148
......@@ -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)
......@@ -81,6 +84,8 @@ public:
// Property accesors
LinkManager* linkManager () { return _linkManager; }
MultiVehicleManager* multiVehicleManager () { return _multiVehicleManager; }
HomePositionManager* homePositionManager () { return _homePositionManager; }
FlightMapSettings* flightMapSettings () { return _flightMapSettings; }
......@@ -124,6 +129,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.
QList<SharedLinkInterface> _links;
QList<LinkInterface*> _links;
JoystickMode_t _joystickMode;
bool _joystickEnabled;
......@@ -394,6 +393,8 @@ private:
int _satelliteCount;
int _satelliteLock;
int _updateCount;
int _rcRSSI;
double _rcRSSIstore;
MissionManager* _missionManager;
bool _missionManagerInitialRequestComplete;
......@@ -434,6 +435,8 @@ private:
int _flowImageIndex;
bool _allLinksInactiveSent; ///< true: allLinkInactive signal already sent one time
// Settings keys
static const char* _settingsGroup;
static const char* _joystickModeSettingsKey;
......
......@@ -26,12 +26,13 @@ import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Dialogs 1.2
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.ScreenTools 1.0
QGCView {
id: qgcView
......@@ -88,7 +89,7 @@ QGCView {
onBoardFound: {
if (initialBoardSearch) {
// Board was found right away, so something is already plugged in before we've started upgrade
if (controller.qgcConnections) {
if (QGroundControl.linkManager.anyActiveLinks) {
statusTextArea.append(qgcDisconnectText)
} else {
statusTextArea.append(usbUnplugText.replace('{0}', controller.boardType))
......
......@@ -68,13 +68,17 @@ FirmwareUpgradeController::FirmwareUpgradeController(void) :
connect(_threadController, &PX4FirmwareUpgradeThreadController::flashComplete, this, &FirmwareUpgradeController::_flashComplete);
connect(_threadController, &PX4FirmwareUpgradeThreadController::updateProgress, this, &FirmwareUpgradeController::_updateProgress);
connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkDisconnected, this, &FirmwareUpgradeController::_linkDisconnected);
connect(&_eraseTimer, &QTimer::timeout, this, &FirmwareUpgradeController::_eraseProgressTick);
}
FirmwareUpgradeController::~FirmwareUpgradeController()
{
qgcApp()->toolbox()->linkManager()->setConnectionsAllowed();
}
void FirmwareUpgradeController::startBoardSearch(void)
{
qgcApp()->toolbox()->linkManager()->setConnectionsSuspended(tr("Connect not allowed during Firmware Upgrade."));
_bootloaderFound = false;
_startFlashWhenBootloaderFound = false;
_threadController->startFindBoardLoop();
......@@ -556,17 +560,6 @@ void FirmwareUpgradeController::_appendStatusLog(const QString& text, bool criti
Q_ARG(QVariant, varText));
}
bool FirmwareUpgradeController::qgcConnections(void)
{
return qgcApp()->toolbox()->linkManager()->anyConnectedLinks();
}
void FirmwareUpgradeController::_linkDisconnected(LinkInterface* link)
{
Q_UNUSED(link);
emit qgcConnectionsChanged(qgcConnections());
}
void FirmwareUpgradeController::_errorCancel(const QString& msg)
{
_appendStatusLog(msg, false);
......
Supports Markdown
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