Browse Source

Merge branch 'Stable_V3.2' of https://github.com/mavlink/qgroundcontrol into cameraControl

# Conflicts:
#	src/Vehicle/Vehicle.h
QGC4.4
Gus Grubba 8 years ago
parent
commit
4362d4e562
  1. 2
      QGCInstaller.pri
  2. 6
      deploy/qgroundcontrol_installer.nsi
  3. 2
      ios/iOSForAppStore-Info-Source.plist
  4. 6
      qgroundcontrol.pro
  5. 1
      qgroundcontrol.qrc
  6. 410
      src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml
  7. 18
      src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml
  8. 17
      src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml
  9. 20
      src/FirmwarePlugin/CameraMetaData.cc
  10. 3
      src/FirmwarePlugin/CameraMetaData.h
  11. 9
      src/FirmwarePlugin/FirmwarePlugin.cc
  12. 16
      src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc
  13. 65
      src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml
  14. 6
      src/FirmwarePlugin/PX4/px4_custom_mode.h
  15. 1
      src/FlightDisplay/FlightDisplayView.qml
  16. 7
      src/FlightDisplay/FlightDisplayViewMap.qml
  17. 2
      src/FlightDisplay/GuidedActionConfirm.qml
  18. 2
      src/FlightDisplay/GuidedActionList.qml
  19. 17
      src/FlightDisplay/GuidedActionsController.qml
  20. 32
      src/MissionManager/CameraSection.cc
  21. 3
      src/MissionManager/CameraSection.h
  22. 21
      src/MissionManager/CameraSectionTest.cc
  23. 5
      src/MissionManager/MissionController.cc
  24. 19
      src/MissionManager/PlanMasterController.cc
  25. 12
      src/MissionManager/QGCMapPolygon.cc
  26. 3
      src/MissionManager/QGCMapPolygonTest.cc
  27. 7
      src/MissionManager/QGCMapPolygonVisuals.qml
  28. 6
      src/MissionManager/Survey.SettingsGroup.json
  29. 52
      src/MissionManager/SurveyMissionItem.cc
  30. 22
      src/MissionManager/SurveyMissionItem.h
  31. 44
      src/PlanView/SurveyItemEditor.qml
  32. 4
      src/QmlControls/MissionItemIndexLabel.qml
  33. 14
      src/QmlControls/NoMouseThroughRectangle.qml
  34. 1
      src/QmlControls/QGroundControl.Controls.qmldir
  35. 7
      src/Vehicle/Vehicle.cc
  36. 4
      src/Vehicle/Vehicle.h
  37. 125
      src/VehicleSetup/FirmwareUpgradeController.cc
  38. 7
      src/api/QGCCorePlugin.cc
  39. 36
      src/ui/MainWindow.cc
  40. 3
      src/ui/MainWindow.h

2
QGCInstaller.pri

@ -35,7 +35,7 @@ installer {
QMAKE_POST_LINK += && hdiutil create -verbose -stretch 4g -layout SPUD -srcfolder $${DESTDIR}/$${TARGET}.app -volname $${TARGET} $${DESTDIR}/package/$${TARGET}.dmg QMAKE_POST_LINK += && hdiutil create -verbose -stretch 4g -layout SPUD -srcfolder $${DESTDIR}/$${TARGET}.app -volname $${TARGET} $${DESTDIR}/package/$${TARGET}.dmg
} }
WindowsBuild { WindowsBuild {
QMAKE_POST_LINK += $$escape_expand(\\n) cd $$BASEDIR_WIN && $$quote("\"C:\\Program Files \(x86\)\\NSIS\\makensis.exe\"" /DAPPNAME="\"$${QGC_APP_NAME}\"" /DEXENAME="\"$${TARGET}\"" /DORGNAME="\"$${QGC_ORG_NAME}\"" /DDESTDIR=$${DESTDIR} /NOCD "\"/XOutFile $${DESTDIR_WIN}\\$${TARGET}-installer.exe\"" "$$BASEDIR_WIN\\deploy\\qgroundcontrol_installer.nsi") QMAKE_POST_LINK += $$escape_expand(\\n) cd $$BASEDIR_WIN && $$quote("\"C:\\Program Files \(x86\)\\NSIS\\makensis.exe\"" /DINSTALLER_ICON="\"$${QGC_INSTALLER_ICON}\"" /DHEADER_BITMAP="\"$${QGC_INSTALLER_HEADER_BITMAP}\"" /DAPPNAME="\"$${QGC_APP_NAME}\"" /DEXENAME="\"$${TARGET}\"" /DORGNAME="\"$${QGC_ORG_NAME}\"" /DDESTDIR=$${DESTDIR} /NOCD "\"/XOutFile $${DESTDIR_WIN}\\$${TARGET}-installer.exe\"" "$$BASEDIR_WIN\\deploy\\qgroundcontrol_installer.nsi")
OTHER_FILES += deploy/qgroundcontrol_installer.nsi OTHER_FILES += deploy/qgroundcontrol_installer.nsi
} }
LinuxBuild { LinuxBuild {

6
deploy/qgroundcontrol_installer.nsi

@ -44,9 +44,9 @@ InstallDir "$PROGRAMFILES\${APPNAME}"
SetCompressor /SOLID /FINAL lzma SetCompressor /SOLID /FINAL lzma
!define MUI_HEADERIMAGE !define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "installheader.bmp"; !define MUI_HEADERIMAGE_BITMAP "${HEADER_BITMAP}";
!define MUI_ICON "WindowsQGC.ico"; !define MUI_ICON "${INSTALLER_ICON}";
!define MUI_UNICON "WindowsQGC.ico"; !define MUI_UNICON "${INSTALLER_ICON}";
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder !insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder
!insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_DIRECTORY

2
ios/iOSForAppStore-Info-Source.plist

@ -85,6 +85,8 @@
<string>Ground Station Location</string> <string>Ground Station Location</string>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>QGCLaunchScreen</string> <string>QGCLaunchScreen</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>QGroundControl would like to use bluetooth.</string>
<key>UIRequiresFullScreen</key> <key>UIRequiresFullScreen</key>
<true/> <true/>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>

6
qgroundcontrol.pro

@ -55,6 +55,8 @@ iOSBuild {
count(APP_ERROR, 1) { count(APP_ERROR, 1) {
error("Error building .plist file. 'ForAppStore' builds are only possible through the official build system.") error("Error building .plist file. 'ForAppStore' builds are only possible through the official build system.")
} }
QT += qml-private
CONFIG += qtquickcompiler
QMAKE_INFO_PLIST = $${BASEDIR}/ios/iOSForAppStore-Info.plist QMAKE_INFO_PLIST = $${BASEDIR}/ios/iOSForAppStore-Info.plist
OTHER_FILES += $${BASEDIR}/ios/iOSForAppStore-Info.plist OTHER_FILES += $${BASEDIR}/ios/iOSForAppStore-Info.plist
} else { } else {
@ -82,6 +84,10 @@ QGC_ORG_DOMAIN = "org.qgroundcontrol"
QGC_APP_DESCRIPTION = "Open source ground control app provided by QGroundControl dev team" QGC_APP_DESCRIPTION = "Open source ground control app provided by QGroundControl dev team"
QGC_APP_COPYRIGHT = "Copyright (C) 2017 QGroundControl Development Team. All rights reserved." QGC_APP_COPYRIGHT = "Copyright (C) 2017 QGroundControl Development Team. All rights reserved."
WindowsBuild {
QGC_INSTALLER_ICON = "WindowsQGC.ico"
QGC_INSTALLER_HEADER_BITMAP = "installheader.bmp"
}
# Load additional config flags from user_config.pri # Load additional config flags from user_config.pri
exists(user_config.pri):infile(user_config.pri, CONFIG) { exists(user_config.pri):infile(user_config.pri, CONFIG) {

1
qgroundcontrol.qrc

@ -74,6 +74,7 @@
<file alias="QGroundControl/Controls/MissionItemStatus.qml">src/PlanView/MissionItemStatus.qml</file> <file alias="QGroundControl/Controls/MissionItemStatus.qml">src/PlanView/MissionItemStatus.qml</file>
<file alias="QGroundControl/Controls/ModeSwitchDisplay.qml">src/QmlControls/ModeSwitchDisplay.qml</file> <file alias="QGroundControl/Controls/ModeSwitchDisplay.qml">src/QmlControls/ModeSwitchDisplay.qml</file>
<file alias="QGroundControl/Controls/MultiRotorMotorDisplay.qml">src/QmlControls/MultiRotorMotorDisplay.qml</file> <file alias="QGroundControl/Controls/MultiRotorMotorDisplay.qml">src/QmlControls/MultiRotorMotorDisplay.qml</file>
<file alias="QGroundControl/Controls/NoMouseThroughRectangle.qml">src/QmlControls/NoMouseThroughRectangle.qml</file>
<file alias="QGroundControl/Controls/OfflineMapButton.qml">src/QmlControls/OfflineMapButton.qml</file> <file alias="QGroundControl/Controls/OfflineMapButton.qml">src/QmlControls/OfflineMapButton.qml</file>
<file alias="QGroundControl/Controls/ParameterEditor.qml">src/QmlControls/ParameterEditor.qml</file> <file alias="QGroundControl/Controls/ParameterEditor.qml">src/QmlControls/ParameterEditor.qml</file>
<file alias="QGroundControl/Controls/ParameterEditorDialog.qml">src/QmlControls/ParameterEditorDialog.qml</file> <file alias="QGroundControl/Controls/ParameterEditorDialog.qml">src/QmlControls/ParameterEditorDialog.qml</file>

410
src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml

@ -5,6 +5,7 @@
<airframe_version_minor>1</airframe_version_minor> <airframe_version_minor>1</airframe_version_minor>
<airframe_group image="HelicopterCoaxial" name="Coaxial Helicopter"> <airframe_group image="HelicopterCoaxial" name="Coaxial Helicopter">
<airframe id="15001" maintainer="Emmanuel Roussel" name="Esky (Big) Lama v4"> <airframe id="15001" maintainer="Emmanuel Roussel" name="Esky (Big) Lama v4">
<class>Copter</class>
<maintainer>Emmanuel Roussel</maintainer> <maintainer>Emmanuel Roussel</maintainer>
<type>Coaxial Helicopter</type> <type>Coaxial Helicopter</type>
<output name="MAIN1">Left swashplate servomotor, pitch axis</output> <output name="MAIN1">Left swashplate servomotor, pitch axis</output>
@ -13,77 +14,28 @@
<output name="MAIN4">Lower rotor (CW)</output> <output name="MAIN4">Lower rotor (CW)</output>
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="FlyingWing" name="Flying Wing"> <airframe_group image="AirframeUnknown" name="Dodecarotor cox">
<airframe id="3030" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="IO Camflyer"> <airframe id="24001" maintainer="William Peale &lt;develop707@gmail.com&gt;" name="Generic Dodecarotor cox geometry">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer> <class>Copter</class>
<type>Flying Wing</type> <maintainer>William Peale &lt;develop707@gmail.com&gt;</maintainer>
<url>https://pixhawk.org/platforms/planes/bormatec_camflyer_q</url> <type>Dodecarotor cox</type>
<output name="MAIN1">left aileron</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">right aileron</output> <output name="MAIN2">motor 2</output>
<output name="MAIN4">throttle</output> <output name="MAIN3">motor 3</output>
<output name="AUX1">feed-through of RC AUX1 channel</output> <output name="MAIN4">motor 4</output>
<output name="AUX2">feed-through of RC AUX2 channel</output> <output name="MAIN5">motor 5</output>
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="MAIN6">motor 6</output>
</airframe> <output name="AUX1">motor 7</output>
<airframe id="3031" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="Phantom FPV Flying Wing"> <output name="AUX2">motor 8</output>
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer> <output name="AUX3">motor 9</output>
<type>Flying Wing</type> <output name="AUX4">motor 10</output>
<url>https://pixhawk.org/platforms/planes/z-84_wing_wing</url> <output name="AUX5">motor 11</output>
<output name="MAIN1">left aileron</output> <output name="AUX6">motor 12</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3032" maintainer="Thomas Gubler &lt;thomas@px4.io&gt;, Julian Oes &lt;julian@px4.io&gt;" name="Skywalker X5 Flying Wing">
<maintainer>Thomas Gubler &lt;thomas@px4.io&gt;, Julian Oes &lt;julian@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/skywalker_x5</url>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3033" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Wing Wing (aka Z-84) Flying Wing">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/z-84_wing_wing</url>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3034" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="FX-79 Buffalo Flying Wing">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Flying Wing</type>
</airframe>
<airframe id="3035" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="Viper">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Flying Wing</type>
</airframe>
<airframe id="3036" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="Sparkle Tech Pigeon">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>http://www.sparkletech.hk/</url>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3100" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="TBS Caipirinha">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Flying Wing</type>
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="Helicopter" name="Helicopter"> <airframe_group image="Helicopter" name="Helicopter">
<airframe id="16001" maintainer="Bart Slinger &lt;bartslinger@gmail.com&gt;" name="Blade 130X"> <airframe id="16001" maintainer="Bart Slinger &lt;bartslinger@gmail.com&gt;" name="Blade 130X">
<class>Copter</class>
<maintainer>Bart Slinger &lt;bartslinger@gmail.com&gt;</maintainer> <maintainer>Bart Slinger &lt;bartslinger@gmail.com&gt;</maintainer>
<type>Helicopter</type> <type>Helicopter</type>
<output name="MAIN1">main motor</output> <output name="MAIN1">main motor</output>
@ -94,8 +46,9 @@
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="HexaRotorPlus" name="Hexarotor +"> <airframe_group image="HexaRotorPlus" name="Hexarotor +">
<airframe id="7001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Hexarotor + geometry"> <airframe id="7001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Hexarotor + geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Hexarotor +</type> <type>Hexarotor +</type>
<output name="MAIN1">motor1</output> <output name="MAIN1">motor1</output>
<output name="MAIN2">motor2</output> <output name="MAIN2">motor2</output>
@ -110,6 +63,7 @@
</airframe_group> </airframe_group>
<airframe_group image="Y6B" name="Hexarotor Coaxial"> <airframe_group image="Y6B" name="Hexarotor Coaxial">
<airframe id="11001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Hexa coaxial geometry"> <airframe id="11001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Hexa coaxial geometry">
<class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Hexarotor Coaxial</type> <type>Hexarotor Coaxial</type>
<output angle="60" direction="CW" name="MAIN1">front right top, CW</output> <output angle="60" direction="CW" name="MAIN1">front right top, CW</output>
@ -124,8 +78,9 @@
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="HexaRotorX" name="Hexarotor x"> <airframe_group image="HexaRotorX" name="Hexarotor x">
<airframe id="6001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Hexarotor x geometry"> <airframe id="6001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Hexarotor x geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Hexarotor x</type> <type>Hexarotor x</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output> <output name="MAIN2">motor 2</output>
@ -140,6 +95,7 @@
</airframe_group> </airframe_group>
<airframe_group image="OctoRotorXCoaxial" name="Octo Coax Wide"> <airframe_group image="OctoRotorXCoaxial" name="Octo Coax Wide">
<airframe id="12002" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Steadidrone MAVRIK"> <airframe id="12002" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Steadidrone MAVRIK">
<class>Copter</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer> <maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Octo Coax Wide</type> <type>Octo Coax Wide</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
@ -153,8 +109,9 @@
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="OctoRotorPlus" name="Octorotor +"> <airframe_group image="OctoRotorPlus" name="Octorotor +">
<airframe id="9001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Octocopter + geometry"> <airframe id="9001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Octocopter + geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Octorotor +</type> <type>Octorotor +</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output> <output name="MAIN2">motor 2</output>
@ -171,6 +128,7 @@
</airframe_group> </airframe_group>
<airframe_group image="OctoRotorXCoaxial" name="Octorotor Coaxial"> <airframe_group image="OctoRotorXCoaxial" name="Octorotor Coaxial">
<airframe id="12001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic 10&quot; Octo coaxial geometry"> <airframe id="12001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic 10&quot; Octo coaxial geometry">
<class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Octorotor Coaxial</type> <type>Octorotor Coaxial</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
@ -184,8 +142,9 @@
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="OctoRotorX" name="Octorotor x"> <airframe_group image="OctoRotorX" name="Octorotor x">
<airframe id="8001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Octocopter X geometry"> <airframe id="8001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Octocopter X geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Octorotor x</type> <type>Octorotor x</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output> <output name="MAIN2">motor 2</output>
@ -200,26 +159,10 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="PlaneATail" name="Plane A-Tail">
<airframe id="2106" maintainer="Andreas Antener &lt;andreas@uaventure.com&gt;" name="Applied Aeronautics Albatross">
<maintainer>Andreas Antener &lt;andreas@uaventure.com&gt;</maintainer>
<type>Plane A-Tail</type>
<output name="MAIN1">aileron right</output>
<output name="MAIN2">aileron left</output>
<output name="MAIN3">v-tail right</output>
<output name="MAIN4">v-tail left</output>
<output name="MAIN5">throttle</output>
<output name="MAIN6">wheel</output>
<output name="MAIN7">flaps right</output>
<output name="MAIN8">flaps left</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
</airframe_group>
<airframe_group image="QuadRotorPlus" name="Quadrotor +"> <airframe_group image="QuadRotorPlus" name="Quadrotor +">
<airframe id="5001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic 10&quot; Quad + geometry"> <airframe id="5001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic 10&quot; Quad + geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor +</type> <type>Quadrotor +</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output> <output name="MAIN2">motor 2</output>
@ -234,8 +177,9 @@
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="QuadRotorWide" name="Quadrotor Wide"> <airframe_group image="QuadRotorWide" name="Quadrotor Wide">
<airframe id="10015" maintainer="Anton Babushkin &lt;anton@px4.io&gt;, Simon Wilks &lt;simon@px4.io&gt;" name="Team Blacksheep Discovery"> <airframe id="10015" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Team Blacksheep Discovery">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;, Simon Wilks &lt;simon@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor Wide</type> <type>Quadrotor Wide</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output> <output name="MAIN2">motor 2</output>
@ -248,8 +192,9 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="AUX4">feed-through of RC FLAPS channel</output> <output name="AUX4">feed-through of RC FLAPS channel</output>
</airframe> </airframe>
<airframe id="10016" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="3DR Iris Quadrotor"> <airframe id="10016" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="3DR Iris Quadrotor">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor Wide</type> <type>Quadrotor Wide</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output> <output name="MAIN2">motor 2</output>
@ -260,8 +205,9 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="AUX4">feed-through of RC FLAPS channel</output> <output name="AUX4">feed-through of RC FLAPS channel</output>
</airframe> </airframe>
<airframe id="10017" maintainer="Thomas Gubler &lt;thomas@px4.io&gt;" name="Steadidrone QU4D"> <airframe id="10017" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Steadidrone QU4D">
<maintainer>Thomas Gubler &lt;thomas@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor Wide</type> <type>Quadrotor Wide</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output> <output name="MAIN2">motor 2</output>
@ -274,8 +220,9 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="AUX4">feed-through of RC FLAPS channel</output> <output name="AUX4">feed-through of RC FLAPS channel</output>
</airframe> </airframe>
<airframe id="10018" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="Team Blacksheep Discovery Endurance"> <airframe id="10018" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Team Blacksheep Discovery Endurance">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Quadrotor Wide</type> <type>Quadrotor Wide</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output> <output name="MAIN2">motor 2</output>
@ -290,8 +237,9 @@
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="AirframeUnknown" name="Quadrotor asymmetric"> <airframe_group image="AirframeUnknown" name="Quadrotor asymmetric">
<airframe id="4051" maintainer="Mark Whitehorn &lt;kd0aij@gmail.com&gt;" name="Spedix S250AQ"> <airframe id="4051" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Spedix S250AQ">
<maintainer>Mark Whitehorn &lt;kd0aij@gmail.com&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor asymmetric</type> <type>Quadrotor asymmetric</type>
<output name="MAIN1">motor1 (front right: CCW)</output> <output name="MAIN1">motor1 (front right: CCW)</output>
<output name="MAIN2">motor2 (back left: CCW)</output> <output name="MAIN2">motor2 (back left: CCW)</output>
@ -303,14 +251,17 @@
</airframe_group> </airframe_group>
<airframe_group image="QuadRotorX" name="Quadrotor x"> <airframe_group image="QuadRotorX" name="Quadrotor x">
<airframe id="10020" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="3DR DIY Quad"> <airframe id="10020" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="3DR DIY Quad">
<class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="10021" maintainer="Leon Mueller &lt;thedevleon&gt;" name="H4 680mm with Z1 Tiny2 Gimbal"> <airframe id="10021" maintainer="Leon Mueller &lt;thedevleon&gt;" name="H4 680mm with Z1 Tiny2 Gimbal">
<class>Copter</class>
<maintainer>Leon Mueller &lt;thedevleon&gt;</maintainer> <maintainer>Leon Mueller &lt;thedevleon&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Quadrotor X config"> <airframe id="4001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Quadrotor X config">
<class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
@ -325,6 +276,7 @@
<output name="AUX4">feed-through of RC FLAPS channel</output> <output name="AUX4">feed-through of RC FLAPS channel</output>
</airframe> </airframe>
<airframe id="4002" maintainer="Leon Mueller &lt;thedevleon&gt;" name="Generic Quadrotor X config with mount (e.g. gimbal)"> <airframe id="4002" maintainer="Leon Mueller &lt;thedevleon&gt;" name="Generic Quadrotor X config with mount (e.g. gimbal)">
<class>Copter</class>
<maintainer>Leon Mueller &lt;thedevleon&gt;</maintainer> <maintainer>Leon Mueller &lt;thedevleon&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
@ -339,64 +291,183 @@
<output name="AUX4">Mount retract</output> <output name="AUX4">Mount retract</output>
</airframe> </airframe>
<airframe id="4003" maintainer="James Goppert &lt;james.goppert@gmail.com&gt;" name="Lumenier QAV-R (raceblade) 5&quot; arms"> <airframe id="4003" maintainer="James Goppert &lt;james.goppert@gmail.com&gt;" name="Lumenier QAV-R (raceblade) 5&quot; arms">
<class>Copter</class>
<maintainer>James Goppert &lt;james.goppert@gmail.com&gt;</maintainer> <maintainer>James Goppert &lt;james.goppert@gmail.com&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4009" maintainer="Mark Whitehorn &lt;kd0aij@gmail.com&gt;" name="Lumenier QAV250"> <airframe id="4009" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Lumenier QAV250">
<maintainer>Mark Whitehorn &lt;kd0aij@gmail.com&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4010" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="DJI Flame Wheel F330"> <airframe id="4010" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="DJI Flame Wheel F330">
<class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4011" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="DJI Flame Wheel F450"> <airframe id="4011" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="DJI Flame Wheel F450">
<class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4012" maintainer="Pavel Kirienko &lt;pavel@px4.io&gt;" name="F450-sized quadrotor with CAN"> <airframe id="4012" maintainer="Pavel Kirienko &lt;pavel.kirienko@gmail.com&gt;" name="F450-sized quadrotor with CAN">
<maintainer>Pavel Kirienko &lt;pavel@px4.io&gt;</maintainer> <class>Copter</class>
<maintainer>Pavel Kirienko &lt;pavel.kirienko@gmail.com&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4040" maintainer="Blankered" name="Reaper 500 Quad"> <airframe id="4040" maintainer="Blankered" name="Reaper 500 Quad">
<class>Copter</class>
<maintainer>Blankered</maintainer> <maintainer>Blankered</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4050" maintainer="Mark Whitehorn &lt;kd0aij@gmail.com&gt;" name="Generic 250 Racer"> <airframe id="4050" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic 250 Racer">
<maintainer>Mark Whitehorn &lt;kd0aij@gmail.com&gt;</maintainer> <class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4060" maintainer="James Goppert &lt;james.goppert@gmail.com&gt;" name="DJI Matrice 100"> <airframe id="4060" maintainer="James Goppert &lt;james.goppert@gmail.com&gt;" name="DJI Matrice 100">
<class>Copter</class>
<maintainer>James Goppert &lt;james.goppert@gmail.com&gt;</maintainer> <maintainer>James Goppert &lt;james.goppert@gmail.com&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
<airframe id="4080" maintainer="Anton Matosov &lt;anton.matosov@gmail.com&gt;" name="ZMR250 Racer"> <airframe id="4080" maintainer="Anton Matosov &lt;anton.matosov@gmail.com&gt;" name="ZMR250 Racer">
<class>Copter</class>
<maintainer>Anton Matosov &lt;anton.matosov@gmail.com&gt;</maintainer> <maintainer>Anton Matosov &lt;anton.matosov@gmail.com&gt;</maintainer>
<type>Quadrotor x</type> <type>Quadrotor x</type>
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="Rover" name="Rover"> <airframe_group image="AirframeUnknown" name="Simulation (Copter)">
<airframe id="50001" maintainer="John Doe &lt;john@example.com&gt;" name="Axial Racing AX10"> <airframe id="1001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="HIL Quadcopter X">
<type>Rover</type> <class>Copter</class>
<output name="MAIN1">pass-through of control group 0, channel 0</output> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<output name="MAIN2">pass-through of control group 0, channel 1</output> <type>Simulation</type>
<output name="MAIN3">pass-through of control group 0, channel 2</output>
<output name="MAIN4">pass-through of control group 0, channel 3</output>
<output name="MAIN5">pass-through of control group 0, channel 4</output>
<output name="MAIN6">pass-through of control group 0, channel 5</output>
<output name="MAIN7">pass-through of control group 0, channel 6</output>
<output name="MAIN8">pass-through of control group 0, channel 7</output>
</airframe> </airframe>
<airframe id="50002" maintainer="Marco Zorzi" name="Traxxas stampede vxl 2wd"> <airframe id="1003" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="HIL Quadcopter +">
<maintainer>Marco Zorzi</maintainer> <class>Copter</class>
<type>Rover</type> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<url>https://traxxas.com/products/models/electric/stampede-vxl-tsm</url> <type>Simulation</type>
<output name="MAIN2">steering</output> </airframe>
</airframe_group>
<airframe_group image="YPlus" name="Tricopter Y+">
<airframe id="14001" maintainer="Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;" name="Generic Tricopter Y+ Geometry">
<class>Copter</class>
<maintainer>Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;</maintainer>
<type>Tricopter Y+</type>
<output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output>
<output name="MAIN3">motor 3</output>
<output name="MAIN4">yaw servo</output>
</airframe>
</airframe_group>
<airframe_group image="YMinus" name="Tricopter Y-">
<airframe id="14002" maintainer="Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;" name="Generic Tricopter Y- Geometry">
<class>Copter</class>
<maintainer>Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;</maintainer>
<type>Tricopter Y-</type>
<output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output>
<output name="MAIN3">motor 3</output>
<output name="MAIN4">yaw servo</output>
</airframe>
</airframe_group>
<airframe_group image="FlyingWing" name="Flying Wing">
<airframe id="3030" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="IO Camflyer">
<class>Plane</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/bormatec_camflyer_q</url>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3031" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Phantom FPV Flying Wing">
<class>Plane</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/z-84_wing_wing</url>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3032" maintainer="Julian Oes &lt;julian@px4.io&gt;" name="Skywalker X5 Flying Wing">
<class>Plane</class>
<maintainer>Julian Oes &lt;julian@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/skywalker_x5</url>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3033" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Wing Wing (aka Z-84) Flying Wing">
<class>Plane</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/z-84_wing_wing</url>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output> <output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3034" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="FX-79 Buffalo Flying Wing">
<class>Plane</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Flying Wing</type>
</airframe>
<airframe id="3035" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Viper">
<class>Plane</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Flying Wing</type>
</airframe>
<airframe id="3036" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Sparkle Tech Pigeon">
<class>Plane</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Flying Wing</type>
<url>http://www.sparkletech.hk/</url>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="3100" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="TBS Caipirinha">
<class>Plane</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Flying Wing</type>
</airframe>
</airframe_group>
<airframe_group image="PlaneATail" name="Plane A-Tail">
<airframe id="2106" maintainer="Andreas Antener &lt;andreas@uaventure.com&gt;" name="Applied Aeronautics Albatross">
<class>Plane</class>
<maintainer>Andreas Antener &lt;andreas@uaventure.com&gt;</maintainer>
<type>Plane A-Tail</type>
<output name="MAIN1">aileron right</output>
<output name="MAIN2">aileron left</output>
<output name="MAIN3">v-tail right</output>
<output name="MAIN4">v-tail left</output>
<output name="MAIN5">throttle</output>
<output name="MAIN6">wheel</output>
<output name="MAIN7">flaps right</output>
<output name="MAIN8">flaps left</output>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="AirframeSimulation" name="Simulation"> <airframe_group image="AirframeUnknown" name="Simulation (Plane)">
<airframe id="1000" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="HILStar (XPlane)"> <airframe id="1000" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="HILStar (XPlane)">
<class>Plane</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Simulation</type> <type>Simulation</type>
<output name="MAIN1">aileron</output> <output name="MAIN1">aileron</output>
@ -404,17 +475,10 @@
<output name="MAIN3">rudder</output> <output name="MAIN3">rudder</output>
<output name="MAIN4">throttle</output> <output name="MAIN4">throttle</output>
</airframe> </airframe>
<airframe id="1001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="HIL Quadcopter X">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Simulation</type>
</airframe>
<airframe id="1003" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="HIL Quadcopter +">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Simulation</type>
</airframe>
</airframe_group> </airframe_group>
<airframe_group image="Plane" name="Standard Plane"> <airframe_group image="Plane" name="Standard Plane">
<airframe id="2100" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Multiplex Easystar"> <airframe id="2100" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Multiplex Easystar">
<class>Plane</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type> <type>Standard Plane</type>
<output name="MAIN1">aileron</output> <output name="MAIN1">aileron</output>
@ -423,6 +487,7 @@
<output name="MAIN4">throttle</output> <output name="MAIN4">throttle</output>
</airframe> </airframe>
<airframe id="2101" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Standard AERT Plane"> <airframe id="2101" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Standard AERT Plane">
<class>Plane</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type> <type>Standard Plane</type>
<output name="MAIN1">aileron</output> <output name="MAIN1">aileron</output>
@ -435,6 +500,7 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe> </airframe>
<airframe id="2102" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Skywalker (3DR Aero)"> <airframe id="2102" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Skywalker (3DR Aero)">
<class>Plane</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type> <type>Standard Plane</type>
<output name="MAIN1">aileron</output> <output name="MAIN1">aileron</output>
@ -447,6 +513,7 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe> </airframe>
<airframe id="2103" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Skyhunter 1800"> <airframe id="2103" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Skyhunter 1800">
<class>Plane</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type> <type>Standard Plane</type>
<output name="MAIN1">aileron</output> <output name="MAIN1">aileron</output>
@ -457,6 +524,7 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe> </airframe>
<airframe id="2104" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Standard AETR Plane"> <airframe id="2104" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Standard AETR Plane">
<class>Plane</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer> <maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type> <type>Standard Plane</type>
<output name="MAIN1">aileron</output> <output name="MAIN1">aileron</output>
@ -469,6 +537,7 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe> </airframe>
<airframe id="2105" maintainer="Andreas Antener &lt;andreas@uaventure.com&gt;" name="Bormatec Maja"> <airframe id="2105" maintainer="Andreas Antener &lt;andreas@uaventure.com&gt;" name="Bormatec Maja">
<class>Plane</class>
<maintainer>Andreas Antener &lt;andreas@uaventure.com&gt;</maintainer> <maintainer>Andreas Antener &lt;andreas@uaventure.com&gt;</maintainer>
<type>Standard Plane</type> <type>Standard Plane</type>
<output name="MAIN1">aileron</output> <output name="MAIN1">aileron</output>
@ -483,8 +552,40 @@
<output name="AUX3">feed-through of RC AUX3 channel</output> <output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="Rover" name="Rover">
<airframe id="50001" maintainer="John Doe &lt;john@example.com&gt;" name="Axial Racing AX10">
<class>Rover</class>
<type>Rover</type>
<output name="MAIN1">pass-through of control group 0, channel 0</output>
<output name="MAIN2">pass-through of control group 0, channel 1</output>
<output name="MAIN3">pass-through of control group 0, channel 2</output>
<output name="MAIN4">pass-through of control group 0, channel 3</output>
<output name="MAIN5">pass-through of control group 0, channel 4</output>
<output name="MAIN6">pass-through of control group 0, channel 5</output>
<output name="MAIN7">pass-through of control group 0, channel 6</output>
<output name="MAIN8">pass-through of control group 0, channel 7</output>
</airframe>
<airframe id="50002" maintainer="Marco Zorzi" name="Traxxas stampede vxl 2wd">
<class>Rover</class>
<maintainer>Marco Zorzi</maintainer>
<type>Rover</type>
<url>https://traxxas.com/products/models/electric/stampede-vxl-tsm</url>
<output name="MAIN2">steering</output>
<output name="MAIN4">throttle</output>
</airframe>
</airframe_group>
<airframe_group image="AirframeUnknown" name="custom">
<airframe id="20000" maintainer="Julian Oes &lt;julian@oes.ch&gt;&#10;This startup can be used on Pixhawk/Pixfalcon/Pixracer for the&#10;passthrough of RC input and PWM output." name="Passthrough mode for Snapdragon">
<class>Tool</class>
<maintainer>Julian Oes &lt;julian@oes.ch&gt;
This startup can be used on Pixhawk/Pixfalcon/Pixracer for the
passthrough of RC input and PWM output.</maintainer>
<type>custom</type>
</airframe>
</airframe_group>
<airframe_group image="VTOLPlane" name="Standard VTOL"> <airframe_group image="VTOLPlane" name="Standard VTOL">
<airframe id="13005" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Fun Cub Quad VTOL"> <airframe id="13005" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Fun Cub Quad VTOL">
<class>VTOL</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer> <maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Standard VTOL</type> <type>Standard VTOL</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
@ -498,6 +599,7 @@
<output name="AUX5">Throttle</output> <output name="AUX5">Throttle</output>
</airframe> </airframe>
<airframe id="13006" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Generic quad delta VTOL"> <airframe id="13006" maintainer="Simon Wilks &lt;simon@uaventure.com&gt;" name="Generic quad delta VTOL">
<class>VTOL</class>
<maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer> <maintainer>Simon Wilks &lt;simon@uaventure.com&gt;</maintainer>
<type>Standard VTOL</type> <type>Standard VTOL</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
@ -509,18 +611,22 @@
<output name="AUX3">Motor</output> <output name="AUX3">Motor</output>
</airframe> </airframe>
<airframe id="13007" maintainer="Sander Smeets &lt;sander@droneslab.com&gt;" name="Generic AAVVT v-tail plane airframe with Quad VTOL."> <airframe id="13007" maintainer="Sander Smeets &lt;sander@droneslab.com&gt;" name="Generic AAVVT v-tail plane airframe with Quad VTOL.">
<class>VTOL</class>
<maintainer>Sander Smeets &lt;sander@droneslab.com&gt;</maintainer> <maintainer>Sander Smeets &lt;sander@droneslab.com&gt;</maintainer>
<type>Standard VTOL</type> <type>Standard VTOL</type>
</airframe> </airframe>
<airframe id="13008" maintainer="Sander Smeets &lt;sander@droneslab.com&gt;" name="QuadRanger"> <airframe id="13008" maintainer="Sander Smeets &lt;sander@droneslab.com&gt;" name="QuadRanger">
<class>VTOL</class>
<maintainer>Sander Smeets &lt;sander@droneslab.com&gt;</maintainer> <maintainer>Sander Smeets &lt;sander@droneslab.com&gt;</maintainer>
<type>Standard VTOL</type> <type>Standard VTOL</type>
</airframe> </airframe>
<airframe id="13009" maintainer="Andreas Antener &lt;andreas@uaventure.com&gt;" name="Sparkle Tech Ranger VTOL"> <airframe id="13009" maintainer="Andreas Antener &lt;andreas@uaventure.com&gt;" name="Sparkle Tech Ranger VTOL">
<class>VTOL</class>
<maintainer>Andreas Antener &lt;andreas@uaventure.com&gt;</maintainer> <maintainer>Andreas Antener &lt;andreas@uaventure.com&gt;</maintainer>
<type>Standard VTOL</type> <type>Standard VTOL</type>
</airframe> </airframe>
<airframe id="13013" maintainer="Sander Smeets &lt;sander@droneslab.com&gt;" name="DeltaQuad"> <airframe id="13013" maintainer="Sander Smeets &lt;sander@droneslab.com&gt;" name="DeltaQuad">
<class>VTOL</class>
<maintainer>Sander Smeets &lt;sander@droneslab.com&gt;</maintainer> <maintainer>Sander Smeets &lt;sander@droneslab.com&gt;</maintainer>
<type>Standard VTOL</type> <type>Standard VTOL</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
@ -532,28 +638,9 @@
<output name="AUX3">Motor</output> <output name="AUX3">Motor</output>
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="YPlus" name="Tricopter Y+">
<airframe id="14001" maintainer="Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;" name="Generic Tricopter Y+ Geometry">
<maintainer>Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;</maintainer>
<type>Tricopter Y+</type>
<output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output>
<output name="MAIN3">motor 3</output>
<output name="MAIN4">yaw servo</output>
</airframe>
</airframe_group>
<airframe_group image="YMinus" name="Tricopter Y-">
<airframe id="14002" maintainer="Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;" name="Generic Tricopter Y- Geometry">
<maintainer>Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;</maintainer>
<type>Tricopter Y-</type>
<output name="MAIN1">motor 1</output>
<output name="MAIN2">motor 2</output>
<output name="MAIN3">motor 3</output>
<output name="MAIN4">yaw servo</output>
</airframe>
</airframe_group>
<airframe_group image="VTOLDuoRotorTailSitter" name="VTOL Duo Tailsitter"> <airframe_group image="VTOLDuoRotorTailSitter" name="VTOL Duo Tailsitter">
<airframe id="13001" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Caipiroshka Duo Tailsitter"> <airframe id="13001" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Caipiroshka Duo Tailsitter">
<class>VTOL</class>
<maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer> <maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer>
<type>VTOL Duo Tailsitter</type> <type>VTOL Duo Tailsitter</type>
<output name="MAIN1">motor right</output> <output name="MAIN1">motor right</output>
@ -564,10 +651,12 @@
</airframe_group> </airframe_group>
<airframe_group image="VTOLQuadRotorTailSitter" name="VTOL Quad Tailsitter"> <airframe_group image="VTOLQuadRotorTailSitter" name="VTOL Quad Tailsitter">
<airframe id="13003" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Quadrotor X Tailsitter"> <airframe id="13003" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Quadrotor X Tailsitter">
<class>VTOL</class>
<maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer> <maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer>
<type>VTOL Quad Tailsitter</type> <type>VTOL Quad Tailsitter</type>
</airframe> </airframe>
<airframe id="13004" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Quadrotor + Tailsitter"> <airframe id="13004" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Quadrotor + Tailsitter">
<class>VTOL</class>
<maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer> <maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer>
<type>VTOL Quad Tailsitter</type> <type>VTOL Quad Tailsitter</type>
<output name="MAIN1">motor 1</output> <output name="MAIN1">motor 1</output>
@ -582,6 +671,7 @@
</airframe_group> </airframe_group>
<airframe_group image="VTOLTiltRotor" name="VTOL Tiltrotor"> <airframe_group image="VTOLTiltRotor" name="VTOL Tiltrotor">
<airframe id="13002" maintainer="Roman Bapst &lt;roman@uaventure.com&gt;" name="BirdsEyeView Aerobotics FireFly6"> <airframe id="13002" maintainer="Roman Bapst &lt;roman@uaventure.com&gt;" name="BirdsEyeView Aerobotics FireFly6">
<class>VTOL</class>
<maintainer>Roman Bapst &lt;roman@uaventure.com&gt;</maintainer> <maintainer>Roman Bapst &lt;roman@uaventure.com&gt;</maintainer>
<type>VTOL Tiltrotor</type> <type>VTOL Tiltrotor</type>
<output name="MAIN1">Front right motor bottom</output> <output name="MAIN1">Front right motor bottom</output>
@ -596,10 +686,12 @@
<output name="AUX4">Gear</output> <output name="AUX4">Gear</output>
</airframe> </airframe>
<airframe id="13010" maintainer="Samay Siga &lt;samay_s@icloud.com&gt;" name="CruiseAder Claire"> <airframe id="13010" maintainer="Samay Siga &lt;samay_s@icloud.com&gt;" name="CruiseAder Claire">
<class>VTOL</class>
<maintainer>Samay Siga &lt;samay_s@icloud.com&gt;</maintainer> <maintainer>Samay Siga &lt;samay_s@icloud.com&gt;</maintainer>
<type>VTOL Tiltrotor</type> <type>VTOL Tiltrotor</type>
</airframe> </airframe>
<airframe id="13012" maintainer="Andreas Antener &lt;andreas@uaventure.com&gt;" name="E-flite Convergence"> <airframe id="13012" maintainer="Andreas Antener &lt;andreas@uaventure.com&gt;" name="E-flite Convergence">
<class>VTOL</class>
<maintainer>Andreas Antener &lt;andreas@uaventure.com&gt;</maintainer> <maintainer>Andreas Antener &lt;andreas@uaventure.com&gt;</maintainer>
<type>VTOL Tiltrotor</type> <type>VTOL Tiltrotor</type>
<output name="MAIN1">Motor right</output> <output name="MAIN1">Motor right</output>
@ -612,12 +704,4 @@
<output name="MAIN8">Elevon left</output> <output name="MAIN8">Elevon left</output>
</airframe> </airframe>
</airframe_group> </airframe_group>
<airframe_group image="AirframeUnknown" name="custom">
<airframe id="20000" maintainer="Julian Oes &lt;julian@oes.ch&gt;&#10;This startup can be used on Pixhawk/Pixfalcon/Pixracer for the&#10;passthrough of RC input and PWM output." name="Passthrough mode for Snapdragon">
<maintainer>Julian Oes &lt;julian@oes.ch&gt;
This startup can be used on Pixhawk/Pixfalcon/Pixracer for the
passthrough of RC input and PWM output.</maintainer>
<type>custom</type>
</airframe>
</airframe_group>
</airframes> </airframes>

18
src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml

@ -60,24 +60,6 @@ SetupPage {
max: 0.25 max: 0.25
step: 0.01 step: 0.01
} }
ListElement {
title: qsTr("Altitude control sensitivity")
description: qsTr("Slide to the left to make altitude control smoother and less twitchy. Slide to the right to make altitude control more accurate and more aggressive.")
param: "MPC_Z_FF"
min: 0
max: 1.0
step: 0.1
}
ListElement {
title: qsTr("Position control sensitivity")
description: qsTr("Slide to the left to make flight in position control mode smoother and less twitchy. Slide to the right to make position control more accurate and more aggressive.")
param: "MPC_XY_FF"
min: 0
max: 1.0
step: 0.1
}
} }
} }
} // Component } // Component

17
src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml

@ -45,23 +45,6 @@ SetupPage {
} }
ListElement { ListElement {
title: qsTr("Hover Altitude control sensitivity")
description: qsTr("Slide to the left to make altitude control during hover smoother and less twitchy. Slide to the right to make altitude control more accurate and more aggressive.")
param: "MPC_Z_FF"
min: 0
max: 1.0
step: 0.1
}
ListElement {
title: qsTr("Hover Position control sensitivity")
description: qsTr("Slide to the left to make flight during hover in position control mode smoother and less twitchy. Slide to the right to make position control more accurate and more aggressive.")
param: "MPC_XY_FF"
min: 0
max: 1.0
step: 0.1
}
ListElement {
title: qsTr("Plane Roll sensitivity") title: qsTr("Plane Roll sensitivity")
description: qsTr("Slide to the left to make roll control faster and more accurate. Slide to the right if roll oscillates or is too twitchy.") description: qsTr("Slide to the left to make roll control faster and more accurate. Slide to the right if roll oscillates or is too twitchy.")
param: "FW_R_TC" param: "FW_R_TC"

20
src/FirmwarePlugin/CameraMetaData.cc

@ -17,16 +17,18 @@ CameraMetaData::CameraMetaData(const QString& name,
double focalLength, double focalLength,
bool landscape, bool landscape,
bool fixedOrientation, bool fixedOrientation,
double minTriggerInterval,
QObject* parent) QObject* parent)
: QObject(parent) : QObject (parent)
, _name(name) , _name (name)
, _sensorWidth(sensorWidth) , _sensorWidth (sensorWidth)
, _sensorHeight(sensorHeight) , _sensorHeight (sensorHeight)
, _imageWidth(imageWidth) , _imageWidth (imageWidth)
, _imageHeight(imageHeight) , _imageHeight (imageHeight)
, _focalLength(focalLength) , _focalLength (focalLength)
, _landscape(landscape) , _landscape (landscape)
, _fixedOrientation(fixedOrientation) , _fixedOrientation (fixedOrientation)
, _minTriggerInterval (minTriggerInterval)
{ {
} }

3
src/FirmwarePlugin/CameraMetaData.h

@ -26,6 +26,7 @@ public:
double focalLength, double focalLength,
bool landscape, bool landscape,
bool fixedOrientation, bool fixedOrientation,
double minTriggerInterval,
QObject* parent = NULL); QObject* parent = NULL);
Q_PROPERTY(QString name MEMBER _name CONSTANT) ///< Camera name Q_PROPERTY(QString name MEMBER _name CONSTANT) ///< Camera name
@ -36,6 +37,7 @@ public:
Q_PROPERTY(double focalLength MEMBER _focalLength CONSTANT) ///< Focal length in millimeters Q_PROPERTY(double focalLength MEMBER _focalLength CONSTANT) ///< Focal length in millimeters
Q_PROPERTY(bool landscape MEMBER _landscape CONSTANT) ///< true: camera is in landscape orientation Q_PROPERTY(bool landscape MEMBER _landscape CONSTANT) ///< true: camera is in landscape orientation
Q_PROPERTY(bool fixedOrientation MEMBER _fixedOrientation CONSTANT) ///< true: camera is in fixed orientation Q_PROPERTY(bool fixedOrientation MEMBER _fixedOrientation CONSTANT) ///< true: camera is in fixed orientation
Q_PROPERTY(double minTriggerInterval MEMBER _minTriggerInterval CONSTANT) ///< Minimum time in seconds between each photo taken, 0 for not specified
private: private:
QString _name; QString _name;
@ -46,6 +48,7 @@ private:
double _focalLength; double _focalLength;
bool _landscape; bool _landscape;
bool _fixedOrientation; bool _fixedOrientation;
double _minTriggerInterval;
}; };
#endif #endif

9
src/FirmwarePlugin/FirmwarePlugin.cc

@ -354,6 +354,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
16, 16,
true, true,
false, false,
0,
this); this);
_cameraList.append(QVariant::fromValue(metaData)); _cameraList.append(QVariant::fromValue(metaData));
@ -365,6 +366,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
5.2, 5.2,
true, true,
false, false,
0,
this); this);
_cameraList.append(QVariant::fromValue(metaData)); _cameraList.append(QVariant::fromValue(metaData));
@ -376,6 +378,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
10.2, 10.2,
true, true,
false, false,
0,
this); this);
_cameraList.append(QVariant::fromValue(metaData)); _cameraList.append(QVariant::fromValue(metaData));
@ -387,6 +390,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
4.5, 4.5,
true, true,
false, false,
0,
this); this);
metaData = new CameraMetaData(tr("Canon EOS-M 22mm"), metaData = new CameraMetaData(tr("Canon EOS-M 22mm"),
@ -397,6 +401,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
22, 22,
true, true,
false, false,
0,
this); this);
_cameraList.append(QVariant::fromValue(metaData)); _cameraList.append(QVariant::fromValue(metaData));
@ -408,6 +413,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
16, 16,
true, true,
false, false,
0,
this); this);
_cameraList.append(QVariant::fromValue(metaData)); _cameraList.append(QVariant::fromValue(metaData));
@ -419,6 +425,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
10.4, 10.4,
true, true,
false, false,
0,
this); this);
_cameraList.append(QVariant::fromValue(metaData)); _cameraList.append(QVariant::fromValue(metaData));
} }
@ -478,7 +485,7 @@ bool FirmwarePlugin::_setFlightModeAndValidate(Vehicle* vehicle, const QString&
vehicle->setFlightMode(flightMode); vehicle->setFlightMode(flightMode);
// Wait for vehicle to return flight mode // Wait for vehicle to return flight mode
for (int i=0; i<30; i++) { for (int i=0; i<13; i++) {
if (vehicle->flightMode() == flightMode) { if (vehicle->flightMode() == flightMode) {
flightModeChanged = true; flightModeChanged = true;
break; break;

16
src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc

@ -76,7 +76,8 @@ PX4FirmwarePlugin::PX4FirmwarePlugin(void)
{ PX4_CUSTOM_MAIN_MODE_RATTITUDE, 0, true, true, true }, { PX4_CUSTOM_MAIN_MODE_RATTITUDE, 0, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_ALTCTL, 0, true, true, true }, { PX4_CUSTOM_MAIN_MODE_ALTCTL, 0, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_POSCTL, 0, true, true, true }, { PX4_CUSTOM_MAIN_MODE_POSCTL, 0, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_SIMPLE, 0, true, false, true }, // simple can't be set by the user right now
{ PX4_CUSTOM_MAIN_MODE_SIMPLE, 0, false, false, true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LOITER, true, true, true }, { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LOITER, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_MISSION, true, true, true }, { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_MISSION, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTL, true, true, true }, { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTL, true, true, true },
@ -460,12 +461,15 @@ void PX4FirmwarePlugin::guidedModeChangeAltitude(Vehicle* vehicle, double altitu
void PX4FirmwarePlugin::startMission(Vehicle* vehicle) void PX4FirmwarePlugin::startMission(Vehicle* vehicle)
{ {
if (!_armVehicleAndValidate(vehicle)) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle failed to arm."));
return;
}
_setFlightModeAndValidate(vehicle, missionFlightMode()); if (_setFlightModeAndValidate(vehicle, missionFlightMode())) {
if (!_armVehicleAndValidate(vehicle)) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle rejected arming."));
return;
}
} else {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle not ready."));
}
} }
void PX4FirmwarePlugin::setGuidedMode(Vehicle* vehicle, bool guidedMode) void PX4FirmwarePlugin::setGuidedMode(Vehicle* vehicle, bool guidedMode)

65
src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml

@ -1234,6 +1234,14 @@ This parameter is used when the magnetometer fusion method is set automatically
<decimal>2</decimal> <decimal>2</decimal>
<scope>modules/ekf2</scope> <scope>modules/ekf2</scope>
</parameter> </parameter>
<parameter default="0.05" name="EKF2_RNG_SFE" type="FLOAT">
<short_desc>Range finder range dependant noise scaler</short_desc>
<long_desc>Specifies the increase in range finder noise with range.</long_desc>
<min>0.0</min>
<max>0.2</max>
<unit>m/m</unit>
<scope>modules/ekf2</scope>
</parameter>
<parameter default="5.0" name="EKF2_RNG_GATE" type="FLOAT"> <parameter default="5.0" name="EKF2_RNG_GATE" type="FLOAT">
<short_desc>Gate size for range finder fusion</short_desc> <short_desc>Gate size for range finder fusion</short_desc>
<min>1.0</min> <min>1.0</min>
@ -1522,6 +1530,29 @@ Smaller values make the saved mag bias learn slower from flight to flight. Large
<decimal>2</decimal> <decimal>2</decimal>
<scope>modules/ekf2</scope> <scope>modules/ekf2</scope>
</parameter> </parameter>
<parameter default="0" name="EKF2_RNG_AID" type="INT32">
<short_desc>Range sensor aid</short_desc>
<long_desc>If this parameter is enabled then the estimator will make use of the range finder measurements to estimate it's height even if range sensor is not the primary height source. It will only do so if conditions for range measurement fusion are met.</long_desc>
<scope>modules/ekf2</scope>
<values>
<value code="1">Range aid enabled</value>
<value code="0">Range aid disabled</value>
</values>
</parameter>
<parameter default="1.0" name="EKF2_RNG_A_VMAX" type="FLOAT">
<short_desc>Maximum horizontal velocity allowed for range aid mode</short_desc>
<long_desc>If the vehicle horizontal speed exceeds this value then the estimator will not fuse range measurements to estimate it's height. This only applies when range aid mode is activated (EKF2_RNG_AID = enabled).</long_desc>
<min>0.1</min>
<max>2</max>
<scope>modules/ekf2</scope>
</parameter>
<parameter default="5.0" name="EKF2_RNG_A_HMAX" type="FLOAT">
<short_desc>Maximum absolute altitude (height above ground level) allowed for range aid mode</short_desc>
<long_desc>If the vehicle absolute altitude exceeds this value then the estimator will not fuse range measurements to estimate it's height. This only applies when range aid mode is activated (EKF2_RNG_AID = enabled).</long_desc>
<min>1.0</min>
<max>10.0</max>
<scope>modules/ekf2</scope>
</parameter>
</group> </group>
<group name="FW Attitude Control"> <group name="FW Attitude Control">
<parameter default="0.4" name="FW_R_TC" type="FLOAT"> <parameter default="0.4" name="FW_R_TC" type="FLOAT">
@ -2638,6 +2669,21 @@ but also ignore less noise</short_desc>
<value code="0">Disable</value> <value code="0">Disable</value>
</values> </values>
</parameter> </parameter>
<parameter default="7" name="GPS_UBX_DYNMODEL" type="INT32">
<short_desc>u-blox GPS dynamic platform model</short_desc>
<long_desc>u-blox receivers support different dynamic platform models to adjust the navigation engine to the expected application environment.</long_desc>
<min>0</min>
<max>9</max>
<reboot_required>true</reboot_required>
<scope>drivers/gps</scope>
<values>
<value code="8">airborne with &lt;4g acceleration</value>
<value code="2">stationary</value>
<value code="4">automotive</value>
<value code="7">airborne with &lt;2g acceleration</value>
<value code="6">airborne with &lt;1g acceleration</value>
</values>
</parameter>
</group> </group>
<group name="GPS Failure Navigation"> <group name="GPS Failure Navigation">
<parameter default="30.0" name="NAV_GPSF_LT" type="FLOAT"> <parameter default="30.0" name="NAV_GPSF_LT" type="FLOAT">
@ -3983,14 +4029,6 @@ if required for the gimbal (only in AUX output mode)</short_desc>
<unit>m/s</unit> <unit>m/s</unit>
<scope>modules/mc_pos_control</scope> <scope>modules/mc_pos_control</scope>
</parameter> </parameter>
<parameter default="0.5" name="MPC_Z_FF" type="FLOAT">
<short_desc>Vertical velocity feed forward</short_desc>
<long_desc>Feed forward weight for altitude control in stabilized modes (ALTCTRL, POSCTRL). 0 will give slow responce and no overshot, 1 - fast responce and big overshot.</long_desc>
<min>0.0</min>
<max>1.0</max>
<decimal>2</decimal>
<scope>modules/mc_pos_control</scope>
</parameter>
<parameter default="0.95" name="MPC_XY_P" type="FLOAT"> <parameter default="0.95" name="MPC_XY_P" type="FLOAT">
<short_desc>Proportional gain for horizontal position error</short_desc> <short_desc>Proportional gain for horizontal position error</short_desc>
<min>0.0</min> <min>0.0</min>
@ -4059,14 +4097,6 @@ if required for the gimbal (only in AUX output mode)</short_desc>
<increment>1</increment> <increment>1</increment>
<scope>modules/mc_pos_control</scope> <scope>modules/mc_pos_control</scope>
</parameter> </parameter>
<parameter default="0.5" name="MPC_XY_FF" type="FLOAT">
<short_desc>Horizontal velocity feed forward</short_desc>
<long_desc>Feed forward weight for position control in position control mode (POSCTRL). 0 will give slow responce and no overshot, 1 - fast responce and big overshot.</long_desc>
<min>0.0</min>
<max>1.0</max>
<decimal>2</decimal>
<scope>modules/mc_pos_control</scope>
</parameter>
<parameter default="45.0" name="MPC_TILTMAX_AIR" type="FLOAT"> <parameter default="45.0" name="MPC_TILTMAX_AIR" type="FLOAT">
<short_desc>Maximum tilt angle in air</short_desc> <short_desc>Maximum tilt angle in air</short_desc>
<long_desc>Limits maximum tilt in AUTO and POSCTRL modes during flight.</long_desc> <long_desc>Limits maximum tilt in AUTO and POSCTRL modes during flight.</long_desc>
@ -7291,7 +7321,8 @@ This is used for gathering replay logs for the ekf2 module</short_desc>
<scope>modules/sensors</scope> <scope>modules/sensors</scope>
</parameter> </parameter>
<parameter default="0" name="SENS_EXT_MAG" type="INT32"> <parameter default="0" name="SENS_EXT_MAG" type="INT32">
<short_desc>Select primary magnetometer</short_desc> <short_desc>Select primary magnetometer.
DEPRECATED, only used on V1 hardware</short_desc>
<min>0</min> <min>0</min>
<max>2</max> <max>2</max>
<scope>modules/sensors</scope> <scope>modules/sensors</scope>

6
src/FirmwarePlugin/PX4/px4_custom_mode.h

@ -34,7 +34,7 @@
/** /**
* @file px4_custom_mode.h * @file px4_custom_mode.h
* PX4 custom flight modes * PX4 custom flight modes
* * Copied from PX4 2017-07-08 - https://github.com/PX4/Firmware/blob/master/src/modules/commander/px4_custom_mode.h#L45
*/ */
#ifndef PX4_CUSTOM_MODE_H_ #ifndef PX4_CUSTOM_MODE_H_
@ -50,8 +50,8 @@ enum PX4_CUSTOM_MAIN_MODE {
PX4_CUSTOM_MAIN_MODE_ACRO, PX4_CUSTOM_MAIN_MODE_ACRO,
PX4_CUSTOM_MAIN_MODE_OFFBOARD, PX4_CUSTOM_MAIN_MODE_OFFBOARD,
PX4_CUSTOM_MAIN_MODE_STABILIZED, PX4_CUSTOM_MAIN_MODE_STABILIZED,
PX4_CUSTOM_MAIN_MODE_RATTITUDE, PX4_CUSTOM_MAIN_MODE_RATTITUDE,
PX4_CUSTOM_MAIN_MODE_SIMPLE PX4_CUSTOM_MAIN_MODE_SIMPLE /* unused, but reserved for future use */
}; };
enum PX4_CUSTOM_SUB_MODE_AUTO { enum PX4_CUSTOM_SUB_MODE_AUTO {

1
src/FlightDisplay/FlightDisplayView.qml

@ -542,6 +542,7 @@ QGCView {
id: guidedActionsController id: guidedActionsController
missionController: _missionController missionController: _missionController
confirmDialog: guidedActionConfirm confirmDialog: guidedActionConfirm
actionList: guidedActionList
altitudeSlider: _altitudeSlider altitudeSlider: _altitudeSlider
z: _flightVideoPipControl.z + 1 z: _flightVideoPipControl.z + 1

7
src/FlightDisplay/FlightDisplayViewMap.qml

@ -240,8 +240,9 @@ FlightMap {
anchorPoint.y: sourceItem.anchorPointY anchorPoint.y: sourceItem.anchorPointY
sourceItem: MissionItemIndexLabel { sourceItem: MissionItemIndexLabel {
checked: true checked: true
label: qsTr("G", "Goto here waypoint") // second string is translator's hint. index: -1
label: qsTr("Goto here", "Goto here waypoint")
} }
} }
@ -260,7 +261,7 @@ FlightMap {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
if (guidedActionsController.showGotoLocation) { if (guidedActionsController.showGotoLocation && !guidedActionsController.guidedUIVisible) {
_gotoHereCoordinate = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */) _gotoHereCoordinate = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
guidedActionsController.confirmAction(guidedActionsController.actionGoto, _gotoHereCoordinate) guidedActionsController.confirmAction(guidedActionsController.actionGoto, _gotoHereCoordinate)
} }

2
src/FlightDisplay/GuidedActionConfirm.qml

@ -16,7 +16,7 @@ import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0 import QGroundControl.Palette 1.0
/// Guided actions confirmation dialog /// Guided actions confirmation dialog
Rectangle { NoMouseThroughRectangle {
id: _root id: _root
border.color: qgcPal.alertBorder border.color: qgcPal.alertBorder
border.width: 1 border.width: 1

2
src/FlightDisplay/GuidedActionList.qml

@ -17,7 +17,7 @@ import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0 import QGroundControl.Palette 1.0
/// Dialog showing list of available guided actions /// Dialog showing list of available guided actions
Rectangle { NoMouseThroughRectangle {
id: _root id: _root
width: actionColumn.width + (_margins * 4) width: actionColumn.width + (_margins * 4)
height: actionColumn.height + (_margins * 4) height: actionColumn.height + (_margins * 4)

17
src/FlightDisplay/GuidedActionsController.qml

@ -29,6 +29,7 @@ Item {
property var missionController property var missionController
property var confirmDialog property var confirmDialog
property var actionList
property var altitudeSlider property var altitudeSlider
readonly property string emergencyStopTitle: qsTr("Emergency Stop") readonly property string emergencyStopTitle: qsTr("Emergency Stop")
@ -89,13 +90,15 @@ Item {
property bool showLand: _activeVehicle && _activeVehicle.guidedModeSupported && _vehicleArmed && !_activeVehicle.fixedWing && !_vehicleInLandMode property bool showLand: _activeVehicle && _activeVehicle.guidedModeSupported && _vehicleArmed && !_activeVehicle.fixedWing && !_vehicleInLandMode
property bool showStartMission: _activeVehicle && _missionAvailable && !_missionActive && !_vehicleFlying property bool showStartMission: _activeVehicle && _missionAvailable && !_missionActive && !_vehicleFlying
property bool showContinueMission: _activeVehicle && _missionAvailable && !_missionActive && _vehicleFlying && (_currentMissionIndex < missionController.visualItems.count - 1) property bool showContinueMission: _activeVehicle && _missionAvailable && !_missionActive && _vehicleFlying && (_currentMissionIndex < missionController.visualItems.count - 1)
property bool showResumeMission: _activeVehicle && !_vehicleFlying && _missionAvailable && _resumeMissionIndex > 0 && (_resumeMissionIndex < missionController.visualItems.count - 2) property bool showResumeMission: _activeVehicle && !_vehicleArmed && _vehicleWasFlying && _missionAvailable && _resumeMissionIndex > 0 && (_resumeMissionIndex < missionController.visualItems.count - 2)
property bool showPause: _activeVehicle && _vehicleArmed && _activeVehicle.pauseVehicleSupported && _vehicleFlying && !_vehiclePaused property bool showPause: _activeVehicle && _vehicleArmed && _activeVehicle.pauseVehicleSupported && _vehicleFlying && !_vehiclePaused
property bool showChangeAlt: (_activeVehicle && _vehicleFlying) && _activeVehicle.guidedModeSupported && _vehicleArmed && !_missionActive property bool showChangeAlt: (_activeVehicle && _vehicleFlying) && _activeVehicle.guidedModeSupported && _vehicleArmed && !_missionActive
property bool showOrbit: !_hideOrbit && _activeVehicle && _vehicleFlying && _activeVehicle.orbitModeSupported && _vehicleArmed && !_missionActive property bool showOrbit: !_hideOrbit && _activeVehicle && _vehicleFlying && _activeVehicle.orbitModeSupported && _vehicleArmed && !_missionActive
property bool showLandAbort: _activeVehicle && _vehicleFlying && _activeVehicle.fixedWing && _vehicleLanding property bool showLandAbort: _activeVehicle && _vehicleFlying && _activeVehicle.fixedWing && _vehicleLanding
property bool showGotoLocation: _activeVehicle && _activeVehicle.guidedMode && _vehicleFlying property bool showGotoLocation: _activeVehicle && _activeVehicle.guidedMode && _vehicleFlying
property bool guidedUIVisible: guidedActionConfirm.visible || guidedActionList.visible
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property string _flightMode: _activeVehicle ? _activeVehicle.flightMode : "" property string _flightMode: _activeVehicle ? _activeVehicle.flightMode : ""
property bool _missionAvailable: missionController.containsItems property bool _missionAvailable: missionController.containsItems
@ -111,6 +114,7 @@ Item {
property int _resumeMissionIndex: missionController.resumeMissionIndex property int _resumeMissionIndex: missionController.resumeMissionIndex
property bool _hideEmergenyStop: !QGroundControl.corePlugin.options.guidedBarShowEmergencyStop property bool _hideEmergenyStop: !QGroundControl.corePlugin.options.guidedBarShowEmergencyStop
property bool _hideOrbit: !QGroundControl.corePlugin.options.guidedBarShowOrbit property bool _hideOrbit: !QGroundControl.corePlugin.options.guidedBarShowOrbit
property bool _vehicleWasFlying: false
// This is a temporary hack to debug a problem with RTL and Pause being disabled at the wrong time // This is a temporary hack to debug a problem with RTL and Pause being disabled at the wrong time
@ -125,7 +129,6 @@ Item {
Component.onCompleted: _outputState() Component.onCompleted: _outputState()
on_ActiveVehicleChanged: _outputState() on_ActiveVehicleChanged: _outputState()
on_VehicleArmedChanged: _outputState() on_VehicleArmedChanged: _outputState()
on_VehicleFlyingChanged: _outputState()
on_VehicleInRTLModeChanged: _outputState() on_VehicleInRTLModeChanged: _outputState()
on_VehiclePausedChanged: _outputState() on_VehiclePausedChanged: _outputState()
on__FlightModeChanged: _outputState() on__FlightModeChanged: _outputState()
@ -134,6 +137,15 @@ Item {
// End of hack // End of hack
on_VehicleFlyingChanged: {
_outputState()
if (!_vehicleFlying) {
// We use _vehicleWasFLying to help trigger Resume Mission only if the vehicle actually flew and came back down.
// Otherwise it may trigger during the Start Mission sequence due to signal ordering or armed and resume mission index.
_vehicleWasFlying = true
}
}
property var _actionData property var _actionData
on_CurrentMissionIndexChanged: console.log("_currentMissionIndex", _currentMissionIndex) on_CurrentMissionIndexChanged: console.log("_currentMissionIndex", _currentMissionIndex)
@ -262,6 +274,7 @@ Item {
missionController.resumeMission(missionController.resumeMissionIndex) missionController.resumeMission(missionController.resumeMissionIndex)
break break
case actionResumeMissionReady: case actionResumeMissionReady:
_vehicleWasFlying = false
_activeVehicle.startMission() _activeVehicle.startMission()
break break
case actionStartMission: case actionStartMission:

32
src/MissionManager/CameraSection.cc

@ -165,7 +165,9 @@ void CameraSection::appendSectionItems(QList<MissionItem*>& items, QObject* miss
MAV_CMD_DO_SET_CAM_TRIGG_DIST, MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION, MAV_FRAME_MISSION,
_cameraPhotoIntervalDistanceFact.rawValue().toDouble(), // Trigger distance _cameraPhotoIntervalDistanceFact.rawValue().toDouble(), // Trigger distance
0, 0, 0, 0, 0, 0, // param 2-7 not used 0, // No shutter integartion
1, // Trigger immediately
0, 0, 0, 0, // param 4-7 not used
true, // autoContinue true, // autoContinue
false, // isCurrentItem false, // isCurrentItem
missionItemParent); missionItemParent);
@ -313,13 +315,31 @@ bool CameraSection::_scanStopTakingPhotos(QmlObjectListModel* visualItems, int s
return false; return false;
} }
bool CameraSection::_scanTriggerDistance(QmlObjectListModel* visualItems, int scanIndex) bool CameraSection::_scanTriggerStartDistance(QmlObjectListModel* visualItems, int scanIndex)
{ {
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex); SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) { if (item) {
MissionItem& missionItem = item->missionItem(); MissionItem& missionItem = item->missionItem();
if ((MAV_CMD)item->command() == MAV_CMD_DO_SET_CAM_TRIGG_DIST) { if ((MAV_CMD)item->command() == MAV_CMD_DO_SET_CAM_TRIGG_DIST) {
if (missionItem.param1() >= 0 && missionItem.param2() == 0 && missionItem.param3() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) { if (missionItem.param1() > 0 && missionItem.param2() == 0 && missionItem.param3() == 1 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
cameraAction()->setRawValue(TakePhotoIntervalDistance);
cameraPhotoIntervalDistance()->setRawValue(missionItem.param1());
visualItems->removeAt(scanIndex)->deleteLater();
return true;
}
}
}
return false;
}
bool CameraSection::_scanTriggerStopDistance(QmlObjectListModel* visualItems, int scanIndex)
{
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
if ((MAV_CMD)item->command() == MAV_CMD_DO_SET_CAM_TRIGG_DIST) {
if (missionItem.param1() == 0 && missionItem.param2() == 0 && missionItem.param3() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
cameraAction()->setRawValue(TakePhotoIntervalDistance); cameraAction()->setRawValue(TakePhotoIntervalDistance);
cameraPhotoIntervalDistance()->setRawValue(missionItem.param1()); cameraPhotoIntervalDistance()->setRawValue(missionItem.param1());
visualItems->removeAt(scanIndex)->deleteLater(); visualItems->removeAt(scanIndex)->deleteLater();
@ -415,7 +435,11 @@ bool CameraSection::scanForSection(QmlObjectListModel* visualItems, int scanInde
foundCameraAction = true; foundCameraAction = true;
continue; continue;
} }
if (!foundCameraAction && _scanTriggerDistance(visualItems, scanIndex)) { if (!foundCameraAction && _scanTriggerStartDistance(visualItems, scanIndex)) {
foundCameraAction = true;
continue;
}
if (!foundCameraAction && _scanTriggerStopDistance(visualItems, scanIndex)) {
foundCameraAction = true; foundCameraAction = true;
continue; continue;
} }

3
src/MissionManager/CameraSection.h

@ -94,7 +94,8 @@ private:
bool _scanTakePhoto(QmlObjectListModel* visualItems, int scanIndex); bool _scanTakePhoto(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTakePhotosIntervalTime(QmlObjectListModel* visualItems, int scanIndex); bool _scanTakePhotosIntervalTime(QmlObjectListModel* visualItems, int scanIndex);
bool _scanStopTakingPhotos(QmlObjectListModel* visualItems, int scanIndex); bool _scanStopTakingPhotos(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTriggerDistance(QmlObjectListModel* visualItems, int scanIndex); bool _scanTriggerStartDistance(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTriggerStopDistance(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTakeVideo(QmlObjectListModel* visualItems, int scanIndex); bool _scanTakeVideo(QmlObjectListModel* visualItems, int scanIndex);
bool _scanStopTakingVideo(QmlObjectListModel* visualItems, int scanIndex); bool _scanStopTakingVideo(QmlObjectListModel* visualItems, int scanIndex);
bool _scanSetCameraMode(QmlObjectListModel* visualItems, int scanIndex); bool _scanSetCameraMode(QmlObjectListModel* visualItems, int scanIndex);

21
src/MissionManager/CameraSectionTest.cc

@ -50,7 +50,14 @@ void CameraSectionTest::init(void)
MissionItem(0, MAV_CMD_IMAGE_START_CAPTURE, MAV_FRAME_MISSION, 0, 48, 0, NAN, NAN, NAN, NAN, true, false), MissionItem(0, MAV_CMD_IMAGE_START_CAPTURE, MAV_FRAME_MISSION, 0, 48, 0, NAN, NAN, NAN, NAN, true, false),
this); this);
_validDistanceItem = new SimpleMissionItem(_offlineVehicle, _validDistanceItem = new SimpleMissionItem(_offlineVehicle,
MissionItem(0, MAV_CMD_DO_SET_CAM_TRIGG_DIST, MAV_FRAME_MISSION, 72, 0, 0, 0, 0, 0, 0, true, false), MissionItem(0,
MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION,
72, // trigger distance
0, // not shutter integration
1, // trigger immediately
0, 0, 0, 0,
true, false),
this); this);
_validStartVideoItem = new SimpleMissionItem(_offlineVehicle, _validStartVideoItem = new SimpleMissionItem(_offlineVehicle,
MissionItem(0, // sequence number MissionItem(0, // sequence number
@ -729,15 +736,15 @@ void CameraSectionTest::_testScanForPhotoIntervalDistanceSection(void)
_commonScanTest(_cameraSection); _commonScanTest(_cameraSection);
/* /*
MAV_CMD_DO_SET_CAM_TRIGG_DIST Mission command to set CAM_TRIGG_DIST for this flight MAV_CMD_DO_SET_CAM_TRIGG_DIST Mission command to set camera trigger distance for this flight. The camera is trigerred each time this distance is exceeded. This command can also be used to set the shutter integration time for the camera.
Mission Param #1 Camera trigger distance (meters) Mission Param #1 Camera trigger distance (meters). 0 to stop triggering.
Mission Param #2 Empty Mission Param #2 Camera shutter integration time (milliseconds). -1 or 0 to ignore
Mission Param #3 Empty Mission Param #3 Trigger camera once immediately. (0 = no trigger, 1 = trigger)
Mission Param #4 Empty Mission Param #4 Empty
Mission Param #5 Empty Mission Param #5 Empty
Mission Param #6 Empty Mission Param #6 Empty
Mission Param #7 Empty Mission Param #7 Empty
*/ */
SimpleMissionItem* newValidDistanceItem = new SimpleMissionItem(_offlineVehicle, this); SimpleMissionItem* newValidDistanceItem = new SimpleMissionItem(_offlineVehicle, this);
newValidDistanceItem->missionItem() = _validDistanceItem->missionItem(); newValidDistanceItem->missionItem() = _validDistanceItem->missionItem();
@ -769,7 +776,7 @@ void CameraSectionTest::_testScanForPhotoIntervalDistanceSection(void)
visualItems.clear(); visualItems.clear();
invalidSimpleItem.missionItem() = _validDistanceItem->missionItem(); invalidSimpleItem.missionItem() = _validDistanceItem->missionItem();
invalidSimpleItem.missionItem().setParam3(1); // must be 0 invalidSimpleItem.missionItem().setParam3(0); // must be 1
visualItems.append(&invalidSimpleItem); visualItems.append(&invalidSimpleItem);
QCOMPARE(_cameraSection->scanForSection(&visualItems, scanIndex), false); QCOMPARE(_cameraSection->scanForSection(&visualItems, scanIndex), false);
QCOMPARE(visualItems.count(), 1); QCOMPARE(visualItems.count(), 1);

5
src/MissionManager/MissionController.cc

@ -158,7 +158,10 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque
qWarning() << "First item is not settings item"; qWarning() << "First item is not settings item";
return; return;
} }
settingsItem->setCoordinate(newMissionItems[0]->coordinate()); MissionItem* fakeHomeItem = newMissionItems[0];
if (fakeHomeItem->coordinate().latitude() != 0 || fakeHomeItem->coordinate().longitude() != 0) {
settingsItem->setCoordinate(fakeHomeItem->coordinate());
}
i = 1; i = 1;
} }

19
src/MissionManager/PlanMasterController.cc

@ -89,6 +89,16 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged" << activeVehicle; qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged" << activeVehicle;
if (_managerVehicle) {
// Disconnect old vehicle
disconnect(_managerVehicle->missionManager(), &MissionManager::newMissionItemsAvailable, this, &PlanMasterController::_loadMissionComplete);
disconnect(_managerVehicle->geoFenceManager(), &GeoFenceManager::loadComplete, this, &PlanMasterController::_loadGeoFenceComplete);
disconnect(_managerVehicle->rallyPointManager(), &RallyPointManager::loadComplete, this, &PlanMasterController::_loadRallyPointsComplete);
disconnect(_managerVehicle->missionManager(), &MissionManager::sendComplete, this, &PlanMasterController::_sendMissionComplete);
disconnect(_managerVehicle->geoFenceManager(), &GeoFenceManager::sendComplete, this, &PlanMasterController::_sendGeoFenceComplete);
disconnect(_managerVehicle->rallyPointManager(), &RallyPointManager::sendComplete, this, &PlanMasterController::_sendRallyPointsComplete);
}
bool newOffline = false; bool newOffline = false;
if (activeVehicle == NULL) { if (activeVehicle == NULL) {
// Since there is no longer an active vehicle we use the offline controller vehicle as the manager vehicle // Since there is no longer an active vehicle we use the offline controller vehicle as the manager vehicle
@ -353,6 +363,7 @@ void PlanMasterController::removeAllFromVehicle(void)
_missionController.removeAllFromVehicle(); _missionController.removeAllFromVehicle();
_geoFenceController.removeAllFromVehicle(); _geoFenceController.removeAllFromVehicle();
_rallyPointController.removeAllFromVehicle(); _rallyPointController.removeAllFromVehicle();
setDirty(false);
} else { } else {
qWarning() << "PlanMasterController::removeAllFromVehicle called while offline"; qWarning() << "PlanMasterController::removeAllFromVehicle called while offline";
} }
@ -410,6 +421,14 @@ void PlanMasterController::sendPlanToVehicle(Vehicle* vehicle, const QString& fi
void PlanMasterController::_showPlanFromManagerVehicle(void) void PlanMasterController::_showPlanFromManagerVehicle(void)
{ {
if (!_managerVehicle->initialPlanRequestComplete() &&
!_missionController.syncInProgress() &&
!_geoFenceController.syncInProgress() &&
!_rallyPointController.syncInProgress()) {
// Something went wrong with initial load. All controllers are idle, so just force it off
_managerVehicle->forceInitialPlanRequestComplete();
}
// The crazy if structure is to handle the load propogating by itself through the system // The crazy if structure is to handle the load propogating by itself through the system
if (!_missionController.showPlanFromManagerVehicle()) { if (!_missionController.showPlanFromManagerVehicle()) {
if (!_geoFenceController.showPlanFromManagerVehicle()) { if (!_geoFenceController.showPlanFromManagerVehicle()) {

12
src/MissionManager/QGCMapPolygon.cc

@ -253,6 +253,8 @@ void QGCMapPolygon::removeVertex(int vertexIndex)
_polygonPath.removeAt(vertexIndex); _polygonPath.removeAt(vertexIndex);
emit pathChanged(); emit pathChanged();
_updateCenter();
} }
void QGCMapPolygon::_polygonModelCountChanged(int count) void QGCMapPolygon::_polygonModelCountChanged(int count)
@ -265,9 +267,13 @@ void QGCMapPolygon::_updateCenter(void)
if (!_ignoreCenterUpdates) { if (!_ignoreCenterUpdates) {
QGeoCoordinate center; QGeoCoordinate center;
if (_polygonPath.count() > 2) { if (_polygonPath.count() > 2) {
QPointF centerPoint = _toPolygonF().boundingRect().center(); QPointF centroid(0, 0);
center = _coordFromPointF(centerPoint); QPolygonF polygonF = _toPolygonF();
for (int i=0; i<polygonF.count(); i++) {
centroid += polygonF[i];
}
center = _coordFromPointF(QPointF(centroid.x() / polygonF.count(), centroid.y() / polygonF.count()));
} }
_center = center; _center = center;

3
src/MissionManager/QGCMapPolygonTest.cc

@ -171,7 +171,8 @@ void QGCMapPolygonTest::_testVertexManipulation(void)
// Vertex removal testing // Vertex removal testing
_mapPolygon->removeVertex(1); _mapPolygon->removeVertex(1);
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(pathChangedMask | polygonDirtyChangedMask | polygonCountChangedMask | centerChangedMask)); // There is some double signalling on centerChanged which is not yet fixed, hence checkOnlySignals
QVERIFY(_multiSpyPolygon->checkOnlySignalsByMask(pathChangedMask | polygonDirtyChangedMask | polygonCountChangedMask | centerChangedMask));
QVERIFY(_multiSpyModel->checkOnlySignalByMask(modelDirtyChangedMask | modelCountChangedMask)); QVERIFY(_multiSpyModel->checkOnlySignalByMask(modelDirtyChangedMask | modelCountChangedMask));
QCOMPARE(_mapPolygon->count(), 3); QCOMPARE(_mapPolygon->count(), 3);
polyList = _mapPolygon->path(); polyList = _mapPolygon->path();

7
src/MissionManager/QGCMapPolygonVisuals.qml

@ -35,8 +35,9 @@ Item {
property var _splitHandlesComponent property var _splitHandlesComponent
property var _centerDragHandleComponent property var _centerDragHandleComponent
property real _zorderDragHandle: QGroundControl.zOrderMapItems + 2 property real _zorderDragHandle: QGroundControl.zOrderMapItems + 3 // Highest to prevent splitting when items overlap
property real _zorderSplitHandle: QGroundControl.zOrderMapItems + 1 property real _zorderSplitHandle: QGroundControl.zOrderMapItems + 2
property real _zorderCenterHandle: QGroundControl.zOrderMapItems + 1 // Lowest such that drag or split takes precedence
function addVisuals() { function addVisuals() {
_polygonComponent = polygonComponent.createObject(mapControl) _polygonComponent = polygonComponent.createObject(mapControl)
@ -281,7 +282,7 @@ Item {
id: centerDragAreaComponent id: centerDragAreaComponent
MissionItemIndicatorDrag { MissionItemIndicatorDrag {
z: _zorderDragHandle z: _zorderCenterHandle
onItemCoordinateChanged: mapPolygon.center = itemCoordinate onItemCoordinateChanged: mapPolygon.center = itemCoordinate
onDragStart: mapPolygon.centerDrag = true onDragStart: mapPolygon.centerDrag = true
onDragStop: mapPolygon.centerDrag = false onDragStop: mapPolygon.centerDrag = false

6
src/MissionManager/Survey.SettingsGroup.json

@ -64,7 +64,7 @@
"min": 0, "min": 0,
"max": 85, "max": 85,
"units": "%", "units": "%",
"defaultValue": 10 "defaultValue": 70
}, },
{ {
"name": "SideOverlap", "name": "SideOverlap",
@ -74,7 +74,7 @@
"min": 0, "min": 0,
"max": 85, "max": 85,
"units": "%", "units": "%",
"defaultValue": 10 "defaultValue": 70
}, },
{ {
"name": "CameraSensorWidth", "name": "CameraSensorWidth",
@ -132,7 +132,7 @@
"name": "CameraTriggerInTurnaround", "name": "CameraTriggerInTurnaround",
"shortDescription": "Camera continues taking images in turnarounds.", "shortDescription": "Camera continues taking images in turnarounds.",
"type": "bool", "type": "bool",
"defaultValue": false "defaultValue": true
}, },
{ {
"name": "HoverAndCapture", "name": "HoverAndCapture",

52
src/MissionManager/SurveyMissionItem.cc

@ -39,6 +39,7 @@ const char* SurveyMissionItem::_jsonCameraSensorHeightKey = "sensorHeigh
const char* SurveyMissionItem::_jsonCameraResolutionWidthKey = "resolutionWidth"; const char* SurveyMissionItem::_jsonCameraResolutionWidthKey = "resolutionWidth";
const char* SurveyMissionItem::_jsonCameraResolutionHeightKey = "resolutionHeight"; const char* SurveyMissionItem::_jsonCameraResolutionHeightKey = "resolutionHeight";
const char* SurveyMissionItem::_jsonCameraFocalLengthKey = "focalLength"; const char* SurveyMissionItem::_jsonCameraFocalLengthKey = "focalLength";
const char* SurveyMissionItem::_jsonCameraMinTriggerIntervalKey = "minTriggerInterval";
const char* SurveyMissionItem::_jsonCameraObjectKey = "camera"; const char* SurveyMissionItem::_jsonCameraObjectKey = "camera";
const char* SurveyMissionItem::_jsonCameraNameKey = "name"; const char* SurveyMissionItem::_jsonCameraNameKey = "name";
const char* SurveyMissionItem::_jsonManualGridKey = "manualGrid"; const char* SurveyMissionItem::_jsonManualGridKey = "manualGrid";
@ -79,6 +80,7 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent)
, _missionCommandCount(0) , _missionCommandCount(0)
, _refly90Degrees(false) , _refly90Degrees(false)
, _additionalFlightDelaySeconds(0) , _additionalFlightDelaySeconds(0)
, _cameraMinTriggerInterval(0)
, _ignoreRecalc(false) , _ignoreRecalc(false)
, _surveyDistance(0.0) , _surveyDistance(0.0)
, _cameraShots(0) , _cameraShots(0)
@ -240,6 +242,7 @@ void SurveyMissionItem::save(QJsonArray& missionItems)
cameraObject[_jsonCameraResolutionWidthKey] = _cameraResolutionWidthFact.rawValue().toDouble(); cameraObject[_jsonCameraResolutionWidthKey] = _cameraResolutionWidthFact.rawValue().toDouble();
cameraObject[_jsonCameraResolutionHeightKey] = _cameraResolutionHeightFact.rawValue().toDouble(); cameraObject[_jsonCameraResolutionHeightKey] = _cameraResolutionHeightFact.rawValue().toDouble();
cameraObject[_jsonCameraFocalLengthKey] = _cameraFocalLengthFact.rawValue().toDouble(); cameraObject[_jsonCameraFocalLengthKey] = _cameraFocalLengthFact.rawValue().toDouble();
cameraObject[_jsonCameraMinTriggerIntervalKey] = _cameraMinTriggerInterval;
cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble(); cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble();
cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt(); cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt();
cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt(); cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt();
@ -373,6 +376,7 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe
{ _jsonCameraFocalLengthKey, QJsonValue::Double, true }, { _jsonCameraFocalLengthKey, QJsonValue::Double, true },
{ _jsonCameraNameKey, QJsonValue::String, true }, { _jsonCameraNameKey, QJsonValue::String, true },
{ _jsonCameraOrientationLandscapeKey, QJsonValue::Bool, true }, { _jsonCameraOrientationLandscapeKey, QJsonValue::Bool, true },
{ _jsonCameraMinTriggerIntervalKey, QJsonValue::Double, false },
}; };
if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) { if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) {
return false; return false;
@ -389,6 +393,7 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe
_cameraResolutionWidthFact.setRawValue (cameraObject[_jsonCameraResolutionWidthKey].toDouble()); _cameraResolutionWidthFact.setRawValue (cameraObject[_jsonCameraResolutionWidthKey].toDouble());
_cameraResolutionHeightFact.setRawValue (cameraObject[_jsonCameraResolutionHeightKey].toDouble()); _cameraResolutionHeightFact.setRawValue (cameraObject[_jsonCameraResolutionHeightKey].toDouble());
_cameraFocalLengthFact.setRawValue (cameraObject[_jsonCameraFocalLengthKey].toDouble()); _cameraFocalLengthFact.setRawValue (cameraObject[_jsonCameraFocalLengthKey].toDouble());
_cameraMinTriggerInterval = cameraObject[_jsonCameraMinTriggerIntervalKey].toDouble(0);
} }
// Polygon shape // Polygon shape
@ -967,8 +972,8 @@ int SurveyMissionItem::_gridGenerator(const QList<QPointF>& polygonPoints, QLis
qCDebug(SurveyMissionItemLog) << "Generate left to right"; qCDebug(SurveyMissionItemLog) << "Generate left to right";
float x = largeBoundRect.topLeft().x() - (gridSpacing / 2); float x = largeBoundRect.topLeft().x() - (gridSpacing / 2);
while (x < largeBoundRect.bottomRight().x()) { while (x < largeBoundRect.bottomRight().x()) {
float yTop = largeBoundRect.topLeft().y() - 100.0; float yTop = largeBoundRect.topLeft().y() - 10000.0;
float yBottom = largeBoundRect.bottomRight().y() + 100.0; float yBottom = largeBoundRect.bottomRight().y() + 10000.0;
lineList += QLineF(_rotatePoint(QPointF(x, yTop), boundingCenter, gridAngle), _rotatePoint(QPointF(x, yBottom), boundingCenter, gridAngle)); lineList += QLineF(_rotatePoint(QPointF(x, yTop), boundingCenter, gridAngle), _rotatePoint(QPointF(x, yBottom), boundingCenter, gridAngle));
qCDebug(SurveyMissionItemLog) << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; qCDebug(SurveyMissionItemLog) << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")";
@ -980,8 +985,8 @@ int SurveyMissionItem::_gridGenerator(const QList<QPointF>& polygonPoints, QLis
qCDebug(SurveyMissionItemLog) << "Generate right to left"; qCDebug(SurveyMissionItemLog) << "Generate right to left";
float x = largeBoundRect.topRight().x() + (gridSpacing / 2); float x = largeBoundRect.topRight().x() + (gridSpacing / 2);
while (x > largeBoundRect.bottomLeft().x()) { while (x > largeBoundRect.bottomLeft().x()) {
float yTop = largeBoundRect.topRight().y() - 100.0; float yTop = largeBoundRect.topRight().y() - 10000.0;
float yBottom = largeBoundRect.bottomLeft().y() + 100.0; float yBottom = largeBoundRect.bottomLeft().y() + 10000.0;
lineList += QLineF(_rotatePoint(QPointF(x, yTop), boundingCenter, gridAngle), _rotatePoint(QPointF(x, yBottom), boundingCenter, gridAngle)); lineList += QLineF(_rotatePoint(QPointF(x, yTop), boundingCenter, gridAngle), _rotatePoint(QPointF(x, yBottom), boundingCenter, gridAngle));
qCDebug(SurveyMissionItemLog) << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; qCDebug(SurveyMissionItemLog) << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")";
@ -997,8 +1002,8 @@ int SurveyMissionItem::_gridGenerator(const QList<QPointF>& polygonPoints, QLis
qCDebug(SurveyMissionItemLog) << "Generate top to bottom"; qCDebug(SurveyMissionItemLog) << "Generate top to bottom";
float y = largeBoundRect.bottomLeft().y() + (gridSpacing / 2); float y = largeBoundRect.bottomLeft().y() + (gridSpacing / 2);
while (y > largeBoundRect.topRight().y()) { while (y > largeBoundRect.topRight().y()) {
float xLeft = largeBoundRect.bottomLeft().x() - 100.0; float xLeft = largeBoundRect.bottomLeft().x() - 10000.0;
float xRight = largeBoundRect.topRight().x() + 100.0; float xRight = largeBoundRect.topRight().x() + 10000.0;
lineList += QLineF(_rotatePoint(QPointF(xLeft, y), boundingCenter, gridAngle), _rotatePoint(QPointF(xRight, y), boundingCenter, gridAngle)); lineList += QLineF(_rotatePoint(QPointF(xLeft, y), boundingCenter, gridAngle), _rotatePoint(QPointF(xRight, y), boundingCenter, gridAngle));
qCDebug(SurveyMissionItemLog) << "y:xLeft:xRight" << y << xLeft << xRight << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; qCDebug(SurveyMissionItemLog) << "y:xLeft:xRight" << y << xLeft << xRight << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")";
@ -1010,8 +1015,8 @@ int SurveyMissionItem::_gridGenerator(const QList<QPointF>& polygonPoints, QLis
qCDebug(SurveyMissionItemLog) << "Generate bottom to top"; qCDebug(SurveyMissionItemLog) << "Generate bottom to top";
float y = largeBoundRect.topLeft().y() - (gridSpacing / 2); float y = largeBoundRect.topLeft().y() - (gridSpacing / 2);
while (y < largeBoundRect.bottomRight().y()) { while (y < largeBoundRect.bottomRight().y()) {
float xLeft = largeBoundRect.topLeft().x() - 100.0; float xLeft = largeBoundRect.topLeft().x() - 10000.0;
float xRight = largeBoundRect.bottomRight().x() + 100.0; float xRight = largeBoundRect.bottomRight().x() + 10000.0;
lineList += QLineF(_rotatePoint(QPointF(xLeft, y), boundingCenter, gridAngle), _rotatePoint(QPointF(xRight, y), boundingCenter, gridAngle)); lineList += QLineF(_rotatePoint(QPointF(xLeft, y), boundingCenter, gridAngle), _rotatePoint(QPointF(xRight, y), boundingCenter, gridAngle));
qCDebug(SurveyMissionItemLog) << "y:xLeft:xRight" << y << xLeft << xRight << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")"; qCDebug(SurveyMissionItemLog) << "y:xLeft:xRight" << y << xLeft << xRight << "line(" << lineList.last().x1() << ", " << lineList.last().y1() << ")-(" << lineList.last().x2() <<", " << lineList.last().y2() << ")";
@ -1133,9 +1138,11 @@ int SurveyMissionItem::_appendWaypointToMission(QList<MissionItem*>& items, int
MAV_CMD_DO_SET_CAM_TRIGG_DIST, MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION, MAV_FRAME_MISSION,
cameraTrigger == CameraTriggerOn ? _triggerDistance() : 0, cameraTrigger == CameraTriggerOn ? _triggerDistance() : 0,
0, 0, 0, 0, 0, 0, // param 2-7 unused 0, // shutter integration (ignore)
true, // autoContinue cameraTrigger == CameraTriggerOn ? 1 : 0, // trigger immediately when starting
false, // isCurrentItem 0, 0, 0, 0, // param 4-7 unused
true, // autoContinue
false, // isCurrentItem
missionItemParent); missionItemParent);
items.append(item); items.append(item);
break; break;
@ -1191,21 +1198,14 @@ bool SurveyMissionItem::_nextTransectCoord(const QList<QGeoCoordinate>& transect
/// @return false: Generation failed /// @return false: Generation failed
bool SurveyMissionItem::_appendMissionItemsWorker(QList<MissionItem*>& items, QObject* missionItemParent, int& seqNum, bool hasRefly, bool buildRefly) bool SurveyMissionItem::_appendMissionItemsWorker(QList<MissionItem*>& items, QObject* missionItemParent, int& seqNum, bool hasRefly, bool buildRefly)
{ {
bool firstWaypointTrigger = false;
qCDebug(SurveyMissionItemLog) << "hasTurnaround:triggerCamera:hoverAndCapture:imagesEverywhere:hasRefly:buildRefly" << _hasTurnaround() << _triggerCamera() << _hoverAndCaptureEnabled() << _imagesEverywhere() << hasRefly << buildRefly; qCDebug(SurveyMissionItemLog) << "hasTurnaround:triggerCamera:hoverAndCapture:imagesEverywhere:hasRefly:buildRefly" << _hasTurnaround() << _triggerCamera() << _hoverAndCaptureEnabled() << _imagesEverywhere() << hasRefly << buildRefly;
QList<QList<QGeoCoordinate>>& transectSegments = buildRefly ? _reflyTransectSegments : _transectSegments; QList<QList<QGeoCoordinate>>& transectSegments = buildRefly ? _reflyTransectSegments : _transectSegments;
if (!buildRefly && _imagesEverywhere()) { if (!buildRefly && _imagesEverywhere()) {
// We are taking images in turnaround, so we start command once at beginning firstWaypointTrigger = true;
MissionItem* item = new MissionItem(seqNum++,
MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION,
_triggerDistance(),
0, 0, 0, 0, 0, 0, // param 2-7 unused
true, // autoContinue
false, // isCurrentItem
missionItemParent);
items.append(item);
} }
for (int segmentIndex=0; segmentIndex<transectSegments.count(); segmentIndex++) { for (int segmentIndex=0; segmentIndex<transectSegments.count(); segmentIndex++) {
@ -1221,15 +1221,21 @@ bool SurveyMissionItem::_appendMissionItemsWorker(QList<MissionItem*>& items, QO
if (!_nextTransectCoord(segment, pointIndex++, coord)) { if (!_nextTransectCoord(segment, pointIndex++, coord)) {
return false; return false;
} }
seqNum = _appendWaypointToMission(items, seqNum, coord, CameraTriggerNone, missionItemParent); seqNum = _appendWaypointToMission(items, seqNum, coord, firstWaypointTrigger ? CameraTriggerOn : CameraTriggerNone, missionItemParent);
firstWaypointTrigger = false;
} }
// Add polygon entry point // Add polygon entry point
if (!_nextTransectCoord(segment, pointIndex++, coord)) { if (!_nextTransectCoord(segment, pointIndex++, coord)) {
return false; return false;
} }
cameraTrigger = _imagesEverywhere() || !_triggerCamera() ? CameraTriggerNone : (_hoverAndCaptureEnabled() ? CameraTriggerHoverAndCapture : CameraTriggerOn); if (firstWaypointTrigger) {
cameraTrigger = CameraTriggerOn;
} else {
cameraTrigger = _imagesEverywhere() || !_triggerCamera() ? CameraTriggerNone : (_hoverAndCaptureEnabled() ? CameraTriggerHoverAndCapture : CameraTriggerOn);
}
seqNum = _appendWaypointToMission(items, seqNum, coord, cameraTrigger, missionItemParent); seqNum = _appendWaypointToMission(items, seqNum, coord, cameraTrigger, missionItemParent);
firstWaypointTrigger = false;
// Add internal hover and capture points // Add internal hover and capture points
if (_hoverAndCaptureEnabled()) { if (_hoverAndCaptureEnabled()) {

22
src/MissionManager/SurveyMissionItem.h

@ -43,14 +43,15 @@ public:
Q_PROPERTY(Fact* cameraResolutionWidth READ cameraResolutionWidth CONSTANT) Q_PROPERTY(Fact* cameraResolutionWidth READ cameraResolutionWidth CONSTANT)
Q_PROPERTY(Fact* cameraResolutionHeight READ cameraResolutionHeight CONSTANT) Q_PROPERTY(Fact* cameraResolutionHeight READ cameraResolutionHeight CONSTANT)
Q_PROPERTY(Fact* cameraFocalLength READ cameraFocalLength CONSTANT) Q_PROPERTY(Fact* cameraFocalLength READ cameraFocalLength CONSTANT)
Q_PROPERTY(Fact* fixedValueIsAltitude READ fixedValueIsAltitude CONSTANT)
Q_PROPERTY(Fact* cameraOrientationLandscape READ cameraOrientationLandscape CONSTANT) Q_PROPERTY(Fact* cameraOrientationLandscape READ cameraOrientationLandscape CONSTANT)
Q_PROPERTY(Fact* fixedValueIsAltitude READ fixedValueIsAltitude CONSTANT)
Q_PROPERTY(Fact* manualGrid READ manualGrid CONSTANT) Q_PROPERTY(Fact* manualGrid READ manualGrid CONSTANT)
Q_PROPERTY(Fact* camera READ camera CONSTANT) Q_PROPERTY(Fact* camera READ camera CONSTANT)
Q_PROPERTY(bool cameraOrientationFixed MEMBER _cameraOrientationFixed NOTIFY cameraOrientationFixedChanged) Q_PROPERTY(bool cameraOrientationFixed MEMBER _cameraOrientationFixed NOTIFY cameraOrientationFixedChanged)
Q_PROPERTY(bool hoverAndCaptureAllowed READ hoverAndCaptureAllowed CONSTANT) Q_PROPERTY(bool hoverAndCaptureAllowed READ hoverAndCaptureAllowed CONSTANT)
Q_PROPERTY(bool refly90Degrees READ refly90Degrees WRITE setRefly90Degrees NOTIFY refly90DegreesChanged) Q_PROPERTY(bool refly90Degrees READ refly90Degrees WRITE setRefly90Degrees NOTIFY refly90DegreesChanged)
Q_PROPERTY(double cameraMinTriggerInterval MEMBER _cameraMinTriggerInterval NOTIFY cameraMinTriggerIntervalChanged)
Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged) Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged)
Q_PROPERTY(QVariantList gridPoints READ gridPoints NOTIFY gridPointsChanged) Q_PROPERTY(QVariantList gridPoints READ gridPoints NOTIFY gridPointsChanged)
@ -165,14 +166,15 @@ public:
static const char* cameraName; static const char* cameraName;
signals: signals:
void gridPointsChanged (void); void gridPointsChanged (void);
void cameraShotsChanged (int cameraShots); void cameraShotsChanged (int cameraShots);
void coveredAreaChanged (double coveredArea); void coveredAreaChanged (double coveredArea);
void cameraValueChanged (void); void cameraValueChanged (void);
void gridTypeChanged (QString gridType); void gridTypeChanged (QString gridType);
void timeBetweenShotsChanged (void); void timeBetweenShotsChanged (void);
void cameraOrientationFixedChanged (bool cameraOrientationFixed); void cameraOrientationFixedChanged (bool cameraOrientationFixed);
void refly90DegreesChanged (bool refly90Degrees); void refly90DegreesChanged (bool refly90Degrees);
void cameraMinTriggerIntervalChanged (double cameraMinTriggerInterval);
private slots: private slots:
void _setDirty(void); void _setDirty(void);
@ -233,6 +235,7 @@ private:
int _missionCommandCount; int _missionCommandCount;
bool _refly90Degrees; bool _refly90Degrees;
double _additionalFlightDelaySeconds; double _additionalFlightDelaySeconds;
double _cameraMinTriggerInterval;
bool _ignoreRecalc; bool _ignoreRecalc;
double _surveyDistance; double _surveyDistance;
@ -283,6 +286,7 @@ private:
static const char* _jsonCameraResolutionWidthKey; static const char* _jsonCameraResolutionWidthKey;
static const char* _jsonCameraResolutionHeightKey; static const char* _jsonCameraResolutionHeightKey;
static const char* _jsonCameraFocalLengthKey; static const char* _jsonCameraFocalLengthKey;
static const char* _jsonCameraMinTriggerIntervalKey;
static const char* _jsonManualGridKey; static const char* _jsonManualGridKey;
static const char* _jsonCameraObjectKey; static const char* _jsonCameraObjectKey;
static const char* _jsonCameraNameKey; static const char* _jsonCameraNameKey;

44
src/PlanView/SurveyItemEditor.qml

@ -57,7 +57,9 @@ Rectangle {
gridTypeCombo.currentIndex = index gridTypeCombo.currentIndex = index
if (index != 1) { if (index != 1) {
// Specific camera is selected // Specific camera is selected
missionItem.cameraOrientationFixed = _vehicleCameraList[index - _gridTypeCamera].fixedOrientation var camera = _vehicleCameraList[index - _gridTypeCamera]
missionItem.cameraOrientationFixed = camera.fixedOrientation
missionItem.cameraMinTriggerInterval = camera.minTriggerInterval
} }
} }
} }
@ -181,6 +183,15 @@ Rectangle {
anchors.right: parent.right anchors.right: parent.right
spacing: _margin spacing: _margin
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("WARNING: Photo interval is below minimum interval (%1 secs) supported by camera.").arg(missionItem.cameraMinTriggerInterval.toFixed(1))
wrapMode: Text.WordWrap
color: qgcPal.warningText
visible: missionItem.manualGrid.value !== true && missionItem.cameraShots > 0 && missionItem.cameraMinTriggerInterval !== 0 && missionItem.cameraMinTriggerInterval > missionItem.timeBetweenShots
}
SectionHeader { SectionHeader {
id: cameraHeader id: cameraHeader
text: qsTr("Camera") text: qsTr("Camera")
@ -207,6 +218,7 @@ Rectangle {
missionItem.manualGrid.value = false missionItem.manualGrid.value = false
missionItem.camera.value = gridTypeCombo.textAt(index) missionItem.camera.value = gridTypeCombo.textAt(index)
missionItem.cameraOrientationFixed = false missionItem.cameraOrientationFixed = false
missionItem.cameraMinTriggerInterval = 0
} else { } else {
missionItem.manualGrid.value = false missionItem.manualGrid.value = false
missionItem.camera.value = gridTypeCombo.textAt(index) missionItem.camera.value = gridTypeCombo.textAt(index)
@ -219,6 +231,7 @@ Rectangle {
missionItem.cameraFocalLength.rawValue = _vehicleCameraList[listIndex].focalLength missionItem.cameraFocalLength.rawValue = _vehicleCameraList[listIndex].focalLength
missionItem.cameraOrientationLandscape.rawValue = _vehicleCameraList[listIndex].landscape ? 1 : 0 missionItem.cameraOrientationLandscape.rawValue = _vehicleCameraList[listIndex].landscape ? 1 : 0
missionItem.cameraOrientationFixed = _vehicleCameraList[listIndex].fixedOrientation missionItem.cameraOrientationFixed = _vehicleCameraList[listIndex].fixedOrientation
missionItem.cameraMinTriggerInterval = _vehicleCameraList[listIndex].minTriggerInterval
_noCameraValueRecalc = false _noCameraValueRecalc = false
recalcFromCameraValues() recalcFromCameraValues()
} }
@ -252,12 +265,6 @@ Rectangle {
enabled: cameraTriggerDistanceCheckBox.checked enabled: cameraTriggerDistanceCheckBox.checked
} }
} }
FactCheckBox {
text: qsTr("Hover and capture image")
fact: missionItem.hoverAndCapture
visible: missionItem.hoverAndCaptureAllowed
}
} }
// Camera based grid ui // Camera based grid ui
@ -387,6 +394,23 @@ Rectangle {
} }
} }
FactCheckBox {
text: qsTr("Hover and capture image")
fact: missionItem.hoverAndCapture
visible: missionItem.hoverAndCaptureAllowed
onClicked: {
if (checked) {
missionItem.cameraTriggerInTurnaround.rawValue = false
}
}
}
FactCheckBox {
text: qsTr("Take images in turnarounds")
fact: missionItem.cameraTriggerInTurnaround
enabled: !missionItem.hoverAndCapture.rawValue
}
SectionHeader { SectionHeader {
id: gridHeader id: gridHeader
text: qsTr("Grid") text: qsTr("Grid")
@ -418,7 +442,8 @@ Rectangle {
id: windRoseButton id: windRoseButton
anchors.verticalCenter: angleText.verticalCenter anchors.verticalCenter: angleText.verticalCenter
iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg" iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
visible: _vehicle.fixedWing // Wind Rose is temporarily turned off until bugs are fixed
visible: false//_vehicle.fixedWing
onClicked: { onClicked: {
var cords = windRoseButton.mapToItem(_root, 0, 0) var cords = windRoseButton.mapToItem(_root, 0, 0)
@ -519,7 +544,8 @@ Rectangle {
anchors.verticalCenter: manualAngleText.verticalCenter anchors.verticalCenter: manualAngleText.verticalCenter
Layout.columnSpan: 1 Layout.columnSpan: 1
iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg" iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
visible: _vehicle.fixedWing // Wind Rose is temporarily turned off until bugs are fixed
visible: false//_vehicle.fixedWing
onClicked: { onClicked: {
var cords = manualWindRoseButton.mapToItem(_root, 0, 0) var cords = manualWindRoseButton.mapToItem(_root, 0, 0)

4
src/QmlControls/MissionItemIndexLabel.qml

@ -13,7 +13,7 @@ Canvas {
signal clicked signal clicked
property string label ///< Label to show to the side of the index indicator property string label ///< Label to show to the side of the index indicator
property int index: 0 ///< Index to show in the indicator, 0 will show label instead property int index: 0 ///< Index to show in the indicator, 0 will show single char label instead, -1 first char of label in indicator full label to the side
property bool checked: false property bool checked: false
property bool small: false property bool small: false
property var color: checked ? "green" : qgcPal.mapButtonHighlight property var color: checked ? "green" : qgcPal.mapButtonHighlight
@ -33,7 +33,7 @@ Canvas {
property real _labelMargin: 2 property real _labelMargin: 2
property real _labelRadius: _indicatorRadius + _labelMargin property real _labelRadius: _indicatorRadius + _labelMargin
property string _label: index === 0 ? "" : label property string _label: index === 0 ? "" : label
property string _index: index === 0 ? label : index property string _index: index === 0 || index === -1 ? label.charAt(0) : index
onColorChanged: requestPaint() onColorChanged: requestPaint()
onShowGimbalYawChanged: requestPaint() onShowGimbalYawChanged: requestPaint()

14
src/QmlControls/NoMouseThroughRectangle.qml

@ -0,0 +1,14 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
/// This control is used to create a Rectangle control which does not allow mouse events to bleed through to the control
/// which is beneath it.
Rectangle {
MouseArea {
anchors.fill: parent
preventStealing: true
onWheel: { wheel.accepted = true; }
onPressed: { mouse.accepted = true; }
onReleased: { mouse.accepted = true; }
}
}

1
src/QmlControls/QGroundControl.Controls.qmldir

@ -25,6 +25,7 @@ MissionItemMapVisual 1.0 MissionItemMapVisual.qml
MissionItemStatus 1.0 MissionItemStatus.qml MissionItemStatus 1.0 MissionItemStatus.qml
ModeSwitchDisplay 1.0 ModeSwitchDisplay.qml ModeSwitchDisplay 1.0 ModeSwitchDisplay.qml
MultiRotorMotorDisplay 1.0 MultiRotorMotorDisplay.qml MultiRotorMotorDisplay 1.0 MultiRotorMotorDisplay.qml
NoMouseThroughRectangle 1.0 NoMouseThroughRectangle.qml
ParameterEditor 1.0 ParameterEditor.qml ParameterEditor 1.0 ParameterEditor.qml
ParameterEditorDialog 1.0 ParameterEditorDialog.qml ParameterEditorDialog 1.0 ParameterEditorDialog.qml
PlanToolBar 1.0 PlanToolBar.qml PlanToolBar 1.0 PlanToolBar.qml

7
src/Vehicle/Vehicle.cc

@ -688,8 +688,8 @@ void Vehicle::_handleGlobalPositionInt(mavlink_message_t& message)
mavlink_global_position_int_t globalPositionInt; mavlink_global_position_int_t globalPositionInt;
mavlink_msg_global_position_int_decode(&message, &globalPositionInt); mavlink_msg_global_position_int_decode(&message, &globalPositionInt);
// ArduPilot sends bogus GLOBAL_POSITION_INT messages with lat/lat/alt 0/0/0 even when it has not gps signal // ArduPilot sends bogus GLOBAL_POSITION_INT messages with lat/lat 0/0 even when it has not gps signal
if (globalPositionInt.lat == 0 && globalPositionInt.lon == 0 && globalPositionInt.alt == 0) { if (globalPositionInt.lat == 0 && globalPositionInt.lon == 0) {
return; return;
} }
@ -723,6 +723,7 @@ void Vehicle::_setCapabilities(uint64_t capabilityBits)
_supportsMissionItemInt = true; _supportsMissionItemInt = true;
} }
_vehicleCapabilitiesKnown = true; _vehicleCapabilitiesKnown = true;
emit capabilitiesKnownChanged(true);
qCDebug(VehicleLog) << QString("Vehicle %1 MISSION_ITEM_INT").arg(_supportsMissionItemInt ? QStringLiteral("supports") : QStringLiteral("does not support")); qCDebug(VehicleLog) << QString("Vehicle %1 MISSION_ITEM_INT").arg(_supportsMissionItemInt ? QStringLiteral("supports") : QStringLiteral("does not support"));
} }
@ -795,7 +796,7 @@ void Vehicle::_handleHilActuatorControls(mavlink_message_t &message)
void Vehicle::_handleCommandAck(mavlink_message_t& message) void Vehicle::_handleCommandAck(mavlink_message_t& message)
{ {
bool showError = true; bool showError = false;
mavlink_command_ack_t ack; mavlink_command_ack_t ack;
mavlink_msg_command_ack_decode(&message, &ack); mavlink_msg_command_ack_decode(&message, &ack);

4
src/Vehicle/Vehicle.h

@ -677,6 +677,7 @@ public:
QGCCameraManager* dynamicCameras () { return _cameras; } QGCCameraManager* dynamicCameras () { return _cameras; }
bool capabilitiesKnown(void) const { return _vehicleCapabilitiesKnown; }
bool supportsMissionItemInt(void) const { return _supportsMissionItemInt; } bool supportsMissionItemInt(void) const { return _supportsMissionItemInt; }
/// @true: When flying a mission the vehicle is always facing towards the next waypoint /// @true: When flying a mission the vehicle is always facing towards the next waypoint
@ -686,6 +687,8 @@ public:
/// @return: true: initial request is complete, false: initial request is still in progress; /// @return: true: initial request is complete, false: initial request is still in progress;
bool initialPlanRequestComplete(void) const { return _initialPlanRequestComplete; } bool initialPlanRequestComplete(void) const { return _initialPlanRequestComplete; }
void forceInitialPlanRequestComplete(void) { _initialPlanRequestComplete = true; }
void _setFlying(bool flying); void _setFlying(bool flying);
void _setLanding(bool landing); void _setLanding(bool landing);
void _setHomePosition(QGeoCoordinate& homeCoord); void _setHomePosition(QGeoCoordinate& homeCoord);
@ -717,6 +720,7 @@ signals:
void firmwareTypeChanged(void); void firmwareTypeChanged(void);
void vehicleTypeChanged(void); void vehicleTypeChanged(void);
void dynamicCamerasChanged(); void dynamicCamerasChanged();
void capabilitiesKnownChanged(bool capabilitiesKnown);
void messagesReceivedChanged (); void messagesReceivedChanged ();
void messagesSentChanged (); void messagesSentChanged ();

125
src/VehicleSetup/FirmwareUpgradeController.cc

@ -211,12 +211,7 @@ void FirmwareUpgradeController::_initFirmwareHash()
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v4_default.px4"}, { AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v4_default.px4"},
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v4_default.px4"}, { AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v4_default.px4"},
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v4_default.px4"}, { AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v4_default.px4"},
{ AutoPilotStackAPM, StableFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-quad/ArduCopter-v4.px4"}, { AutoPilotStackAPM, StableFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4/ArduCopter-v4.px4"},
{ AutoPilotStackAPM, StableFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa-quad/ArduCopter-v4.px4"},
{ AutoPilotStackAPM, StableFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-hexa/ArduCopter-v4.px4"},
{ AutoPilotStackAPM, StableFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa/ArduCopter-v4.px4"},
{ AutoPilotStackAPM, StableFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-tri/ArduCopter-v4.px4"},
{ AutoPilotStackAPM, StableFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-y6/ArduCopter-v4.px4"},
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v4.px4"}, { AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v4.px4"},
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v4.px4"}, { AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v4.px4"},
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v4.px4"}, { AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v4.px4"},
@ -232,18 +227,12 @@ void FirmwareUpgradeController::_initFirmwareHash()
}; };
//////////////////////////////////// PX4FMUV3 firmwares ////////////////////////////////////////////////// //////////////////////////////////// PX4FMUV3 firmwares //////////////////////////////////////////////////
// Note: ArduPilot stable does not yet support V3 firmwares, so fall back to V2
FirmwareToUrlElement_t rgPX4FMV3FirmwareArray[] = { FirmwareToUrlElement_t rgPX4FMV3FirmwareArray[] = {
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v3_default.px4"}, { AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v3_default.px4"},
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v3_default.px4"}, { AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v3_default.px4"},
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v3_default.px4"}, { AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v3_default.px4"},
{ AutoPilotStackAPM, StableFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-quad/ArduCopter-v2.px4"}, { AutoPilotStackAPM, StableFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4/ArduCopter-v3.px4"},
{ AutoPilotStackAPM, StableFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa-quad/ArduCopter-v2.px4"}, { AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v3.px4"},
{ AutoPilotStackAPM, StableFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-hexa/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-tri/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-y6/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v2.px4"}, { AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v2.px4"}, { AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, SubFirmware, "http://firmware.ardupilot.org/Sub/stable/PX4/ArduSub-v2.px4"}, { AutoPilotStackAPM, StableFirmware, SubFirmware, "http://firmware.ardupilot.org/Sub/stable/PX4/ArduSub-v2.px4"},
@ -265,12 +254,7 @@ void FirmwareUpgradeController::_initFirmwareHash()
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v2_default.px4"}, { AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v2_default.px4"},
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v2_default.px4"}, { AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v2_default.px4"},
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v2_default.px4"}, { AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v2_default.px4"},
{ AutoPilotStackAPM, StableFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-quad/ArduCopter-v2.px4"}, { AutoPilotStackAPM, StableFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa-quad/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-hexa/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-tri/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-y6/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v2.px4"}, { AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v2.px4"}, { AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v2.px4"}, { AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v2.px4"},
@ -322,12 +306,7 @@ void FirmwareUpgradeController::_initFirmwareHash()
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v1_default.px4"}, { AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v1_default.px4"},
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v1_default.px4"}, { AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v1_default.px4"},
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v1_default.px4"}, { AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v1_default.px4"},
{ AutoPilotStackAPM, StableFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-quad/ArduCopter-v1.px4"}, { AutoPilotStackAPM, StableFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4/ArduCopter-v1.px4"},
{ AutoPilotStackAPM, StableFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa-quad/ArduCopter-v1.px4"},
{ AutoPilotStackAPM, StableFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-hexa/ArduCopter-v1.px4"},
{ AutoPilotStackAPM, StableFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa/ArduCopter-v1.px4"},
{ AutoPilotStackAPM, StableFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-tri/ArduCopter-v1.px4"},
{ AutoPilotStackAPM, StableFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-y6/ArduCopter-v1.px4"},
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v1.px4"}, { AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v1.px4"},
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v1.px4"}, { AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v1.px4"},
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v1.px4"}, { AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v1.px4"},
@ -530,9 +509,9 @@ void FirmwareUpgradeController::_getFirmwareFile(FirmwareIdentifier firmwareId)
if (firmwareId.firmwareType == CustomFirmware) { if (firmwareId.firmwareType == CustomFirmware) {
_firmwareFilename = QGCQFileDialog::getOpenFileName(NULL, // Parent to main window _firmwareFilename = QGCQFileDialog::getOpenFileName(NULL, // Parent to main window
"Select Firmware File", // Dialog Caption "Select Firmware File", // Dialog Caption
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), // Initial directory QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), // Initial directory
"Firmware Files (*.px4 *.bin *.ihx)"); // File filter "Firmware Files (*.px4 *.bin *.ihx)"); // File filter
} else { } else {
if (prgFirmware->contains(firmwareId)) { if (prgFirmware->contains(firmwareId)) {
_firmwareFilename = prgFirmware->value(firmwareId); _firmwareFilename = prgFirmware->value(firmwareId);
@ -774,51 +753,57 @@ void FirmwareUpgradeController::setSelectedFirmwareType(FirmwareType_t firmwareT
QStringList FirmwareUpgradeController::apmAvailableVersions(void) QStringList FirmwareUpgradeController::apmAvailableVersions(void)
{ {
QStringList list; QStringList list;
QList<FirmwareVehicleType_t> vehicleTypes;
// This allows up to force the order of the combo box display
vehicleTypes << CopterFirmware << HeliFirmware << PlaneFirmware << RoverFirmware << SubFirmware;
_apmVehicleTypeFromCurrentVersionList.clear(); _apmVehicleTypeFromCurrentVersionList.clear();
foreach (FirmwareVehicleType_t vehicleType, _apmVersionMap[_selectedFirmwareType].keys()) { foreach (FirmwareVehicleType_t vehicleType, vehicleTypes) {
QString version; if (_apmVersionMap[_selectedFirmwareType].contains(vehicleType)) {
QString version;
switch (vehicleType) {
case QuadFirmware: switch (vehicleType) {
version = "Quad - "; case QuadFirmware:
break; version = "Quad - ";
case X8Firmware: break;
version = "X8 - "; case X8Firmware:
break; version = "X8 - ";
case HexaFirmware: break;
version = "Hexa - "; case HexaFirmware:
break; version = "Hexa - ";
case OctoFirmware: break;
version = "Octo - "; case OctoFirmware:
break; version = "Octo - ";
case YFirmware: break;
version = "Y - "; case YFirmware:
break; version = "Y - ";
case Y6Firmware: break;
version = "Y6 - "; case Y6Firmware:
break; version = "Y6 - ";
case HeliFirmware: break;
version = "Heli - "; case HeliFirmware:
break; version = "Heli - ";
case CopterFirmware: break;
version = "MultiRotor - "; case CopterFirmware:
break; version = "MultiRotor - ";
case SubFirmware: break;
version = "Sub - "; case SubFirmware:
break; version = "Sub - ";
case PlaneFirmware: break;
case RoverFirmware: case PlaneFirmware:
case DefaultVehicleFirmware: case RoverFirmware:
break; case DefaultVehicleFirmware:
break;
}
version += _apmVersionMap[_selectedFirmwareType][vehicleType];
_apmVehicleTypeFromCurrentVersionList.append(vehicleType);
list << version;
} }
version += _apmVersionMap[_selectedFirmwareType][vehicleType];
_apmVehicleTypeFromCurrentVersionList.append(vehicleType);
list << version;
} }
return list; return list;

7
src/api/QGCCorePlugin.cc

@ -176,6 +176,13 @@ bool QGCCorePlugin::adjustSettingMetaData(FactMetaData& metaData)
metaData.setRawDefaultValue(true); metaData.setRawDefaultValue(true);
return true; return true;
#endif #endif
#if defined(__ios__)
} else if (metaData.name() == AppSettings::savePathName) {
QString appName = qgcApp()->applicationName();
QDir rootDir = QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
metaData.setRawDefaultValue(rootDir.filePath(appName));
return false;
#endif
} }
return true; // Show setting in ui return true; // Show setting in ui
} }

36
src/ui/MainWindow.cc

@ -108,10 +108,11 @@ void MainWindow::deleteInstance(void)
/// by MainWindow::_create method. Hence no other code should have access to /// by MainWindow::_create method. Hence no other code should have access to
/// constructor. /// constructor.
MainWindow::MainWindow() MainWindow::MainWindow()
: _lowPowerMode(false) : _mavlinkDecoder (NULL)
, _showStatusBar(false) , _lowPowerMode (false)
, _mainQmlWidgetHolder(NULL) , _showStatusBar (false)
, _forceClose(false) , _mainQmlWidgetHolder (NULL)
, _forceClose (false)
{ {
_instance = this; _instance = this;
@ -272,10 +273,13 @@ MainWindow::MainWindow()
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
// Enforce thread-safe shutdown of the mavlink decoder if (_mavlinkDecoder) {
mavlinkDecoder->finish(); // Enforce thread-safe shutdown of the mavlink decoder
mavlinkDecoder->wait(1000); _mavlinkDecoder->finish();
mavlinkDecoder->deleteLater(); _mavlinkDecoder->wait(1000);
_mavlinkDecoder->deleteLater();
_mavlinkDecoder = NULL;
}
// This needs to happen before we get into the QWidget dtor // This needs to happen before we get into the QWidget dtor
// otherwise the QML engine reads freed data and tries to // otherwise the QML engine reads freed data and tries to
@ -290,12 +294,18 @@ QString MainWindow::_getWindowGeometryKey()
} }
#ifndef __mobile__ #ifndef __mobile__
void MainWindow::_buildCommonWidgets(void) MAVLinkDecoder* MainWindow::_mavLinkDecoderInstance(void)
{ {
// Add generic MAVLink decoder if (!_mavlinkDecoder) {
mavlinkDecoder = new MAVLinkDecoder(qgcApp()->toolbox()->mavlinkProtocol()); _mavlinkDecoder = new MAVLinkDecoder(qgcApp()->toolbox()->mavlinkProtocol());
connect(mavlinkDecoder.data(), &MAVLinkDecoder::valueChanged, this, &MainWindow::valueChanged); connect(_mavlinkDecoder, &MAVLinkDecoder::valueChanged, this, &MainWindow::valueChanged);
}
return _mavlinkDecoder;
}
void MainWindow::_buildCommonWidgets(void)
{
// Log player // Log player
// TODO: Make this optional with a preferences setting or under a "View" menu // TODO: Make this optional with a preferences setting or under a "View" menu
logPlayer = new QGCMAVLinkLogPlayer(statusBar()); logPlayer = new QGCMAVLinkLogPlayer(statusBar());
@ -363,7 +373,7 @@ bool MainWindow::_createInnerDockWidget(const QString& widgetName)
widget = new HILDockWidget(widgetName, action, this); widget = new HILDockWidget(widgetName, action, this);
break; break;
case ANALYZE: case ANALYZE:
widget = new Linecharts(widgetName, action, mavlinkDecoder, this); widget = new Linecharts(widgetName, action, _mavLinkDecoderInstance(), this);
break; break;
} }
if(widget) { if(widget) {

3
src/ui/MainWindow.h

@ -127,7 +127,6 @@ protected:
QSettings settings; QSettings settings;
QPointer<MAVLinkDecoder> mavlinkDecoder;
QGCMAVLinkLogPlayer* logPlayer; QGCMAVLinkLogPlayer* logPlayer;
#ifdef QGC_MOUSE_ENABLED_WIN #ifdef QGC_MOUSE_ENABLED_WIN
/** @brief 3d Mouse support (WIN only) */ /** @brief 3d Mouse support (WIN only) */
@ -181,7 +180,9 @@ private:
void _showDockWidget(const QString &name, bool show); void _showDockWidget(const QString &name, bool show);
void _loadVisibleWidgetsSettings(void); void _loadVisibleWidgetsSettings(void);
void _storeVisibleWidgetsSettings(void); void _storeVisibleWidgetsSettings(void);
MAVLinkDecoder* _mavLinkDecoderInstance(void);
MAVLinkDecoder* _mavlinkDecoder;
bool _lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets bool _lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets
bool _showStatusBar; bool _showStatusBar;
QVBoxLayout* _centralLayout; QVBoxLayout* _centralLayout;

Loading…
Cancel
Save