Commit 4112826b authored by dogmaphobic's avatar dogmaphobic

Merge remote-tracking branch 'MavLink/master' into mapCache

* MavLink/master: (59 commits)
  Fix incorrect method name
  Add vehicles to Plan view
  Flight lines different color than waypoint lines
  In progress indicator for vehicle sync
  Land items default to 0 altitude
  Keep ParameterLoader on first seen dedicated link
  Keep ParameterLoader on first seen dedicated link
  Only save to eeprom when value changes
  Remove 3D Mouse Support
  Don't auto-select on mobile
  Fix ArduPlane FLTMODE_CH usage
  Don't try to use QCoreApplication::arguments before an app is created
  Move the buglist override to as early as possible, include switches for specific rendering backends on windows
  Add Intel PowerVR based GPUs to the naughty list
  Remove unused code
  PX4: Rename auto loiter to auto pause
  Update param meta data for PX4
  Don't check driver version on Intel GMA graphics adapters
  Thumbtack alternate instrument panel
  Vehicle.battery FactGroup
  ...
parents 8624fb71 1f63fcfb
Thank you for considering to contribute to QGroundControl.
Contributions must be made under QGroundControl's dual-license system, under GPLv3 and Apache 2.0. This by definition rules out the re-use of any copyleft (e.g. GPL) licensed code. All contributions must be original or from a compatible license (BSD 2/3 clause, MIT, Apache 2.0).
* https://opensource.org/licenses/gpl-3.0.html
* https://opensource.org/licenses/Apache-2.0
Users of the codebase are free to use it under either license. The dual approach is necessary to be able to offer QGroundControl through the iOS and Android app stores and offers the open source community choice.
......@@ -115,51 +115,6 @@ contains(DEFINES, DISABLE_XBEE) {
message("Skipping support for XBee API (unsupported platform)")
}
#
# [OPTIONAL] Magellan 3DxWare library. Provides support for 3DConnexion's 3D mice.
#
contains(DEFINES, DISABLE_3DMOUSE) {
message("Skipping support for 3DConnexion mice (manual override from command line)")
DEFINES -= DISABLE_3DMOUSE
# Otherwise the user can still disable this feature in the user_config.pri file.
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, DISABLE_3DMOUSE) {
message("Skipping support for 3DConnexion mice (manual override from user_config.pri)")
} else:LinuxBuild {
exists(/usr/local/lib/libxdrvlib.so) {
message("Including support for 3DConnexion mice")
DEFINES += \
QGC_MOUSE_ENABLED_LINUX \
ParameterCheck
# Hack: Has to be defined for magellan usage
HEADERS += src/input/Mouse6dofInput.h
SOURCES += src/input/Mouse6dofInput.cpp
LIBS += -L/usr/local/lib/ -lxdrvlib
} else {
warning("Skipping support for 3DConnexion mice (missing libraries, see README)")
}
} else:WindowsBuild {
message("Including support for 3DConnexion mice")
DEFINES += QGC_MOUSE_ENABLED_WIN
INCLUDEPATH += libs/thirdParty/3DMouse/win
HEADERS += \
libs/thirdParty/3DMouse/win/I3dMouseParams.h \
libs/thirdParty/3DMouse/win/MouseParameters.h \
libs/thirdParty/3DMouse/win/Mouse3DInput.h \
src/input/Mouse6dofInput.h
SOURCES += \
libs/thirdParty/3DMouse/win/MouseParameters.cpp \
libs/thirdParty/3DMouse/win/Mouse3DInput.cpp \
src/input/Mouse6dofInput.cpp
} else {
message("Skipping support for 3DConnexion mice (unsupported platform)")
}
#
# [OPTIONAL] Opal RT-LAB Library. Provides integration with Opal-RT's RT-LAB simulator.
#
......
......@@ -70,6 +70,8 @@ Section "create Start Menu Shortcuts"
SetShellVarContext all
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\QGroundControl.lnk" "$INSTDIR\qgroundcontrol.exe" "" "$INSTDIR\qgroundcontrol.exe" 0
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\QGroundControl (GPU Compatibility Mode).lnk" "$INSTDIR\qgroundcontrol.exe" "-angle" "$INSTDIR\qgroundcontrol.exe" 0
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\QGroundControl (GPU Safe Mode).lnk" "$INSTDIR\qgroundcontrol.exe" "-swrast" "$INSTDIR\qgroundcontrol.exe" 0
SectionEnd
Function .onInit
......
Subproject commit eca21980688a7f0abe15993227bb07bb92f22c63
Subproject commit a2f37a142c14acbc56390f7a8c6946730f4ae25e
#ifndef I3D_MOUSE_PARAMS_H
#define I3D_MOUSE_PARAMS_H
/*
Parameters for the 3D mouse based on the SDK from 3Dconnexion
*/
class I3dMouseSensor
{
public:
enum ESpeed {
kLowSpeed = 0,
kMidSpeed,
kHighSpeed
};
virtual bool IsPanZoom() const = 0;
virtual bool IsRotate() const = 0;
virtual ESpeed GetSpeed() const = 0;
virtual void SetPanZoom(bool isPanZoom) = 0;
virtual void SetRotate(bool isRotate) = 0;
virtual void SetSpeed(ESpeed speed) = 0;
protected:
virtual ~I3dMouseSensor() {}
};
class I3dMouseNavigation
{
public:
enum EPivot {
kManualPivot = 0,
kAutoPivot,
kAutoPivotOverride
};
enum ENavigation {
kObjectMode = 0,
kCameraMode,
kFlyMode,
kWalkMode,
kHelicopterMode
};
enum EPivotVisibility {
kHidePivot = 0,
kShowPivot,
kShowMovingPivot
};
virtual ENavigation GetNavigationMode() const = 0;
virtual EPivot GetPivotMode() const = 0;
virtual EPivotVisibility GetPivotVisibility() const = 0;
virtual bool IsLockHorizon() const = 0;
virtual void SetLockHorizon(bool bOn) = 0;
virtual void SetNavigationMode(ENavigation navigation) = 0;
virtual void SetPivotMode(EPivot pivot) = 0;
virtual void SetPivotVisibility(EPivotVisibility visibility) = 0;
protected:
virtual ~I3dMouseNavigation(){}
};
class I3dMouseParam : public I3dMouseSensor, public I3dMouseNavigation
{
public:
virtual ~I3dMouseParam() {}
};
#endif
This diff is collapsed.
#ifndef T3DMOUSE_INPUT_H
#define T3DMOUSE_INPUT_H
#include "MouseParameters.h"
#include <QWidget>
#include <QByteArray>
#include <QAbstractNativeEventFilter>
#include <vector>
#include <map>
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 //target at least windows XP
#endif
#include <windows.h>
/*
A class for connecting to and receiving data from a 3D Connexion 3D mouse
This helper class manages the connection to a 3D mouse, collecting WM_INPUT
messages from Windows and converting the data into 3D motion data.
This class is based on the SDK from 3D Connexion but is modified to work with Qt.
It is Windows only since it uses the WM_INPUT messages from windows directly
rather than Qt events.
Note that it needs to be compiled with _WIN32_WINNT defined as 0x0501 (windows XP)
or later because the raw input API was added in Windows XP. This also means that
Qt needs to be compiled with this enabled otherwise the QEventDispatcherWin32 blocks
in processEvents because the raw input messages do not cause the thread to be woken if
Qt is compiled for Win 2000 targets.
*/
class Mouse3DInput : public QObject, public QAbstractNativeEventFilter
{
Q_OBJECT
public:
Mouse3DInput(QWidget* widget);
~Mouse3DInput();
virtual bool nativeEventFilter(const QByteArray& eventType, void* msg, long* result);
static bool Is3dmouseAttached();
I3dMouseParam& MouseParams();
const I3dMouseParam& MouseParams() const;
virtual void Move3d(HANDLE device, std::vector<float>& motionData);
virtual void On3dmouseKeyDown(HANDLE device, int virtualKeyCode);
virtual void On3dmouseKeyUp(HANDLE device, int virtualKeyCode);
signals:
void Move3d(std::vector<float>& motionData);
void On3dmouseKeyDown(int virtualKeyCode);
void On3dmouseKeyUp(int virtualKeyCode);
private:
bool InitializeRawInput(HWND hwndTarget);
void OnRawInput(UINT nInputCode, HRAWINPUT hRawInput);
UINT GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader);
bool TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput);
void On3dmouseInput();
class TInputData
{
public:
TInputData() : fAxes(6) {}
bool IsZero() {
return (0.==fAxes[0] && 0.==fAxes[1] && 0.==fAxes[2] &&
0.==fAxes[3] && 0.==fAxes[4] && 0.==fAxes[5]);
}
int fTimeToLive; // For telling if the device was unplugged while sending data
bool fIsDirty;
std::vector<float> fAxes;
};
HWND fWindow;
// Data cache to handle multiple rawinput devices
std::map< HANDLE, TInputData> fDevice2Data;
std::map< HANDLE, unsigned long> fDevice2Keystate;
// 3dmouse parameters
MouseParameters f3dMouseParams; // Rotate, Pan Zoom etc.
// use to calculate distance traveled since last event
DWORD fLast3dmouseInputTime;
};
#endif
#include "MouseParameters.h"
MouseParameters::MouseParameters(): fNavigation(kObjectMode)
, fPivot(kAutoPivot)
, fPivotVisibility(kShowPivot)
, fIsLockHorizon(true)
, fIsPanZoom(true)
, fIsRotate(true)
, fSpeed(kLowSpeed)
{
}
MouseParameters::~MouseParameters()
{
}
bool MouseParameters::IsPanZoom() const
{
return fIsPanZoom;
}
bool MouseParameters::IsRotate() const
{
return fIsRotate;
}
MouseParameters::ESpeed MouseParameters::GetSpeed() const
{
return fSpeed;
}
void MouseParameters::SetPanZoom(bool isPanZoom)
{
fIsPanZoom=isPanZoom;
}
void MouseParameters::SetRotate(bool isRotate)
{
fIsRotate=isRotate;
}
void MouseParameters::SetSpeed(ESpeed speed)
{
fSpeed=speed;
}
MouseParameters::ENavigation MouseParameters::GetNavigationMode() const
{
return fNavigation;
}
MouseParameters::EPivot MouseParameters::GetPivotMode() const
{
return fPivot;
}
MouseParameters::EPivotVisibility MouseParameters::GetPivotVisibility() const
{
return fPivotVisibility;
}
bool MouseParameters::IsLockHorizon() const
{
return fIsLockHorizon;
}
void MouseParameters::SetLockHorizon(bool bOn)
{
fIsLockHorizon=bOn;
}
void MouseParameters::SetNavigationMode(ENavigation navigation)
{
fNavigation=navigation;
}
void MouseParameters::SetPivotMode(EPivot pivot)
{
if (fPivot!=kManualPivot || pivot!=kAutoPivotOverride)
fPivot = pivot;
}
void MouseParameters::SetPivotVisibility(EPivotVisibility visibility)
{
fPivotVisibility = visibility;
}
#ifndef T3D_MOUSE_PARAMS_H
#define T3D_MOUSE_PARAMS_H
#include "I3dMouseParams.h"
class MouseParameters : public I3dMouseParam
{
public:
MouseParameters();
~MouseParameters();
// I3dmouseSensor interface
bool IsPanZoom() const;
bool IsRotate() const;
ESpeed GetSpeed() const;
void SetPanZoom(bool isPanZoom);
void SetRotate(bool isRotate);
void SetSpeed(ESpeed speed);
// I3dmouseNavigation interface
ENavigation GetNavigationMode() const;
EPivot GetPivotMode() const;
EPivotVisibility GetPivotVisibility() const;
bool IsLockHorizon() const;
void SetLockHorizon(bool bOn);
void SetNavigationMode(ENavigation navigation);
void SetPivotMode(EPivot pivot);
void SetPivotVisibility(EPivotVisibility visibility);
private:
MouseParameters (const MouseParameters&);
const MouseParameters& operator =(const MouseParameters&);
ENavigation fNavigation;
EPivot fPivot;
EPivotVisibility fPivotVisibility;
bool fIsLockHorizon;
bool fIsPanZoom;
bool fIsRotate;
ESpeed fSpeed;
};
#endif
......@@ -237,4 +237,7 @@
<qresource prefix="/FirmwarePlugin/APM">
<file alias="apm.pdef.xml">src/FirmwarePlugin/APM/apm.pdef.xml</file>
</qresource>
<qresource prefix="/opengl">
<file>resources/opengl/buglist.json</file>
</qresource>
</RCC>
......@@ -186,6 +186,7 @@ INCLUDEPATH += \
src/comm \
src/FlightDisplay \
src/FlightMap \
src/FlightMap/Widgets \
src/input \
src/Joystick \
src/lib/qmapcontrol \
......@@ -247,10 +248,12 @@ HEADERS += \
src/comm/UDPLink.h \
src/FlightDisplay/FlightDisplayViewController.h \
src/FlightMap/FlightMapSettings.h \
src/FlightMap/Widgets/ValuesWidgetController.h \
src/GAudioOutput.h \
src/HomePositionManager.h \
src/Joystick/Joystick.h \
src/Joystick/JoystickManager.h \
src/JsonHelper.h \
src/LogCompressor.h \
src/MG.h \
src/MissionManager/MissionCommandList.h \
......@@ -372,10 +375,12 @@ SOURCES += \
src/comm/UDPLink.cc \
src/FlightDisplay/FlightDisplayViewController.cc \
src/FlightMap/FlightMapSettings.cc \
src/FlightMap/Widgets/ValuesWidgetController.cc \
src/GAudioOutput.cc \
src/HomePositionManager.cc \
src/Joystick/Joystick.cc \
src/Joystick/JoystickManager.cc \
src/JsonHelper.cc \
src/LogCompressor.cc \
src/main.cc \
src/MissionManager/MissionCommandList.cc \
......@@ -675,6 +680,7 @@ INCLUDEPATH += \
HEADERS += \
src/FactSystem/Fact.h \
src/FactSystem/FactGroup.h \
src/FactSystem/FactControls/FactPanelController.h \
src/FactSystem/FactMetaData.h \
src/FactSystem/FactSystem.h \
......@@ -684,6 +690,7 @@ HEADERS += \
SOURCES += \
src/FactSystem/Fact.cc \
src/FactSystem/FactGroup.cc \
src/FactSystem/FactControls/FactPanelController.cc \
src/FactSystem/FactMetaData.cc \
src/FactSystem/FactSystem.cc \
......
......@@ -93,6 +93,8 @@
<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/qmldir">src/FlightMap/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>
......@@ -102,11 +104,13 @@
<file alias="QGroundControl/FlightMap/QGCAttitudeWidget.qml">src/FlightMap/Widgets/QGCAttitudeWidget.qml</file>
<file alias="QGroundControl/FlightMap/QGCCompassWidget.qml">src/FlightMap/Widgets/QGCCompassWidget.qml</file>
<file alias="QGroundControl/FlightMap/QGCInstrumentWidget.qml">src/FlightMap/Widgets/QGCInstrumentWidget.qml</file>
<file alias="QGroundControl/FlightMap/QGCInstrumentWidgetAlternate.qml">src/FlightMap/Widgets/QGCInstrumentWidgetAlternate.qml</file>
<file alias="QGroundControl/FlightMap/QGCPitchIndicator.qml">src/FlightMap/Widgets/QGCPitchIndicator.qml</file>
<file alias="QGroundControl/FlightMap/QGCSlider.qml">src/FlightMap/Widgets/QGCSlider.qml</file>
<file alias="QGroundControl/FlightMap/QGCVideoBackground.qml">src/FlightMap/QGCVideoBackground.qml</file>
<file alias="QGroundControl/FlightMap/qmldir">src/FlightMap/qmldir</file>
<file alias="QGroundControl/FlightMap/ValuesWidget.qml">src/FlightMap/Widgets/ValuesWidget.qml</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>
......@@ -150,5 +154,8 @@
<file alias="PX4/MavCmdInfoCommon.json">src/FirmwarePlugin/PX4/MavCmdInfoCommon.json</file>
<file alias="PX4/MavCmdInfoFixedWing.json">src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json</file>
<file alias="PX4/MavCmdInfoMultiRotor.json">src/FirmwarePlugin/PX4/MavCmdInfoMultiRotor.json</file>
<file alias="Vehicle/VehicleFact.json">src/Vehicle/VehicleFact.json</file>
<file alias="Vehicle/BatteryFact.json">src/Vehicle/BatteryFact.json</file>
<file alias="Vehicle/GPSFact.json">src/Vehicle/GPSFact.json</file>
</qresource>
</RCC>
{
"name": "QGroundControl OpenGL Driver Blacklist",
"version": "5.5",
"entries": [
{
"id": 1,
"description": "Desktop OpenGL is unreliable on some Intel HD laptops (QTBUG-43263, QTBUG-42240)",
"vendor_id": "0x8086",
"device_id": [ "0x0A16" ],
"os": {
"type": "win"
},
"driver_version": {
"op": "<=",
"value": "10.18.10.3277"
},
"features": [
"disable_desktopgl"
]
},
{
"id": 2,
"description": "Desktop OpenGL is unreliable on some Intel Mobile GMA Devices",
"vendor_id": "0x8086",
"device_id": [ "0x2972", "0x2973",
"0x2992", "0x2993",
"0x29A2", "0x29A3",
"0x2982", "0x2983",
"0x2A02", "0x2A03", "0x2A12", "0x2A13",
"0x2E42", "0x2E43", "0x2E92", "0x2E93",
"0x2E12", "0x2E13",
"0x2E32", "0x2E33",
"0x2E22", "0x2E23",
"0x2A42", "0x2A43",
"0x2E5B",
"0x8108", "0x8109",
"0x4102",
"0x0BE0", "0x0BE1", "0x0BE2", "0x0BE0",
"0x08C7", "0x08C8", "0x08C9", "0x08CA", "0x08CB", "0x08CC", "0x08CD", "0x08CE", "0x08CF"
],
"os": {
"type": "win"
},
"features": [
"disable_desktopgl"
]
}
]
}
......@@ -32,6 +32,8 @@ APMFlightModesComponentController::APMFlightModesComponentController(void)
: _activeFlightMode(0)
, _channelCount(Vehicle::cMaxRcChannels)
, _fixedWing(_vehicle->vehicleType() == MAV_TYPE_FIXED_WING)
, _flightModeChannel(4)
{
QStringList usedParams;
usedParams << QStringLiteral("FLTMODE1") << QStringLiteral("FLTMODE2") << QStringLiteral("FLTMODE3")
......@@ -40,6 +42,10 @@ APMFlightModesComponentController::APMFlightModesComponentController(void)
return;
}
if (parameterExists(FactSystem::defaultComponentId, QStringLiteral("FLTMODE_CH"))) {
_flightModeChannel = getParameterFact(FactSystem::defaultComponentId, QStringLiteral("FLTMODE_CH"))->rawValue().toInt();
}
_rgChannelOptionEnabled << QVariant(false) << QVariant(false) << QVariant(false) << QVariant(false) << QVariant(false) << QVariant(false);
connect(_vehicle, &Vehicle::rcChannelsChanged, this, &APMFlightModesComponentController::_rcChannelsChanged);
......@@ -48,10 +54,12 @@ APMFlightModesComponentController::APMFlightModesComponentController(void)
/// Connected to Vehicle::rcChannelsChanged signal
void APMFlightModesComponentController::_rcChannelsChanged(int channelCount, int pwmValues[Vehicle::cMaxRcChannels])
{
Q_UNUSED(channelCount);
if (_flightModeChannel > channelCount) {
return;
}
_activeFlightMode = 0;
int channelValue = pwmValues[4];
int channelValue = pwmValues[_flightModeChannel - 1];
if (channelValue != -1) {
bool found = false;
int rgThreshold[] = { 1230, 1360, 1490, 1620, 1749 };
......
......@@ -62,6 +62,7 @@ private:
int _channelCount;
QVariantList _rgChannelOptionEnabled;
bool _fixedWing;
int _flightModeChannel;
};
#endif
......@@ -102,6 +102,12 @@
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
</airframe_group>
<airframe_group image="OctoRotorXCoaxial" name="Octo Coax Wide">
<airframe id="12002" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Steadidrone MAVRIK">
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Octo Coax Wide</type>
</airframe>
</airframe_group>
<airframe_group image="OctoRotorPlus" name="Octorotor +">
<airframe id="9001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Octocopter + geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
......@@ -349,9 +355,13 @@
</airframe>
</airframe_group>
<airframe_group image="VTOLDuoRotorTailSitter" name="VTOL Duo Tailsitter">
<airframe id="13001" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Duorotor Tailsitter">
<airframe id="13001" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Caipiroshka Duo Tailsitter">
<maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer>
<type>VTOL Duo Tailsitter</type>
<output name="MAIN1">motor left</output>
<output name="MAIN2">motor right</output>
<output name="MAIN5">elevon left</output>
<output name="MAIN6">elevon right</output>
</airframe>
</airframe_group>
<airframe_group image="VTOLQuadRotorTailSitter" name="VTOL Quad Tailsitter">
......
......@@ -35,6 +35,8 @@ Fact::Fact(QObject* parent)
, _rawValue(0)
, _type(FactMetaData::valueTypeInt32)
, _metaData(NULL)
, _sendValueChangedSignals(true)
, _deferredValueChangeSignal(false)
{
FactMetaData* metaData = new FactMetaData(_type, this);
setMetaData(metaData);
......@@ -47,6 +49,8 @@ Fact::Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObjec
, _rawValue(0)
, _type(type)
, _metaData(NULL)
, _sendValueChangedSignals(true)
, _deferredValueChangeSignal(false)
{
FactMetaData* metaData = new FactMetaData(_type, this);
setMetaData(metaData);
......@@ -60,11 +64,13 @@ Fact::Fact(const Fact& other, QObject* parent)
const Fact& Fact::operator=(const Fact& other)
{
_name = other._name;
_componentId = other._componentId;
_rawValue = other._rawValue;
_type = other._type;
_name = other._name;
_componentId = other._componentId;
_rawValue = other._rawValue;
_type = other._type;
_sendValueChangedSignals = other._sendValueChangedSignals;
_deferredValueChangeSignal = other._deferredValueChangeSignal;
if (_metaData && other._metaData) {
*_metaData = *other._metaData;
} else {
......@@ -82,7 +88,7 @@ void Fact::forceSetRawValue(const QVariant& value)
if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
_rawValue.setValue(typedValue);
emit valueChanged(cookedValue());
_sendValueChangedSignal(cookedValue());
emit _containerRawValueChanged(rawValue());
}
} else {
......@@ -99,7 +105,7 @@ void Fact::setRawValue(const QVariant& value)
if (_metaData->convertAndValidateRaw(value, true /* convertOnly */, typedValue, errorString)) {
if (typedValue != _rawValue) {
_rawValue.setValue(typedValue);
emit valueChanged(cookedValue());
_sendValueChangedSignal(cookedValue());
emit _containerRawValueChanged(rawValue());
}
}
......@@ -141,7 +147,7 @@ void Fact::setEnumIndex(int index)
void Fact::_containerSetRawValue(const QVariant& value)
{
_rawValue = value;
emit valueChanged(cookedValue());
_sendValueChangedSignal(cookedValue());
emit vehicleUpdated(_rawValue);
}
......@@ -492,3 +498,43 @@ bool Fact::rebootRequired(void) const
return false;
}
}
void Fact::setSendValueChangedSignals (bool sendValueChangedSignals)
{
if (sendValueChangedSignals != _sendValueChangedSignals) {
_sendValueChangedSignals = sendValueChangedSignals;
emit sendValueChangedSignalsChanged(_sendValueChangedSignals);
}
}
void Fact::_sendValueChangedSignal(QVariant value)
{
if (_sendValueChangedSignals) {
emit valueChanged(value);
_deferredValueChangeSignal = false;
} else {
_deferredValueChangeSignal = true;
}
}
void Fact::sendDeferredValueChangedSignal(void)
{
if (_deferredValueChangeSignal) {
_deferredValueChangeSignal = false;
emit valueChanged(cookedValue());
}
}
QString Fact::enumOrValueString(void)
{
if (_metaData) {
if (_metaData->enumStrings().count()) {
return enumStringValue();
} else {
return cookedValueString();
}
} else {
qWarning() << "Meta data pointer missing";
}
return QString();
}
......@@ -72,7 +72,8 @@ public:
Q_PROPERTY(QString units READ cookedUnits CONSTANT)
Q_PROPERTY(QVariant value READ cookedValue WRITE setCookedValue NOTIFY valueChanged)
Q_PROPERTY(bool valueEqualsDefault READ valueEqualsDefault NOTIFY valueChanged)
Q_PROPERTY(QVariant valueString READ cookedValueString NOTIFY valueChanged)
Q_PROPERTY(QString valueString READ cookedValueString NOTIFY valueChanged)
Q_PROPERTY(QString enumOrValueString READ enumOrValueString NOTIFY valueChanged)
/// Convert and validate value
/// @param convertOnly true: validate type conversion only, false: validate against meta data as well
......@@ -111,12 +112,22 @@ public:
QString cookedValueString (void) const;
bool valueEqualsDefault (void) const;
bool rebootRequired (void) const;
QString enumOrValueString (void); // This is not const, since an unknown value can modify the enum lists
void setRawValue (const QVariant& value);
void setCookedValue (const QVariant& value);
void setEnumIndex (int index);
void setEnumStringValue (const QString& value);
// The following methods allow you to defer sending of the valueChanged signals in order to implement
// rate limited signalling for ui performance. Used by FactGroup for example.
void setSendValueChangedSignals (bool sendValueChangedSignals);
bool sendValueChangedSignals (void) const { return _sendValueChangedSignals; }
bool deferredValueChangeSignal(void) const { return _deferredValueChangeSignal; }
void clearDeferredValueChangeSignal(void) { _deferredValueChangeSignal = false; }
void sendDeferredValueChangedSignal(void);
// C++ methods
/// Sets and sends new value to vehicle even if value is the same
......@@ -129,12 +140,14 @@ public:
/// Generally you should not change the name of a fact. But if you know what you are doing, you can.
void _setName(const QString& name) { _name = name; }
signals:
void bitmaskStringsChanged(void);
void bitmaskValuesChanged(void);
void enumStringsChanged(void);
void enumValuesChanged(void);
void sendValueChangedSignalsChanged(bool sendValueChangedSignals);
/// QObject Property System signal for value property changes
///
......@@ -151,12 +164,15 @@ signals:
protected:
QString _variantToString(const QVariant& variant) const;
void _sendValueChangedSignal(QVariant value);
QString _name;
int _componentId;
QVariant _rawValue;
FactMetaData::ValueType_t _type;
FactMetaData* _metaData;
bool _sendValueChangedSignals;
bool _deferredValueChangeSignal;
};
#endif
/*=====================================================================
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/>.
======================================================================*/
#include "FactGroup.h"
#include "JsonHelper.h"
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonArray>
#include <QDebug>
#include <QFile>
#include <QQmlEngine>
QGC_LOGGING_CATEGORY(FactGroupLog, "FactGroupLog")
const char* FactGroup::_decimalPlacesJsonKey = "decimalPlaces";
const char* FactGroup::_nameJsonKey = "name";
const char* FactGroup::_propertiesJsonKey = "properties";
const char* FactGroup::_versionJsonKey = "version";
const char* FactGroup::_typeJsonKey = "type";
const char* FactGroup::_shortDescriptionJsonKey = "shortDescription";
const char* FactGroup::_unitsJsonKey = "units";
FactGroup::FactGroup(int updateRateMsecs, const QString& metaDataFile, QObject* parent)
: QObject(parent)
, _updateRateMSecs(updateRateMsecs)
{
if (_updateRateMSecs > 0) {
connect(&_updateTimer, &QTimer::timeout, this, &FactGroup::_updateAllValues);
_updateTimer.setSingleShot(false);
_updateTimer.start(_updateRateMSecs);
}
_loadMetaData(metaDataFile);
}
Fact* FactGroup::getFact(const QString& name)
{
Fact* fact = NULL;
if (name.contains(".")) {
QStringList parts = name.split(".");
if (parts.count() != 2) {
qWarning() << "Only single level of hierarchy supported";
return NULL;
}
FactGroup * factGroup = getFactGroup(parts[0]);
if (!factGroup) {
qWarning() << "Unknown FactGroup" << parts[0];
return NULL;
}
return factGroup->getFact(parts[1]);
}
if (_nameToFactMap.contains(name)) {
fact = _nameToFactMap[name];
QQmlEngine::setObjectOwnership(fact, QQmlEngine::CppOwnership);
} else {
qWarning() << "Unknown Fact" << name;
}
return fact;
}
FactGroup* FactGroup::getFactGroup(const QString& name)
{
FactGroup* factGroup = NULL;
if (_nameToFactGroupMap.contains(name)) {
factGroup = _nameToFactGroupMap[name];
QQmlEngine::setObjectOwnership(factGroup, QQmlEngine::CppOwnership);
} else {
qWarning() << "Unknown FactGroup" << name;
}
return factGroup;
}
void FactGroup::_addFact(Fact* fact, const QString& name)
{
if (_nameToFactMap.contains(name)) {
qWarning() << "Duplicate Fact" << name;
return;
}
fact->setSendValueChangedSignals(_updateRateMSecs == 0);
if (_nameToFactMetaDataMap.contains(name)) {
fact->setMetaData(_nameToFactMetaDataMap[name]);
}
_nameToFactMap[name] = fact;
}
void FactGroup::_addFactGroup(FactGroup* factGroup, const QString& name)
{
if (_nameToFactGroupMap.contains(name)) {
qWarning() << "Duplicate FactGroup" << name;
return;
}
_nameToFactGroupMap[name] = factGroup;
}
void FactGroup::_updateAllValues(void)
{
foreach(Fact* fact, _nameToFactMap) {
fact->sendDeferredValueChangedSignal();
}
}
void FactGroup::_loadMetaData(const QString& jsonFilename)
{
if (jsonFilename.isEmpty()) {
return;
}
qCDebug(FactGroupLog) << "Loading" << jsonFilename;
QFile jsonFile(jsonFilename);
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Unable to open file" << jsonFilename << jsonFile.errorString();
return;
}
QByteArray bytes = jsonFile.readAll();
jsonFile.close();
QJsonParseError jsonParseError;
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
qWarning() << "Unable to open json document" << jsonFilename << jsonParseError.errorString();
return;
}
QJsonObject json = doc.object();
int version = json.value(_versionJsonKey).toInt();
if (version != 1) {
qWarning() << "Invalid version" << version;
return;
}
QJsonValue jsonValue = json.value(_propertiesJsonKey);
if (!jsonValue.isArray()) {
qWarning() << "properties object not array";
return;
}
QJsonArray jsonArray = jsonValue.toArray();
foreach(QJsonValue property, jsonArray) {
if (!property.isObject()) {
qWarning() << "properties object should contain only objects";
return;
}
QJsonObject jsonObject = property.toObject();
// Make sure we have the required keys
QString errorString;
QStringList requiredKeys;
requiredKeys << _nameJsonKey << _decimalPlacesJsonKey << _typeJsonKey << _shortDescriptionJsonKey;
if (!JsonHelper::validateRequiredKeys(jsonObject, requiredKeys, errorString)) {
qWarning() << errorString;
return;
}
// Validate key types
QStringList keys;
QList<QJsonValue::Type> types;
keys << _nameJsonKey << _decimalPlacesJsonKey;
types << QJsonValue::String << QJsonValue::Double;
if (!JsonHelper::validateKeyTypes(jsonObject, keys, types, errorString)) {
qWarning() << errorString;
return;
}
QString name = jsonObject.value(_nameJsonKey).toString();
if (_nameToFactMetaDataMap.contains(name)) {
qWarning() << "Duplicate property name" << name;
continue;
}
bool unknownType;
FactMetaData::ValueType_t type = FactMetaData::stringToType(jsonObject.value(_typeJsonKey).toString(), unknownType);
if (unknownType) {
qWarning() << "Unknown type" << jsonObject.value(_typeJsonKey).toString();
return;
}
QStringList enumValues, enumStrings;
if (!JsonHelper::parseEnum(jsonObject, enumStrings, enumValues, errorString)) {
qWarning() << errorString;
return;
}
FactMetaData* metaData = new FactMetaData(type, this);
metaData->setDecimalPlaces(jsonObject.value(_decimalPlacesJsonKey).toInt());
metaData->setShortDescription(jsonObject.value(_shortDescriptionJsonKey).toString());
metaData->setRawUnits(jsonObject.value(_unitsJsonKey).toString());
for (int i=0; i<enumValues.count(); i++) {
QVariant enumVariant;
QString errorString;
if (metaData->convertAndValidateRaw(enumValues[i], false /* validate */, enumVariant, errorString)) {
metaData->addEnumInfo(enumStrings[i], enumVariant);
} else {
qWarning() << "Invalid enum value, name:" << metaData->name()
<< " type:" << metaData->type() << " value:" << enumValues[i]
<< " error:" << errorString;
delete metaData;
return;
}
}
_nameToFactMetaDataMap[name] = metaData;
}
}
/*=====================================================================
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/>.
======================================================================*/
#ifndef FactGroup_H
#define FactGroup_H
#include "Fact.h"
#include "QGCLoggingCategory.h"
#include <QStringList>
#include <QMap>
#include <QTimer>
Q_DECLARE_LOGGING_CATEGORY(VehicleLog)
/// Used to group Facts together into an object hierarachy.
class FactGroup : public QObject
{
Q_OBJECT
public:
FactGroup(int updateRateMsecs, const QString& metaDataFile, QObject* parent = NULL);
Q_PROPERTY(QStringList factNames READ factNames CONSTANT)
Q_PROPERTY(QStringList factGroupNames READ factGroupNames CONSTANT)
/// @return Fact for specified name, NULL if not found
Q_INVOKABLE Fact* getFact(const QString& name);
/// @return FactGroup for specified name, NULL if not found
Q_INVOKABLE FactGroup* getFactGroup(const QString& name);
QStringList factNames(void) const { return _nameToFactMap.keys(); }
QStringList factGroupNames(void) const { return _nameToFactGroupMap.keys(); }
protected:
void _addFact(Fact* fact, const QString& name);
void _addFactGroup(FactGroup* factGroup, const QString& name);
int _updateRateMSecs; ///< Update rate for Fact::valueChanged signals, 0: immediate update
private slots:
void _updateAllValues(void);
private:
void _loadMetaData(const QString& filename);
QMap<QString, Fact*> _nameToFactMap;
QMap<QString, FactGroup*> _nameToFactGroupMap;
QMap<QString, FactMetaData*> _nameToFactMetaDataMap;
QTimer _updateTimer;
static const char* _propertiesJsonKey;
static const char* _nameJsonKey;
static const char* _decimalPlacesJsonKey;
static const char* _typeJsonKey;
static const char* _versionJsonKey;
static const char* _shortDescriptionJsonKey;
static const char* _unitsJsonKey;
};
#endif
......@@ -398,3 +398,39 @@ void FactMetaData::setRawUnits(const QString& rawUnits)
_setBuiltInTranslator();
}
FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString, bool& unknownType)
{
QStringList knownTypeStrings;
QList<ValueType_t> knownTypes;
unknownType = false;
knownTypeStrings << QStringLiteral("Uint8")
<< QStringLiteral("Int8")
<< QStringLiteral("Uint16")
<< QStringLiteral("Int16")
<< QStringLiteral("Uint32")
<< QStringLiteral("Int32")
<< QStringLiteral("Float")
<< QStringLiteral("Double");
knownTypes << valueTypeUint8
<< valueTypeInt8
<< valueTypeUint16
<< valueTypeInt16
<< valueTypeUint32
<< valueTypeInt32
<< valueTypeFloat
<< valueTypeDouble;
for (int i=0; i<knownTypeStrings.count(); i++) {
if (knownTypeStrings[i].compare(typeString, Qt::CaseInsensitive) == 0) {
return knownTypes[i];
}
}
unknownType = true;
return valueTypeDouble;
}
......@@ -120,6 +120,8 @@ public:
static const int defaultDecimalPlaces = 3;
static ValueType_t stringToType(const QString& typeString, bool& unknownType);
private:
QVariant _minForType(void) const;
QVariant _maxForType(void) const;
......
......@@ -25,6 +25,7 @@
/// @author Don Gagne <don@thegagnes.com>
#include "FactSystem.h"
#include "FactGroup.h"
#include "FactPanelController.h"
#include <QtQml>
......@@ -41,6 +42,8 @@ void FactSystem::setToolbox(QGCToolbox *toolbox)
{
QGCTool::setToolbox(toolbox);
qmlRegisterType<Fact>(_factSystemQmlUri, 1, 0, "Fact");
qmlRegisterType<Fact> (_factSystemQmlUri, 1, 0, "Fact");
qmlRegisterType<FactPanelController>(_factSystemQmlUri, 1, 0, "FactPanelController");
qmlRegisterUncreatableType<FactGroup>(_factSystemQmlUri, 1, 0, "FactGroup", "ReferenceOnly");
}
......@@ -50,8 +50,10 @@ ParameterLoader::ParameterLoader(AutoPilotPlugin* autopilot, Vehicle* vehicle, Q
, _autopilot(autopilot)
, _vehicle(vehicle)
, _mavlink(qgcApp()->toolbox()->mavlinkProtocol())
, _dedicatedLink(_vehicle->priorityLink())
, _parametersReady(false)
, _initialLoadComplete(false)
, _saveRequired(false)
, _defaultComponentId(FactSystem::defaultComponentId)
, _totalParamCount(0)
{
......@@ -290,6 +292,7 @@ void ParameterLoader::_valueUpdated(const QVariant& value)
_waitingWriteParamNameMap[componentId].remove(name); // Remove any old entry
_waitingWriteParamNameMap[componentId][name] = 0; // Add new entry and set retry count
_waitingParamTimeoutTimer.start();
_saveRequired = true;
_dataMutex.unlock();
......@@ -327,7 +330,7 @@ void ParameterLoader::refreshAllParameters(uint8_t componentID)
mavlink_message_t msg;
mavlink_msg_param_request_list_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, _vehicle->id(), componentID);
_vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg);
_vehicle->sendMessageOnLink(_dedicatedLink, msg);
QString what = (componentID == MAV_COMP_ID_ALL) ? "MAV_COMP_ID_ALL" : QString::number(componentID);
qCDebug(ParameterLoaderLog) << "Request to refresh all parameters for component ID:" << what;
......@@ -529,7 +532,7 @@ void ParameterLoader::_tryCacheLookup()
mavlink_message_t msg;
mavlink_msg_param_request_read_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, _vehicle->id(), MAV_COMP_ID_ALL, "_HASH_CHECK", -1);
_vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg);
_vehicle->sendMessageOnLink(_dedicatedLink, msg);
}
void ParameterLoader::_readParameterRaw(int componentId, const QString& paramName, int paramIndex)
......@@ -545,7 +548,7 @@ void ParameterLoader::_readParameterRaw(int componentId, const QString& paramNam
componentId, // Target component id
fixedParamName, // Named parameter being requested
paramIndex); // Parameter index being requested, -1 for named
_vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg);
_vehicle->sendMessageOnLink(_dedicatedLink, msg);
}
void ParameterLoader::_writeParameterRaw(int componentId, const QString& paramName, const QVariant& value)
......@@ -598,7 +601,7 @@ void ParameterLoader::_writeParameterRaw(int componentId, const QString& paramNa
mavlink_message_t msg;
mavlink_msg_param_set_encode(_mavlink->getSystemId(), _mavlink->getComponentId(), &msg, &p);
_vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg);
_vehicle->sendMessageOnLink(_dedicatedLink, msg);
}
void ParameterLoader::_writeLocalParamCache()
......@@ -672,13 +675,16 @@ void ParameterLoader::_tryCacheHashLoad(int uasId, QVariant hash_value)
void ParameterLoader::_saveToEEPROM(void)
{
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->sendMessageOnLink(_vehicle->priorityLink(), msg);
qCDebug(ParameterLoaderLog) << "_saveToEEPROM";
} else {
qCDebug(ParameterLoaderLog) << "_saveToEEPROM skipped due to FirmwarePlugin::isCapable";
if (_saveRequired) {
_saveRequired = false;
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->sendMessageOnLink(_dedicatedLink, msg);
qCDebug(ParameterLoaderLog) << "_saveToEEPROM";
} else {
qCDebug(ParameterLoaderLog) << "_saveToEEPROM skipped due to FirmwarePlugin::isCapable";
}
}
}
......
......@@ -127,6 +127,8 @@ private:
FactMetaData::ValueType_t _mavTypeToFactType(MAV_PARAM_TYPE mavType);
void _saveToEEPROM(void);
void _checkInitialLoadComplete(void);
LinkInterface* _dedicatedLink; ///< Parameter protocol stays on this link
/// First mapping is by component id
/// Second mapping is parameter name, to Fact* in QVariant
......@@ -139,6 +141,7 @@ private:
bool _parametersReady; ///< true: full set of parameters correctly loaded
bool _initialLoadComplete; ///< true: Initial load of all parameters complete, whether succesful or not
bool _saveRequired; ///< true: _saveToEEPROM should be called
int _defaultComponentId;
QString _defaultComponentIdParam;
......
......@@ -483,8 +483,8 @@ QList<MAV_CMD> APMFirmwarePlugin::supportedMissionCommands(void)
{
QList<MAV_CMD> list;
list << MAV_CMD_NAV_WAYPOINT
<< MAV_CMD_NAV_LOITER_UNLIM << MAV_CMD_NAV_LOITER_TURNS << MAV_CMD_NAV_LOITER_TIME
list << MAV_CMD_NAV_WAYPOINT << MAV_CMD_NAV_SPLINE_WAYPOINT
<< MAV_CMD_NAV_LOITER_UNLIM << MAV_CMD_NAV_LOITER_TURNS << MAV_CMD_NAV_LOITER_TIME << MAV_CMD_NAV_LOITER_TO_ALT
<< MAV_CMD_NAV_RETURN_TO_LAUNCH << MAV_CMD_NAV_LAND << MAV_CMD_NAV_TAKEOFF
<< MAV_CMD_NAV_GUIDED_ENABLE
<< MAV_CMD_DO_SET_ROI << MAV_CMD_DO_GUIDED_LIMITS << MAV_CMD_DO_JUMP << MAV_CMD_DO_CHANGE_SPEED << MAV_CMD_DO_SET_CAM_TRIGG_DIST
......@@ -492,7 +492,13 @@ QList<MAV_CMD> APMFirmwarePlugin::supportedMissionCommands(void)
<< MAV_CMD_DO_SET_SERVO << MAV_CMD_DO_REPEAT_SERVO
<< MAV_CMD_DO_DIGICAM_CONFIGURE << MAV_CMD_DO_DIGICAM_CONTROL
<< MAV_CMD_DO_MOUNT_CONTROL
<< MAV_CMD_CONDITION_DELAY << MAV_CMD_CONDITION_CHANGE_ALT << MAV_CMD_CONDITION_DISTANCE << MAV_CMD_CONDITION_YAW;
<< MAV_CMD_DO_SET_HOME
<< MAV_CMD_DO_LAND_START
<< MAV_CMD_DO_FENCE_ENABLE << MAV_CMD_DO_PARACHUTE << MAV_CMD_DO_INVERTED_FLIGHT << MAV_CMD_DO_GRIPPER
<< MAV_CMD_CONDITION_DELAY << MAV_CMD_CONDITION_CHANGE_ALT << MAV_CMD_CONDITION_DISTANCE << MAV_CMD_CONDITION_YAW
<< MAV_CMD_NAV_VTOL_TAKEOFF << MAV_CMD_NAV_VTOL_LAND
<< MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT;
return list;
}
......
......@@ -2,5 +2,44 @@
"version": 1,
"mavCmdInfo": [
{
"id": 22,
"rawName": "MAV_CMD_NAV_TAKEOFF",
"friendlyName": "Takeoff",
"description": "Take off from the ground.",
"specifiesCoordinate": false,
"friendlyEdit": true,
"category": "Basic",
"param1": {
"label": "Pitch:",
"units": "radians",
"default": 0.26179939,
"decimalPlaces": 2
}
},
{
"id": 84,
"rawName": "MAV_CMD_NAV_VTOL_TAKEOFF",
"friendlyName": "VTOL takeoff",
"description": "Takeoff from ground using VTOL mode.",
"specifiesCoordinate": true,
"friendlyEdit": true,
"category": "VTOL"
},
{
"id": 85,
"rawName": "MAV_CMD_NAV_VTOL_LAND",
"friendlyName": "VTOL land",
"description": "Land using VTOL mode.",
"specifiesCoordinate": true,
"friendlyEdit": true,
"category": "VTOL",
"param7": {
"label": "Altitude:",
"units": "meters",
"default": 0.0,
"decimalPlaces": 2
}
}
]
}
......@@ -2,20 +2,5 @@
"version": 1,
"mavCmdInfo": [
{
"id": 22,
"rawName": "MAV_CMD_NAV_TAKEOFF",
"friendlyName": "Takeoff",
"description": "Take off from the ground.",
"specifiesCoordinate": true,
"friendlyEdit": true,
"category": "Basic",
"param1": {
"label": "Pitch:",
"units": "radians",
"default": 0.26179939,
"decimalPlaces": 2
}
}
]
}
......@@ -7,7 +7,7 @@
"rawName": "MAV_CMD_NAV_TAKEOFF",
"friendlyName": "Takeoff",
"description": "Take off from the ground.",
"specifiesCoordinate": true,
"specifiesCoordinate": false,
"friendlyEdit": true,
"category": "Basic"
},
......
......@@ -68,7 +68,7 @@ struct Modes2Name {
};
/// Tranlates from PX4 custom modes to flight mode names
// FIXME: Doens't handle fixed-wing/multi-rotor name differences
static const struct Modes2Name rgModes2Name[] = {
{ PX4_CUSTOM_MAIN_MODE_MANUAL, 0, "Manual", true },
{ PX4_CUSTOM_MAIN_MODE_ACRO, 0, "Acro", true },
......@@ -77,12 +77,12 @@ static const struct Modes2Name rgModes2Name[] = {
{ PX4_CUSTOM_MAIN_MODE_ALTCTL, 0, "Altitude Control", true },
{ PX4_CUSTOM_MAIN_MODE_POSCTL, 0, "Position Control", true },
{ PX4_CUSTOM_MAIN_MODE_OFFBOARD, 0, "Offboard Control", true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_READY, "Auto Ready", false },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_TAKEOFF, "Taking Off", false },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LOITER, "Loiter", true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_MISSION, "Mission", true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTL, "Return To Land", true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LAND, "Landing", false },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_READY, "Auto: Ready", false },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_TAKEOFF, "Auto: Takeoff", false },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LOITER, "Auto: Pause", true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_MISSION, "Auto: Mission", true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTL, "Auto: Return To Land", true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LAND, "Auto: Landing", false },
};
......@@ -215,14 +215,15 @@ QList<MAV_CMD> PX4FirmwarePlugin::supportedMissionCommands(void)
list << MAV_CMD_NAV_WAYPOINT
<< MAV_CMD_NAV_LOITER_UNLIM << MAV_CMD_NAV_LOITER_TIME
<< MAV_CMD_NAV_RETURN_TO_LAUNCH << MAV_CMD_NAV_LAND << MAV_CMD_NAV_TAKEOFF
<< MAV_CMD_NAV_LAND << MAV_CMD_NAV_TAKEOFF
<< MAV_CMD_NAV_ROI
<< MAV_CMD_DO_JUMP
<< MAV_CMD_CONDITION_DELAY
<< MAV_CMD_DO_VTOL_TRANSITION
<< MAV_CMD_DO_VTOL_TRANSITION << MAV_CMD_NAV_VTOL_TAKEOFF << MAV_CMD_NAV_VTOL_LAND
<< MAV_CMD_DO_DIGICAM_CONTROL
<< MAV_CMD_DO_SET_SERVO
<< MAV_CMD_DO_CHANGE_SPEED;
<< MAV_CMD_DO_CHANGE_SPEED
<< MAV_CMD_NAV_PATHPLANNING;
return list;
}
......
......@@ -198,30 +198,9 @@ void PX4ParameterMetaData::_loadParameterFactMetaData(void)
qCDebug(PX4ParameterMetaDataLog) << "Found parameter name:" << name << " type:" << type << " default:" << strDefault;
// Convert type from string to FactMetaData::ValueType_t
struct String2Type {
const char* strType;
FactMetaData::ValueType_t type;
};
static const struct String2Type rgString2Type[] = {
{ "FLOAT", FactMetaData::valueTypeFloat },
{ "INT32", FactMetaData::valueTypeInt32 },
};
static const size_t crgString2Type = sizeof(rgString2Type) / sizeof(rgString2Type[0]);
bool found = false;
FactMetaData::ValueType_t foundType;
for (size_t i=0; i<crgString2Type; i++) {
const struct String2Type* info = &rgString2Type[i];
if (type == info->strType) {
found = true;
foundType = info->type;
break;
}
}
if (!found) {
bool unknownType;
FactMetaData::ValueType_t foundType = FactMetaData::stringToType(type, unknownType);
if (unknownType) {
qWarning() << "Parameter meta data with bad type:" << type << " name:" << name;
return;
}
......
This diff is collapsed.
......@@ -44,6 +44,9 @@ FlightMap {
property bool _activeVehicleCoordinateValid: multiVehicleManager.activeVehicle ? multiVehicleManager.activeVehicle.coordinateValid : false
property var activeVehicleCoordinate: multiVehicleManager.activeVehicle ? multiVehicleManager.activeVehicle.coordinate : QtPositioning.coordinate()
Component.onCompleted: QGroundControl.flightMapPosition = center
onCenterChanged: QGroundControl.flightMapPosition = center
onActiveVehicleCoordinateChanged: {
if (_followVehicle && _activeVehicleCoordinateValid && activeVehicleCoordinate.isValid) {
_initialMapPositionSet = true
......@@ -62,7 +65,7 @@ FlightMap {
delegate:
MapPolyline {
line.width: 3
line.color: "orange"
line.color: "red"
z: QGroundControl.zOrderMapItems - 1
path: [
{ latitude: object.coordinate1.latitude, longitude: object.coordinate1.longitude },
......
......@@ -36,10 +36,10 @@ import QGroundControl.Vehicle 1.0
import QGroundControl.FlightMap 1.0
Item {
id: _root
readonly property string _InstrumentVisibleKey: "IsInstrumentPanelVisible"
property bool _isInstrumentVisible: QGroundControl.loadBoolGlobalSetting(_InstrumentVisibleKey, true)
property var _activeVehicle: multiVehicleManager.activeVehicle
property bool _isSatellite: _mainIsMap ? _flightMap ? _flightMap.isSatelliteMap : true : true
QGCMapPalette { id: mapPal; lightColors: !isBackgroundDark }
......@@ -95,99 +95,46 @@ Item {
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
visible: _isInstrumentVisible && !QGroundControl.virtualTabletJoystick
visible: !QGroundControl.virtualTabletJoystick
size: getGadgetWidth()
active: _activeVehicle != null
heading: _heading
rollAngle: _roll
pitchAngle: _pitch
altitude: _altitudeWGS84
groundSpeed: _groundSpeed
airSpeed: _airSpeed
isSatellite: _mainIsMap ? _flightMap ? _flightMap.isSatelliteMap : true : true
groundSpeedFact: _groundSpeedFact
airSpeedFact: _airSpeedFact
isSatellite: _isSatellite
z: QGroundControl.zOrderWidgets
onClicked: {
_isInstrumentVisible = false
QGroundControl.saveBoolGlobalSetting(_InstrumentVisibleKey, false)
}
qgcView: parent.parent.qgcView
maxHeight: parent.height - (ScreenTools.defaultFontPixelHeight * 2)
}
//-- Alternate Instrument Panel
Rectangle {
visible: QGroundControl.virtualTabletJoystick
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.right: parent.right
anchors.bottom: parent.bottom
width: pipSize
height: pipSize * (9/16)
color: Qt.rgba(0,0,0,0.75)
Column {
id: instruments
width: parent.width
spacing: ScreenTools.defaultFontPixelSize * 0.33
anchors.verticalCenter: parent.verticalCenter
QGCLabel {
text: "Altitude (m)"
font.pixelSize: ScreenTools.defaultFontPixelSize * 0.75
width: parent.width
height: ScreenTools.defaultFontPixelSize * 0.75
color: "white"
horizontalAlignment: TextEdit.AlignHCenter
}
QGCLabel {
text: _altitudeWGS84 < 10000 ? _altitudeWGS84.toFixed(1) : _altitudeWGS84.toFixed(0)
font.pixelSize: ScreenTools.defaultFontPixelSize * 1.5
font.weight: Font.DemiBold
width: parent.width
color: "white"
horizontalAlignment: TextEdit.AlignHCenter
}
QGCLabel {
text: "Ground Speed (km/h)"
font.pixelSize: ScreenTools.defaultFontPixelSize * 0.75
width: parent.width
height: ScreenTools.defaultFontPixelSize * 0.75
color: "white"
horizontalAlignment: TextEdit.AlignHCenter
}
QGCLabel {
text: (_groundSpeed * 3.6).toFixed(1)
font.pixelSize: ScreenTools.defaultFontPixelSize
font.weight: Font.DemiBold
width: parent.width
color: "white"
horizontalAlignment: TextEdit.AlignHCenter
}
}
QGCInstrumentWidgetAlternate {
id: instrumentGadgetAlternate
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.top: parent.top
anchors.right: parent.right
visible: QGroundControl.virtualTabletJoystick
width: getGadgetWidth()
active: _activeVehicle != null
heading: _heading
rollAngle: _roll
pitchAngle: _pitch
groundSpeedFact: _groundSpeedFact
airSpeedFact: _airSpeedFact
isSatellite: _isSatellite
z: QGroundControl.zOrderWidgets
}
//-- Show (Hidden) Instrument Panel
Rectangle {
id: openButton
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: ScreenTools.defaultFontPixelHeight
height: ScreenTools.defaultFontPixelSize * 2
width: ScreenTools.defaultFontPixelSize * 2
radius: ScreenTools.defaultFontPixelSize / 3
visible: !_isInstrumentVisible && !QGroundControl.virtualTabletJoystick
color: isBackgroundDark ? Qt.rgba(0,0,0,0.75) : Qt.rgba(0,0,0,0.5)
Image {
width: parent.width * 0.75
height: parent.height * 0.75
source: "/res/buttonLeft.svg"
mipmap: true
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
_isInstrumentVisible = true
QGroundControl.saveBoolGlobalSetting(_InstrumentVisibleKey, true)
}
}
ValuesWidget {
anchors.topMargin: ScreenTools.defaultFontPixelHeight
anchors.top: instrumentGadgetAlternate.bottom
anchors.left: instrumentGadgetAlternate.left
width: getGadgetWidth()
qgcView: parent.parent.qgcView
textColor: _isSatellite ? "white" : "black"
visible: QGroundControl.virtualTabletJoystick
maxHeight: multiTouchItem.y - y
}
//-- Vertical Tool Buttons
......
......@@ -51,7 +51,7 @@ Map {
readonly property real maxZoomLevel: 20
zoomLevel: 18
center: QGroundControl.defaultMapPosition
center: QGroundControl.lastKnownHomePosition
gesture.flickDeceleration: 3000
gesture.activeGestures: MapGestureArea.ZoomGesture | MapGestureArea.PanGesture | MapGestureArea.FlickGesture
......
......@@ -35,41 +35,13 @@ import QGroundControl.Controls 1.0
MapItemView {
id: _root
property var itemDragger ///< Set to item drag control if you want to support drag
delegate: MissionItemIndicator {
id: itemIndicator
coordinate: object.coordinate
visible: object.specifiesCoordinate && (!object.homePosition || object.homePositionValid)
visible: object.specifiesCoordinate && (index != 0 || object.showHomePosition)
z: QGroundControl.zOrderMapItems
missionItem: object
onClicked: setCurrentItem(object.sequenceNumber)
Connections {
target: object
onIsCurrentItemChanged: {
if (isCurrentItem) {
if (_root.itemDragger) {
// Setup our drag item
if (object.sequenceNumber != 0) {
_root.itemDragger.visible = true
_root.itemDragger.missionItem = Qt.binding(function() { return object })
_root.itemDragger.missionItemIndicator = Qt.binding(function() { return itemIndicator })
} else {
_root.itemDragger.clearItem()
}
}
// Zoom the map and move to the new position
_root.parent.zoomLevel = _root.parent.maxZoomLevel
_root.parent.latitude = object.coordinate.latitude
_root.parent.longitude = object.coordinate.longitude
}
}
}
// These are the non-coordinate child mission items attached to this item
Row {
anchors.top: parent.top
......
......@@ -30,6 +30,10 @@ import QGroundControl.Palette 1.0
/// The MissionLineView control is used to add lines between mission items
MapItemView {
id: _root
property bool homePositionValid: true ///< true: show home position, false: don't show home position
delegate: MapPolyline {
line.width: 3
line.color: "#be781c" // Hack, can't get palette to work in here
......
......@@ -51,7 +51,7 @@ MapQuickItem {
transform: Rotation {
origin.x: vehicleIcon.width / 2
origin.y: vehicleIcon.height / 2
angle: vehicle ? vehicle.heading : 0
angle: vehicle ? vehicle.heading.value : 0
}
}
}
......@@ -29,24 +29,30 @@ This file is part of the QGROUNDCONTROL project
import QtQuick 2.4
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
Item {
id: root
height: size
signal clicked
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FlightMap 1.0
Rectangle {
id: instrumentPanel
height: compass.y + compass.height + _topBottomMargin
width: size
radius: size / 2
color: isSatellite ? Qt.rgba(1,1,1,0.75) : Qt.rgba(0,0,0,0.75)
property alias heading: compass.heading
property alias rollAngle: attitude.rollAngle
property alias pitchAngle: attitude.pitchAngle
property real altitude: 0
property real groundSpeed: 0
property real airSpeed: 0
property real size: _defaultSize
property bool isSatellite: false
property bool active: false
property var qgcView
property real maxHeight
property Fact _emptyFact: Fact { }
property Fact groundSpeedFact: _emptyFact
property Fact airSpeedFact: _emptyFact
property real _defaultSize: ScreenTools.defaultFontPixelSize * (9)
......@@ -54,122 +60,59 @@ Item {
property real _bigFontSize: ScreenTools.defaultFontPixelSize * 2.5 * _sizeRatio
property real _normalFontSize:ScreenTools.defaultFontPixelSize * 1.5 * _sizeRatio
property real _labelFontSize: ScreenTools.defaultFontPixelSize * 0.75 * _sizeRatio
property real _spacing: ScreenTools.defaultFontPixelSize * 0.33
property real _topBottomMargin: (size * 0.05) / 2
property real _availableValueHeight: maxHeight - (attitude.height + _spacer1.height + _spacer2.height + compass.height + (_spacing * 4))
MouseArea {
anchors.fill: parent
onClicked: _valuesWidget.showPicker()
}
QGCAttitudeWidget {
id: attitude
y: _topBottomMargin
size: parent.width * 0.95
active: active
anchors.horizontalCenter: parent.horizontalCenter
}
//-- Instrument Panel
Rectangle {
id: instrumentPanel
height: instruments.height + (size * 0.05)
width: root.size
radius: root.size / 2
color: isSatellite ? Qt.rgba(1,1,1,0.75) : Qt.rgba(0,0,0,0.75)
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
Column {
id: instruments
width: parent.width
spacing: ScreenTools.defaultFontPixelSize * 0.33
anchors.verticalCenter: parent.verticalCenter
//-- Attitude Indicator
QGCAttitudeWidget {
id: attitude
size: parent.width * 0.95
active: root.active
anchors.horizontalCenter: parent.horizontalCenter
}
//-- Altitude
Rectangle {
height: 1
width: parent.width * 0.9
color: isSatellite ? Qt.rgba(0,0,0,0.25) : Qt.rgba(1,1,1,0.25)
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: "Altitude (m)"
font.pixelSize: _labelFontSize
width: parent.width
height: _labelFontSize
color: isSatellite ? "black" : "white"
horizontalAlignment: TextEdit.AlignHCenter
}
QGCLabel {
text: altitude < 10000 ? altitude.toFixed(1) : altitude.toFixed(0)
font.pixelSize: _bigFontSize
font.weight: Font.DemiBold
width: parent.width
color: isSatellite ? "black" : "white"
horizontalAlignment: TextEdit.AlignHCenter
}
//-- Ground Speed
Rectangle {
height: 1
width: parent.width * 0.9
color: isSatellite ? Qt.rgba(0,0,0,0.25) : Qt.rgba(1,1,1,0.25)
anchors.horizontalCenter: parent.horizontalCenter
visible: airSpeed <= 0 && !ScreenTools.isTinyScreen
}
QGCLabel {
text: "Ground Speed (km/h)"
font.pixelSize: _labelFontSize
width: parent.width
height: _labelFontSize
color: isSatellite ? "black" : "white"
horizontalAlignment: TextEdit.AlignHCenter
visible: airSpeed <= 0 && !ScreenTools.isTinyScreen
}
QGCLabel {
text: (groundSpeed * 3.6).toFixed(1)
font.pixelSize: _normalFontSize
font.weight: Font.DemiBold
width: parent.width
color: isSatellite ? "black" : "white"
horizontalAlignment: TextEdit.AlignHCenter
visible: airSpeed <= 0 && !ScreenTools.isTinyScreen
}
//-- Air Speed
Rectangle {
height: 1
width: parent.width * 0.9
color: isSatellite ? Qt.rgba(0,0,0,0.25) : Qt.rgba(1,1,1,0.25)
anchors.horizontalCenter: parent.horizontalCenter
visible: airSpeed > 0 && !ScreenTools.isTinyScreen
}
QGCLabel {
text: "Air Speed (km/h)"
font.pixelSize: _labelFontSize
width: parent.width
height: _labelFontSize
color: isSatellite ? "black" : "white"
visible: airSpeed > 0 && !ScreenTools.isTinyScreen
horizontalAlignment: TextEdit.AlignHCenter
}
QGCLabel {
text: (airSpeed * 3.6).toFixed(1)
font.pixelSize: _normalFontSize
font.weight: Font.DemiBold
width: parent.width
color: isSatellite ? "black" : "white"
visible: airSpeed > 0 && !ScreenTools.isTinyScreen
horizontalAlignment: TextEdit.AlignHCenter
}
//-- Compass
Rectangle {
height: 1
width: parent.width * 0.9
color: isSatellite ? Qt.rgba(0,0,0,0.25) : Qt.rgba(1,1,1,0.25)
anchors.horizontalCenter: parent.horizontalCenter
}
QGCCompassWidget {
id: compass
size: parent.width * 0.95
active: root.active
anchors.horizontalCenter: parent.horizontalCenter
}
}
MouseArea {
anchors.fill: parent
onClicked: {
onClicked: root.clicked()
}
}
id: _spacer1
anchors.topMargin: _spacing
anchors.top: attitude.bottom
height: 1
width: parent.width * 0.9
color: isSatellite ? Qt.rgba(0,0,0,0.25) : Qt.rgba(1,1,1,0.25)
anchors.horizontalCenter: parent.horizontalCenter
}
ValuesWidget {
id: _valuesWidget
anchors.topMargin: _spacing
anchors.top: _spacer1.bottom
width: parent.width
qgcView: instrumentPanel.qgcView
textColor: isSatellite ? "black" : "white"
maxHeight: _availableValueHeight
}
Rectangle {
id: _spacer2
anchors.topMargin: _spacing
anchors.top: _valuesWidget.bottom
height: 1
width: parent.width * 0.9
color: isSatellite ? Qt.rgba(0,0,0,0.25) : Qt.rgba(1,1,1,0.25)
anchors.horizontalCenter: parent.horizontalCenter
}
QGCCompassWidget {
id: compass
anchors.topMargin: _spacing
anchors.top: _spacer2.bottom
size: parent.width * 0.95
active: active
anchors.horizontalCenter: parent.horizontalCenter
}
}
/*=====================================================================
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/>.
======================================================================*/
import QtQuick 2.4
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FlightMap 1.0
/// Instrument panel shown when virtual thumbsticks are visible
Rectangle {
id: root
height: _outerRadius * 2
radius: _outerRadius
color: isSatellite ? Qt.rgba(1,1,1,0.75) : Qt.rgba(0,0,0,0.75)
property alias heading: compass.heading
property alias rollAngle: attitude.rollAngle
property alias pitchAngle: attitude.pitchAngle
property real size: _defaultSize
property bool isSatellite: false
property bool active: false
property Fact _emptyFact: Fact { }
property Fact groundSpeedFact: _emptyFact
property Fact airSpeedFact: _emptyFact
property Fact altitudeFact: _emptyFact
property real _innerRadius: (width - (_topBottomMargin * 3)) / 4
property real _outerRadius: _innerRadius + _topBottomMargin
property real _defaultSize: ScreenTools.defaultFontPixelSize * (9)
property real _sizeRatio: ScreenTools.isTinyScreen ? (size / _defaultSize) * 0.5 : size / _defaultSize
property real _bigFontSize: ScreenTools.defaultFontPixelSize * 2.5 * _sizeRatio
property real _normalFontSize:ScreenTools.defaultFontPixelSize * 1.5 * _sizeRatio
property real _labelFontSize: ScreenTools.defaultFontPixelSize * 0.75 * _sizeRatio
property real _spacing: ScreenTools.defaultFontPixelSize * 0.33
property real _topBottomMargin: (size * 0.05) / 2
QGCAttitudeWidget {
id: attitude
anchors.leftMargin: _topBottomMargin
anchors.left: parent.left
size: _innerRadius * 2
active: active
anchors.verticalCenter: parent.verticalCenter
}
QGCCompassWidget {
id: compass
anchors.leftMargin: _spacing
anchors.left: attitude.right
size: _innerRadius * 2
active: active
anchors.verticalCenter: parent.verticalCenter
}
}
/*=====================================================================
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/>.
======================================================================*/
import QtQuick 2.4
import QtQuick.Dialogs 1.2
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.Palette 1.0
import QGroundControl 1.0
QGCFlickable {
id: _root
visible: _activeVehicle
height: Math.min(maxHeight, _smallFlow.y + _smallFlow.height)
contentHeight: _smallFlow.y + _smallFlow.height
flickableDirection: Flickable.VerticalFlick
clip: true
property var qgcView
property color textColor
property var maxHeight
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property real _margins: ScreenTools.defaultFontPixelWidth / 2
QGCPalette { id:qgcPal; colorGroupEnabled: true }
ValuesWidgetController {
id: controller
}
function showPicker() {
qgcView.showDialog(propertyPicker, "Value Widget Setup", qgcView.showDialogDefaultWidth, StandardButton.Ok)
}
MouseArea {
anchors.fill: parent
onClicked: showPicker()
}
Column {
id: _largeColumn
width: parent.width
spacing: _margins
Repeater {
model: _activeVehicle ? controller.largeValues : 0
Column {
id: valueColumn
width: _largeColumn.width
property Fact fact: _activeVehicle.getFact(modelData.replace("Vehicle.", ""))
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
color: textColor
text: fact.shortDescription + (fact.units ? " (" + fact.units + ")" : "")
}
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
font.pixelSize: ScreenTools.largeFontPixelSize
font.weight: Font.DemiBold
color: textColor
text: fact.valueString
}
}
} // Repeater - Large
} // Column - Large
Flow {
id: _smallFlow
width: parent.width
anchors.topMargin: _margins
anchors.top: _largeColumn.bottom
layoutDirection: Qt.LeftToRight
spacing: _margins
Repeater {
model: _activeVehicle ? controller.smallValues : 0
Column {
id: valueColumn
width: (_root.width / 2) - (_margins / 2) - 0.1
clip: true
property Fact fact: _activeVehicle.getFact(modelData.replace("Vehicle.", ""))
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
font.pixelSize: ScreenTools.smallFontPixelSize
color: textColor
text: fact.shortDescription
}
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
color: textColor
text: fact.enumOrValueString
}
QGCLabel {
width: parent.width
horizontalAlignment: Text.AlignHCenter
font.pixelSize: ScreenTools.smallFontPixelSize
color: textColor
text: fact.units
}
}
} // Repeater - Small
} // Flow
Component {
id: propertyPicker
QGCViewDialog {
id: _propertyPickerDialog
QGCLabel {
id: _label
text: "Select the values you want to display:"
}
Loader {
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: _margins
anchors.top: _label.bottom
anchors.bottom: parent.bottom
sourceComponent: factGroupList
property var factGroup: _activeVehicle
property var factGroupName: "Vehicle"
}
}
}
Component {
id: factGroupList
// You must push in the following properties from the Loader
// property var factGroup
// property string factGroupName
Column {
id: _root
spacing: _margins
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: factGroup ? factGroupName : "Vehicle must be connected to assign values."
}
Repeater {
model: factGroup ? factGroup.factNames : 0
Row {
spacing: _margins
property string propertyName: factGroupName + "." + modelData
function contains(list, value) {
for (var i=0; i<list.length; i++) {
if (list[i] === value) {
return true
}
}
return false
}
function removeFromList(list, value) {
var newList = []
for (var i=0; i<list.length; i++) {
if (list[i] !== value) {
newList.push(list[i])
}
}
return newList
}
function addToList(list, value) {
var found = false
for (var i=0; i<list.length; i++) {
if (list[i] === value) {
found = true
break
}
}
if (!found) {
list.push(value)
}
return list
}
function updateValues() {
if (_addCheckBox.checked) {
if (_largeCheckBox.checked) {
controller.largeValues = addToList(controller.largeValues, propertyName)
controller.smallValues = removeFromList(controller.smallValues, propertyName)
} else {
controller.smallValues = addToList(controller.smallValues, propertyName)
controller.largeValues = removeFromList(controller.largeValues, propertyName)
}
} else {
controller.largeValues = removeFromList(controller.largeValues, propertyName)
controller.smallValues = removeFromList(controller.smallValues, propertyName)
}
}
QGCCheckBox {
id: _addCheckBox
text: factGroup.getFact(modelData).shortDescription
checked: _largeCheckBox.checked || parent.contains(controller.smallValues, propertyName)
onClicked: updateValues()
}
QGCCheckBox {
id: _largeCheckBox
text: "large"
checked: parent.contains(controller.largeValues, propertyName)
enabled: _addCheckBox.checked
onClicked: updateValues()
}
}
}
Item { height: 1; width: 1 }
Repeater {
model: factGroup ? factGroup.factGroupNames : 0
Loader {
sourceComponent: factGroupList
property var factGroup: _root ? _root.parent.factGroup.getFactGroup(modelData) : undefined
property string factGroupName: _root ? _root.parent.factGroupName + "." + modelData : undefined
}
}
}
}
}
/*=====================================================================
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/>.
======================================================================*/
#include "ValuesWidgetController.h"
#include <QSettings>
const char* ValuesWidgetController::_groupKey = "ValuesWidget";
const char* ValuesWidgetController::_largeValuesKey = "large";
const char* ValuesWidgetController::_smallValuesKey = "small";
ValuesWidgetController::ValuesWidgetController(void)
{
QSettings settings;
QStringList largeDefaults;
settings.beginGroup(_groupKey);
largeDefaults << "Vehicle.altitudeRelative" << "Vehicle.groundSpeed";
_largeValues = settings.value(_largeValuesKey, largeDefaults).toStringList();
_smallValues = settings.value(_smallValuesKey, QStringList()).toStringList();
// Keep back compat for removed WGS84 value
if (_largeValues.contains ("Vehicle.altitudeWGS84")) {
setLargeValues(_largeValues.replaceInStrings("Vehicle.altitudeWGS84", "Vehicle.altitudeRelative"));
}
if (_smallValues.contains ("Vehicle.altitudeWGS84")) {
setSmallValues(_largeValues.replaceInStrings("Vehicle.altitudeWGS84", "Vehicle.altitudeRelative"));
}
}
void ValuesWidgetController::setLargeValues(const QStringList& values)
{
QSettings settings;
settings.beginGroup(_groupKey);
settings.setValue(_largeValuesKey, values);
_largeValues = values;
emit largeValuesChanged(values);
}
void ValuesWidgetController::setSmallValues(const QStringList& values)
{
QSettings settings;
settings.beginGroup(_groupKey);
settings.setValue(_smallValuesKey, values);
_smallValues = values;
emit smallValuesChanged(values);
}
/*=====================================================================
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/>.
======================================================================*/
#ifndef ValuesWidgetController_H
#define ValuesWidgetController_H
#include <QObject>
class ValuesWidgetController : public QObject
{
Q_OBJECT
public:
ValuesWidgetController(void);
Q_PROPERTY(QStringList largeValues READ largeValues WRITE setLargeValues NOTIFY largeValuesChanged)
Q_PROPERTY(QStringList smallValues READ smallValues WRITE setSmallValues NOTIFY smallValuesChanged)
QStringList largeValues(void) const { return _largeValues; }
QStringList smallValues(void) const { return _smallValues; }
void setLargeValues(const QStringList& values);
void setSmallValues(const QStringList& values);
signals:
void largeValuesChanged(QStringList values);
void smallValuesChanged(QStringList values);
private:
QStringList _largeValues;
QStringList _smallValues;
static const char* _groupKey;
static const char* _largeValuesKey;
static const char* _smallValuesKey;
};
#endif
......@@ -5,13 +5,15 @@ FlightMap 1.0 FlightMap.qml
QGCVideoBackground 1.0 QGCVideoBackground.qml
# Widgets
QGCArtificialHorizon 1.0 QGCArtificialHorizon.qml
QGCAttitudeHUD 1.0 QGCAttitudeHUD.qml
QGCAttitudeWidget 1.0 QGCAttitudeWidget.qml
QGCCompassWidget 1.0 QGCCompassWidget.qml
QGCInstrumentWidget 1.0 QGCInstrumentWidget.qml
QGCPitchIndicator 1.0 QGCPitchIndicator.qml
QGCSlider 1.0 QGCSlider.qml
QGCArtificialHorizon 1.0 QGCArtificialHorizon.qml
QGCAttitudeHUD 1.0 QGCAttitudeHUD.qml
QGCAttitudeWidget 1.0 QGCAttitudeWidget.qml
QGCCompassWidget 1.0 QGCCompassWidget.qml
QGCInstrumentWidget 1.0 QGCInstrumentWidget.qml
QGCInstrumentWidgetAlternate 1.0 QGCInstrumentWidgetAlternate.qml
QGCPitchIndicator 1.0 QGCPitchIndicator.qml
QGCSlider 1.0 QGCSlider.qml
ValuesWidget 1.0 ValuesWidget.qml
# Map items
MissionItemIndicator 1.0 MissionItemIndicator.qml
......
/*===================================================================
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/>.
======================================================================*/
#include "JsonHelper.h"
#include <QJsonArray>
const char* JsonHelper::_enumStringsJsonKey = "enumStrings";
const char* JsonHelper::_enumValuesJsonKey = "enumValues";
bool JsonHelper::validateRequiredKeys(const QJsonObject& jsonObject, const QStringList& keys, QString& errorString)
{
QString missingKeys;
foreach(const QString& key, keys) {
if (!jsonObject.contains(key)) {
if (!missingKeys.isEmpty()) {
missingKeys += QStringLiteral(", ");
}
missingKeys += key;
}
}
if (missingKeys.count() != 0) {
errorString = QString("The following required keys are missing: %1").arg(missingKeys);
return false;
}
return true;
}
bool JsonHelper::toQGeoCoordinate(const QJsonValue& jsonValue, QGeoCoordinate& coordinate, bool altitudeRequired, QString& errorString)
{
if (!jsonValue.isArray()) {
errorString = QStringLiteral("JSon value for coordinate is not array");
return false;
}
QJsonArray coordinateArray = jsonValue.toArray();
int requiredCount = altitudeRequired ? 3 : 2;
if (coordinateArray.count() != requiredCount) {
errorString = QString("Json array must contains %1 values").arg(requiredCount);
return false;
}
coordinate = QGeoCoordinate(coordinateArray[0].toDouble(), coordinateArray[1].toDouble());
if (altitudeRequired) {
coordinate.setAltitude(coordinateArray[2].toDouble());
}
if (!coordinate.isValid()) {
errorString = QString("Coordinate is invalid: %1").arg(coordinate.toString());
return false;
}
return true;
}
bool JsonHelper::validateKeyTypes(QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString)
{
for (int i=0; i<keys.count(); i++) {
if (jsonObject.contains(keys[i])) {
if (jsonObject.value(keys[i]).type() != types[i]) {
errorString = QString("Incorrect type key:type:expected %1 %2 %3").arg(keys[i]).arg(jsonObject.value(keys[i]).type()).arg(types[i]);
return false;
}
}
}
return true;
}
bool JsonHelper::parseEnum(QJsonObject& jsonObject, QStringList& enumStrings, QStringList& enumValues, QString& errorString)
{
enumStrings = jsonObject.value(_enumStringsJsonKey).toString().split(",", QString::SkipEmptyParts);
enumValues = jsonObject.value(_enumValuesJsonKey).toString().split(",", QString::SkipEmptyParts);
if (enumStrings.count() != enumValues.count()) {
errorString = QString("enum strings/values count mismatch: %1");
return false;
}
return 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/>.
======================================================================*/
#ifndef JsonHelper_H
#define JsonHelper_H
#include <QJsonObject>
#include <QGeoCoordinate>
class JsonHelper
{
public:
static bool validateRequiredKeys(const QJsonObject& jsonObject, const QStringList& keys, QString& errorString);
static bool validateKeyTypes(QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString);
static bool toQGeoCoordinate(const QJsonValue& jsonValue, QGeoCoordinate& coordinate, bool altitudeRequired, QString& errorString);
static bool parseEnum(QJsonObject& jsonObject, QStringList& enumStrings, QStringList& enumValues, QString& errorString);
static const char* _enumStringsJsonKey;
static const char* _enumValuesJsonKey;
};
#endif
This diff is collapsed.
......@@ -32,7 +32,6 @@ Rectangle {
property var currentMissionItem ///< Mission item to display status for
property var missionItems ///< List of all available mission items
property real expandedWidth ///< Width of control when expanded
property bool homePositionValid: false /// true: home position in missionItems[0] is valid
width: _expanded ? expandedWidth : _collapsedWidth
height: expandLabel.y + expandLabel.height + _margins
......@@ -49,7 +48,7 @@ Rectangle {
property real _altDifference: _currentMissionItem ? _currentMissionItem.altDifference : -1
property real _azimuth: _currentMissionItem ? _currentMissionItem.azimuth : -1
property real _isHomePosition: _currentMissionItem ? _currentMissionItem.homePosition : false
property bool _statusValid: _distance != -1 && ((_isHomePosition && homePositionValid) || !_isHomePosition)
property bool _statusValid: _distance != -1
property string _distanceText: _statusValid ? Math.round(_distance) + " meters" : ""
property string _altText: _statusValid ? Math.round(_altDifference) + " meters" : ""
property string _azimuthText: _statusValid ? Math.round(_azimuth) : ""
......@@ -97,6 +96,8 @@ Rectangle {
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
contentWidth: graphRow.width
clip: true
Row {
id: graphRow
......@@ -108,14 +109,14 @@ Rectangle {
model: missionItems
Item {
height: graphRow.height
width: ScreenTools.smallFontPixelWidth * 2
height: graphRow.height
width: ScreenTools.smallFontPixelWidth * 2
visible: object.specifiesCoordinate && !object.standaloneCoordinate
property real availableHeight: height - ScreenTools.smallFontPixelHeight - indicator.height
// If home position is not valid we are graphing relative based on a home alt of 0. Because of this
// we cannot graph absolute altitudes since we have no basis for comparison against the relative values.
property bool graphAbsolute: homePositionValid
property bool graphAbsolute: true
MissionItemIndexLabel {
id: indicator
......
This diff is collapsed.
......@@ -26,6 +26,7 @@ This file is part of the QGROUNDCONTROL project
#include "FirmwarePluginManager.h"
#include "QGCApplication.h"
#include "QGroundControlQmlGlobal.h"
#include "JsonHelper.h"
#include <QStringList>
#include <QJsonDocument>
......@@ -62,20 +63,6 @@ MissionCommandList::MissionCommandList(const QString& jsonFilename, QObject* par
_loadMavCmdInfoJson(jsonFilename);
}
bool MissionCommandList::_validateKeyTypes(QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types)
{
for (int i=0; i<keys.count(); i++) {
if (jsonObject.contains(keys[i])) {
if (jsonObject.value(keys[i]).type() != types[i]) {
qWarning() << "Incorrect type key:type:expected" << keys[i] << jsonObject.value(keys[i]).type() << types[i];
return false;
}
}
}
return true;
}
void MissionCommandList::_loadMavCmdInfoJson(const QString& jsonFilename)
{
if (jsonFilename.isEmpty()) {
......@@ -122,13 +109,12 @@ void MissionCommandList::_loadMavCmdInfoJson(const QString& jsonFilename)
QJsonObject jsonObject = info.toObject();
// Make sure we have the required keys
QString errorString;
QStringList requiredKeys;
requiredKeys << _idJsonKey << _rawNameJsonKey;
foreach (const QString &key, requiredKeys) {
if (!jsonObject.contains(key)) {
qWarning() << "Mission required key" << key;
return;
}
if (!JsonHelper::validateRequiredKeys(jsonObject, requiredKeys, errorString)) {
qWarning() << errorString;
return;
}
// Validate key types
......@@ -139,7 +125,8 @@ void MissionCommandList::_loadMavCmdInfoJson(const QString& jsonFilename)
<< _param1JsonKey << _param2JsonKey << _param3JsonKey << _param4JsonKey << _categoryJsonKey;
types << QJsonValue::Double << QJsonValue::String << QJsonValue::String<< QJsonValue::String << QJsonValue::Bool << QJsonValue::Bool << QJsonValue::Bool
<< QJsonValue::Object << QJsonValue::Object << QJsonValue::Object << QJsonValue::Object << QJsonValue::String;
if (!_validateKeyTypes(jsonObject, keys, types)) {
if (!JsonHelper::validateKeyTypes(jsonObject, keys, types, errorString)) {
qWarning() << errorString;
return;
}
......@@ -184,7 +171,8 @@ void MissionCommandList::_loadMavCmdInfoJson(const QString& jsonFilename)
QList<QJsonValue::Type> types;
keys << _defaultJsonKey << _decimalPlacesJsonKey << _enumStringsJsonKey << _enumValuesJsonKey << _labelJsonKey << _unitsJsonKey;
types << QJsonValue::Double << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String;
if (!_validateKeyTypes(paramObject, keys, types)) {
if (!JsonHelper::validateKeyTypes(jsonObject, keys, types, errorString)) {
qWarning() << errorString;
return;
}
......
......@@ -143,7 +143,6 @@ public:
private:
void _loadMavCmdInfoJson(const QString& jsonFilename);
bool _validateKeyTypes(QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types);
private:
QMap<MAV_CMD, MavCmdInfo*> _mavCmdInfoMap;
......
......@@ -77,10 +77,14 @@ void MissionCommands::_createCategories(void)
foreach (MAV_CMD command, cmdList) {
MavCmdInfo* mavCmdInfo = _commonMissionCommands.getMavCmdInfo(command);
if (mavCmdInfo->friendlyEdit()) {
_categoryToMavCmdListMap[firmwareType][mavCmdInfo->category()].append(command);
} else if (!allCommandsSupported) {
qWarning() << "Attempt to add non friendly edit supported command";
if (mavCmdInfo) {
if (mavCmdInfo->friendlyEdit()) {
_categoryToMavCmdListMap[firmwareType][mavCmdInfo->category()].append(command);
} else if (!allCommandsSupported) {
qWarning() << "Attempt to add non friendly edit supported command" << command;
}
} else {
qCDebug(MissionCommandsLog) << "Command missing from json" << command;
}
}
}
......@@ -146,20 +150,20 @@ MavCmdInfo* MissionCommands::getMavCmdInfo(MAV_CMD command, Vehicle* vehicle) co
if (vehicle) {
if (vehicle->fixedWing()) {
if (_autopilotToFixedWingMissionCommands[firmwareType]->contains(command)) {
if (_autopilotToFixedWingMissionCommands.contains(firmwareType) && _autopilotToFixedWingMissionCommands[firmwareType]->contains(command)) {
mavCmdInfo = _autopilotToFixedWingMissionCommands[firmwareType]->getMavCmdInfo(command);
}
} else if (vehicle->multiRotor()) {
if (_autopilotToMultiRotorMissionCommands[firmwareType]->contains(command)) {
if (_autopilotToMultiRotorMissionCommands.contains(firmwareType) && _autopilotToMultiRotorMissionCommands[firmwareType]->contains(command)) {
mavCmdInfo = _autopilotToMultiRotorMissionCommands[firmwareType]->getMavCmdInfo(command);
}
} else {
if (_autopilotToCommonMissionCommands[firmwareType]->contains(command)) {
mavCmdInfo = _autopilotToCommonMissionCommands[firmwareType]->getMavCmdInfo(command);
}
}
}
if (!mavCmdInfo && _autopilotToCommonMissionCommands.contains(firmwareType) && _autopilotToCommonMissionCommands[firmwareType]->contains(command)) {
mavCmdInfo = _autopilotToCommonMissionCommands[firmwareType]->getMavCmdInfo(command);
}
if (!mavCmdInfo) {
mavCmdInfo = _commonMissionCommands.getMavCmdInfo(command);
}
......
This diff is collapsed.
......@@ -42,17 +42,19 @@ public:
Q_PROPERTY(QmlObjectListModel* missionItems READ missionItems NOTIFY missionItemsChanged)
Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged)
Q_PROPERTY(bool liveHomePositionAvailable READ liveHomePositionAvailable NOTIFY liveHomePositionAvailableChanged)
Q_PROPERTY(QGeoCoordinate liveHomePosition READ liveHomePosition NOTIFY liveHomePositionChanged)
Q_PROPERTY(bool autoSync READ autoSync WRITE setAutoSync NOTIFY autoSyncChanged)
Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged)
Q_INVOKABLE void start(bool editMode);
Q_INVOKABLE void getMissionItems(void);
Q_INVOKABLE void sendMissionItems(void);
Q_INVOKABLE void loadMissionFromFile(void);
Q_INVOKABLE void saveMissionToFile(void);
Q_INVOKABLE void loadMobileMissionFromFile(const QString& file);
Q_INVOKABLE void saveMobileMissionToFile(const QString& file);
Q_INVOKABLE void removeMissionItem(int index);
Q_INVOKABLE void removeAllMissionItems(void);
Q_INVOKABLE QStringList getMobileMissionFiles(void);
/// @param i: index to insert at
Q_INVOKABLE int insertMissionItem(QGeoCoordinate coordinate, int i);
......@@ -61,18 +63,16 @@ public:
QmlObjectListModel* missionItems(void);
QmlObjectListModel* waypointLines(void) { return &_waypointLines; }
bool liveHomePositionAvailable(void) { return _liveHomePositionAvailable; }
QGeoCoordinate liveHomePosition(void) { return _liveHomePosition; }
bool autoSync(void) { return _autoSync; }
void setAutoSync(bool autoSync);
bool syncInProgress(void);
signals:
void missionItemsChanged(void);
void waypointLinesChanged(void);
void liveHomePositionAvailableChanged(bool homePositionAvailable);
void liveHomePositionChanged(const QGeoCoordinate& homePosition);
void autoSyncChanged(bool autoSync);
void newItemsFromVehicle(void);
void syncInProgressChanged(bool syncInProgress);
private slots:
void _newMissionItemsAvailableFromVehicle();
......@@ -84,6 +84,7 @@ private slots:
void _activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
void _dirtyChanged(bool dirty);
void _inProgressChanged(bool inProgress);
void _currentMissionItemChanged(int sequenceNumber);
private:
void _recalcSequence(void);
......@@ -95,25 +96,34 @@ private:
void _initMissionItem(MissionItem* item);
void _deinitMissionItem(MissionItem* item);
void _autoSyncSend(void);
void _setupMissionItems(bool loadFromVehicle, bool forceLoad);
void _setupActiveVehicle(Vehicle* activeVehicle, bool forceLoadFromVehicle);
void _calcPrevWaypointValues(bool homePositionValid, double homeAlt, MissionItem* currentItem, MissionItem* prevItem, double* azimuth, double* distance, double* altDifference);
void _calcPrevWaypointValues(double homeAlt, MissionItem* currentItem, MissionItem* prevItem, double* azimuth, double* distance, double* altDifference);
bool _findLastAltitude(double* lastAltitude);
bool _findLastAcceptanceRadius(double* lastAcceptanceRadius);
void _addPlannedHomePosition(QmlObjectListModel* missionItems, bool addToCenter);
double _normalizeLat(double lat);
double _normalizeLon(double lon);
bool _loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* missionItems, QString& errorString);
bool _loadTextMissionFile(QTextStream& stream, QmlObjectListModel* missionItems, QString& errorString);
void _loadMissionFromFile(const QString& file);
void _saveMissionToFile(const QString& file);
private:
bool _editMode;
QmlObjectListModel* _missionItems;
QmlObjectListModel _waypointLines;
Vehicle* _activeVehicle;
bool _liveHomePositionAvailable;
QGeoCoordinate _liveHomePosition;
bool _autoSync;
bool _firstItemsFromVehicle;
bool _missionItemsRequested;
bool _queuedSend;
static const char* _settingsGroup;
static const char* _settingsGroup;
static const char* _jsonVersionKey;
static const char* _jsonGroundStationKey;
static const char* _jsonMavAutopilotKey;
static const char* _jsonItemsKey;
static const char* _jsonPlannedHomePositionKey;
};
#endif
This diff is collapsed.
......@@ -61,13 +61,11 @@ private:
enum {
coordinateChangedSignalIndex = 0,
homePositionValidChangedSignalIndex,
missionItemMaxSignalIndex
};
enum {
coordinateChangedSignalMask = 1 << coordinateChangedSignalIndex,
homePositionValidChangedSignalMask = 1 << homePositionValidChangedSignalIndex,
missionItemMaxSignalMask = 1 << missionItemMaxSignalIndex,
};
......@@ -76,16 +74,12 @@ private:
enum {
missionItemsChangedSignalIndex = 0,
waypointLinesChangedSignalIndex,
liveHomePositionAvailableChangedSignalIndex,
liveHomePositionChangedSignalIndex,
missionControllerMaxSignalIndex
};
enum {
missionItemsChangedSignalMask = 1 << missionItemsChangedSignalIndex,
waypointLinesChangedSignalMask = 1 << waypointLinesChangedSignalIndex,
liveHomePositionAvailableChangedSignalMask = 1 << liveHomePositionAvailableChangedSignalIndex,
liveHomePositionChangedSignalMask = 1 << liveHomePositionChangedSignalIndex,
};
MultiSignalSpy* _multiSpyMissionController;
......
This diff is collapsed.
This diff is collapsed.
......@@ -38,7 +38,6 @@ const MissionItemTest::ItemInfo_t MissionItemTest::_rgItemInfo[] = {
const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesWaypoint[] = {
{ "Altitude:", 70.1234567 },
{ "Hold:", 10.1234567 },
{ "Accept radius:", 20.1234567 },
};
const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesLoiterUnlim[] = {
......@@ -97,6 +96,9 @@ MissionItemTest::MissionItemTest(void)
void MissionItemTest::_test(void)
{
#if 0
// FIXME: Update to json
for (size_t i=0; i<sizeof(_rgItemInfo)/sizeof(_rgItemInfo[0]); i++) {
const ItemInfo_t* info = &_rgItemInfo[i];
const ItemExpected_t* expected = &_rgItemExpected[i];
......@@ -177,6 +179,7 @@ void MissionItemTest::_test(void)
delete item;
delete loadedItem;
}
#endif
}
void MissionItemTest::_testDefaultValues(void)
......@@ -185,6 +188,5 @@ void MissionItemTest::_testDefaultValues(void)
item.setCommand(MAV_CMD_NAV_WAYPOINT);
item.setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
QCOMPARE(item.param2(), 3.0);
QCOMPARE(item.param7(), MissionItem::defaultAltitude);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -71,7 +71,7 @@ TextField {
}
onActiveFocusChanged: {
if (activeFocus) {
if (!ScreenTools.isMobile && activeFocus) {
selectAll()
}
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -37,6 +37,7 @@ MAVLinkDecoder::MAVLinkDecoder(MAVLinkProtocol* protocol, QObject *parent) :
messageFilter.insert(MAVLINK_MSG_ID_DATA_STREAM, false);
messageFilter.insert(MAVLINK_MSG_ID_GPS_STATUS, false);
messageFilter.insert(MAVLINK_MSG_ID_RC_CHANNELS_RAW, false);
messageFilter.insert(MAVLINK_MSG_ID_LOG_DATA, false);
#ifdef MAVLINK_MSG_ID_ENCAPSULATED_DATA
messageFilter.insert(MAVLINK_MSG_ID_ENCAPSULATED_DATA, false);
#endif
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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