Commit 5f01d50a authored by Pritam Ghanghas's avatar Pritam Ghanghas

Merge branch 'master' of https://github.com/mavlink/qgroundcontrol into apm_support

parents a16a5f81 af9fb749
......@@ -2,7 +2,7 @@
environment:
matrix:
- BUILD: 'Release'
CONFIG: release
CONFIG: installer
- BUILD: 'Debug'
CONFIG: debug
......@@ -11,11 +11,33 @@ install:
- call "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86
- set PATH=C:\Qt\Tools\QtCreator\bin;C:\Qt\5.4\msvc2013_opengl\bin;%PATH%
- mkdir %LOCALAPPDATA%\QtProject && copy test\qtlogging.ini %LOCALAPPDATA%\QtProject\
- cinst nsis -y -installArgs /D="%programfiles(x86)%\NSIS"
build_script:
- C:\Qt\5.4\msvc2013_opengl\bin\qmake -r CONFIG-=debug_and_release CONFIG+=%CONFIG% CONFIG+=WarningsAsErrorsOn qgroundcontrol.pro
- jom -j 2
- C:\Qt\5.4\msvc2013_opengl\bin\qmake -r CONFIG-=debug_and_release CONFIG+=%CONFIG% CONFIG+=WarningsAsErrorsOn qgroundcontrol.pro
- jom -j 4
test_script:
# - if "%CONFIG%" EQU "debug" ( debug\qgroundcontrol --unittest )
- if "%CONFIG%" EQU "debug" ( debug\qgroundcontrol --unittest )
after_build:
- if "%CONFIG%" EQU "installer" ( appveyor PushArtifact C:\projects\qgroundcontrol\release\qgroundcontrol-installer-win32.exe )
deploy:
- provider: S3
name: qgroundcontrol-s3
access_key_id: AKIAIVORNALE7NHD3T6Q
secret_access_key:
secure: RiYqaR+3T2PMNz2j5ur8LCA6H/Zfd4jTX33CZE5iBxm+zaz4QLs25p0B7prpaoNN
bucket: qgrondcontrol
set_public: true
folder: "%APPVEYOR_REPO_BRANCH%"
artifact: C:\projects\qgroundcontrol\release\qgroundcontrol-installer-win32.exe
- provider: GitHub
artifact: C:\projects\qgroundcontrol\release\qgroundcontrol-installer-win32.exe
draft: false
prerelease: false
on:
appveyor_repo_tag: true
......@@ -17,10 +17,10 @@ matrix:
env: SPEC=linux-g++-64 CONFIG=installer
sudo: true
- os: osx
osx_image: beta-xcode6.3
osx_image: xcode7
env: SPEC=macx-clang CONFIG=debug
- os: osx
osx_image: beta-xcode6.3
osx_image: xcode7
env: SPEC=macx-clang CONFIG=installer
- os: android
language: android
......@@ -44,6 +44,7 @@ before_install:
- cd ${TRAVIS_BUILD_DIR} && git fetch --unshallow && git fetch --tags
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then mkdir -p ~/.config/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/.config/QtProject/; fi
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then mkdir -p ~/Library/Preferences/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/Library/Preferences/QtProject/; fi
- if [ "${TRAVIS_OS_NAME}" = "android" ]; then wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/gstreamer-1.0-android-armv7-1.5.2.tar.bz2 && mkdir -p ${TRAVIS_BUILD_DIR}/gstreamer-1.0-android-armv7-1.5.2 && tar jxf gstreamer-1.0-android-armv7-1.5.2.tar.bz2 -C ${TRAVIS_BUILD_DIR}/gstreamer-1.0-android-armv7-1.5.2; fi
install:
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
......
......@@ -264,6 +264,7 @@ HEADERS += \
src/QmlControls/MavlinkQmlSingleton.h \
src/QmlControls/ParameterEditorController.h \
src/QmlControls/ScreenToolsController.h \
src/QmlControls/QGroundControlQmlGlobal.h \
src/QmlControls/QmlObjectListModel.h \
src/SerialPortIds.h \
src/uas/FileManager.h \
......@@ -335,7 +336,6 @@ HEADERS += \
src/ui/WaypointViewOnlyView.h \
src/ViewWidgets/CustomCommandWidget.h \
src/ViewWidgets/CustomCommandWidgetController.h \
src/ViewWidgets/ParameterEditorWidget.h \
src/ViewWidgets/ViewWidgetController.h \
src/MissionItem.h \
src/AutoPilotPlugins/PX4/PX4AirframeLoader.h
......@@ -395,6 +395,7 @@ SOURCES += \
src/QGCTemporaryFile.cc \
src/QmlControls/ParameterEditorController.cc \
src/QmlControls/ScreenToolsController.cc \
src/QmlControls/QGroundControlQmlGlobal.cc \
src/QmlControls/QmlObjectListModel.cc \
src/uas/FileManager.cc \
src/uas/UAS.cc \
......@@ -464,7 +465,6 @@ SOURCES += \
src/ui/WaypointViewOnlyView.cc \
src/ViewWidgets/CustomCommandWidget.cc \
src/ViewWidgets/CustomCommandWidgetController.cc \
src/ViewWidgets/ParameterEditorWidget.cc \
src/ViewWidgets/ViewWidgetController.cc \
src/MissionItem.cc \
src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc
......@@ -578,6 +578,7 @@ HEADERS+= \
src/AutoPilotPlugins/PX4/SensorsComponentController.h \
src/FirmwarePlugin/FirmwarePluginManager.h \
src/FirmwarePlugin/FirmwarePlugin.h \
src/FirmwarePlugin/APM/APMFirmwarePlugin.h \
src/FirmwarePlugin/Generic/GenericFirmwarePlugin.h \
src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h \
src/Vehicle/MultiVehicleManager.h \
......@@ -614,6 +615,7 @@ SOURCES += \
src/AutoPilotPlugins/PX4/SafetyComponent.cc \
src/AutoPilotPlugins/PX4/SensorsComponent.cc \
src/AutoPilotPlugins/PX4/SensorsComponentController.cc \
src/FirmwarePlugin/APM/APMFirmwarePlugin.cc \
src/FirmwarePlugin/FirmwarePluginManager.cc \
src/FirmwarePlugin/Generic/GenericFirmwarePlugin.cc \
src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc \
......
......@@ -157,7 +157,7 @@ MacBuild {
CONFIG += x86_64
CONFIG -= x86
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
QMAKE_MAC_SDK = macosx10.9
QMAKE_MAC_SDK = macosx10.11
}
LinuxBuild {
......
......@@ -110,7 +110,6 @@
<file alias="SetupParameterEditor.qml">src/VehicleSetup/SetupParameterEditor.qml</file>
<file alias="ScreenToolsFontQuery.qml">src/QmlControls/ScreenToolsFontQuery.qml</file>
<file alias="ParameterEditorWidget.qml">src/ViewWidgets/ParameterEditorWidget.qml</file>
<file alias="CustomCommandWidget.qml">src/ViewWidgets/CustomCommandWidget.qml</file>
<file alias="SafetyComponent.qml">src/AutoPilotPlugins/PX4/SafetyComponent.qml</file>
<file alias="RadioComponent.qml">src/AutoPilotPlugins/PX4/RadioComponent.qml</file>
......
......@@ -157,9 +157,9 @@ Fact* AutoPilotPlugin::getFact(FactSystem::Provider_t provider, int componentId,
return NULL;
}
QStringList AutoPilotPlugin::parameterNames(void)
QStringList AutoPilotPlugin::parameterNames(int componentId)
{
return _getParameterLoader()->parameterNames();
return _getParameterLoader()->parameterNames(componentId);
}
const QMap<int, QMap<QString, QStringList> >& AutoPilotPlugin::getGroupMap(void)
......
......@@ -81,8 +81,7 @@ public:
Q_INVOKABLE bool parameterExists(int componentId, const QString& name);
/// Returns all parameter names
/// FIXME: component id missing, generic to fact
QStringList parameterNames(void);
QStringList parameterNames(int componentId);
/// Returns the specified parameter Fact from the default component
/// WARNING: Returns a default Fact if parameter does not exists. If that possibility exists, check for existince first with
......
......@@ -38,5 +38,5 @@ FactSystemTestGeneric::FactSystemTestGeneric(void)
void FactSystemTestGeneric::init(void)
{
UnitTest::init();
_init(MAV_AUTOPILOT_ARDUPILOTMEGA);
_init(MAV_AUTOPILOT_GENERIC);
}
......@@ -30,6 +30,7 @@
#include "QGCApplication.h"
#include "QGCMessageBox.h"
#include "UASMessageHandler.h"
#include "FirmwarePlugin.h"
#include <QFile>
#include <QDebug>
......@@ -387,11 +388,11 @@ Fact* ParameterLoader::getFact(int componentId, const QString& name)
return _mapParameterName2Variant[componentId][name].value<Fact*>();
}
QStringList ParameterLoader::parameterNames(void)
QStringList ParameterLoader::parameterNames(int componentId)
{
QStringList names;
foreach(QString paramName, _mapParameterName2Variant[_defaultComponentId].keys()) {
foreach(QString paramName, _mapParameterName2Variant[_actualComponentId(componentId)].keys()) {
names << paramName;
}
......@@ -499,8 +500,6 @@ void ParameterLoader::_readParameterRaw(int componentId, const QString& paramNam
void ParameterLoader::_writeParameterRaw(int componentId, const QString& paramName, const QVariant& value)
{
bool floatHack = _vehicle->firmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA;
mavlink_param_set_t p;
mavlink_param_union_t union_value;
......@@ -509,43 +508,23 @@ void ParameterLoader::_writeParameterRaw(int componentId, const QString& paramNa
switch (factType) {
case FactMetaData::valueTypeUint8:
if (floatHack) {
union_value.param_float = (uint8_t)value.toUInt();
} else {
union_value.param_uint8 = (uint8_t)value.toUInt();
}
union_value.param_uint8 = (uint8_t)value.toUInt();
break;
case FactMetaData::valueTypeInt8:
if (floatHack) {
union_value.param_float = (int8_t)value.toInt();
} else {
union_value.param_int8 = (int8_t)value.toInt();
}
union_value.param_int8 = (int8_t)value.toInt();
break;
case FactMetaData::valueTypeUint16:
if (floatHack) {
union_value.param_float = (uint16_t)value.toUInt();
} else {
union_value.param_uint16 = (uint16_t)value.toUInt();
}
union_value.param_uint16 = (uint16_t)value.toUInt();
break;
case FactMetaData::valueTypeInt16:
if (floatHack) {
union_value.param_float = (int16_t)value.toInt();
} else {
union_value.param_int16 = (int16_t)value.toInt();
}
union_value.param_int16 = (int16_t)value.toInt();
break;
case FactMetaData::valueTypeUint32:
if (floatHack) {
union_value.param_float = (uint32_t)value.toUInt();
} else {
union_value.param_uint32 = (uint32_t)value.toUInt();
}
union_value.param_uint32 = (uint32_t)value.toUInt();
break;
case FactMetaData::valueTypeFloat:
......@@ -557,11 +536,7 @@ void ParameterLoader::_writeParameterRaw(int componentId, const QString& paramNa
// fall through
case FactMetaData::valueTypeInt32:
if (floatHack) {
union_value.param_float = (int32_t)value.toInt();
} else {
union_value.param_int32 = (int32_t)value.toInt();
}
union_value.param_int32 = (int32_t)value.toInt();
break;
}
......@@ -578,10 +553,14 @@ void ParameterLoader::_writeParameterRaw(int componentId, const QString& paramNa
void ParameterLoader::_saveToEEPROM(void)
{
mavlink_message_t msg;
mavlink_msg_command_long_pack(_mavlink->getSystemId(), _mavlink->getComponentId(), &msg, _vehicle->id(), 0, MAV_CMD_PREFLIGHT_STORAGE, 1, 1, -1, -1, -1, 0, 0, 0);
_vehicle->sendMessage(msg);
qCDebug(ParameterLoaderLog) << "_saveToEEPROM";
if (_vehicle->firmwarePlugin()->isCapable(FirmwarePlugin::MavCmdPreflightStorageCapability)) {
mavlink_message_t msg;
mavlink_msg_command_long_pack(_mavlink->getSystemId(), _mavlink->getComponentId(), &msg, _vehicle->id(), 0, MAV_CMD_PREFLIGHT_STORAGE, 1, 1, -1, -1, -1, 0, 0, 0);
_vehicle->sendMessage(msg);
qCDebug(ParameterLoaderLog) << "_saveToEEPROM";
} else {
qCDebug(ParameterLoaderLog) << "_saveToEEPROM skipped due to FirmwarePlugin::isCapable";
}
}
QString ParameterLoader::readParametersFromStream(QTextStream& stream)
......
......@@ -69,8 +69,7 @@ public:
const QString& name); ///< fact name
/// Returns all parameter names
/// FIXME: component id missing
QStringList parameterNames(void);
QStringList parameterNames(int componentId);
/// Returns the specified Fact.
/// WARNING: Will assert if parameter does not exists. If that possibily exists, check for existince first with
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "APMFirmwarePlugin.h"
#include "Generic/GenericFirmwarePlugin.h"
#include <QDebug>
IMPLEMENT_QGC_SINGLETON(APMFirmwarePlugin, FirmwarePlugin)
APMFirmwarePlugin::APMFirmwarePlugin(QObject* parent) :
FirmwarePlugin(parent)
{
}
bool APMFirmwarePlugin::isCapable(FirmwareCapabilities capabilities)
{
Q_UNUSED(capabilities);
// FIXME: No capabilitis yet supported
return false;
}
QList<VehicleComponent*> APMFirmwarePlugin::componentsForVehicle(AutoPilotPlugin* vehicle)
{
Q_UNUSED(vehicle);
return QList<VehicleComponent*>();
}
QStringList APMFirmwarePlugin::flightModes(void)
{
// FIXME: NYI
qWarning() << "APMFirmwarePlugin::flightModes not supported";
return QStringList();
}
QString APMFirmwarePlugin::flightMode(uint8_t base_mode, uint32_t custom_mode)
{
// FIXME: Nothing more than generic support yet
return GenericFirmwarePlugin::instance()->flightMode(base_mode, custom_mode);
}
bool APMFirmwarePlugin::setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode)
{
Q_UNUSED(flightMode);
Q_UNUSED(base_mode);
Q_UNUSED(custom_mode);
qWarning() << "APMFirmwarePlugin::setFlightMode called on base class, not supported";
return false;
}
int APMFirmwarePlugin::manualControlReservedButtonCount(void)
{
// We don't know whether the firmware is going to used any of these buttons.
// So reserve them all.
return -1;
}
void APMFirmwarePlugin::adjustMavlinkMessage(mavlink_message_t* message)
{
if (message->msgid == MAVLINK_MSG_ID_PARAM_VALUE) {
mavlink_param_value_t paramValue;
mavlink_param_union_t paramUnion;
// APM stack passes all parameter values in mavlink_param_union_t.param_float no matter what
// type they are. Fix that up to correct usage.
mavlink_msg_param_value_decode(message, &paramValue);
switch (paramValue.param_type) {
case MAV_PARAM_TYPE_UINT8:
paramUnion.param_uint8 = (uint8_t)paramValue.param_value;
break;
case MAV_PARAM_TYPE_INT8:
paramUnion.param_int8 = (int8_t)paramValue.param_value;
break;
case MAV_PARAM_TYPE_UINT16:
paramUnion.param_uint16 = (uint16_t)paramValue.param_value;
break;
case MAV_PARAM_TYPE_INT16:
paramUnion.param_int16 = (int16_t)paramValue.param_value;
break;
case MAV_PARAM_TYPE_UINT32:
paramUnion.param_uint32 = (uint32_t)paramValue.param_value;
break;
case MAV_PARAM_TYPE_INT32:
paramUnion.param_int32 = (int32_t)paramValue.param_value;
break;
case MAV_PARAM_TYPE_REAL32:
paramUnion.param_float = paramValue.param_value;
break;
default:
qCritical() << "Invalid/Unsupported data type used in parameter:" << paramValue.param_type;
}
paramValue.param_value = paramUnion.param_float;
mavlink_msg_param_value_encode(message->sysid, message->compid, message, &paramValue);
} else if (message->msgid == MAVLINK_MSG_ID_PARAM_SET) {
mavlink_param_set_t paramSet;
mavlink_param_union_t paramUnion;
// APM stack passes all parameter values in mavlink_param_union_t.param_float no matter what
// type they are. Fix it back to the wrong way on the way out.
mavlink_msg_param_set_decode(message, &paramSet);
paramUnion.param_float = paramSet.param_value;
switch (paramSet.param_type) {
case MAV_PARAM_TYPE_UINT8:
paramSet.param_value = paramUnion.param_uint8;
break;
case MAV_PARAM_TYPE_INT8:
paramSet.param_value = paramUnion.param_int8;
break;
case MAV_PARAM_TYPE_UINT16:
paramSet.param_value = paramUnion.param_uint16;
break;
case MAV_PARAM_TYPE_INT16:
paramSet.param_value = paramUnion.param_int16;
break;
case MAV_PARAM_TYPE_UINT32:
paramSet.param_value = paramUnion.param_uint32;
break;
case MAV_PARAM_TYPE_INT32:
paramSet.param_value = paramUnion.param_int32;
break;
case MAV_PARAM_TYPE_REAL32:
// Already in param_float
break;
default:
qCritical() << "Invalid/Unsupported data type used in parameter:" << paramSet.param_type;
}
mavlink_msg_param_set_encode(message->sysid, message->compid, message, &paramSet);
}
// FIXME: Need to implement mavlink message severity adjustment
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef APMFirmwarePlugin_H
#define APMFirmwarePlugin_H
#include "FirmwarePlugin.h"
class APMFirmwarePlugin : public FirmwarePlugin
{
Q_OBJECT
DECLARE_QGC_SINGLETON(APMFirmwarePlugin, FirmwarePlugin)
public:
// Overrides from FirmwarePlugin
virtual bool isCapable(FirmwareCapabilities capabilities);
virtual QList<VehicleComponent*> componentsForVehicle(AutoPilotPlugin* vehicle);
virtual QStringList flightModes(void);
virtual QString flightMode(uint8_t base_mode, uint32_t custom_mode);
virtual bool setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode);
virtual int manualControlReservedButtonCount(void);
virtual void adjustMavlinkMessage(mavlink_message_t* message);
private:
/// All access to singleton is through AutoPilotPluginManager::instance
APMFirmwarePlugin(QObject* parent = NULL);
};
#endif
......@@ -51,7 +51,9 @@ class FirmwarePlugin : public QGCSingleton
public:
/// Set of optional capabilites which firmware may support
typedef enum {
SetFlightModeCapability,
SetFlightModeCapability, ///< FirmwarePlugin::setFlightMode method is supported
MavCmdPreflightStorageCapability, ///< MAV_CMD_PREFLIGHT_STORAGE is supported
} FirmwareCapabilities;
/// @return true: Firmware supports all specified capabilites
......@@ -76,12 +78,20 @@ public:
/// @param[out] custom_mode Custom mode for SET_MODE mavlink message
virtual bool setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode) = 0;
/// FIXME: This isn't quite correct being here. All code for Joystick support is currently firmware specific
/// not just this. I'm going to try to change that. If not, this will need to be removed.
/// 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.
/// The remainder can be assigned to Vehicle actions.
/// @return -1: reserver all buttons, >0 number of buttons to reserve
virtual int manualControlReservedButtonCount(void) = 0;
/// Called before any mavlink message is processed by Vehicle such taht the firmwre plugin
/// can adjust any message characteristics. This is handy to adjust or differences in mavlink
/// spec implementations such that the base code can remain mavlink generic.
/// @param message[in,out] Mavlink message to adjust if needed.
virtual void adjustMavlinkMessage(mavlink_message_t* message) = 0;
protected:
FirmwarePlugin(QObject* parent = NULL) : QGCSingleton(parent) { }
};
......
......@@ -26,6 +26,7 @@
#include "FirmwarePluginManager.h"
#include "Generic/GenericFirmwarePlugin.h"
#include "APM/APMFirmwarePlugin.h"
#include "PX4/PX4FirmwarePlugin.h"
IMPLEMENT_QGC_SINGLETON(FirmwarePluginManager, FirmwarePluginManager)
......@@ -43,9 +44,12 @@ FirmwarePluginManager::~FirmwarePluginManager()
FirmwarePlugin* FirmwarePluginManager::firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType)
{
if (autopilotType == MAV_AUTOPILOT_PX4) {
return PX4FirmwarePlugin::instance();
} else {
return GenericFirmwarePlugin::instance();
switch (autopilotType) {
case MAV_AUTOPILOT_ARDUPILOTMEGA:
return APMFirmwarePlugin::instance();
case MAV_AUTOPILOT_PX4:
return PX4FirmwarePlugin::instance();
default:
return GenericFirmwarePlugin::instance();
}
}
......@@ -96,3 +96,10 @@ int GenericFirmwarePlugin::manualControlReservedButtonCount(void)
// So reserve them all.
return -1;
}
void GenericFirmwarePlugin::adjustMavlinkMessage(mavlink_message_t* message)
{
Q_UNUSED(message);
// Generic plugin does no message adjustment
}
......@@ -44,7 +44,8 @@ public:
virtual QString flightMode(uint8_t base_mode, uint32_t custom_mode);
virtual bool setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode);
virtual int manualControlReservedButtonCount(void);
virtual void adjustMavlinkMessage(mavlink_message_t* message);
private:
/// All access to singleton is through AutoPilotPluginManager::instance
GenericFirmwarePlugin(QObject* parent = NULL);
......
......@@ -181,3 +181,15 @@ int PX4FirmwarePlugin::manualControlReservedButtonCount(void)
{
return 8; // 8 buttons reserved for rc switch simulation
}
void PX4FirmwarePlugin::adjustMavlinkMessage(mavlink_message_t* message)
{
Q_UNUSED(message);
// PX4 Flight Stack plugin does no message adjustment
}
bool PX4FirmwarePlugin::isCapable(FirmwareCapabilities capabilities)
{
return capabilities == MavCmdPreflightStorageCapability;
}
......@@ -38,13 +38,14 @@ class PX4FirmwarePlugin : public FirmwarePlugin
public:
// Overrides from FirmwarePlugin
virtual bool isCapable(FirmwareCapabilities capabilities) { Q_UNUSED(capabilities); return false; }
virtual bool isCapable(FirmwareCapabilities capabilities);
virtual QList<VehicleComponent*> componentsForVehicle(AutoPilotPlugin* vehicle);
virtual QStringList flightModes(void);
virtual QString flightMode(uint8_t base_mode, uint32_t custom_mode);
virtual bool setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode);
virtual int manualControlReservedButtonCount(void);
virtual void adjustMavlinkMessage(mavlink_message_t* message);
private:
/// All access to singleton is through AutoPilotPluginManager::instance
PX4FirmwarePlugin(QObject* parent = NULL);
......
......@@ -40,24 +40,47 @@
IMPLEMENT_QGC_SINGLETON(HomePositionManager, HomePositionManager)
HomePositionManager::HomePositionManager(QObject* parent) :
QObject(parent),
homeLat(47.3769),
homeLon(8.549444),
homeAlt(470.0),
homeFrame(MAV_FRAME_GLOBAL)
const char* HomePositionManager::_settingsGroup = "HomePositionManager";
const char* HomePositionManager::_latitudeKey = "Latitude";
const char* HomePositionManager::_longitudeKey = "Longitude";
const char* HomePositionManager::_altitudeKey = "Altitude";
HomePositionManager::HomePositionManager(QObject* parent)
: QObject(parent)
, homeLat(47.3769)
, homeLon(8.549444)
, homeAlt(470.0)
{
loadSettings();
_loadSettings();
}
HomePositionManager::~HomePositionManager()
{
storeSettings();
}
void HomePositionManager::storeSettings()
void HomePositionManager::_storeSettings(void)
{
QSettings settings;
settings.remove(_settingsGroup);
settings.beginGroup(_settingsGroup);
for (int i=0; i<_homePositions.count(); i++) {
HomePosition* homePos = qobject_cast<HomePosition*>(_homePositions[i]);
qDebug() << "Saving" << homePos->name();
settings.beginGroup(homePos->name());
settings.setValue(_latitudeKey, homePos->coordinate().latitude());
settings.setValue(_longitudeKey, homePos->coordinate().longitude());
settings.setValue(_altitudeKey, homePos->coordinate().altitude());
settings.endGroup();
}
settings.endGroup();
// Deprecated settings for old editor
settings.beginGroup("QGC_UASMANAGER");
settings.setValue("HOMELAT", homeLat);
settings.setValue("HOMELON", homeLon);
......@@ -65,9 +88,36 @@ void HomePositionManager::storeSettings()
settings.endGroup();
}
void HomePositionManager::loadSettings()
void HomePositionManager::_loadSettings(void)
{
QSettings settings;
_homePositions.clear();
settings.beginGroup(_settingsGroup);
foreach(QString name, settings.childGroups()) {
QGeoCoordinate coordinate;
qDebug() << "Load setting" << name;
settings.beginGroup(name);
coordinate.setLatitude(settings.value(_latitudeKey).toDouble());
coordinate.setLongitude(settings.value(_longitudeKey).toDouble());
coordinate.setAltitude(settings.value(_altitudeKey).toDouble());
settings.endGroup();
_homePositions.append(new HomePosition(name, coordinate, this));
}
settings.endGroup();
if (_homePositions.count() == 0) {
_homePositions.append(new HomePosition("ETH Campus", QGeoCoordinate(47.3769, 8.549444, 470.0)));
}
// Deprecated settings for old editor
settings.beginGroup("QGC_UASMANAGER");
bool changed = setHomePosition(settings.value("HOMELAT", homeLat).toDouble(),
settings.value("HOMELON", homeLon).toDouble(),
......@@ -97,9 +147,6 @@ bool HomePositionManager::setHomePosition(double lat, double lon, double alt)
if (fabs(homeLon - lon) > 1e-7) changed = true;
if (fabs(homeAlt - alt) > 0.5f) changed = true;
// Initialize conversion reference in any case
initReference(lat, lon, alt);
if (changed)
{
homeLat = lat;
......@@ -125,75 +172,81 @@ bool HomePositionManager::setHomePositionAndNotify(double lat, double lon, doubl
return changed;
}
void HomePositionManager::initReference(const double & latitude, const double & longitude, const double & altitude)
void HomePositionManager::updateHomePosition(const QString& name, const QGeoCoordinate& coordinate)
{
Eigen::Matrix3d R;
double s_long, s_lat, c_long, c_lat;
sincos(latitude * DEG2RAD, &s_lat, &c_lat);
sincos(longitude * DEG2RAD, &s_long, &c_long);
R(0, 0) = -s_long;
R(0, 1) = c_long;
R(0, 2) = 0;
R(1, 0) = -s_lat * c_long;
R(1, 1) = -s_lat * s_long;
R(1, 2) = c_lat;
R(2, 0) = c_lat * c_long;
R(2, 1) = c_lat * s_long;
R(2, 2) = s_lat;
ecef_ref_orientation_ = Eigen::Quaterniond(R);
ecef_ref_point_ = wgs84ToEcef(latitude, longitude, altitude);
HomePosition * homePos = NULL;
for (int i=0; i<_homePositions.count(); i++) {
homePos = qobject_cast<HomePosition*>(_homePositions[i]);
if (homePos->name() == name) {
break;
}
homePos = NULL;
}
if (homePos == NULL) {
HomePosition* homePos = new HomePosition(name, coordinate, this);
_homePositions.append(homePos);
} else {
homePos->setName(name);
homePos->setCoordinate(coordinate);
}
_storeSettings();
}
Eigen::Vector3d HomePositionManager::wgs84ToEcef(const double & latitude, const double & longitude, const double & altitude)
void HomePositionManager::deleteHomePosition(const QString& name)
{
const double a = 6378137.0; // semi-major axis
const double e_sq = 6.69437999014e-3; // first eccentricity squared
double s_long, s_lat, c_long, c_lat;
sincos(latitude * DEG2RAD, &s_lat, &c_lat);
sincos(longitude * DEG2RAD, &s_long, &c_long);
const double N = a / sqrt(1 - e_sq * s_lat * s_lat);
Eigen::Vector3d ecef;
ecef[0] = (N + altitude) * c_lat * c_long;
ecef[1] = (N + altitude) * c_lat * s_long;
ecef[2] = (N * (1 - e_sq) + altitude) * s_lat;
// Don't allow delete of last position
if (_homePositions.count() == 1) {
return;
}
qDebug() << "Attempting delete" << name;
for (int i=0; i<_homePositions.count(); i++) {
if (qobject_cast<HomePosition*>(_homePositions[i])->name() == name) {
qDebug() << "Deleting" << name;
_homePositions.removeAt(i);
break;
}
}
_storeSettings();
}
return ecef;
HomePosition::HomePosition(const QString& name, const QGeoCoordinate& coordinate, QObject* parent)
: QObject(parent)
, _coordinate(coordinate)
{
setObjectName(name);
}
Eigen::Vector3d HomePositionManager::ecefToEnu(const Eigen::Vector3d & ecef)
HomePosition::~HomePosition()
{
return ecef_ref_orientation_ * (ecef - ecef_ref_point_);
}
void HomePositionManager::wgs84ToEnu(const double& lat, const double& lon, const double& alt, double* east, double* north, double* up)
QString HomePosition::name(void)
{
Eigen::Vector3d ecef = wgs84ToEcef(lat, lon, alt);
Eigen::Vector3d enu = ecefToEnu(ecef);
*east = enu.x();
*north = enu.y();
*up = enu.z();
return objectName();
}
void HomePositionManager::enuToWgs84(const double& x, const double& y, const double& z, double* lat, double* lon, double* alt)
void HomePosition::setName(const QString& name)
{
*lat=homeLat+y/MEAN_EARTH_DIAMETER*360./PI;
*lon=homeLon+x/MEAN_EARTH_DIAMETER*360./PI/cos(homeLat*UMR);
*alt=homeAlt+z;
setObjectName(name);
HomePositionManager::instance()->_storeSettings();
emit nameChanged(name);
}
void HomePositionManager::nedToWgs84(const double& x, const double& y, const double& z, double* lat, double* lon, double* alt)
QGeoCoordinate HomePosition::coordinate(void)
{
*lat=homeLat+x/MEAN_EARTH_DIAMETER*360./PI;
*lon=homeLon+y/MEAN_EARTH_DIAMETER*360./PI/cos(homeLat*UMR);
*alt=homeAlt-z;
return _coordinate;
}
void HomePosition::setCoordinate(const QGeoCoordinate& coordinate)
{
_coordinate = coordinate;
HomePositionManager::instance()->_storeSettings();
emit coordinateChanged(coordinate);
}
......@@ -21,21 +21,41 @@ This file is part of the QGROUNDCONTROL project
======================================================================*/
#ifndef _UASMANAGER_H_
#define _UASMANAGER_H_
#ifndef HomePositionManager_H
#define HomePositionManager_H
#include "UASInterface.h"
#include <QList>
#include <QMutex>
#include "QGCSingleton.h"
#include "QmlObjectListModel.h"
#include <Eigen/Eigen>
#include <QGeoCoordinate>
#include "QGCGeo.h"
#include "QGCSingleton.h"
class HomePosition : public QObject
{
Q_OBJECT
public:
HomePosition(const QString& name, const QGeoCoordinate& coordinate, QObject* parent = NULL);
~HomePosition();
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged)
// Property accessors
QString name(void);
void setName(const QString& name);
QGeoCoordinate coordinate(void);
void setCoordinate(const QGeoCoordinate& coordinate);
signals:
void nameChanged(const QString& name);
void coordinateChanged(const QGeoCoordinate& coordinate);
private:
QGeoCoordinate _coordinate;
};
/// Manages an offline home position as well as performance coordinate transformations
/// around a home position.
class HomePositionManager : public QObject
{
Q_OBJECT
......@@ -43,6 +63,40 @@ class HomePositionManager : public QObject
DECLARE_QGC_SINGLETON(HomePositionManager, HomePositionManager)
public:
Q_PROPERTY(QmlObjectListModel* homePositions READ homePositions CONSTANT)
/// If name is not already a home position a new one will be added, otherwise the existing
/// home position will be updated
Q_INVOKABLE void updateHomePosition(const QString& name, const QGeoCoordinate& coordinate);
Q_INVOKABLE void deleteHomePosition(const QString& name);
// Property accesors
QmlObjectListModel* homePositions(void) { return &_homePositions; }
// Should only be called by HomePosition
void _storeSettings(void);
private:
/// @brief All access to HomePositionManager singleton is through HomePositionManager::instance
HomePositionManager(QObject* parent = NULL);
~HomePositionManager();
void _loadSettings(void);
QmlObjectListModel _homePositions;
static const char* _settingsGroup;
static const char* _latitudeKey;
static const char* _longitudeKey;
static const char* _altitudeKey;
// Everything below is deprecated and will be removed once old Map code is removed
public:
// Deprecated methods
/** @brief Get home position latitude */
double getHomeLatitude() const {
return homeLat;
......@@ -56,24 +110,10 @@ public:
return homeAlt;
}
/** @brief Get the home position coordinate frame */
int getHomeFrame() const
{
return homeFrame;
}
/** @brief Convert WGS84 coordinates to earth centric frame */
Eigen::Vector3d wgs84ToEcef(const double & latitude, const double & longitude, const double & altitude);
/** @brief Convert earth centric frame to EAST-NORTH-UP frame (x-y-z directions */
Eigen::Vector3d ecefToEnu(const Eigen::Vector3d & ecef);
/** @brief Convert WGS84 lat/lon coordinates to carthesian coordinates with home position as origin */
void wgs84ToEnu(const double& lat, const double& lon, const double& alt, double* east, double* north, double* up);
/** @brief Convert x,y,z coordinates to lat / lon / alt coordinates in east-north-up frame */
void enuToWgs84(const double& x, const double& y, const double& z, double* lat, double* lon, double* alt);
/** @brief Convert x,y,z coordinates to lat / lon / alt coordinates in north-east-down frame */
void nedToWgs84(const double& x, const double& y, const double& z, double* lat, double* lon, double* alt);
public slots:
// Deprecated methods
/** @brief Set the current home position, but do not change it on the UAVs */
bool setHomePosition(double lat, double lon, double alt);
......@@ -81,11 +121,6 @@ public slots:
bool setHomePositionAndNotify(double lat, double lon, double alt);
/** @brief Load settings */
void loadSettings();
/** @brief Store settings */
void storeSettings();
signals:
/** @brief Current home position changed */
void homePositionChanged(double lat, double lon, double alt);
......@@ -94,23 +129,6 @@ protected:
double homeLat;
double homeLon;
double homeAlt;
int homeFrame;
Eigen::Quaterniond ecef_ref_orientation_;
Eigen::Vector3d ecef_ref_point_;
void initReference(const double & latitude, const double & longitude, const double & altitude);
private:
/// @brief All access to HomePositionManager singleton is through HomePositionManager::instance
HomePositionManager(QObject* parent = NULL);
~HomePositionManager();
public:
/* Need to align struct pointer to prevent a memory assertion:
* See http://eigen.tuxfamily.org/dox-devel/TopicUnalignedArrayAssert.html
* for details
*/
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
#endif // _UASMANAGER_H_
#endif
......@@ -25,6 +25,7 @@ This file is part of the QGROUNDCONTROL project
#include "ScreenToolsController.h"
#include "MultiVehicleManager.h"
#include "MissionManager.h"
#include "QGCFileDialog.h"
#include <QQmlContext>
#include <QQmlEngine>
......@@ -35,6 +36,7 @@ const char* MissionEditor::_settingsGroup = "MissionEditor";
MissionEditor::MissionEditor(QWidget *parent)
: QGCQmlWidgetHolder(parent)
, _missionItems(NULL)
, _canEdit(true)
{
// Get rid of layout default margins
QLayout* pl = layout();
......@@ -66,10 +68,14 @@ void MissionEditor::_newMissionItemsAvailable(void)
_missionItems->deleteLater();
}
_missionItems = MultiVehicleManager::instance()->activeVehicle()->missionManager()->copyMissionItems();
MissionManager* missionManager = MultiVehicleManager::instance()->activeVehicle()->missionManager();
_canEdit = missionManager->canEdit();
_missionItems = missionManager->copyMissionItems();
_reSequence();
emit missionItemsChanged();
emit canEditChanged(_canEdit);
}
void MissionEditor::getMissionItems(void)
......@@ -77,6 +83,8 @@ void MissionEditor::getMissionItems(void)
Vehicle* activeVehicle = MultiVehicleManager::instance()->activeVehicle();
if (activeVehicle) {
MissionManager* missionManager = activeVehicle->missionManager();
connect(missionManager, &MissionManager::newMissionItemsAvailable, this, &MissionEditor::_newMissionItemsAvailable);
activeVehicle->missionManager()->requestMissionItems();
}
}
......@@ -92,6 +100,10 @@ void MissionEditor::setMissionItems(void)
int MissionEditor::addMissionItem(QGeoCoordinate coordinate)
{
if (!_canEdit) {
qWarning() << "addMissionItem called with _canEdit == false";
}
MissionItem * newItem = new MissionItem(this, _missionItems->count(), coordinate);
if (_missionItems->count() == 0) {
newItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF);
......@@ -111,12 +123,22 @@ void MissionEditor::_reSequence(void)
void MissionEditor::removeMissionItem(int index)
{
if (!_canEdit) {
qWarning() << "addMissionItem called with _canEdit == false";
return;
}
_missionItems->removeAt(index);
_reSequence();
}
void MissionEditor::moveUp(int index)
{
if (!_canEdit) {
qWarning() << "addMissionItem called with _canEdit == false";
return;
}
if (_missionItems->count() < 2 || index <= 0 || index >= _missionItems->count()) {
return;
}
......@@ -135,6 +157,11 @@ void MissionEditor::moveUp(int index)
void MissionEditor::moveDown(int index)
{
if (!_canEdit) {
qWarning() << "addMissionItem called with _canEdit == false";
return;
}
if (_missionItems->count() < 2 || index >= _missionItems->count() - 1) {
return;
}
......@@ -150,3 +177,76 @@ void MissionEditor::moveDown(int index)
_reSequence();
}
void MissionEditor::loadMissionFromFile(void)
{
QString errorString;
QString filename = QGCFileDialog::getOpenFileName(NULL, "Select Mission File to load");
if (filename.isEmpty()) {
return;
}
_missionItems->clear();
_canEdit = true;
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorString = file.errorString();
} else {
QTextStream in(&file);
const QStringList& version = in.readLine().split(" ");
if (!(version.size() == 3 && version[0] == "QGC" && version[1] == "WPL" && version[2] == "120")) {
errorString = "The mission file is not compatible with the current version of QGroundControl.";
} else {
while (!in.atEnd()) {
MissionItem* item = new MissionItem();
if (item->load(in)) {
_missionItems->append(item);
if (!item->canEdit()) {
_canEdit = false;
}
} else {
errorString = "The mission file is corrupted.";
break;
}
}
}
}
if (!errorString.isEmpty()) {
_missionItems->clear();
}
emit canEditChanged(_canEdit);
}
void MissionEditor::saveMissionToFile(void)
{
QString errorString;
QString filename = QGCFileDialog::getSaveFileName(NULL, "Select file to save mission to");
if (filename.isEmpty()) {
return;
}
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
errorString = file.errorString();
} else {
QTextStream out(&file);
out << "QGC WPL 120\r\n"; // Version string
for (int i=0; i<_missionItems->count(); i++) {
qobject_cast<MissionItem*>(_missionItems->get(i))->save(out);
}
}
}
......@@ -35,11 +35,14 @@ public:
MissionEditor(QWidget* parent = NULL);
~MissionEditor();
Q_PROPERTY(QmlObjectListModel* missionItems READ missionItemsModel NOTIFY missionItemsChanged)
Q_PROPERTY(QmlObjectListModel* missionItems READ missionItemsModel NOTIFY missionItemsChanged)
Q_PROPERTY(bool canEdit READ canEdit NOTIFY canEditChanged)
Q_INVOKABLE int addMissionItem(QGeoCoordinate coordinate);
Q_INVOKABLE void getMissionItems(void);
Q_INVOKABLE void setMissionItems(void);
Q_INVOKABLE void loadMissionFromFile(void);
Q_INVOKABLE void saveMissionToFile(void);
Q_INVOKABLE void removeMissionItem(int index);
Q_INVOKABLE void moveUp(int index);
Q_INVOKABLE void moveDown(int index);
......@@ -47,9 +50,11 @@ public:
// Property accessors
QmlObjectListModel* missionItemsModel(void) { return _missionItems; }
bool canEdit(void) { return _canEdit; }
signals:
void missionItemsChanged(void);
void canEditChanged(bool canEdit);
private slots:
void _newMissionItemsAvailable();
......@@ -59,6 +64,7 @@ private:
private:
QmlObjectListModel* _missionItems;
bool _canEdit; ///< true: UI can edit these items, false: can't edit, can only send to vehicle or save
static const char* _settingsGroup;
};
......
This diff is collapsed.
......@@ -34,6 +34,7 @@ This file is part of the QGROUNDCONTROL project
#include "MissionItem.h"
QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog")
QDebug operator<<(QDebug dbg, const MissionItem& missionItem)
{
......@@ -313,12 +314,20 @@ void MissionItem::setAction(int /*MAV_CMD*/ action)
if (_command != action) {
_command = (MavlinkQmlSingleton::Qml_MAV_CMD)action;
// Flick defaults according to WP type
// Fix defaults according to WP type
if (_command == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) {
// We default to 15 degrees minimum takeoff pitch
setParam1(15.0);
}
if (specifiesCoordinate()) {
if (_frame != MAV_FRAME_GLOBAL && _frame != MAV_FRAME_GLOBAL_RELATIVE_ALT) {
setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
}
} else {
setFrame(MAV_FRAME_MISSION);
}
emit changed(this);
emit commandNameChanged(commandName());
......@@ -758,3 +767,32 @@ void MissionItem::setCoordinate(const QGeoCoordinate& coordinate)
setLongitude(coordinate.longitude());
setAltitude(coordinate.altitude());
}
bool MissionItem::canEdit(void)
{
bool found = false;
for (int i=0; i<_cMavCmd2Name; i++) {
if (_rgMavCmd2Name[i].command == (MAV_CMD)_command) {
found = true;
break;
}
}
if (found) {
if (!_autocontinue) {
qCDebug(MissionItemLog) << "canEdit false due to _autocontinue != true";
return false;
}
if (_frame != MAV_FRAME_GLOBAL && _frame != MAV_FRAME_GLOBAL_RELATIVE_ALT && _frame != MAV_FRAME_MISSION) {
qCDebug(MissionItemLog) << "canEdit false due unsupported frame type:" << _frame;
return false;
}
return true;
} else {
qCDebug(MissionItemLog) << "canEdit false due unsupported command:" << _command;
return false;
}
}
......@@ -35,6 +35,9 @@
#include "MavlinkQmlSingleton.h"
#include "QmlObjectListModel.h"
#include "Fact.h"
#include "QGCLoggingCategory.h"
Q_DECLARE_LOGGING_CATEGORY(MissionItemLog)
class MissionItem : public QObject
{
......@@ -104,6 +107,9 @@ public:
void setYawDegrees(double yaw);
// C++ only methods
/// Returns true if this item can be edited in the ui
bool canEdit(void);
double latitude(void) const { return _latitudeFact->value().toDouble(); }
double longitude(void) const { return _longitudeFact->value().toDouble(); }
......
......@@ -31,43 +31,26 @@
QGC_LOGGING_CATEGORY(MissionManagerLog, "MissionManagerLog")
MissionManager::MissionManager(Vehicle* vehicle)
: QThread()
, _vehicle(vehicle)
: _vehicle(vehicle)
, _cMissionItems(0)
, _canEdit(true)
, _ackTimeoutTimer(NULL)
, _retryAck(AckNone)
{
moveToThread(this);
connect(_vehicle, &Vehicle::mavlinkMessageReceived, this, &MissionManager::_mavlinkMessageReceived);
connect(this, &MissionManager::_writeMissionItemsOnThread, this, &MissionManager::_writeMissionItems);
connect(this, &MissionManager::_requestMissionItemsOnThread, this, &MissionManager::_requestMissionItems);
start();
}
MissionManager::~MissionManager()
{
}
void MissionManager::run(void)
{
_ackTimeoutTimer = new QTimer(this);
_ackTimeoutTimer->setSingleShot(true);
_ackTimeoutTimer->setInterval(_ackTimeoutMilliseconds);
connect(_ackTimeoutTimer, &QTimer::timeout, this, &MissionManager::_ackTimeout);
_requestMissionItems();
exec();
requestMissionItems();
}
void MissionManager::requestMissionItems(void)
MissionManager::~MissionManager()
{
emit _requestMissionItemsOnThread();
}
void MissionManager::writeMissionItems(const QmlObjectListModel& missionItems)
......@@ -77,10 +60,28 @@ void MissionManager::writeMissionItems(const QmlObjectListModel& missionItems)
_missionItems.append(new MissionItem(*qobject_cast<const MissionItem*>(missionItems[i])));
}
emit _writeMissionItemsOnThread();
qCDebug(MissionManagerLog) << "writeMissionItems count:" << _missionItems.count();
if (inProgress()) {
qCDebug(MissionManagerLog) << "writeMissionItems called while transaction in progress";
// FIXME: Better error handling
return;
}
mavlink_message_t message;
mavlink_mission_count_t missionCount;
missionCount.target_system = _vehicle->id();
missionCount.target_component = MAV_COMP_ID_MISSIONPLANNER;
missionCount.count = _missionItems.count();
mavlink_msg_mission_count_encode(MAVLinkProtocol::instance()->getSystemId(), MAVLinkProtocol::instance()->getComponentId(), &message, &missionCount);
_vehicle->sendMessage(message);
_startAckTimeout(AckMissionRequest, message);
}
void MissionManager::_requestMissionItems(void)
void MissionManager::requestMissionItems(void)
{
qCDebug(MissionManagerLog) << "_requestMissionItems";
......@@ -172,7 +173,7 @@ void MissionManager::_handleMissionCount(const mavlink_message_t& message)
qCDebug(MissionManagerLog) << "_handleMissionCount count:" << _cMissionItems;
if (_cMissionItems == 0) {
_sendTransactionComplete();
emit newMissionItemsAvailable();
} else {
_requestNextMissionItem(0);
}
......@@ -231,6 +232,11 @@ void MissionManager::_handleMissionItem(const mavlink_message_t& message)
missionItem.command);
_missionItems.append(item);
if (!item->canEdit()) {
_canEdit = false;
emit canEditChanged(false);
}
int nextSequenceNumber = missionItem.seq + 1;
if (nextSequenceNumber == _cMissionItems) {
_sendTransactionComplete();
......@@ -245,29 +251,6 @@ void MissionManager::_clearMissionItems(void)
_missionItems.clear();
}
void MissionManager::_writeMissionItems(void)
{
qCDebug(MissionManagerLog) << "writeMissionItems count:" << _missionItems.count();
if (inProgress()) {
qCDebug(MissionManagerLog) << "writeMissionItems called while transaction in progress";
// FIXME: Better error handling
return;
}
mavlink_message_t message;
mavlink_mission_count_t missionCount;
missionCount.target_system = _vehicle->id();
missionCount.target_component = MAV_COMP_ID_MISSIONPLANNER;
missionCount.count = _missionItems.count();
mavlink_msg_mission_count_encode(MAVLinkProtocol::instance()->getSystemId(), MAVLinkProtocol::instance()->getComponentId(), &message, &missionCount);
_vehicle->sendMessage(message);
_startAckTimeout(AckMissionRequest, message);
}
void MissionManager::_handleMissionRequest(const mavlink_message_t& message)
{
mavlink_mission_request_t missionRequest;
......
......@@ -38,7 +38,7 @@ class Vehicle;
Q_DECLARE_LOGGING_CATEGORY(MissionManagerLog)
class MissionManager : public QThread
class MissionManager : public QObject
{
Q_OBJECT
......@@ -47,13 +47,17 @@ public:
MissionManager(Vehicle* vehicle);
~MissionManager();
Q_PROPERTY(bool inProgress READ inProgress CONSTANT)
Q_PROPERTY(QmlObjectListModel* missionItems READ missionItems CONSTANT)
Q_PROPERTY(bool inProgress READ inProgress CONSTANT)
Q_PROPERTY(QmlObjectListModel* missionItems READ missionItems CONSTANT)
Q_PROPERTY(bool canEdit READ canEdit NOTIFY canEditChanged)
// Property accessors
bool inProgress(void) { return _retryAck != AckNone; }
QmlObjectListModel* missionItems(void) { return &_missionItems; }
bool canEdit(void) { return _canEdit; }
// C++ methods
void requestMissionItems(void);
......@@ -63,11 +67,11 @@ public:
/// Returns a copy of the current set of mission items. Caller is responsible for
/// freeing returned object.
QmlObjectListModel* copyMissionItems(void);
signals:
// Public signals
void canEditChanged(bool canEdit);
void newMissionItemsAvailable(void);
void _requestMissionItemsOnThread(void);
void _writeMissionItemsOnThread(void);
private slots:
void _mavlinkMessageReceived(const mavlink_message_t& message);
......@@ -90,16 +94,12 @@ private:
void _handleMissionAck(const mavlink_message_t& message);
void _requestNextMissionItem(int sequenceNumber);
void _clearMissionItems(void);
void _requestMissionItems(void);
void _writeMissionItems(void);
// Overrides from QThread
void run(void);
private:
Vehicle* _vehicle;
int _cMissionItems; ///< Mission items on vehicle
bool _canEdit; ///< true: Mission items are editable in the ui
QTimer* _ackTimeoutTimer;
AckType_t _retryAck;
......
......@@ -74,12 +74,15 @@
#include "FirmwarePluginManager.h"
#include "MultiVehicleManager.h"
#include "Generic/GenericFirmwarePlugin.h"
#include "APM/APMFirmwarePlugin.h"
#include "PX4/PX4FirmwarePlugin.h"
#include "Vehicle.h"
#include "MavlinkQmlSingleton.h"
#include "JoystickManager.h"
#include "QmlObjectListModel.h"
#include "MissionManager.h"
#include "QGroundControlQmlGlobal.h"
#include "HomePositionManager.h"
#ifndef __ios__
#include "SerialLink.h"
......@@ -124,6 +127,11 @@ static QObject* mavlinkQmlSingletonFactory(QQmlEngine*, QJSEngine*)
return new MavlinkQmlSingleton;
}
static QObject* qgroundcontrolQmlGlobalSingletonFactory(QQmlEngine*, QJSEngine*)
{
return new QGroundControlQmlGlobal;
}
#if defined(QGC_GST_STREAMING)
#ifdef Q_OS_MAC
#ifndef __ios__
......@@ -297,14 +305,15 @@ void QGCApplication::_initCommon(void)
qmlRegisterType<QGCPalette>("QGroundControl.Palette", 1, 0, "QGCPalette");
qmlRegisterUncreatableType<AutoPilotPlugin> ("QGroundControl.AutoPilotPlugin", 1, 0, "AutoPilotPlugin", "Can only reference, cannot create");
qmlRegisterUncreatableType<VehicleComponent> ("QGroundControl.AutoPilotPlugin", 1, 0, "VehicleComponent", "Can only reference, cannot create");
qmlRegisterUncreatableType<Vehicle> ("QGroundControl.Vehicle", 1, 0, "Vehicle", "Can only reference, cannot create");
qmlRegisterUncreatableType<MissionItem> ("QGroundControl.Vehicle", 1, 0, "MissionItem", "Can only reference, cannot create");
qmlRegisterUncreatableType<MissionManager> ("QGroundControl.Vehicle", 1, 0, "MissionManager", "Can only reference, cannot create");
qmlRegisterUncreatableType<JoystickManager> ("QGroundControl.JoystickManager", 1, 0, "JoystickManager", "Reference only");
qmlRegisterUncreatableType<Joystick> ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only");
qmlRegisterUncreatableType<QmlObjectListModel> ("QGroundControl", 1, 0, "QmlObjectListModel", "Reference only");
qmlRegisterUncreatableType<AutoPilotPlugin> ("QGroundControl.AutoPilotPlugin", 1, 0, "AutoPilotPlugin", "Reference only");
qmlRegisterUncreatableType<VehicleComponent> ("QGroundControl.AutoPilotPlugin", 1, 0, "VehicleComponent", "Reference only");
qmlRegisterUncreatableType<Vehicle> ("QGroundControl.Vehicle", 1, 0, "Vehicle", "Reference only");
qmlRegisterUncreatableType<MissionItem> ("QGroundControl.Vehicle", 1, 0, "MissionItem", "Reference only");
qmlRegisterUncreatableType<MissionManager> ("QGroundControl.Vehicle", 1, 0, "MissionManager", "Reference only");
qmlRegisterUncreatableType<JoystickManager> ("QGroundControl.JoystickManager", 1, 0, "JoystickManager", "Reference only");
qmlRegisterUncreatableType<Joystick> ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only");
qmlRegisterUncreatableType<QmlObjectListModel> ("QGroundControl", 1, 0, "QmlObjectListModel", "Reference only");
qmlRegisterUncreatableType<HomePositionManager> ("QGroundControl", 1, 0, "HomePositionManager", "Reference only");
qmlRegisterType<ViewWidgetController> ("QGroundControl.Controllers", 1, 0, "ViewWidgetController");
qmlRegisterType<ParameterEditorController> ("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
......@@ -322,8 +331,9 @@ void QGCApplication::_initCommon(void)
#endif
// Register Qml Singletons
qmlRegisterSingletonType<ScreenToolsController> ("QGroundControl.ScreenToolsController", 1, 0, "ScreenToolsController", screenToolsControllerSingletonFactory);
qmlRegisterSingletonType<MavlinkQmlSingleton> ("QGroundControl.Mavlink", 1, 0, "Mavlink", mavlinkQmlSingletonFactory);
qmlRegisterSingletonType<QGroundControlQmlGlobal> ("QGroundControl", 1, 0, "QGroundControl", qgroundcontrolQmlGlobalSingletonFactory);
qmlRegisterSingletonType<ScreenToolsController> ("QGroundControl.ScreenToolsController", 1, 0, "ScreenToolsController", screenToolsControllerSingletonFactory);
qmlRegisterSingletonType<MavlinkQmlSingleton> ("QGroundControl.Mavlink", 1, 0, "Mavlink", mavlinkQmlSingletonFactory);
// Show user an upgrade message if the settings version has been bumped up
bool settingsUpgraded = false;
......@@ -547,6 +557,7 @@ void QGCApplication::_createSingletons(void)
// No dependencies
firmwarePlugin = PX4FirmwarePlugin::_createSingleton();
firmwarePlugin = APMFirmwarePlugin::_createSingleton();
// No dependencies
FirmwarePluginManager* firmwarePluginManager = FirmwarePluginManager::_createSingleton();
......@@ -628,6 +639,7 @@ void QGCApplication::_destroySingletons(void)
FirmwarePluginManager::_deleteSingleton();
GenericFirmwarePlugin::_deleteSingleton();
PX4FirmwarePlugin::_deleteSingleton();
APMFirmwarePlugin::_deleteSingleton();
}
void QGCApplication::informationMessageBoxOnMainThread(const QString& title, const QString& msg)
......
This diff is collapsed.
......@@ -53,13 +53,35 @@ QStringList ParameterEditorController::getGroupsForComponent(int componentId)
return groupMap[componentId].keys();
}
QStringList ParameterEditorController::getFactsForGroup(int componentId, QString group)
QStringList ParameterEditorController::getParametersForGroup(int componentId, QString group)
{
const QMap<int, QMap<QString, QStringList> >& groupMap = _autopilot->getGroupMap();
return groupMap[componentId][group];
}
QStringList ParameterEditorController::searchParametersForComponent(int componentId, const QString& searchText, bool searchInName, bool searchInDescriptions)
{
QStringList list;
foreach(QString paramName, _autopilot->parameterNames(componentId)) {
if (searchText.isEmpty()) {
list += paramName;
} else {
Fact* fact = _autopilot->getParameterFact(componentId, paramName);
if (searchInName && fact->name().contains(searchText, Qt::CaseInsensitive)) {
list += paramName;
} else if (searchInDescriptions && (fact->shortDescription().contains(searchText, Qt::CaseInsensitive) || fact->longDescription().contains(searchText, Qt::CaseInsensitive))) {
list += paramName;
}
}
}
list.sort();
return list;
}
void ParameterEditorController::clearRCToParam(void)
{
Q_ASSERT(_uas);
......
......@@ -45,7 +45,8 @@ public:
Q_PROPERTY(QStringList componentIds MEMBER _componentIds CONSTANT)
Q_INVOKABLE QStringList getGroupsForComponent(int componentId);
Q_INVOKABLE QStringList getFactsForGroup(int componentId, QString group);
Q_INVOKABLE QStringList getParametersForGroup(int componentId, QString group);
Q_INVOKABLE QStringList searchParametersForComponent(int componentId, const QString& searchText, bool searchInName, bool searchInDescriptions);
Q_INVOKABLE void clearRCToParam(void);
Q_INVOKABLE void saveToFile(void);
......
......@@ -106,6 +106,9 @@ FactPanel {
} else if (buttons & StandardButton.Abort) {
__rejectButton.text = "Abort"
__rejectButton.visible = true
} else if (buttons & StandardButton.Reset) {
__rejectButton.text = "Reset"
__rejectButton.visible = true
}
}
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "QGroundControlQmlGlobal.h"
QGroundControlQmlGlobal::QGroundControlQmlGlobal(QObject* parent)
: QObject(parent)
, _homePositionManager(HomePositionManager::instance())
{
}
QGroundControlQmlGlobal::~QGroundControlQmlGlobal()
{
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef QGroundControlQmlGlobal_H
#define QGroundControlQmlGlobal_H
#include <QObject>
#include "HomePositionManager.h"
class QGroundControlQmlGlobal : public QObject
{
Q_OBJECT
public:
QGroundControlQmlGlobal(QObject* parent = NULL);
~QGroundControlQmlGlobal();
Q_PROPERTY(HomePositionManager* homePositionManager READ homePositionManager CONSTANT)
// Property accesors
HomePositionManager* homePositionManager(void) { return _homePositionManager; }
private:
HomePositionManager* _homePositionManager;
};
#endif
......@@ -29,6 +29,7 @@
#include <QDebug>
const int QmlObjectListModel::ObjectRole = Qt::UserRole;
const int QmlObjectListModel::TextRole = Qt::UserRole + 1;
QmlObjectListModel::QmlObjectListModel(QObject* parent)
: QAbstractListModel(parent)
......@@ -60,6 +61,8 @@ QVariant QmlObjectListModel::data(const QModelIndex &index, int role) const
if (role == ObjectRole) {
return QVariant::fromValue(_objectList[index.row()]);
} else if (role == TextRole) {
return QVariant::fromValue(_objectList[index.row()]->objectName());
} else {
return QVariant();
}
......@@ -70,6 +73,7 @@ QHash<int, QByteArray> QmlObjectListModel::roleNames(void) const
QHash<int, QByteArray> hash;
hash[ObjectRole] = "object";
hash[TextRole] = "text";
return hash;
}
......
......@@ -65,6 +65,7 @@ private:
QList<QObject*> _objectList;
static const int ObjectRole;
static const int TextRole;
};
#endif
......@@ -48,10 +48,10 @@ const QString ProviderStrings::kLevelsForSigPacSpainMap[] =
ProviderStrings::ProviderStrings()
{
// Google version strings
VersionGoogleMap = "m@296306248";
VersionGoogleSatellite = "s@168";
VersionGoogleLabels = "h@296000000";
VersionGoogleTerrain = "t@132,r@296000000";
VersionGoogleMap = "m@313";
VersionGoogleSatellite = "s@177";
VersionGoogleLabels = "h@313";
VersionGoogleTerrain = "t@132,r@313";
SecGoogleWord = "Galileo";
// Google (China) version strings
......@@ -196,7 +196,13 @@ void UrlFactory::_tryCorrectGoogleVersions()
_network->setProxy(tProxy);
QString url = "http://maps.google.com/maps?output=classic";
qheader.setUrl(QUrl(url));
#if defined Q_OS_MACX
QByteArray userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0";
#elif defined Q_OS_WIN32
QByteArray userAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7";
#else
QByteArray userAgent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20130331 Firefox/21.0";
#endif
qheader.setRawHeader("User-Agent", userAgent);
_googleReply = _network->get(qheader);
connect(_googleReply, SIGNAL(finished()), this, SLOT(_googleVersionCompleted()));
......
......@@ -95,13 +95,11 @@ void QGeoMapReplyQGC::networkReplyFinished()
{
if (!m_reply)
{
qWarning() << "NULL Map request reply";
return;
}
if (m_reply->error() != QNetworkReply::NoError)
{
qWarning() << "Map request reply error:" << m_reply->error();
return;
}
......@@ -146,14 +144,12 @@ void QGeoMapReplyQGC::networkReplyError(QNetworkReply::NetworkError error)
{
if (!m_reply)
{
qWarning() << "NULL Map request error";
return;
}
if (error != QNetworkReply::OperationCanceledError)
{
setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString());
qWarning() << "Map request reply error:" << m_reply->errorString();
}
setFinished(true);
......
......@@ -121,45 +121,44 @@ QGeoTiledMappingManagerEngineQGC::QGeoTiledMappingManagerEngineQGC(const QVarian
// qDebug() << "Mapping cache directory:" << cacheDir;
//}
QGeoTileCache *tileCache = createTileCacheWithDir(cacheDir);
int cacheLimit = 0;
if (parameters.contains(QStringLiteral("mapping.cache.disk.size"))) {
bool ok = false;
cacheLimit = parameters.value(QStringLiteral("mapping.cache.disk.size")).toString().toInt(&ok);
if (!ok)
cacheLimit = 0;
}
if(!cacheLimit)
// QGC Default
cacheLimit = 1024 * 1024 * 1024;
tileCache->setMaxDiskUsage(cacheLimit);
//qDebug() << "Disk caching limit:" << cacheLimit;
cacheLimit = 0;
if (parameters.contains(QStringLiteral("mapping.cache.memory.size"))) {
bool ok = false;
cacheLimit = parameters.value(QStringLiteral("mapping.cache.memory.size")).toString().toInt(&ok);
if (!ok)
cacheLimit = 0;
}
if(!cacheLimit)
// QGC Default
cacheLimit = 10 * 1024 * 1024;
tileCache->setMaxMemoryUsage(cacheLimit);
//qDebug() << "Memory caching limit:" << cacheLimit;
cacheLimit = 0;
if (parameters.contains(QStringLiteral("mapping.cache.texture.size"))) {
bool ok = false;
cacheLimit = parameters.value(QStringLiteral("mapping.cache.texture.size")).toString().toInt(&ok);
if (!ok)
cacheLimit = 0;
QGeoTileCache* pTileCache = tileCache();
if(pTileCache)
{
int cacheLimit = 0;
//-- Disk Cache
if (parameters.contains(QStringLiteral("mapping.cache.disk.size"))) {
bool ok = false;
cacheLimit = parameters.value(QStringLiteral("mapping.cache.disk.size")).toString().toInt(&ok);
if (!ok)
cacheLimit = 0;
}
if(!cacheLimit)
{
#ifdef __mobile__
cacheLimit = 128 * 1024 * 1024;
#else
cacheLimit = 1024 * 1024 * 1024;
#endif
}
pTileCache->setMaxDiskUsage(cacheLimit);
//-- Memory Cache
cacheLimit = 0;
if (parameters.contains(QStringLiteral("mapping.cache.memory.size"))) {
bool ok = false;
cacheLimit = parameters.value(QStringLiteral("mapping.cache.memory.size")).toString().toInt(&ok);
if (!ok)
cacheLimit = 0;
}
if(!cacheLimit)
{
#ifdef __mobile__
cacheLimit = 16 * 1024 * 1024;
#else
cacheLimit = 128 * 1024 * 1024;
#endif
}
pTileCache->setMaxMemoryUsage(cacheLimit);
}
if(!cacheLimit)
// QGC Default
cacheLimit = 10 * 1024 * 1024;
tileCache->setExtraTextureUsage(cacheLimit);
*error = QGeoServiceProvider::NoError;
errorString->clear();
......
......@@ -55,7 +55,13 @@
QGeoTileFetcherQGC::QGeoTileFetcherQGC(QGeoTiledMappingManagerEngine *parent)
: QGeoTileFetcher(parent)
, m_networkManager(new QNetworkAccessManager(this))
, m_userAgent("Qt Application")
#if defined Q_OS_MACX
, m_userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0")
#elif defined Q_OS_WIN32
, m_userAgent("Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7")
#else
, m_userAgent("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20130331 Firefox/21.0")
#endif
, m_UrlFactory(NULL)
{
QStringList langs = QLocale::system().uiLanguages();
......
......@@ -200,6 +200,9 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes
_addLink(link);
}
// Give the plugin a change to adjust the message contents
_firmwarePlugin->adjustMavlinkMessage(&message);
emit mavlinkMessageReceived(message);
_uas->receiveMessage(message);
......@@ -257,17 +260,17 @@ void Vehicle::_sendMessage(mavlink_message_t message)
if (link->isConnected()) {
MAVLinkProtocol* mavlink = MAVLinkProtocol::instance();
// Give the plugin a chance to adjust
_firmwarePlugin->adjustMavlinkMessage(&message);
static const uint8_t messageKeys[256] = MAVLINK_MESSAGE_CRCS;
mavlink_finalize_message_chan(&message, mavlink->getSystemId(), mavlink->getComponentId(), link->getMavlinkChannel(), message.len, messageKeys[message.msgid]);
// Write message into buffer, prepending start sign
uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
int len = mavlink_msg_to_send_buffer(buffer, &message);
static uint8_t messageKeys[256] = MAVLINK_MESSAGE_CRCS;
mavlink_finalize_message_chan(&message, mavlink->getSystemId(), mavlink->getComponentId(), link->getMavlinkChannel(), message.len, messageKeys[message.msgid]);
if (link->isConnected()) {
link->writeBytes((const char*)buffer, len);
} else {
qWarning() << "Link not connected";
}
link->writeBytes((const char*)buffer, len);
}
}
}
......
......@@ -145,6 +145,9 @@ public:
/// Provides access to uas from vehicle. Temporary workaround until AutoPilotPlugin is fully phased out.
AutoPilotPlugin* autopilotPlugin(void) { return _autopilotPlugin; }
/// Provides access to the Firmware Plugin for this Vehicle
FirmwarePlugin* firmwarePlugin(void) { return _firmwarePlugin; }
QList<LinkInterface*> links(void);
int manualControlReservedButtonCount(void);
......
......@@ -150,7 +150,7 @@ void JoystickConfigController::_setupCurrentState(void)
void JoystickConfigController::_axisValueChanged(int axis, int value)
{
if (axis >= 0 && axis <= _axisMax) {
if (axis >= 0 && axis < _axisMax) {
// We always update raw values
_axisRawValue[axis] = value;
emit axisValueChanged(axis, _axisRawValue[axis]);
......
......@@ -29,5 +29,5 @@ import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
ParameterEditor {
fullMode: true
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of class ParameterEditorWidget
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include "ParameterEditorWidget.h"
ParameterEditorWidget::ParameterEditorWidget(QWidget *parent) :
QGCQmlWidgetHolder(parent)
{
setSource(QUrl::fromUserInput("qrc:/qml/ParameterEditorWidget.qml"));
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef PARAMETEREDITORWIDGET_H
#define PARAMETEREDITORWIDGET_H
#include "QGCQmlWidgetHolder.h"
class ParameterEditorWidget : public QGCQmlWidgetHolder
{
Q_OBJECT
public:
ParameterEditorWidget(QWidget *parent = 0);
};
#endif
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
import QtQuick 2.2
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
ViewWidget {
connectedComponent: editorComponent
Component {
id: editorComponent
ParameterEditor {
fullMode: false
}
}
}
......@@ -98,6 +98,7 @@ MockLink::MockLink(MockConfiguration* config) :
MockLink::~MockLink(void)
{
qDebug() << "MockLink destructor";
_disconnect();
}
......@@ -121,7 +122,8 @@ bool MockLink::_disconnect(void)
{
if (_connected) {
_connected = false;
exit();
quit();
wait();
emit disconnected();
}
......@@ -346,6 +348,10 @@ void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes)
case MAVLINK_MSG_ID_FILE_TRANSFER_PROTOCOL:
_handleFTP(msg);
break;
case MAVLINK_MSG_ID_COMMAND_LONG:
_handleCommandLong(msg);
break;
default:
qDebug() << "MockLink: Unhandled mavlink message, id:" << msg.msgid;
......@@ -724,3 +730,19 @@ void MockLink::_handleFTP(const mavlink_message_t& msg)
Q_ASSERT(_fileServer);
_fileServer->handleFTPMessage(msg);
}
void MockLink::_handleCommandLong(const mavlink_message_t& msg)
{
mavlink_command_long_t request;
mavlink_msg_command_long_decode(&msg, &request);
if (request.command == MAV_CMD_COMPONENT_ARM_DISARM) {
if (request.param1 == 0.0f) {
_mavBaseMode &= ~MAV_MODE_FLAG_SAFETY_ARMED;
} else {
_mavBaseMode |= MAV_MODE_FLAG_SAFETY_ARMED;
}
}
}
......@@ -124,6 +124,7 @@ private:
void _handleMissionRequest(const mavlink_message_t& msg);
void _handleMissionItem(const mavlink_message_t& msg);
void _handleFTP(const mavlink_message_t& msg);
void _handleCommandLong(const mavlink_message_t& msg);
float _floatUnionForParam(int componentId, const QString& paramName);
void _setParamFloatUnionIntoMap(int componentId, const QString& paramName, float paramFloat);
......
......@@ -38,6 +38,7 @@ This file is part of the QGROUNDCONTROL project
#include <QMessageBox>
#include <iostream>
#include <Eigen/Eigen>
#include "QGCFlightGearLink.h"
#include "QGC.h"
......
......@@ -33,10 +33,13 @@ This file is part of the QGROUNDCONTROL project
#include <QDebug>
#include <QMutexLocker>
#include <QNetworkInterface>
#include <QHostInfo>
#include <iostream>
#include <Eigen/Eigen>
#include "QGCXPlaneLink.h"
#include "QGC.h"
#include <QHostInfo>
#include "UAS.h"
#include "UASInterface.h"
#include "QGCMessageBox.h"
......
......@@ -183,7 +183,7 @@ void MavlinkLogTest::_connectLogNoArm_test(void)
void MavlinkLogTest::_connectLogArm_test(void)
{
_connectLogWorker(true);
//_connectLogWorker(true);
}
void MavlinkLogTest::_deleteTempLogFiles_test(void)
......
......@@ -2286,54 +2286,30 @@ void UAS::processParamValueMsg(mavlink_message_t& msg, const QString& paramName,
QVariant paramValue;
// Insert with correct type
// TODO: This is a hack for MAV_AUTOPILOT_ARDUPILOTMEGA until the new version of MAVLink and a fix for their param handling.
switch (rawValue.param_type) {
case MAV_PARAM_TYPE_REAL32:
if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) {
paramValue = QVariant(paramUnion.param_float);
} else {
paramValue = QVariant(paramUnion.param_float);
}
paramValue = QVariant(paramUnion.param_float);
break;
case MAV_PARAM_TYPE_UINT8:
if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) {
paramValue = QVariant((unsigned short)paramUnion.param_float);
} else {
paramValue = QVariant(paramUnion.param_uint8);
}
paramValue = QVariant(paramUnion.param_uint8);
break;
case MAV_PARAM_TYPE_INT8:
if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) {
paramValue = QVariant((short)paramUnion.param_float);
} else {
paramValue = QVariant(paramUnion.param_int8);
}
paramValue = QVariant(paramUnion.param_int8);
break;
case MAV_PARAM_TYPE_INT16:
if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) {
paramValue = QVariant((short)paramUnion.param_float);
} else {
paramValue = QVariant(paramUnion.param_int16);
}
paramValue = QVariant(paramUnion.param_int16);
break;
case MAV_PARAM_TYPE_UINT32:
if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) {
paramValue = QVariant((unsigned int)paramUnion.param_float);
} else {
paramValue = QVariant(paramUnion.param_uint32);
}
paramValue = QVariant(paramUnion.param_uint32);
break;
case MAV_PARAM_TYPE_INT32:
if (getAutopilotType() == MAV_AUTOPILOT_ARDUPILOTMEGA) {
paramValue = QVariant((int)paramUnion.param_float);
} else {
paramValue = QVariant(paramUnion.param_int32);
}
paramValue = QVariant(paramUnion.param_int32);
break;
default:
......@@ -2470,7 +2446,10 @@ void UAS::launch()
*/
void UAS::armSystem()
{
setModeArm(base_mode | MAV_MODE_FLAG_SAFETY_ARMED, custom_mode);
// We specifically do not use setModeArm to change arming state. The APM flight stack does not support
// arm/disarm through the SET_MODE mavlink message. Instead we use COMMAND_LONG:MAV_CMD_COMPONENT_ARM_DISARM
// which works on both PX4 and APM flight stack.
executeCommand(MAV_CMD_COMPONENT_ARM_DISARM, 0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
}
/**
......@@ -2479,12 +2458,19 @@ void UAS::armSystem()
*/
void UAS::disarmSystem()
{
setModeArm(base_mode & ~(MAV_MODE_FLAG_SAFETY_ARMED), custom_mode);
// We specifically do not use setModeArm to change arming state. The APM flight stack does not support
// arm/disarm through the SET_MODE mavlink message. Instead we use COMMAND_LONG:MAV_CMD_COMPONENT_ARM_DISARM
// which works on both PX4 and APM flight stack.
executeCommand(MAV_CMD_COMPONENT_ARM_DISARM, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
}
void UAS::toggleArmedState()
{
setModeArm(base_mode ^ (MAV_MODE_FLAG_SAFETY_ARMED), custom_mode);
if (isArmed()) {
disarmSystem();
} else {
armSystem();
}
}
void UAS::goAutonomous()
......@@ -2798,9 +2784,8 @@ void UAS::home()
double latitude = HomePositionManager::instance()->getHomeLatitude();
double longitude = HomePositionManager::instance()->getHomeLongitude();
double altitude = HomePositionManager::instance()->getHomeAltitude();
int frame = HomePositionManager::instance()->getHomeFrame();
mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, MAV_COMP_ID_ALL, MAV_CMD_OVERRIDE_GOTO, 1, MAV_GOTO_DO_CONTINUE, MAV_GOTO_HOLD_AT_CURRENT_POSITION, frame, 0, latitude, longitude, altitude);
mavlink_msg_command_long_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, uasId, MAV_COMP_ID_ALL, MAV_CMD_OVERRIDE_GOTO, 1, MAV_GOTO_DO_CONTINUE, MAV_GOTO_HOLD_AT_CURRENT_POSITION, MAV_FRAME_GLOBAL, 0, latitude, longitude, altitude);
_vehicle->sendMessage(msg);
}
......
......@@ -90,7 +90,6 @@ const char* MainWindow::_uasControlDockWidgetName = "UNMANNED_SYSTEM_CONTROL_DOC
const char* MainWindow::_uasListDockWidgetName = "UNMANNED_SYSTEM_LIST_DOCKWIDGET";
const char* MainWindow::_waypointsDockWidgetName = "WAYPOINT_LIST_DOCKWIDGET";
const char* MainWindow::_mavlinkDockWidgetName = "MAVLINK_INSPECTOR_DOCKWIDGET";
const char* MainWindow::_parametersDockWidgetName = "PARAMETER_INTERFACE_DOCKWIDGET";
const char* MainWindow::_customCommandWidgetName = "CUSTOM_COMMAND_DOCKWIDGET";
const char* MainWindow::_filesDockWidgetName = "FILE_VIEW_DOCKWIDGET";
const char* MainWindow::_uasStatusDetailsDockWidgetName = "UAS_STATUS_DETAILS_DOCKWIDGET";
......@@ -393,7 +392,6 @@ void MainWindow::_buildCommonWidgets(void)
{ _uasListDockWidgetName, "Unmanned Systems", Qt::RightDockWidgetArea },
{ _waypointsDockWidgetName, "Mission Plan", Qt::BottomDockWidgetArea },
{ _mavlinkDockWidgetName, "MAVLink Inspector", Qt::RightDockWidgetArea },
{ _parametersDockWidgetName, "Parameter Editor", Qt::RightDockWidgetArea },
{ _customCommandWidgetName, "Custom Command", Qt::RightDockWidgetArea },
{ _filesDockWidgetName, "Onboard Files", Qt::RightDockWidgetArea },
{ _uasStatusDetailsDockWidgetName, "Status Details", Qt::RightDockWidgetArea },
......@@ -497,8 +495,6 @@ void MainWindow::_createInnerDockWidget(const QString& widgetName)
widget = new QGCWaypointListMulti(this);
} else if (widgetName == _mavlinkDockWidgetName) {
widget = new QGCMAVLinkInspector(MAVLinkProtocol::instance(),this);
} else if (widgetName == _parametersDockWidgetName) {
widget = new ParameterEditorWidget(this);
} else if (widgetName == _customCommandWidgetName) {
widget = new CustomCommandWidget(this);
} else if (widgetName == _filesDockWidgetName) {
......@@ -613,7 +609,6 @@ void MainWindow::closeEvent(QCloseEvent *event)
_storeCurrentViewState();
storeSettings();
HomePositionManager::instance()->storeSettings();
event->accept();
}
......@@ -827,6 +822,8 @@ void MainWindow::_storeCurrentViewState(void)
{
// HIL dock widgets are dynamic and are not part of the saved state
_hideAllHilDockWidgets();
#ifndef __mobile__
// Save list of visible widgets
bool firstWidget = true;
QString widgetNames = "";
......@@ -840,6 +837,7 @@ void MainWindow::_storeCurrentViewState(void)
}
}
settings.setValue(_getWindowStateKey() + "WIDGETS", widgetNames);
#endif
settings.setValue(_getWindowStateKey(), saveState());
settings.setValue(_getWindowGeometryKey(), saveGeometry());
}
......@@ -910,6 +908,7 @@ void MainWindow::_loadCurrentViewState(void)
// Hide all widgets from previous view
_hideAllDockWidgets();
#ifndef __mobile__
// Restore the widgets for the new view
QString widgetNames = settings.value(_getWindowStateKey() + "WIDGETS", defaultWidgets).toString();
qDebug() << widgetNames;
......@@ -920,6 +919,7 @@ void MainWindow::_loadCurrentViewState(void)
_showDockWidget(widgetName, true);
}
}
#endif
if (settings.contains(_getWindowStateKey())) {
restoreState(settings.value(_getWindowStateKey()).toByteArray());
......
......@@ -49,7 +49,6 @@ This file is part of the QGROUNDCONTROL project
#if (defined QGC_MOUSE_ENABLED_WIN) | (defined QGC_MOUSE_ENABLED_LINUX)
#include "Mouse6dofInput.h"
#endif // QGC_MOUSE_ENABLED_WIN
#include "ParameterEditorWidget.h"
#include "opmapcontrol.h"
#include "MainToolBar.h"
#include "LogCompressor.h"
......@@ -291,7 +290,6 @@ private:
static const char* _uasListDockWidgetName;
static const char* _waypointsDockWidgetName;
static const char* _mavlinkDockWidgetName;
static const char* _parametersDockWidgetName;
static const char* _customCommandWidgetName;
static const char* _filesDockWidgetName;
static const char* _uasStatusDetailsDockWidgetName;
......
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