Browse Source

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

# Conflicts:
#	qgcresources.qrc
#	src/FlightDisplay/FlightDisplayView.qml
#	src/MissionManager/MissionController.cc
#	src/MissionManager/SurveyMissionItem.cc
#	src/MissionManager/SurveyMissionItem.h
#	src/PlanView/PlanView.qml
#	src/QGCApplication.cc
#	src/Settings/AppSettings.h
#	src/Vehicle/Vehicle.h

Note that SurveyMissionItem (.h/.cc) was changed in such a way that all previous changes were lost. Dynamic computation of its bounding box is missing and needs to be added into whatever is now handling these.
QGC4.4
Gus Grubba 7 years ago
parent
commit
1d7cf605b1
  1. 4
      .appveyor.yml
  2. 25
      .travis.yml
  3. 14
      .vagrantconfig.yml
  4. 1
      ISSUE_TEMPLATE.md
  5. 77
      Jenkinsfile
  6. 8
      QGCSetup.pri
  7. 87
      README.md
  8. 1
      Vagrantfile
  9. 10
      android/AndroidManifest.xml
  10. 9
      android/build.gradle
  11. 25
      deploy/MakeQtTravisTarball.sh
  12. BIN
      deploy/libeay32.dll
  13. BIN
      deploy/libssl32.dll
  14. 11
      deploy/qgroundcontrol_installer.nsi
  15. BIN
      deploy/ssleay32.dll
  16. 2
      libs/mavlink/include/mavlink/v2.0
  17. 1
      qgcresources.qrc
  18. 19
      qgroundcontrol.pro
  19. 20
      qgroundcontrol.qrc
  20. BIN
      resources/calibration/mode1/radioRollLeft.png
  21. BIN
      resources/calibration/mode1/radioRollRight.png
  22. 80
      resources/check.svg
  23. 2
      src/Airmap/AirspaceControl.qml
  24. 38
      src/AnalyzeView/GeoTagController.cc
  25. 5
      src/AnalyzeView/GeoTagController.h
  26. 5
      src/AnalyzeView/GeoTagPage.qml
  27. 2
      src/AnalyzeView/LogDownloadController.cc
  28. 7
      src/AnalyzeView/LogDownloadPage.qml
  29. 53
      src/AnalyzeView/MavlinkConsoleController.cc
  30. 22
      src/AnalyzeView/MavlinkConsoleController.h
  31. 25
      src/AnalyzeView/MavlinkConsolePage.qml
  32. 18
      src/AnalyzeView/ULogParser.cc
  33. 7
      src/AnalyzeView/ULogParser.h
  34. 19
      src/Audio/AudioOutput.cc
  35. 2
      src/Audio/AudioOutputTest.cc
  36. 7
      src/AutoPilotPlugins/APM/APMAirframeComponent.qml
  37. 30
      src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml
  38. 32
      src/AutoPilotPlugins/APM/APMCameraComponent.qml
  39. 8
      src/AutoPilotPlugins/APM/APMCameraComponentSummary.qml
  40. 2
      src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc
  41. 12
      src/AutoPilotPlugins/APM/APMFlightModesComponentSummary.qml
  42. 32
      src/AutoPilotPlugins/APM/APMLightsComponent.qml
  43. 4
      src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml
  44. 21
      src/AutoPilotPlugins/APM/APMPowerComponent.h
  45. 373
      src/AutoPilotPlugins/APM/APMPowerComponent.qml
  46. 29
      src/AutoPilotPlugins/APM/APMPowerComponentSummary.qml
  47. 8
      src/AutoPilotPlugins/APM/APMRadioComponentSummary.qml
  48. 288
      src/AutoPilotPlugins/APM/APMSafetyComponentCopter.qml
  49. 4
      src/AutoPilotPlugins/APM/APMSafetyComponentPlane.qml
  50. 86
      src/AutoPilotPlugins/APM/APMSafetyComponentSummaryCopter.qml
  51. 4
      src/AutoPilotPlugins/APM/APMSensorsComponentSummary.qml
  52. 6
      src/AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml
  53. 56
      src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml
  54. 4
      src/AutoPilotPlugins/AutoPilotPlugin.cc
  55. 1
      src/AutoPilotPlugins/AutoPilotPlugin.h
  56. 16
      src/AutoPilotPlugins/Common/ESP8266ComponentSummary.qml
  57. 58
      src/AutoPilotPlugins/Common/SetupPage.qml
  58. 8
      src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml
  59. 5
      src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml
  60. 18
      src/AutoPilotPlugins/PX4/CameraComponent.qml
  61. 12
      src/AutoPilotPlugins/PX4/CameraComponentSummary.qml
  62. 12
      src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml
  63. 14
      src/AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml
  64. 1
      src/AutoPilotPlugins/PX4/PX4TuningComponent.h
  65. 137
      src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml
  66. 106
      src/AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml
  67. 20
      src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml
  68. 23
      src/AutoPilotPlugins/PX4/PowerComponent.h
  69. 32
      src/AutoPilotPlugins/PX4/PowerComponent.qml
  70. 6
      src/AutoPilotPlugins/PX4/PowerComponentSummary.qml
  71. 54
      src/AutoPilotPlugins/PX4/SafetyComponentSummary.qml
  72. 15
      src/AutoPilotPlugins/PX4/SensorsComponent.cc
  73. 3
      src/AutoPilotPlugins/PX4/SensorsComponent.h
  74. 95
      src/AutoPilotPlugins/PX4/SensorsComponentController.cc
  75. 4
      src/AutoPilotPlugins/PX4/SensorsComponentController.h
  76. 10
      src/AutoPilotPlugins/PX4/SensorsComponentSummary.qml
  77. 2
      src/AutoPilotPlugins/PX4/SensorsComponentSummaryFixedWing.qml
  78. 27
      src/AutoPilotPlugins/PX4/SensorsSetup.qml
  79. 2
      src/Camera/QGCCameraControl.cc
  80. 56
      src/FactSystem/Fact.cc
  81. 11
      src/FactSystem/Fact.h
  82. 5
      src/FactSystem/FactControls/FactCheckBox.qml
  83. 2
      src/FactSystem/FactControls/FactPanelController.cc
  84. 5
      src/FactSystem/FactControls/FactTextField.qml
  85. 144
      src/FactSystem/FactControls/FactValueSlider.qml
  86. 1
      src/FactSystem/FactControls/qmldir
  87. 1
      src/FactSystem/FactGroup.cc
  88. 4
      src/FactSystem/FactGroup.h
  89. 106
      src/FactSystem/FactMetaData.cc
  90. 12
      src/FactSystem/FactMetaData.h
  91. 4
      src/FactSystem/FactSystem.h
  92. 33
      src/FactSystem/FactValidator.cc
  93. 56
      src/FactSystem/FactValidator.h
  94. 128
      src/FactSystem/FactValueSliderListModel.cc
  95. 48
      src/FactSystem/FactValueSliderListModel.h
  96. 8
      src/FactSystem/ParameterManager.cc
  97. 30
      src/FactSystem/ParameterManager.h
  98. 20
      src/FactSystem/SettingsFact.cc
  99. 13
      src/FactSystem/SettingsFact.h
  100. 78
      src/FirmwarePlugin/APM/APMFirmwarePlugin.cc
  101. Some files were not shown because too many files have changed in this diff Show More

4
.appveyor.yml

@ -15,7 +15,7 @@ environment: @@ -15,7 +15,7 @@ environment:
install:
- git submodule update --init --recursive
- call "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
- set PATH=C:\Qt\Tools\QtCreator\bin;C:\Qt\5.9.4\msvc2015\bin;%PATH%
- set PATH=C:\Qt\Tools\QtCreator\bin;C:\Qt\5.9.5\msvc2015\bin;%PATH%
- mkdir %LOCALAPPDATA%\QtProject && copy test\qtlogging.ini %LOCALAPPDATA%\QtProject\
- ps: |
Write-Host "Installing GStreamer..." -ForegroundColor Cyan
@ -35,7 +35,7 @@ install: @@ -35,7 +35,7 @@ install:
Write-Host "Installed" -ForegroundColor Green
build_script:
- mkdir %SHADOW_BUILD_DIR% && cd %SHADOW_BUILD_DIR% && C:\Qt\5.9.4\msvc2015\bin\qmake -r CONFIG-=debug_and_release CONFIG+=%CONFIG% CONFIG+=WarningsAsErrorsOn %APPVEYOR_BUILD_FOLDER%\qgroundcontrol.pro
- mkdir %SHADOW_BUILD_DIR% && cd %SHADOW_BUILD_DIR% && C:\Qt\5.9.5\msvc2015\bin\qmake -r CONFIG-=debug_and_release CONFIG+=%CONFIG% CONFIG+=WarningsAsErrorsOn %APPVEYOR_BUILD_FOLDER%\qgroundcontrol.pro
- cd %SHADOW_BUILD_DIR% && jom
- if "%CONFIG%" EQU "installer" ( copy %SHADOW_BUILD_DIR%\release\QGroundControl-installer.exe %APPVEYOR_BUILD_FOLDER%\QGroundControl-installer.exe )
# Generate the source server information to embed in the PDB

25
.travis.yml

@ -73,9 +73,9 @@ before_install: @@ -73,9 +73,9 @@ before_install:
install:
# linux dependencies: qt
- if [ "${SPEC}" = "linux-g++-64" ]; then
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.9.3-gcc_64-min.tar.bz2 &&
tar jxf Qt5.9.3-gcc_64-min.tar.bz2 -C /tmp &&
export PATH=/tmp/Qt5.9-gcc_64/5.9.3/gcc_64/bin:$PATH &&
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.11.0-gcc_64-min.tar.bz2 &&
tar jxf Qt5.11.0-gcc_64-min.tar.bz2 -C /tmp &&
export PATH=/tmp/Qt5.11-gcc_64/5.11.0/gcc_64/bin:$PATH &&
export DISPLAY=:99.0 &&
sh -e /etc/init.d/xvfb start
;
@ -83,8 +83,8 @@ install: @@ -83,8 +83,8 @@ install:
# android dependencies: qt, gstreamer, android-ndk
- if [ "${SPEC}" = "android-g++" ]; then
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.9.3-android_armv7-min.tar.bz2 &&
tar jxf Qt5.9.3-android_armv7-min.tar.bz2 -C /tmp &&
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.11.0-android_armv7-min.tar.bz2 &&
tar jxf Qt5.11.0-android_armv7-min.tar.bz2 -C /tmp &&
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/gstreamer-1.0-android-armv7-1.5.2.tar.bz2 &&
mkdir -p ${TRAVIS_BUILD_DIR}/gstreamer-1.0-android-armv7-1.5.2 &&
tar jxf gstreamer-1.0-android-armv7-1.5.2.tar.bz2 -C ${TRAVIS_BUILD_DIR}/gstreamer-1.0-android-armv7-1.5.2 &&
@ -93,14 +93,14 @@ install: @@ -93,14 +93,14 @@ install:
./android-ndk-r10e-linux-x86_64.bin > /dev/null &&
export ANDROID_NDK_ROOT=`pwd`/android-ndk-r10e &&
export ANDROID_SDK_ROOT=/usr/local/android-sdk &&
export PATH=/tmp/Qt5.9-android_armv7/5.9.3/android_armv7/bin:`pwd`/android-ndk-r10e:$PATH && echo $PATH
export PATH=/tmp/Qt5.11-android_armv7/5.11.0/android_armv7/bin:`pwd`/android-ndk-r10e:$PATH && echo $PATH
;
fi
# osx dependencies: qt (master builds only: gstreamer, gstreamer-devel)
- if [ "${SPEC}" = "macx-clang" ]; then
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.9.3-clang_64-min.tar.bz2 &&
tar jxf Qt5.9.3-clang_64-min.tar.bz2 -C /tmp
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.11.0-clang_64-min.tar.bz2 &&
tar jxf Qt5.11.0-clang_64-min.tar.bz2 -C /tmp
;
fi
@ -123,7 +123,7 @@ install: @@ -123,7 +123,7 @@ install:
fi
- if [ "${SPEC}" = "macx-clang" ]; then
export QT_DIR=Qt5.9-clang_64/5.9.3/clang_64 &&
export QT_DIR=Qt5.11-clang_64/5.11.0/clang_64 &&
export QT_QPA_PLATFORM_PLUGIN_PATH=/tmp/$QT_DIR/plugins &&
export QML2_IMPORT_PATH=/tmp/$QT_DIR/qml &&
export PATH=/tmp/$QT_DIR/bin:$PATH
@ -161,7 +161,12 @@ before_script: @@ -161,7 +161,12 @@ before_script:
script:
# run qmake
- mkdir ${SHADOW_BUILD_DIR} && cd ${SHADOW_BUILD_DIR}
- qmake -r ${TRAVIS_BUILD_DIR}/qgroundcontrol.pro CONFIG+=${CONFIG} CONFIG+=WarningsAsErrorsOn -spec ${SPEC}
# Due to possible bug in Qt 5.11 WarningsAsErrorsOn is off for Linux builds. Hopefully back on once that is resolved.
- if [ "${SPEC}" = "macx-clang" ]; then
qmake -r ${TRAVIS_BUILD_DIR}/qgroundcontrol.pro CONFIG+=${CONFIG} CONFIG+=WarningsAsErrorsOn -spec ${SPEC};
else
qmake -r ${TRAVIS_BUILD_DIR}/qgroundcontrol.pro CONFIG+=${CONFIG} -spec ${SPEC};
fi
# compile
- if [ "${SPEC}" != "macx-ios-clang" ]; then

14
.vagrantconfig.yml

@ -1,13 +1,13 @@ @@ -1,13 +1,13 @@
configs:
dev:
'qt_deps_tarball': 'Qt5.9.1-linux-vagrant.tar.bz2'
'qt_deps_tarball': 'Qt5.11.0-gcc_64-min.tar.bz2'
'qt_deps_unpack_parent_dir': '/tmp'
'qt_deps_unpack_dir': '/tmp/Qt5.9-vagrant/5.9.1'
'qt_deps_bin_unpack_dir': '/tmp/Qt5.9-vagrant/5.9.1/gcc_64/bin'
'qt_deps_lib_unpack_dir': '/tmp/Qt5.9-vagrant/5.9.1/gcc_64/lib'
'qt_deps_plugins_unpack_dir': '/tmp/Qt5.9-vagrant/5.9.1/gcc_64/plugins'
'qt_deps_qml_unpack_dir': '/tmp/Qt5.9-vagrant/5.9.1/gcc_64/qml'
'qt_deps_unpack_dir': '/tmp/Qt5.11-gcc_64/5.11.0'
'qt_deps_bin_unpack_dir': '/tmp/Qt5.11-gcc_64/5.11.0/gcc_64/bin'
'qt_deps_lib_unpack_dir': '/tmp/Qt5.11-gcc_64/5.11.0/gcc_64/lib'
'qt_deps_plugins_unpack_dir': '/tmp/Qt5.11-gcc_64/5.11.0/gcc_64/plugins'
'qt_deps_qml_unpack_dir': '/tmp/Qt5.11-gcc_64/5.11.0/gcc_64/qml'
'project_root_dir': '/vagrant'
@ -20,4 +20,4 @@ configs: @@ -20,4 +20,4 @@ configs:
'spec': 'linux-g++-64'
'shadow_build_dir': '/vagrant/shadow-build'
'pro': '/vagrant/qgroundcontrol.pro'
'deps_url': 'https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.9.1-linux-vagrant.tar.bz2'
'deps_url': 'https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.11.0-gcc_64-min.tar.bz2'

1
ISSUE_TEMPLATE.md

@ -4,6 +4,7 @@ This system is for posting bugs or feature requests ONLY. For questions about ho @@ -4,6 +4,7 @@ This system is for posting bugs or feature requests ONLY. For questions about ho
When posting bug reports, include the following informaiton:
- Ground station operating system.
- QGroundControl version and build (daily, stable, self-built from source, etc.)
- **If you are using a Stable build which is not the latest, first step is to install latest Stable build and try again prior to entering a bug report.**
- Autopilot board: Pixhawk I, Pixhawk Mini, Pixhawk 2, etc.
- Autopilot firmware (e.g. PX4, ArduPilot, custom) and version.
- Exact steps to reproduce the problem. Starting from booting QGroundControl to when the problem occurs.

77
Jenkinsfile vendored

@ -1,8 +1,39 @@ @@ -1,8 +1,39 @@
pipeline {
agent any
agent none
stages {
stage('build') {
parallel {
stage('Android Release') {
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'release'
QMAKE_VER = "5.9.2/android_armv7/bin/qmake"
}
agent {
docker {
image 'mavlink/qgc-build-android:2018-04-14'
args '-v ${CCACHE_DIR}:${CCACHE_DIR}:rw'
}
}
steps {
sh 'export'
sh 'ccache -z'
sh 'git submodule deinit -f .'
sh 'git clean -ff -x -d .'
sh 'git submodule update --init --recursive --force'
sh 'mkdir build; cd build; ${QT_PATH}/${QMAKE_VER} -r ${WORKSPACE}/qgroundcontrol.pro CONFIG+=${QGC_CONFIG} CONFIG+=WarningsAsErrorsOn'
sh 'cd build; make -j`nproc --all`'
sh 'ccache -s'
}
post {
cleanup {
sh 'git clean -ff -x -d .'
}
}
}
stage('Linux Debug') {
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
@ -11,7 +42,7 @@ pipeline { @@ -11,7 +42,7 @@ pipeline {
}
agent {
docker {
image 'mavlink/qgc-build-linux'
image 'mavlink/qgc-build-linux:2018-04-14'
args '-v ${CCACHE_DIR}:${CCACHE_DIR}:rw'
}
}
@ -25,7 +56,13 @@ pipeline { @@ -25,7 +56,13 @@ pipeline {
sh 'cd build; make -j`nproc --all`'
sh 'ccache -s'
}
post {
cleanup {
sh 'git clean -ff -x -d .'
}
}
}
stage('Linux Release') {
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
@ -34,7 +71,7 @@ pipeline { @@ -34,7 +71,7 @@ pipeline {
}
agent {
docker {
image 'mavlink/qgc-build-linux'
image 'mavlink/qgc-build-linux:2018-04-14'
args '-v ${CCACHE_DIR}:${CCACHE_DIR}:rw'
}
}
@ -48,7 +85,13 @@ pipeline { @@ -48,7 +85,13 @@ pipeline {
sh 'cd build; make -j`nproc --all`'
sh 'ccache -s'
}
post {
cleanup {
sh 'git clean -ff -x -d .'
}
}
}
stage('OSX Debug') {
agent {
node {
@ -70,7 +113,13 @@ pipeline { @@ -70,7 +113,13 @@ pipeline {
sh 'cd build; make -j`sysctl -n hw.ncpu`'
sh 'ccache -s'
}
post {
cleanup {
sh 'git clean -ff -x -d .'
}
}
}
stage('OSX Release') {
agent {
node {
@ -79,7 +128,7 @@ pipeline { @@ -79,7 +128,7 @@ pipeline {
}
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'release'
QGC_CONFIG = 'installer'
QMAKE_VER = "5.9.3/clang_64/bin/qmake"
}
steps {
@ -92,13 +141,27 @@ pipeline { @@ -92,13 +141,27 @@ pipeline {
sh 'cd build; make -j`sysctl -n hw.ncpu`'
sh 'ccache -s'
}
post {
success {
archiveArtifacts(artifacts: 'build/**/*.dmg', fingerprint: true)
}
cleanup {
sh 'git clean -ff -x -d .'
}
}
}
}
}
}
} // parallel
} // stage('build')
} // stages
environment {
CCACHE_CPP2 = '1'
CCACHE_DIR = '/tmp/ccache'
QT_FATAL_WARNINGS = '1'
}
options {
buildDiscarder(logRotator(numToKeepStr: '10', artifactDaysToKeepStr: '30'))
timeout(time: 60, unit: 'MINUTES')
}
}

8
QGCSetup.pri

@ -68,7 +68,9 @@ WindowsBuild { @@ -68,7 +68,9 @@ WindowsBuild {
ReleaseBuild: DLL_QT_DEBUGCHAR = ""
COPY_FILE_LIST = \
$$BASEDIR\\libs\\lib\\sdl2\\msvc\\lib\\x86\\SDL2.dll \
$$BASEDIR\\deploy\\libeay32.dll
$$BASEDIR\\deploy\\libeay32.dll \
$$BASEDIR_WIN\\deploy\\libssl32.dll \
$$BASEDIR_WIN\\deploy\\ssleay32.dll
for(COPY_FILE, COPY_FILE_LIST) {
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"$$COPY_FILE\" \"$$DESTDIR_WIN\"
@ -107,15 +109,17 @@ LinuxBuild { @@ -107,15 +109,17 @@ LinuxBuild {
# QT_INSTALL_LIBS
QT_LIB_LIST = \
libQt5Charts.so.5 \
libQt5Core.so.5 \
libQt5DBus.so.5 \
libQt5Gui.so.5 \
libQt5Location.so.5 \
libQt5Multimedia.so.5 \
libQt5MultimediaQuick_p.so.5 \
libQt5MultimediaQuick.so.5 \
libQt5Network.so.5 \
libQt5OpenGL.so.5 \
libQt5Positioning.so.5 \
libQt5PositioningQuick.so.5 \
libQt5PrintSupport.so.5 \
libQt5Qml.so.5 \
libQt5Quick.so.5 \

87
README.md

@ -6,83 +6,20 @@ @@ -6,83 +6,20 @@
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mavlink/qgroundcontrol?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Website: <http://qgroundcontrol.com>
## Obtaining source code
*QGroundControl* (QGC) is an intuitive and powerful ground control station (GCS) for UAVs.
Source code for QGroundControl is kept on GitHub: https://github.com/mavlink/qgroundcontrol.
```
git clone --recursive https://github.com/mavlink/qgroundcontrol.git
```
Each time you pull new source to your repository you should run `git submodule update` to get the latest submodules as well. Since QGroundControl uses submodules, using the zip file for source download will not work. You must use git.
The primary goal of QGC is ease of use for both first time and professional users.
It provides full flight control and mission planning for any MAVLink enabled drone, and vehicle setup for both PX4 and ArduPilot powered UAVs. Instructions for *using QGroundControl* are provided in the [User Manual](https://docs.qgroundcontrol.com/en/) (you may not need them because the UI is very intuitive!)
The source code is [dual-licensed under Apache 2.0 and GPLv3](https://github.com/mavlink/qgroundcontrol/blob/master/COPYING.md).
All the code is open-source, so you can contribute and evolve it as you want.
The [Developer Guide](https://dev.qgroundcontrol.com/en/) explains how to [build](https://dev.qgroundcontrol.com/en/getting_started/) and extend QGC.
### User Manual
https://docs.qgroundcontrol.com/en/
### Supported Builds
#### Native Builds
QGroundControl builds are supported for OSX, Linux, Windows, iOS and Android. QGroundControl uses [Qt](http://www.qt.io) as its cross-platform support library and uses [QtCreator](http://doc.qt.io/qtcreator/index.html) as its default build environment.
* OSX: OSX 10.7 or higher, 64 bit, clang compiler (IMPORTANT: XCode 8 requires a workaround described below)
* Ubuntu: 64 bit, gcc compiler
* Windows: Vista or higher, 32 bit, [Visual Studio 2015 compiler](http://www.visualstudio.com/downloads/download-visual-studio-vs#d-express-windows-desktop)
* iOS: 8.0 and higher
* Android: Jelly Bean (4.1) and higher. Standard QGC is built against ndk version 19.
* Qt version: **5.9.3 only**
###### Install QT
You **need to install Qt as described below** instead of using pre-built packages from say, a Linux distribution, because QGroundControl needs access to private Qt headers.
* Download the [Qt installer](http://www.qt.io/download-open-source)
* Make sure to install Qt version **5.9.3**. You will also need to install the Qt Speech package.
* Ubuntu: Set the downloaded file to executable using:`chmod +x`. Install to default location for use with ./qgroundcontrol-start.sh. If you install Qt to a non-default location you will need to modify qgroundcontrol-start.sh in order to run downloaded builds.
* Windows: Make sure to install VS 2015 32 bit package.
###### Install additional packages:
* Ubuntu: sudo apt-get install speech-dispatcher libudev-dev libsdl2-dev
* Fedora: sudo dnf install speech-dispatcher SDL2-devel SDL2 systemd-devel
* Arch Linux: pacman -Sy speech-dispatcher
* Windows: [USB Driver](http://www.pixhawk.org/firmware/downloads) to connect to Pixhawk/PX4Flow/3DR Radio
* Android: [Qt Android Setup](http://doc.qt.io/qt-5/androidgs.html)
###### Building using Qt Creator
* Launch Qt Creator and open the `qgroundcontrol.pro` project.
* Select the appropriate kit for your needs:
* OSX: Desktop Qt 5.9.3 clang 64 bit
* Ubuntu: Desktop Qt 5.9.3 GCC bit
* Windows: Desktop Qt 5.9.3 MSVC2015 32bit
* Android: Android for armeabi-v7a (GCC 4.9, Qt 5.9.3)
* Note: iOS builds must be built using xCode: http://doc.qt.io/qt-5/ios-support.html. Use Qt Creator to generate the XCode project (*Run Qmake* from the context menu).
#### Vagrant
A Vagrantfile is provided to build QGroundControl using the [Vagrant](https://www.vagrantup.com/) system. This will produce a native Linux build which can be run in the Vagrant Virtual Machine or on the host machine if it is compatible.
* [Download](https://www.vagrantup.com/downloads.html) Vagrant
* [Install](https://www.vagrantup.com/docs/getting-started/) Vagrant
* From the root directory of the QGroundControl repository run "vagrant up"
* To use the graphical environment run "vagrant reload"
#### Additional build notes for all supported OS
* Warnings as Errors: Specifying `CONFIG+=WarningsAsErrorsOn` will turn all warnings into errors which breaks the build. If you are working on a pull request you plan to submit to github for consideration, you should always run with this setting turned on, since it is required for all pull requests. NOTE: Putting this line into a file called "user_config.pri" in the top-level directory (same directory as `qgroundcontrol.pro`) will set this flag on all builds without interfering with the GIT history.
* Parallel builds: For non Windows builds, you can use the '-j#' option to run parellel builds.
* Location of built files: Individual build file results can be found in the `build_debug` or `build_release` directories. The built executable can be found in the `debug` or `release` directory.
* If you get this error when running qgroundcontrol: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version 'GLIBCXX_3.4.20' not found. You need to either update to the latest gcc, or install the latest libstdc++.6 using: sudo apt-get install libstdc++6.
## Additional functionality
QGroundControl has functionality that is dependent on the operating system and libraries installed by the user. The following sections describe these features, their dependencies, and how to disable/alter them during the build process. These features can be forcibly enabled/disabled by specifying additional values to qmake.
### Opal-RT's RT-LAB simulator
Integration with Opal-RT's RT-LAB simulator can be enabled on Windows by installing RT-LAB 7.2.4. This allows vehicles to be simulated in RT-LAB and communicate directly with QGC on the same computer as if the UAS was actually deployed. This support is enabled by default once the requisite RT-LAB software is installed. Disabling this can be done by adding `DEFINES+=DISABLE_RTLAB` to qmake.
### XBee support
QGroundControl can talk to XBee wireless devices using their proprietary protocol directly on Windows and Linux platforms. This support is not necessary if you're not using XBee devices or aren't using their proprietary protocol. On Windows, the necessary dependencies are included in this repository and no additional steps are required. For Linux, change to the `libs/thirdParty/libxbee` folder and run `make;sudo make install` to install libxbee on your system (uninstalling can be done with a `sudo make uninstall`). `qmake` will automatically detect the library on Linux, so no other work is necessary.
To disable XBee support you may add `DEFINES+=DISABLE_XBEE` to qmake.
### Video Streaming
Check the [Video Streaming](https://github.com/mavlink/qgroundcontrol/tree/master/src/VideoStreaming) directory for further instructions.
Key Links:
* [Website](http://qgroundcontrol.com) (qgroundcontrol.com)
* [User Manual](https://docs.qgroundcontrol.com/en/)
* [Developer Guide](https://dev.qgroundcontrol.com/en/)
* [Discussion/Support](https://docs.qgroundcontrol.com/en/Support/Support.html)
* [Contributing](https://dev.qgroundcontrol.com/en/contribute/)
* [License](https://github.com/mavlink/qgroundcontrol/blob/master/COPYING.md)

1
Vagrantfile vendored

@ -45,6 +45,7 @@ Vagrant.configure(2) do |config| @@ -45,6 +45,7 @@ Vagrant.configure(2) do |config|
$config_shell = <<-'SHELL'
set -e
set -x
export %{build_env}
export JOBS=$((`cat /proc/cpuinfo | grep -c ^processor`+1))

10
android/AndroidManifest.xml

@ -59,7 +59,15 @@ @@ -59,7 +59,15 @@
<!-- Support devices without USB host mode since there are other connection types -->
<uses-feature android:name="android.hardware.usb.host" android:required="false"/>
<uses-feature android:name="android.hardware.location.GPS" android:required="false" />
<!-- Support devices without Bluetooth since there are other connection types -->
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<!-- Support devices that don't have location services -->
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location.network" android:required="false"/>
<uses-feature android:name="android.hardware.location" android:required="false"/>
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->

9
android/build.gradle

@ -1,6 +1,9 @@ @@ -1,6 +1,9 @@
buildscript {
repositories {
jcenter()
maven {
url "http://repo1.maven.org/maven2"
}
}
dependencies {
@ -51,6 +54,10 @@ android { @@ -51,6 +54,10 @@ android {
}
}
aaptOptions {
cruncherEnabled = false
}
lintOptions {
abortOnError false
}

25
deploy/MakeQtTravisTarball.sh

@ -1,28 +1,23 @@ @@ -1,28 +1,23 @@
#!/bin/bash -x
if [[ $# -eq 0 ]]; then
echo 'MakeQtTravisTarball.sh QtDirectory QtFullVersion QtBaseVersion BuildType'
exit 1
if [ $# -ne 2 ]; then
echo 'MakeQtTravisTarball.sh QtDirectory BuildType'
exit 1
fi
QT_DIRECTORY=$1
if [ ! -d ${QT_DIRECTORY} ]; then
echo 'Specify directory for Qt Directory.'
exit 1
echo 'Specify directory for Qt Directory to copy from.'
exit 1
fi
QT_FULL_VERSION=$2
if [ ! -d ${QT_DIRECTORY}/${QT_FULL_VERSION} ]; then
echo 'Qt version directory not found'
exit 1
fi
QT_BASE_VERSION=$3
QT_FULL_VERSION=5.11.0
QT_BASE_VERSION=5.11
QT_BUILD_TYPE=$4
QT_BUILD_TYPE=$2
if [ ! -d ${QT_DIRECTORY}/${QT_FULL_VERSION}/${QT_BUILD_TYPE} ]; then
echo 'Qt build type directory not found'
exit 1
echo 'Qt build type directory not found. Specify example: clang_64'
exit 1
fi
mkdir -p Qt${QT_BASE_VERSION}-${QT_BUILD_TYPE}/${QT_FULL_VERSION}/${QT_BUILD_TYPE}

BIN
deploy/libeay32.dll

Binary file not shown.

BIN
deploy/libssl32.dll

Binary file not shown.

11
deploy/qgroundcontrol_installer.nsi

@ -73,8 +73,12 @@ doinstall: @@ -73,8 +73,12 @@ doinstall:
File /r /x ${EXENAME}.pdb /x ${EXENAME}.lib /x ${EXENAME}.exp ${DESTDIR}\*.*
File deploy\px4driver.msi
WriteUninstaller $INSTDIR\${EXENAME}-Uninstall.exe
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$\"$INSTDIR\${EXENAME}-Uninstall.exe$\""
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}"
WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$\"$INSTDIR\${EXENAME}-Uninstall.exe$\""
SetRegView 64
WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\${EXENAME}.exe" "DumpCount" 5
WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\${EXENAME}.exe" "DumpType" 2
WriteRegExpandStr HKLM "SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\${EXENAME}.exe" "DumpFolder" "%LOCALAPPDATA%\QGCCrashDumps"
; Only attempt to install the PX4 driver if the version isn't present
!define ROOTKEY "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\434608CF2B6E31F0DDBA5C511053F957B55F098E"
@ -106,7 +110,8 @@ Section "Uninstall" @@ -106,7 +110,8 @@ Section "Uninstall"
RMDir /r /REBOOTOK "$SMPROGRAMS\$StartMenuFolder\"
SetShellVarContext current
RMDir /r /REBOOTOK "$APPDATA\${ORGNAME}\"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\${EXENAME}.exe"
SectionEnd
Section "create Start Menu Shortcuts"

BIN
deploy/ssleay32.dll

Binary file not shown.

2
libs/mavlink/include/mavlink/v2.0

@ -1 +1 @@ @@ -1 +1 @@
Subproject commit 37d14af47d783eb516959cc10e4cf70d66e927c0
Subproject commit 033fa8e7a4a75a0c3f17cea57e3be8966e05f770

1
qgcresources.qrc

@ -174,6 +174,7 @@ @@ -174,6 +174,7 @@
<file alias="subVehicleArrowOpaque.png">src/FlightMap/Images/sub.png</file>
<file alias="AlertAircraft.svg">src/FlightMap/Images/AlertAircraft.svg</file>
<file alias="AwarenessAircraft.svg">src/FlightMap/Images/AwarenessAircraft.svg</file>
<file alias="check.svg">resources/check.svg</file>
</qresource>
<qresource prefix="/res">
<file alias="action.svg">resources/action.svg</file>

19
qgroundcontrol.pro

@ -240,6 +240,7 @@ AndroidBuild || iOSBuild { @@ -240,6 +240,7 @@ AndroidBuild || iOSBuild {
QT += \
printsupport \
serialport \
charts \
}
contains(DEFINES, QGC_ENABLE_BLUETOOTH) {
@ -392,12 +393,14 @@ HEADERS += \ @@ -392,12 +393,14 @@ HEADERS += \
src/api/QGCOptions.h \
src/api/QGCSettings.h \
src/api/QmlComponentInfo.h \
src/comm/HeartbeatTimer.h
SOURCES += \
src/api/QGCCorePlugin.cc \
src/api/QGCOptions.cc \
src/api/QGCSettings.cc \
src/api/QmlComponentInfo.cc \
src/comm/HeartbeatTimer.cc
#
# Unit Test specific configuration goes here (requires full debug build with all plugins)
@ -432,7 +435,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin { @@ -432,7 +435,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/SimpleMissionItemTest.h \
src/MissionManager/SpeedSectionTest.h \
src/MissionManager/StructureScanComplexItemTest.h \
src/MissionManager/SurveyMissionItemTest.h \
src/MissionManager/SurveyComplexItemTest.h \
src/MissionManager/TransectStyleComplexItemTest.h \
src/MissionManager/VisualMissionItemTest.h \
src/qgcunittest/FileDialogTest.h \
@ -473,7 +476,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin { @@ -473,7 +476,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/SimpleMissionItemTest.cc \
src/MissionManager/SpeedSectionTest.cc \
src/MissionManager/StructureScanComplexItemTest.cc \
src/MissionManager/SurveyMissionItemTest.cc \
src/MissionManager/SurveyComplexItemTest.cc \
src/MissionManager/TransectStyleComplexItemTest.cc \
src/MissionManager/VisualMissionItemTest.cc \
src/qgcunittest/FileDialogTest.cc \
@ -512,6 +515,7 @@ HEADERS += \ @@ -512,6 +515,7 @@ HEADERS += \
src/Joystick/Joystick.h \
src/Joystick/JoystickManager.h \
src/JsonHelper.h \
src/KMLFileHelper.h \
src/LogCompressor.h \
src/MG.h \
src/MissionManager/CameraCalc.h \
@ -545,7 +549,7 @@ HEADERS += \ @@ -545,7 +549,7 @@ HEADERS += \
src/MissionManager/Section.h \
src/MissionManager/SpeedSection.h \
src/MissionManager/StructureScanComplexItem.h \
src/MissionManager/SurveyMissionItem.h \
src/MissionManager/SurveyComplexItem.h \
src/MissionManager/TransectStyleComplexItem.h \
src/MissionManager/VisualMissionItem.h \
src/PositionManager/PositionManager.h \
@ -588,6 +592,7 @@ HEADERS += \ @@ -588,6 +592,7 @@ HEADERS += \
src/Settings/UnitsSettings.h \
src/Settings/VideoSettings.h \
src/Terrain/TerrainQuery.h \
src/TerrainTile.h \
src/Vehicle/MAVLinkLogManager.h \
src/VehicleSetup/JoystickConfigController.h \
src/comm/LinkConfiguration.h \
@ -709,6 +714,7 @@ SOURCES += \ @@ -709,6 +714,7 @@ SOURCES += \
src/Joystick/Joystick.cc \
src/Joystick/JoystickManager.cc \
src/JsonHelper.cc \
src/KMLFileHelper.cc \
src/LogCompressor.cc \
src/MissionManager/CameraCalc.cc \
src/MissionManager/CameraSection.cc \
@ -740,7 +746,7 @@ SOURCES += \ @@ -740,7 +746,7 @@ SOURCES += \
src/MissionManager/SimpleMissionItem.cc \
src/MissionManager/SpeedSection.cc \
src/MissionManager/StructureScanComplexItem.cc \
src/MissionManager/SurveyMissionItem.cc \
src/MissionManager/SurveyComplexItem.cc \
src/MissionManager/TransectStyleComplexItem.cc \
src/MissionManager/VisualMissionItem.cc \
src/PositionManager/PositionManager.cpp \
@ -782,6 +788,7 @@ SOURCES += \ @@ -782,6 +788,7 @@ SOURCES += \
src/Settings/UnitsSettings.cc \
src/Settings/VideoSettings.cc \
src/Terrain/TerrainQuery.cc \
src/TerrainTile.cc\
src/Vehicle/MAVLinkLogManager.cc \
src/VehicleSetup/JoystickConfigController.cc \
src/comm/LinkConfiguration.cc \
@ -1057,7 +1064,7 @@ HEADERS += \ @@ -1057,7 +1064,7 @@ HEADERS += \
src/FactSystem/FactGroup.h \
src/FactSystem/FactMetaData.h \
src/FactSystem/FactSystem.h \
src/FactSystem/FactValidator.h \
src/FactSystem/FactValueSliderListModel.h \
src/FactSystem/ParameterManager.h \
src/FactSystem/SettingsFact.h \
@ -1067,7 +1074,7 @@ SOURCES += \ @@ -1067,7 +1074,7 @@ SOURCES += \
src/FactSystem/FactGroup.cc \
src/FactSystem/FactMetaData.cc \
src/FactSystem/FactSystem.cc \
src/FactSystem/FactValidator.cc \
src/FactSystem/FactValueSliderListModel.cc \
src/FactSystem/ParameterManager.cc \
src/FactSystem/SettingsFact.cc \

20
qgroundcontrol.qrc

@ -9,10 +9,11 @@ @@ -9,10 +9,11 @@
<file alias="GPSRTKIndicator.qml">src/ui/toolbar/GPSRTKIndicator.qml</file>
<file alias="MessageIndicator.qml">src/ui/toolbar/MessageIndicator.qml</file>
<file alias="ModeIndicator.qml">src/ui/toolbar/ModeIndicator.qml</file>
<file alias="VTOLModeIndicator.qml">src/ui/toolbar/VTOLModeIndicator.qml</file>
<file alias="VTOLModeIndicator.qml">src/ui/toolbar/VTOLModeIndicator.qml</file>
<file alias="RCRSSIIndicator.qml">src/ui/toolbar/RCRSSIIndicator.qml</file>
<file alias="TelemetryRSSIIndicator.qml">src/ui/toolbar/TelemetryRSSIIndicator.qml</file>
<file alias="JoystickIndicator.qml">src/ui/toolbar/JoystickIndicator.qml</file>
<file alias="LinkIndicator.qml">src/ui/toolbar/LinkIndicator.qml</file>
</qresource>
<qresource prefix="/qml">
<file alias="CorridorScanEditor.qml">src/PlanView/CorridorScanEditor.qml</file>
@ -85,7 +86,11 @@ @@ -85,7 +86,11 @@
<file alias="QGroundControl/Controls/PageView.qml">src/QmlControls/PageView.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/PIDTuning.qml">src/QmlControls/PIDTuning.qml</file>
<file alias="QGroundControl/Controls/PlanToolBar.qml">src/PlanView/PlanToolBar.qml</file>
<file alias="QGroundControl/Controls/PreFlightCheckButton.qml">src/QmlControls/PreFlightCheckButton.qml</file>
<file alias="QGroundControl/Controls/PreFlightCheckGroup.qml">src/QmlControls/PreFlightCheckGroup.qml</file>
<file alias="QGroundControl/Controls/PreFlightCheckList.qml">src/QmlControls/PreFlightCheckList.qml</file>
<file alias="QGroundControl/Controls/QGCButton.qml">src/QmlControls/QGCButton.qml</file>
<file alias="QGroundControl/Controls/QGCCheckBox.qml">src/QmlControls/QGCCheckBox.qml</file>
<file alias="QGroundControl/Controls/QGCColoredImage.qml">src/QmlControls/QGCColoredImage.qml</file>
@ -118,14 +123,14 @@ @@ -118,14 +123,14 @@
<file alias="QGroundControl/Controls/RallyPointMapVisuals.qml">src/PlanView/RallyPointMapVisuals.qml</file>
<file alias="QGroundControl/Controls/RCChannelMonitor.qml">src/QmlControls/RCChannelMonitor.qml</file>
<file alias="QGroundControl/Controls/RoundButton.qml">src/QmlControls/RoundButton.qml</file>
<file alias="QGroundControl/Controls/SectionHeader.qml">src/PlanView/SectionHeader.qml</file>
<file alias="QGroundControl/Controls/SectionHeader.qml">src/QmlControls/SectionHeader.qml</file>
<file alias="QGroundControl/Controls/SetupPage.qml">src/AutoPilotPlugins/Common/SetupPage.qml</file>
<file alias="QGroundControl/Controls/SignalStrength.qml">src/ui/toolbar/SignalStrength.qml</file>
<file alias="QGroundControl/Controls/SimpleItemMapVisual.qml">src/PlanView/SimpleItemMapVisual.qml</file>
<file alias="QGroundControl/Controls/SliderSwitch.qml">src/QmlControls/SliderSwitch.qml</file>
<file alias="QGroundControl/Controls/SubMenuButton.qml">src/QmlControls/SubMenuButton.qml</file>
<file alias="QGroundControl/Controls/SurveyMapVisual.qml">src/PlanView/SurveyMapVisual.qml</file>
<file alias="QGroundControl/Controls/TransectStyleComplexItemStats.qml">src/PlanView/TransectStyleComplexItemStats.qml</file>
<file alias="QGroundControl/Controls/TransectStyleComplexItemStats.qml">src/PlanView/TransectStyleComplexItemStats.qml</file>
<file alias="QGroundControl/Controls/ToolStrip.qml">src/QmlControls/ToolStrip.qml</file>
<file alias="QGroundControl/Controls/VehicleRotationCal.qml">src/QmlControls/VehicleRotationCal.qml</file>
<file alias="QGroundControl/Controls/VehicleSummaryRow.qml">src/QmlControls/VehicleSummaryRow.qml</file>
@ -138,6 +143,7 @@ @@ -138,6 +143,7 @@
<file alias="QGroundControl/FactControls/FactTextField.qml">src/FactSystem/FactControls/FactTextField.qml</file>
<file alias="QGroundControl/FactControls/FactTextFieldGrid.qml">src/FactSystem/FactControls/FactTextFieldGrid.qml</file>
<file alias="QGroundControl/FactControls/FactTextFieldRow.qml">src/FactSystem/FactControls/FactTextFieldRow.qml</file>
<file alias="QGroundControl/FactControls/FactValueSlider.qml">src/FactSystem/FactControls/FactValueSlider.qml</file>
<file alias="QGroundControl/FactControls/qmldir">src/FactSystem/FactControls/qmldir</file>
<file alias="QGroundControl/FlightDisplay/FlightDisplayView.qml">src/FlightDisplay/FlightDisplayView.qml</file>
<file alias="QGroundControl/FlightDisplay/FlightDisplayViewMap.qml">src/FlightDisplay/FlightDisplayViewMap.qml</file>
@ -148,6 +154,12 @@ @@ -148,6 +154,12 @@
<file alias="QGroundControl/FlightDisplay/GuidedActionsController.qml">src/FlightDisplay/GuidedActionsController.qml</file>
<file alias="QGroundControl/FlightDisplay/GuidedAltitudeSlider.qml">src/FlightDisplay/GuidedAltitudeSlider.qml</file>
<file alias="QGroundControl/FlightDisplay/MultiVehicleList.qml">src/FlightDisplay/MultiVehicleList.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightAHRSCheck.qml">src/FlightDisplay/PreFlightAHRSCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightBatteryCheck.qml">src/FlightDisplay/PreFlightBatteryCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightCheckModel.qml">src/FlightDisplay/PreFlightCheckModel.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightRCCheck.qml">src/FlightDisplay/PreFlightRCCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightSensorsCheck.qml">src/FlightDisplay/PreFlightSensorsCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/PreFlightSoundCheck.qml">src/FlightDisplay/PreFlightSoundCheck.qml</file>
<file alias="QGroundControl/FlightDisplay/qmldir">src/FlightDisplay/qmldir</file>
<file alias="QGroundControl/FlightMap/CameraTriggerIndicator.qml">src/FlightMap/MapItems/CameraTriggerIndicator.qml</file>
<file alias="QGroundControl/FlightMap/CenterMapDropButton.qml">src/FlightMap/Widgets/CenterMapDropButton.qml</file>
@ -222,8 +234,10 @@ @@ -222,8 +234,10 @@
<file alias="USBBoardInfo.json">src/comm/USBBoardInfo.json</file>
<file alias="Vehicle/BatteryFact.json">src/Vehicle/BatteryFact.json</file>
<file alias="Vehicle/ClockFact.json">src/Vehicle/ClockFact.json</file>
<file alias="Vehicle/DistanceSensorFact.json">src/Vehicle/DistanceSensorFact.json</file>
<file alias="Vehicle/GPSFact.json">src/Vehicle/GPSFact.json</file>
<file alias="Vehicle/GPSRTKFact.json">src/Vehicle/GPSRTKFact.json</file>
<file alias="Vehicle/SetpointFact.json">src/Vehicle/SetpointFact.json</file>
<file alias="Vehicle/SubmarineFact.json">src/Vehicle/SubmarineFact.json</file>
<file alias="Vehicle/TemperatureFact.json">src/Vehicle/TemperatureFact.json</file>
<file alias="Vehicle/VehicleFact.json">src/Vehicle/VehicleFact.json</file>

BIN
resources/calibration/mode1/radioRollLeft.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

BIN
resources/calibration/mode1/radioRollRight.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 18 KiB

80
resources/check.svg

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 72 72"
style="enable-background:new 0 0 72 72;"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="check.svg"><metadata
id="metadata3416"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs3414"><linearGradient
id="linearGradient4141"
osb:paint="solid"><stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4143" /></linearGradient><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4141"
id="linearGradient4145"
x1="48.508473"
y1="58.423729"
x2="79.322032"
y2="58.423729"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.8414091,0,0,2.2407508,-82.18242,-94.289127)" /></defs><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1855"
inkscape:window-height="1056"
id="namedview3412"
showgrid="false"
inkscape:zoom="3.2777778"
inkscape:cx="-54.305085"
inkscape:cy="36"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><style
type="text/css"
id="style3406">
.st0{fill:#66BD59;stroke:#FFFFFF;stroke-width:5;stroke-miterlimit:10;}
.st1{fill:none;stroke:#FFFFFF;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
</style><polyline
class="st1"
points="55.1,19.8 30.2,52.2 16.9,36.5 "
id="polyline3410"
transform="matrix(0.85559226,0,0,0.85559226,5.1269823,8.2041673)"
style="fill:none;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10" /><style
id="style3419"
type="text/css">
.st0{fill:none;stroke:#FFFFFF;stroke-width:3;stroke-miterlimit:10;}
.st1{fill:none;stroke:#FFFFFF;stroke-width:8;stroke-miterlimit:10;}
.st2{fill:#FFFFFF;}
</style><circle
style="fill:none;stroke:url(#linearGradient4145);stroke-width:3.25963402;stroke-miterlimit:4;stroke-dasharray:none"
id="path3339"
cx="35.5117"
cy="36.62389"
r="28.370182" /></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

2
src/Airmap/AirspaceControl.qml

@ -288,7 +288,7 @@ Item { @@ -288,7 +288,7 @@ Item {
height: width
radius: 2
color: _colorGray
anchors.verticalCenter: parent.verticalCenter
Layout.alignment: Qt.AlignVCenter
QGCColoredImage {
id: pencilIcon
width: height

38
src/AnalyzeView/GeoTagController.cc

@ -70,8 +70,7 @@ void GeoTagController::startTagging(void) @@ -70,8 +70,7 @@ void GeoTagController::startTagging(void)
QDir imageDirectory = QDir(_worker.imageDirectory());
if(!imageDirectory.exists()) {
_errorMessage = tr("Cannot find the image directory");
emit errorMessageChanged(_errorMessage);
_setErrorMessage(tr("Cannot find the image directory"));
return;
}
if(_worker.saveDirectory() == "") {
@ -83,23 +82,20 @@ void GeoTagController::startTagging(void) @@ -83,23 +82,20 @@ void GeoTagController::startTagging(void)
msgBox.setWindowModality(Qt::ApplicationModal);
msgBox.addButton(tr("Replace"), QMessageBox::ActionRole);
if (msgBox.exec() == QMessageBox::Cancel) {
_errorMessage = tr("Images have already been tagged");
emit errorMessageChanged(_errorMessage);
_setErrorMessage(tr("Images have already been tagged"));
return;
}
QDir oldTaggedFolder = QDir(_worker.imageDirectory() + "/TAGGED");
oldTaggedFolder.removeRecursively();
if(!imageDirectory.mkdir(_worker.imageDirectory() + "/TAGGED")) {
_errorMessage = tr("Couldn't replace the previously tagged images");
emit errorMessageChanged(_errorMessage);
_setErrorMessage(tr("Couldn't replace the previously tagged images"));
return;
}
}
} else {
QDir saveDirectory = QDir(_worker.saveDirectory());
if(!saveDirectory.exists()) {
_errorMessage = tr("Cannot find the save directory");
emit errorMessageChanged(_errorMessage);
_setErrorMessage(tr("Cannot find the save directory"));
return;
}
saveDirectory.setFilter(QDir::Files | QDir::Readable | QDir::NoSymLinks | QDir::Writable);
@ -115,15 +111,13 @@ void GeoTagController::startTagging(void) @@ -115,15 +111,13 @@ void GeoTagController::startTagging(void)
msgBox.setWindowModality(Qt::ApplicationModal);
msgBox.addButton(tr("Replace"), QMessageBox::ActionRole);
if (msgBox.exec() == QMessageBox::Cancel) {
_errorMessage = tr("Save folder not empty");
emit errorMessageChanged(_errorMessage);
_setErrorMessage(tr("Save folder not empty"));
return;
}
foreach(QString dirFile, imageList)
{
if(!saveDirectory.remove(dirFile)) {
_errorMessage = tr("Couldn't replace the existing images");
emit errorMessageChanged(_errorMessage);
_setErrorMessage(tr("Couldn't replace the existing images"));
return;
}
}
@ -144,6 +138,13 @@ void GeoTagController::_workerError(QString errorMessage) @@ -144,6 +138,13 @@ void GeoTagController::_workerError(QString errorMessage)
emit errorMessageChanged(errorMessage);
}
void GeoTagController::_setErrorMessage(const QString& error)
{
_errorMessage = error;
emit errorMessageChanged(error);
}
GeoTagWorker::GeoTagWorker(void)
: _cancel(false)
, _logFile("")
@ -210,9 +211,10 @@ void GeoTagWorker::run(void) @@ -210,9 +211,10 @@ void GeoTagWorker::run(void)
// Instantiate appropriate parser
_triggerList.clear();
bool parseComplete = false;
if(isULog) {
QString errorString;
if (isULog) {
ULogParser parser;
parseComplete = parser.getTagsFromLog(log, _triggerList);
parseComplete = parser.getTagsFromLog(log, _triggerList, errorString);
} else {
PX4LogParser parser;
@ -227,7 +229,8 @@ void GeoTagWorker::run(void) @@ -227,7 +229,8 @@ void GeoTagWorker::run(void)
return;
} else {
qCDebug(GeotaggingLog) << "Log parsing failed";
emit error(tr("Log parsing failed - tagging cancelled"));
errorString = tr("%1 - tagging cancelled").arg(errorString.isEmpty() ? tr("Log parsing failed") : errorString);
emit error(errorString);
return;
}
}
@ -259,6 +262,11 @@ void GeoTagWorker::run(void) @@ -259,6 +262,11 @@ void GeoTagWorker::run(void)
int maxIndex = std::min(_imageIndices.count(), _triggerIndices.count());
maxIndex = std::min(maxIndex, _imageList.count());
for(int i = 0; i < maxIndex; i++) {
int imageIndex = _imageIndices[i];
if (imageIndex >= _imageList.count()) {
emit error(tr("Geotagging failed. Image requested not present."));
return;
}
QFile fileRead(_imageList.at(_imageIndices[i]).absoluteFilePath());
if (!fileRead.open(QIODevice::ReadOnly)) {
emit error(tr("Geotagging failed. Couldn't open an image."));

5
src/AnalyzeView/GeoTagController.h

@ -117,8 +117,9 @@ signals: @@ -117,8 +117,9 @@ signals:
void errorMessageChanged (QString errorMessage);
private slots:
void _workerProgressChanged(double progress);
void _workerError(QString errorMsg);
void _workerProgressChanged (double progress);
void _workerError (QString errorMsg);
void _setErrorMessage (const QString& error);
private:
QString _errorMessage;

5
src/AnalyzeView/GeoTagPage.qml

@ -124,8 +124,9 @@ AnalyzePage { @@ -124,8 +124,9 @@ AnalyzePage {
}
QGCButton {
text: geoController.inProgress ? qsTr("Cancel Tagging") : qsTr("Start Tagging")
width: ScreenTools.defaultFontPixelWidth * 30
text: geoController.inProgress ? qsTr("Cancel Tagging") : qsTr("Start Tagging")
width: ScreenTools.defaultFontPixelWidth * 30
onClicked: {
if (geoController.inProgress) {
geoController.cancelTagging()

2
src/AnalyzeView/LogDownloadController.cc

@ -321,7 +321,7 @@ LogDownloadController::_logData(UASInterface* uas, uint32_t ofs, uint16_t id, ui @@ -321,7 +321,7 @@ LogDownloadController::_logData(UASInterface* uas, uint32_t ofs, uint16_t id, ui
if(ofs <= _downloadData->entry->size()) {
const uint32_t chunk = ofs / kChunkSize;
if (chunk != _downloadData->current_chunk) {
qWarning() << "Ignored packet for out of order chunk" << chunk;
qWarning() << "Ignored packet for out of order chunk actual:expected" << chunk << _downloadData->current_chunk;
return;
}
const uint16_t bin = (ofs - chunk*kChunkSize) / MAVLINK_MSG_LOG_DATA_FIELD_DATA_LEN;

7
src/AnalyzeView/LogDownloadPage.qml

@ -51,8 +51,7 @@ AnalyzePage { @@ -51,8 +51,7 @@ AnalyzePage {
TableView {
id: tableView
anchors.top: parent.top
anchors.bottom: parent.bottom
Layout.fillHeight: true
model: logController.model
selectionMode: SelectionMode.MultiSelection
Layout.fillWidth: true
@ -155,7 +154,7 @@ AnalyzePage { @@ -155,7 +154,7 @@ AnalyzePage {
fileDialog.qgcView = logDownloadPage
fileDialog.title = qsTr("Select save directory")
fileDialog.selectExisting = true
fileDialog.folder = QGroundControl.settingsManager.appSettings.telemetrySavePath
fileDialog.folder = QGroundControl.settingsManager.appSettings.logSavePath
fileDialog.selectFolder = true
fileDialog.openForLoad()
}
@ -186,7 +185,7 @@ AnalyzePage { @@ -186,7 +185,7 @@ AnalyzePage {
message: qsTr("All log files will be erased permanently. Is this really what you want?")
function accept() {
logDownloadPage.hideDialog()
hideDialog()
logController.eraseAll()
}
}

53
src/AnalyzeView/MavlinkConsoleController.cc

@ -33,12 +33,25 @@ MavlinkConsoleController::~MavlinkConsoleController() @@ -33,12 +33,25 @@ MavlinkConsoleController::~MavlinkConsoleController()
void
MavlinkConsoleController::sendCommand(QString command)
{
_history.append(command);
command.append("\n");
_sendSerialData(qPrintable(command));
_cursor_home_pos = -1;
_cursor = rowCount();
}
QString
MavlinkConsoleController::historyUp(const QString& current)
{
return _history.up(current);
}
QString
MavlinkConsoleController::historyDown(const QString& current)
{
return _history.down(current);
}
void
MavlinkConsoleController::_setActiveVehicle(Vehicle* vehicle)
{
@ -192,3 +205,43 @@ MavlinkConsoleController::writeLine(int line, const QByteArray &text) @@ -192,3 +205,43 @@ MavlinkConsoleController::writeLine(int line, const QByteArray &text)
auto idx = index(line);
setData(idx, data(idx, Qt::DisplayRole).toString() + text);
}
void MavlinkConsoleController::CommandHistory::append(const QString& command)
{
if (command.length() > 0) {
// do not append duplicates
if (_history.length() == 0 || _history.last() != command) {
if (_history.length() >= maxHistoryLength) {
_history.removeFirst();
}
_history.append(command);
}
}
_index = _history.length();
}
QString MavlinkConsoleController::CommandHistory::up(const QString& current)
{
if (_index <= 0)
return current;
--_index;
if (_index < _history.length()) {
return _history[_index];
}
return "";
}
QString MavlinkConsoleController::CommandHistory::down(const QString& current)
{
if (_index >= _history.length())
return current;
++_index;
if (_index < _history.length()) {
return _history[_index];
}
return "";
}

22
src/AnalyzeView/MavlinkConsoleController.h

@ -27,13 +27,12 @@ class MavlinkConsoleController : public QStringListModel @@ -27,13 +27,12 @@ class MavlinkConsoleController : public QStringListModel
public:
MavlinkConsoleController();
~MavlinkConsoleController();
virtual ~MavlinkConsoleController();
public slots:
void sendCommand(QString command);
Q_INVOKABLE void sendCommand(QString command);
signals:
void cursorChanged(int);
Q_INVOKABLE QString historyUp(const QString& current);
Q_INVOKABLE QString historyDown(const QString& current);
private slots:
void _setActiveVehicle (Vehicle* vehicle);
@ -44,10 +43,23 @@ private: @@ -44,10 +43,23 @@ private:
void _sendSerialData(QByteArray, bool close = false);
void writeLine(int line, const QByteArray &text);
class CommandHistory
{
public:
void append(const QString& command);
QString up(const QString& current);
QString down(const QString& current);
private:
static constexpr int maxHistoryLength = 100;
QList<QString> _history;
int _index = 0;
};
int _cursor_home_pos;
int _cursor;
QByteArray _incoming_buffer;
Vehicle* _vehicle;
QList<QMetaObject::Connection> _uas_connections;
CommandHistory _history;
};

25
src/AnalyzeView/MavlinkConsolePage.qml

@ -26,7 +26,7 @@ AnalyzePage { @@ -26,7 +26,7 @@ AnalyzePage {
pageName: qsTr("Mavlink Console")
pageDescription: qsTr("Mavlink Console provides a connection to the vehicle's system shell.")
property bool loaded: false
property bool isLoaded: false
Component {
id: pageComponent
@ -41,7 +41,7 @@ AnalyzePage { @@ -41,7 +41,7 @@ AnalyzePage {
onDataChanged: {
// Keep the view in sync if the button is checked
if (loaded) {
if (isLoaded) {
if (followTail.checked) {
listview.positionViewAtEnd();
}
@ -53,7 +53,7 @@ AnalyzePage { @@ -53,7 +53,7 @@ AnalyzePage {
id: delegateItem
Rectangle {
color: qgcPal.windowShade
height: Math.round(ScreenTools.defaultFontPixelHeight * 0.5 + field.height)
height: Math.round(ScreenTools.defaultFontPixelHeight * 0.1 + field.height)
width: listview.width
QGCLabel {
@ -69,11 +69,10 @@ AnalyzePage { @@ -69,11 +69,10 @@ AnalyzePage {
QGCListView {
Component.onCompleted: {
loaded = true
isLoaded = true
}
Layout.fillHeight: true
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
clip: true
id: listview
model: conController
@ -86,8 +85,7 @@ AnalyzePage { @@ -86,8 +85,7 @@ AnalyzePage {
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
Layout.fillWidth: true
QGCTextField {
id: command
Layout.fillWidth: true
@ -96,6 +94,15 @@ AnalyzePage { @@ -96,6 +94,15 @@ AnalyzePage {
conController.sendCommand(text)
text = ""
}
Keys.onPressed: {
if (event.key == Qt.Key_Up) {
text = conController.historyUp(text);
event.accepted = true;
} else if (event.key == Qt.Key_Down) {
text = conController.historyDown(text);
event.accepted = true;
}
}
}
QGCButton {
@ -105,7 +112,7 @@ AnalyzePage { @@ -105,7 +112,7 @@ AnalyzePage {
checked: true
onCheckedChanged: {
if (checked && loaded) {
if (checked && isLoaded) {
listview.positionViewAtEnd();
}
}

18
src/AnalyzeView/ULogParser.cc

@ -86,11 +86,13 @@ bool ULogParser::parseFieldFormat(QString& fields) @@ -86,11 +86,13 @@ bool ULogParser::parseFieldFormat(QString& fields)
return false;
}
bool ULogParser::getTagsFromLog(QByteArray& log, QList<GeoTagWorker::cameraFeedbackPacket>& cameraFeedback)
bool ULogParser::getTagsFromLog(QByteArray& log, QList<GeoTagWorker::cameraFeedbackPacket>& cameraFeedback, QString& errorMessage)
{
errorMessage.clear();
//verify it's an ULog file
if(!log.contains(_ULogMagic)) {
qWarning() << "Could not detect ULog file header magic";
errorMessage = tr("Could not detect ULog file header magic");
return false;
}
@ -139,15 +141,10 @@ bool ULogParser::getTagsFromLog(QByteArray& log, QList<GeoTagWorker::cameraFeedb @@ -139,15 +141,10 @@ bool ULogParser::getTagsFromLog(QByteArray& log, QList<GeoTagWorker::cameraFeedb
case (int)ULogMessageType::DATA:
{
if (!geotagFound) {
qWarning() << "Could not detect geotag packets in ULog";
return false;
}
uint16_t msgID = -1;
memcpy(&msgID, log.data() + index + ULOG_MSG_HEADER_LEN, 2);
if(msgID == _cameraCaptureMsgID) {
if (geotagFound && msgID == _cameraCaptureMsgID) {
// Completely dynamic parsing, so that changing/reordering the message format will not break the parser
GeoTagWorker::cameraFeedbackPacket feedback;
@ -179,5 +176,10 @@ bool ULogParser::getTagsFromLog(QByteArray& log, QList<GeoTagWorker::cameraFeedb @@ -179,5 +176,10 @@ bool ULogParser::getTagsFromLog(QByteArray& log, QList<GeoTagWorker::cameraFeedb
}
if (cameraFeedback.count() == 0) {
errorMessage = tr("Could not detect camera_capture packets in ULog");
return false;
}
return true;
}

7
src/AnalyzeView/ULogParser.h

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
#include <QGeoCoordinate>
#include <QDebug>
#include <QCoreApplication>
#include "GeoTagController.h"
@ -10,10 +11,14 @@ @@ -10,10 +11,14 @@
class ULogParser
{
Q_DECLARE_TR_FUNCTIONS(ULogParser)
public:
ULogParser();
~ULogParser();
bool getTagsFromLog(QByteArray& log, QList<GeoTagWorker::cameraFeedbackPacket>& cameraFeedback);
/// @return true: failed, errorMessage set
bool getTagsFromLog(QByteArray& log, QList<GeoTagWorker::cameraFeedbackPacket>& cameraFeedback, QString& errorMessage);
private:

19
src/Audio/AudioOutput.cc

@ -73,6 +73,7 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) { @@ -73,6 +73,7 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) {
QString match;
QString newNumber;
QString result = string;
//-- Look for codified terms
if(result.contains("ERR ", Qt::CaseInsensitive)) {
result.replace("ERR ", "error ", Qt::CaseInsensitive);
@ -118,6 +119,9 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) { @@ -118,6 +119,9 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) {
if(result.contains(" ADSB ", Qt::CaseInsensitive)) {
result.replace(" ADSB ", " Hey Dee Ess Bee ", Qt::CaseInsensitive);
}
if(result.contains(" EKF ", Qt::CaseInsensitive)) {
result.replace(" EKF ", " Eee Kay Eff ", Qt::CaseInsensitive);
}
// Convert negative numbers
QRegularExpression re(QStringLiteral("(-)[0-9]*\\.?[0-9]"));
@ -125,9 +129,18 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) { @@ -125,9 +129,18 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) {
while (reMatch.hasMatch()) {
if (!reMatch.captured(1).isNull()) {
// There is a negative prefix
qDebug() << "negative" << reMatch.captured(1) << reMatch.capturedStart(1) << reMatch.capturedEnd(1);
result.replace(reMatch.capturedStart(1), reMatch.capturedEnd(1) - reMatch.capturedStart(1), tr(" negative "));
qDebug() << result;
}
reMatch = re.match(result);
}
// Convert real number with decimal point
re.setPattern(QStringLiteral("([0-9]+)(\\.)([0-9]+)"));
reMatch = re.match(result);
while (reMatch.hasMatch()) {
if (!reMatch.captured(2).isNull()) {
// There is a decimal point
result.replace(reMatch.capturedStart(2), reMatch.capturedEnd(2) - reMatch.capturedStart(2), tr(" point "));
}
reMatch = re.match(result);
}
@ -138,9 +151,7 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) { @@ -138,9 +151,7 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) {
while (reMatch.hasMatch()) {
if (!reMatch.captured(1).isNull()) {
// There is a meter postfix
qDebug() << "meters" << reMatch.captured(1) << reMatch.capturedStart(1) << reMatch.capturedEnd(1);
result.replace(reMatch.capturedStart(1), reMatch.capturedEnd(1) - reMatch.capturedStart(1), tr(" meters"));
qDebug() << result;
}
reMatch = re.match(result);
}

2
src/Audio/AudioOutputTest.cc

@ -18,7 +18,7 @@ AudioOutputTest::AudioOutputTest(void) @@ -18,7 +18,7 @@ AudioOutputTest::AudioOutputTest(void)
void AudioOutputTest::_testSpokenReplacements(void)
{
QString result = AudioOutput::fixTextMessageForAudio(QStringLiteral("-10.5m, -10.5m. -10.5 m"));
QCOMPARE(result, QStringLiteral(" negative 10.5 meters, negative 10.5 meters. negative 10.5 meters"));
QCOMPARE(result, QStringLiteral(" negative 10 point 5 meters, negative 10 point 5 meters. negative 10 point 5 meters"));
result = AudioOutput::fixTextMessageForAudio(QStringLiteral("-10m -10 m"));
QCOMPARE(result, QStringLiteral(" negative 10 meters negative 10 meters"));
result = AudioOutput::fixTextMessageForAudio(QStringLiteral("foo -10m -10 m bar"));

7
src/AutoPilotPlugins/APM/APMAirframeComponent.qml

@ -83,10 +83,9 @@ SetupPage { @@ -83,10 +83,9 @@ SetupPage {
id: newFramePageComponent
Grid {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margins
columns: 2
width: availableWidth
spacing: _margins
columns: 2
QGCLabel {
text: qsTr("Frame Class:")

30
src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml

@ -18,36 +18,36 @@ FactPanel { @@ -18,36 +18,36 @@ FactPanel {
factPanel: panel
}
property bool _useOldFrameParam: controller.parameterExists(-1, "FRAME")
property Fact _oldFrameParam: controller.getParameterFact(-1, "FRAME", false)
property Fact _newFrameParam: controller.getParameterFact(-1, "FRAME_CLASS", false)
property Fact _frameTypeParam: controller.getParameterFact(-1, "FRAME_TYPE", false)
property bool _frameAvailable: controller.parameterExists(-1, "FRAME")
property Fact _frame: controller.getParameterFact(-1, "FRAME", false)
property Fact _frameClass: controller.getParameterFact(-1, "FRAME_CLASS", false)
property Fact _frameType: controller.getParameterFact(-1, "FRAME_TYPE", false)
Column {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Frame Type:")
valueText: controller.currentAirframeTypeName() + " " + _oldFrameParam.enumStringValue
visible: _useOldFrameParam
labelText: qsTr("Frame Type")
valueText: visible ? controller.currentAirframeTypeName() + " " + _frame.enumStringValue : ""
visible: _frameAvailable
}
VehicleSummaryRow {
labelText: qsTr("Frame Class:")
valueText: _newFrameParam.enumStringValue
visible: !_useOldFrameParam
labelText: qsTr("Frame Class")
valueText: visible ? _frameClass.enumStringValue : ""
visible: !_frameAvailable
}
VehicleSummaryRow {
labelText: qsTr("Frame Type:")
valueText: _frameTypeParam.enumStringValue
visible: !_useOldFrameParam
labelText: qsTr("Frame Type")
valueText: visible ? _frameType.enumStringValue : ""
visible: !_frameAvailable
}
VehicleSummaryRow {
labelText: qsTr("Firmware Version:")
labelText: qsTr("Firmware Version")
valueText: activeVehicle.firmwareMajorVersion == -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + activeVehicle.firmwareVersionTypeString
}
}

32
src/AutoPilotPlugins/APM/APMCameraComponent.qml

@ -170,17 +170,29 @@ SetupPage { @@ -170,17 +170,29 @@ SetupPage {
ListModel {
id: gimbalOutModel
// It appears that QGCComboBox can't handle models that don't have a initial item
// after onModelChanged
ListElement { text: qsTr("Disabled"); value: 0 }
ListElement { text: qsTr("Channel 5"); value: 5 }
ListElement { text: qsTr("Channel 6"); value: 6 }
ListElement { text: qsTr("Channel 7"); value: 7 }
ListElement { text: qsTr("Channel 8"); value: 8 }
ListElement { text: qsTr("Channel 9"); value: 9 }
ListElement { text: qsTr("Channel 10"); value: 10 }
ListElement { text: qsTr("Channel 11"); value: 11 }
ListElement { text: qsTr("Channel 12"); value: 12 }
ListElement { text: qsTr("Channel 13"); value: 13 }
ListElement { text: qsTr("Channel 14"); value: 14 }
function update(number) {
// Not enough channels
if(number < 6) {
return
}
for(var i = 5; i <= number; i++) {
var text = qsTr("Channel ") + i
append({"text": text, "value": i})
}
}
Component.onCompleted: {
// Number of main outputs
var baseValue = 8
// Extra outputs
// http://ardupilot.org/copter/docs/parameters.html#brd-pwm-count-auxiliary-pin-config
var brd_pwm_count_value = controller.getParameterFact(-1, "BRD_PWM_COUNT").value
update(8 + (brd_pwm_count_value == 7 ? 3 : brd_pwm_count_value))
}
}
Component {

8
src/AutoPilotPlugins/APM/APMCameraComponentSummary.qml

@ -27,22 +27,22 @@ FactPanel { @@ -27,22 +27,22 @@ FactPanel {
VehicleSummaryRow {
visible: _mountTypeExists
labelText: qsTr("Gimbal type:")
labelText: qsTr("Gimbal type")
valueText: _mountTypeValue
}
VehicleSummaryRow {
labelText: qsTr("Tilt input channel:")
labelText: qsTr("Tilt input channel")
valueText: _mountRCInTilt.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Pan input channel:")
labelText: qsTr("Pan input channel")
valueText: _mountRCInPan.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Roll input channel:")
labelText: qsTr("Roll input channel")
valueText: _mountRCInRoll.enumStringValue
}
}

2
src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc

@ -68,7 +68,7 @@ void APMFlightModesComponentController::_rcChannelsChanged(int channelCount, int @@ -68,7 +68,7 @@ void APMFlightModesComponentController::_rcChannelsChanged(int channelCount, int
for (int i=0; i<6; i++) {
_rgChannelOptionEnabled[i] = QVariant(false);
channelValue = pwmValues[i+6];
if (channelValue != -1 && channelValue > 1800) {
if (channelValue > 1800) {
_rgChannelOptionEnabled[i] = QVariant(true);
}
}

12
src/AutoPilotPlugins/APM/APMFlightModesComponentSummary.qml

@ -27,32 +27,32 @@ FactPanel { @@ -27,32 +27,32 @@ FactPanel {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Flight Mode 1:")
labelText: qsTr("Flight Mode 1")
valueText: flightMode1.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Flight Mode 2:")
labelText: qsTr("Flight Mode 2")
valueText: flightMode2.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Flight Mode 3:")
labelText: qsTr("Flight Mode 3")
valueText: flightMode3.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Flight Mode 4:")
labelText: qsTr("Flight Mode 4")
valueText: flightMode4.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Flight Mode 5:")
labelText: qsTr("Flight Mode 5")
valueText: flightMode5.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Flight Mode 6:")
labelText: qsTr("Flight Mode 6")
valueText: flightMode6.enumStringValue
}
}

32
src/AutoPilotPlugins/APM/APMLightsComponent.qml

@ -132,17 +132,29 @@ SetupPage { @@ -132,17 +132,29 @@ SetupPage {
ListModel {
id: lightsOutModel
// It appears that QGCComboBox can't handle models that don't have a initial item
// after onModelChanged
ListElement { text: qsTr("Disabled"); value: 0 }
ListElement { text: qsTr("Channel 5"); value: 5 }
ListElement { text: qsTr("Channel 6"); value: 6 }
ListElement { text: qsTr("Channel 7"); value: 7 }
ListElement { text: qsTr("Channel 8"); value: 8 }
ListElement { text: qsTr("Channel 9"); value: 9 }
ListElement { text: qsTr("Channel 10"); value: 10 }
ListElement { text: qsTr("Channel 11"); value: 11 }
ListElement { text: qsTr("Channel 12"); value: 12 }
ListElement { text: qsTr("Channel 13"); value: 13 }
ListElement { text: qsTr("Channel 14"); value: 14 }
function update(number) {
// Not enough channels
if(number < 6) {
return
}
for(var i = 5; i <= number; i++) {
var text = qsTr("Channel ") + i
append({"text": text, "value": i})
}
}
Component.onCompleted: {
// Number of main outputs
var baseValue = 8
// Extra outputs
// http://ardupilot.org/copter/docs/parameters.html#brd-pwm-count-auxiliary-pin-config
var brd_pwm_count_value = controller.getParameterFact(-1, "BRD_PWM_COUNT").value
update(8 + (brd_pwm_count_value == 7 ? 3 : brd_pwm_count_value))
}
}
Component {

4
src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml

@ -89,12 +89,12 @@ FactPanel { @@ -89,12 +89,12 @@ FactPanel {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Lights Output 1:")
labelText: qsTr("Lights Output 1")
valueText: lightsOutModel.get(lightsLoader.lights1OutIndex).text
}
VehicleSummaryRow {
labelText: qsTr("Lights Output 2:")
labelText: qsTr("Lights Output 2")
valueText: lightsOutModel.get(lightsLoader.lights2OutIndex).text
}
}

21
src/AutoPilotPlugins/APM/APMPowerComponent.h

@ -20,18 +20,19 @@ class APMPowerComponent : public VehicleComponent @@ -20,18 +20,19 @@ class APMPowerComponent : public VehicleComponent
public:
APMPowerComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent = NULL);
// Virtuals from VehicleComponent
QStringList setupCompleteChangedTriggerList(void) const final;
// Overrides from VehicleComponent
QStringList setupCompleteChangedTriggerList(void) const override;
// Virtuals from VehicleComponent
QString name (void) const final;
QString description (void) const final;
QString iconResource (void) const final;
bool requiresSetup (void) const final;
bool setupComplete (void) const final;
QUrl setupSource (void) const final;
QUrl summaryQmlSource (void) const final;
QString name (void) const override;
QString description (void) const override;
QString iconResource (void) const override;
bool requiresSetup (void) const override;
bool setupComplete (void) const override;
QUrl setupSource (void) const override;
QUrl summaryQmlSource (void) const override;
bool allowSetupWhileArmed (void) const override { return true; }
private:
const QString _name;
QVariantList _summaryItems;

373
src/AutoPilotPlugins/APM/APMPowerComponent.qml

@ -23,22 +23,137 @@ SetupPage { @@ -23,22 +23,137 @@ SetupPage {
id: powerPage
pageComponent: powerPageComponent
FactPanelController {
id: controller
factPanel: powerPage.viewPanel
}
Component {
id: powerPageComponent
Flow {
id: flowLayout
width: availableWidth
spacing: _margins
property bool _batt2ParamsAvailable: controller.parameterExists(-1, "BATT2_FS_LOW_ACT")
property bool _batt2MonitorAvailable: controller.parameterExists(-1, "BATT2_MONITOR")
property Fact _batt2Monitor: controller.getParameterFact(-1, "BATT2_MONITOR", false /* reportMissing */)
QGCPalette { id: ggcPal; colorGroupEnabled: true }
// Battery 1 settings
Column {
spacing: _margins / 2
QGCLabel {
text: qsTr("Battery 1")
font.family: ScreenTools.demiboldFontFamily
}
Rectangle {
width: battery1Loader.x + battery1Loader.width + _margins
height: battery1Loader.y + battery1Loader.height + _margins
color: ggcPal.windowShade
Loader {
id: battery1Loader
anchors.margins: _margins
anchors.top: parent.top
anchors.left: parent.left
sourceComponent: powerSetupComponent
property Fact armVoltMin: controller.getParameterFact(-1, "r.ARMING_VOLT_MIN")
property Fact battAmpPerVolt: controller.getParameterFact(-1, "r.BATT_AMP_PERVLT")
property Fact battCapacity: controller.getParameterFact(-1, "BATT_CAPACITY")
property Fact battCurrPin: controller.getParameterFact(-1, "BATT_CURR_PIN")
property Fact battMonitor: controller.getParameterFact(-1, "BATT_MONITOR")
property Fact battVoltMult: controller.getParameterFact(-1, "BATT_VOLT_MULT")
property Fact battVoltPin: controller.getParameterFact(-1, "BATT_VOLT_PIN")
property Fact vehicleVoltage: controller.vehicle.battery.voltage
property Fact vehicleCurrent: controller.vehicle.battery.current
}
}
}
// Batter2 Monitor settings only - used when only monitor param is available
Column {
spacing: _margins / 2
visible: _batt2MonitorAvailable && !_batt2ParamsAvailable
QGCLabel {
text: qsTr("Battery 2")
font.family: ScreenTools.demiboldFontFamily
}
Rectangle {
width: batt2MonitorRow.x + batt2MonitorRow.width + _margins
height: batt2MonitorRow.y + batt2MonitorRow.height + _margins
color: ggcPal.windowShade
RowLayout {
id: batt2MonitorRow
anchors.margins: _margins
anchors.top: parent.top
anchors.left: parent.left
spacing: ScreenTools.defaultFontPixelWidth
visible: _batt2MonitorAvailable && !_batt2ParamsAvailable
QGCLabel { text: qsTr("Battery2 monitor:") }
FactComboBox {
id: monitorCombo
fact: _batt2Monitor
indexModel: false
}
}
}
}
// Battery 2 settings - Used when full params are available
Column {
spacing: _margins / 2
visible: _batt2ParamsAvailable
QGCLabel {
text: qsTr("Battery 2")
font.family: ScreenTools.demiboldFontFamily
}
Rectangle {
width: battery2Loader.x + battery2Loader.width + _margins
height: battery2Loader.y + battery2Loader.height + _margins
color: ggcPal.windowShade
Loader {
id: battery2Loader
anchors.margins: _margins
anchors.top: parent.top
anchors.left: parent.left
sourceComponent: _batt2ParamsAvailable ? powerSetupComponent : undefined
property Fact armVoltMin: controller.getParameterFact(-1, "r.ARMING_VOLT2_MIN", false /* reportMissing */)
property Fact battAmpPerVolt: controller.getParameterFact(-1, "r.BATT2_AMP_PERVLT", false /* reportMissing */)
property Fact battCapacity: controller.getParameterFact(-1, "BATT2_CAPACITY", false /* reportMissing */)
property Fact battCurrPin: controller.getParameterFact(-1, "BATT2_CURR_PIN", false /* reportMissing */)
property Fact battMonitor: controller.getParameterFact(-1, "BATT2_MONITOR", false /* reportMissing */)
property Fact battVoltMult: controller.getParameterFact(-1, "BATT2_VOLT_MULT", false /* reportMissing */)
property Fact battVoltPin: controller.getParameterFact(-1, "BATT2_VOLT_PIN", false /* reportMissing */)
property Fact vehicleVoltage: controller.vehicle.battery2.voltage
property Fact vehicleCurrent: controller.vehicle.battery2.current
}
}
}
} // Flow
} // Component - powerPageComponent
Component {
id: powerSetupComponent
Column {
spacing: _margins
property Fact armVoltMin: controller.getParameterFact(-1, "r.ARMING_VOLT_MIN")
property Fact battAmpPerVolt: controller.getParameterFact(-1, "BATT_AMP_PERVOLT")
property Fact battCapacity: controller.getParameterFact(-1, "BATT_CAPACITY")
property Fact battCurrPin: controller.getParameterFact(-1, "BATT_CURR_PIN")
property Fact battMonitor: controller.getParameterFact(-1, "BATT_MONITOR")
property Fact battVoltMult: controller.getParameterFact(-1, "BATT_VOLT_MULT")
property Fact battVoltPin: controller.getParameterFact(-1, "BATT_VOLT_PIN")
property real _margins: ScreenTools.defaultFontPixelHeight / 2
property bool _showAdvanced: sensorCombo.currentIndex == sensorModel.count - 1
property bool _showAdvanced: sensorCombo.currentIndex === sensorModel.count - 1
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 25
Component.onCompleted: calcSensor()
@ -58,11 +173,6 @@ SetupPage { @@ -58,11 +173,6 @@ SetupPage {
QGCPalette { id: palette; colorGroupEnabled: true }
FactPanelController {
id: controller
factPanel: powerPage.viewPanel
}
ListModel {
id: sensorModel
@ -95,121 +205,6 @@ SetupPage { @@ -95,121 +205,6 @@ SetupPage {
}
}
Component {
id: calcVoltageMultiplierDlgComponent
QGCViewDialog {
id: calcVoltageMultiplierDlg
QGCFlickable {
anchors.fill: parent
contentHeight: column.height
contentWidth: column.width
Column {
id: column
width: calcVoltageMultiplierDlg.width
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("Measure battery voltage using an external voltmeter and enter the value below. Click Calculate to set the new voltage multiplier.")
}
Grid {
columns: 2
spacing: ScreenTools.defaultFontPixelHeight / 2
verticalItemAlignment: Grid.AlignVCenter
QGCLabel {
text: qsTr("Measured voltage:")
}
QGCTextField { id: measuredVoltage }
QGCLabel { text: qsTr("Vehicle voltage:") }
QGCLabel { text: controller.vehicle.battery.voltage.valueString }
QGCLabel { text: qsTr("Voltage multiplier:") }
FactLabel { fact: battVoltMult }
}
QGCButton {
text: "Calculate"
onClicked: {
var measuredVoltageValue = parseFloat(measuredVoltage.text)
if (measuredVoltageValue == 0 || isNaN(measuredVoltageValue)) {
return
}
var newVoltageMultiplier = (measuredVoltageValue * battVoltMult.value) / controller.vehicle.battery.voltage.value
if (newVoltageMultiplier > 0) {
battVoltMult.value = newVoltageMultiplier
}
}
}
} // Column
} // QGCFlickable
} // QGCViewDialog
} // Component - calcVoltageMultiplierDlgComponent
Component {
id: calcAmpsPerVoltDlgComponent
QGCViewDialog {
id: calcAmpsPerVoltDlg
QGCFlickable {
anchors.fill: parent
contentHeight: column.height
contentWidth: column.width
Column {
id: column
width: calcAmpsPerVoltDlg.width
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("Measure current draw using an external current meter and enter the value below. Click Calculate to set the new amps per volt value.")
}
Grid {
columns: 2
spacing: ScreenTools.defaultFontPixelHeight / 2
verticalItemAlignment: Grid.AlignVCenter
QGCLabel {
text: qsTr("Measured current:")
}
QGCTextField { id: measuredCurrent }
QGCLabel { text: qsTr("Vehicle current:") }
QGCLabel { text: controller.vehicle.battery.current.valueString }
QGCLabel { text: qsTr("Amps per volt:") }
FactLabel { fact: battAmpPerVolt }
}
QGCButton {
text: "Calculate"
onClicked: {
var measuredCurrentValue = parseFloat(measuredCurrent.text)
if (measuredCurrentValue == 0) {
return
}
var newAmpsPerVolt = (measuredCurrentValue * battAmpPerVolt.value) / controller.vehicle.battery.current.value
if (newAmpsPerVolt != 0) {
battAmpPerVolt.value = newAmpsPerVolt
}
}
}
} // Column
} // QGCFlickable
} // QGCViewDialog
} // Component - calcAmpsPerVoltDlgComponent
GridLayout {
columns: 3
@ -351,9 +346,125 @@ SetupPage { @@ -351,9 +346,125 @@ SetupPage {
font.pointSize: ScreenTools.smallFontPointSize
wrapMode: Text.WordWrap
text: qsTr("If the current draw reported by the vehicle is largely different than the current read externally using a current meter you can adjust the amps per volt value to correct this. Click the Calculate button for help with calculating a new value.")
visible: _showAdvanced
visible: _showAdvanced
}
} // GridLayout
} // Column
} // Component
} // Component - powerSetupComponent
Component {
id: calcVoltageMultiplierDlgComponent
QGCViewDialog {
id: calcVoltageMultiplierDlg
QGCFlickable {
anchors.fill: parent
contentHeight: column.height
contentWidth: column.width
Column {
id: column
width: calcVoltageMultiplierDlg.width
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("Measure battery voltage using an external voltmeter and enter the value below. Click Calculate to set the new voltage multiplier.")
}
Grid {
columns: 2
spacing: ScreenTools.defaultFontPixelHeight / 2
verticalItemAlignment: Grid.AlignVCenter
QGCLabel {
text: qsTr("Measured voltage:")
}
QGCTextField { id: measuredVoltage }
QGCLabel { text: qsTr("Vehicle voltage:") }
QGCLabel { text: vehicleVoltage.valueString }
QGCLabel { text: qsTr("Voltage multiplier:") }
FactLabel { fact: battVoltMult }
}
QGCButton {
text: "Calculate"
onClicked: {
var measuredVoltageValue = parseFloat(measuredVoltage.text)
if (measuredVoltageValue == 0 || isNaN(measuredVoltageValue)) {
return
}
var newVoltageMultiplier = (measuredVoltageValue * battVoltMult.value) / vehicleVoltage.value
if (newVoltageMultiplier > 0) {
battVoltMult.value = newVoltageMultiplier
}
}
}
} // Column
} // QGCFlickable
} // QGCViewDialog
} // Component - calcVoltageMultiplierDlgComponent
Component {
id: calcAmpsPerVoltDlgComponent
QGCViewDialog {
id: calcAmpsPerVoltDlg
QGCFlickable {
anchors.fill: parent
contentHeight: column.height
contentWidth: column.width
Column {
id: column
width: calcAmpsPerVoltDlg.width
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("Measure current draw using an external current meter and enter the value below. Click Calculate to set the new amps per volt value.")
}
Grid {
columns: 2
spacing: ScreenTools.defaultFontPixelHeight / 2
verticalItemAlignment: Grid.AlignVCenter
QGCLabel {
text: qsTr("Measured current:")
}
QGCTextField { id: measuredCurrent }
QGCLabel { text: qsTr("Vehicle current:") }
QGCLabel { text: vehicleCurrent.valueString }
QGCLabel { text: qsTr("Amps per volt:") }
FactLabel { fact: battAmpPerVolt }
}
QGCButton {
text: "Calculate"
onClicked: {
var measuredCurrentValue = parseFloat(measuredCurrent.text)
if (measuredCurrentValue == 0) {
return
}
var newAmpsPerVolt = (measuredCurrentValue * battAmpPerVolt.value) / vehicleCurrent.value
if (newAmpsPerVolt != 0) {
battAmpPerVolt.value = newAmpsPerVolt
}
}
}
} // Column
} // QGCFlickable
} // QGCViewDialog
} // Component - calcAmpsPerVoltDlgComponent
} // SetupPage

29
src/AutoPilotPlugins/APM/APMPowerComponentSummary.qml

@ -24,20 +24,37 @@ FactPanel { @@ -24,20 +24,37 @@ FactPanel {
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
FactPanelController { id: controller; factPanel: panel }
property Fact battCapacity: controller.getParameterFact(-1, "BATT_CAPACITY")
property Fact battMonitor: controller.getParameterFact(-1, "BATT_MONITOR")
property bool _batt2MonitorAvailable: controller.parameterExists(-1, "BATT2_MONITOR")
property bool _batt2CapacityAvailable: controller.parameterExists(-1, "BATT2_CAPACITY")
property Fact _battCapacity: controller.getParameterFact(-1, "BATT_CAPACITY")
property Fact _batt2Capacity: controller.getParameterFact(-1, "BATT2_CAPACITY", false /* reportMissing */)
property Fact _battMonitor: controller.getParameterFact(-1, "BATT_MONITOR")
property Fact _batt2Monitor: controller.getParameterFact(-1, "BATT2_MONITOR", false /* reportMissing */)
Column {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Battery monitor:")
valueText: battMonitor.enumStringValue
labelText: qsTr("Battery monitor")
valueText: _battMonitor.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Battery capacity")
valueText: _battCapacity.valueString + " " + _battCapacity.units
}
VehicleSummaryRow {
labelText: qsTr("Battery2 monitor")
valueText: _batt2MonitorAvailable ? _batt2Monitor.enumStringValue : ""
visible: _batt2MonitorAvailable
}
VehicleSummaryRow {
labelText: qsTr("Battery capacity:")
valueText: battCapacity.valueString + " " + battCapacity.units
labelText: qsTr("Battery2 capacity")
valueText: _batt2CapacityAvailable ? _batt2Capacity.valueString + " " + _battCapacity.units : ""
visible: _batt2CapacityAvailable
}
}
}

8
src/AutoPilotPlugins/APM/APMRadioComponentSummary.qml

@ -23,22 +23,22 @@ FactPanel { @@ -23,22 +23,22 @@ FactPanel {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Roll:")
labelText: qsTr("Roll")
valueText: mapRollFact.value == 0 ? qsTr("Setup required") : qsTr("Channel %1").arg(mapRollFact.valueString)
}
VehicleSummaryRow {
labelText: qsTr("Pitch:")
labelText: qsTr("Pitch")
valueText: mapPitchFact.value == 0 ? qsTr("Setup required") : qsTr("Channel %1").arg(mapPitchFact.valueString)
}
VehicleSummaryRow {
labelText: qsTr("Yaw:")
labelText: qsTr("Yaw")
valueText: mapYawFact.value == 0 ? qsTr("Setup required") : qsTr("Channel %1").arg(mapYawFact.valueString)
}
VehicleSummaryRow {
labelText: qsTr("Throttle:")
labelText: qsTr("Throttle")
valueText: mapThrottleFact.value == 0 ? qsTr("Setup required") : qsTr("Channel %1").arg(mapThrottleFact.valueString)
}
}

288
src/AutoPilotPlugins/APM/APMSafetyComponentCopter.qml

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
@ -34,12 +35,25 @@ SetupPage { @@ -34,12 +35,25 @@ SetupPage {
QGCPalette { id: ggcPal; colorGroupEnabled: true }
property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABLE")
property Fact _failsafeBattEnable: controller.getParameterFact(-1, "FS_BATT_ENABLE")
property Fact _failsafeBattMah: controller.getParameterFact(-1, "FS_BATT_MAH")
property Fact _failsafeBattVoltage: controller.getParameterFact(-1, "FS_BATT_VOLTAGE")
property Fact _failsafeThrEnable: controller.getParameterFact(-1, "FS_THR_ENABLE")
property Fact _failsafeThrValue: controller.getParameterFact(-1, "FS_THR_VALUE")
property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABLE")
property Fact _failsafeBattLowAct: controller.getParameterFact(-1, "r.BATT_FS_LOW_ACT")
property Fact _failsafeBattMah: controller.getParameterFact(-1, "r.BATT_LOW_MAH")
property Fact _failsafeBattVoltage: controller.getParameterFact(-1, "r.BATT_LOW_VOLT")
property Fact _failsafeThrEnable: controller.getParameterFact(-1, "FS_THR_ENABLE")
property Fact _failsafeThrValue: controller.getParameterFact(-1, "FS_THR_VALUE")
property bool _failsafeBattCritActAvailable: controller.parameterExists(-1, "BATT_FS_CRT_ACT")
property bool _failsafeBatt2LowActAvailable: controller.parameterExists(-1, "BATT2_FS_LOW_ACT")
property bool _failsafeBatt2CritActAvailable: controller.parameterExists(-1, "BATT2_FS_CRT_ACT")
property bool _batt2MonitorAvailable: controller.parameterExists(-1, "BATT2_MONITOR")
property bool _batt2MonitorEnabled: _batt2MonitorAvailable ? _batt2Monitor.rawValue !== 0 : false
property Fact _failsafeBattCritAct: controller.getParameterFact(-1, "BATT_FS_CRT_ACT", false /* reportMissing */)
property Fact _batt2Monitor: controller.getParameterFact(-1, "BATT2_MONITOR", false /* reportMissing */)
property Fact _failsafeBatt2LowAct: controller.getParameterFact(-1, "BATT2_FS_LOW_ACT", false /* reportMissing */)
property Fact _failsafeBatt2CritAct: controller.getParameterFact(-1, "BATT2_FS_CRT_ACT", false /* reportMissing */)
property Fact _failsafeBatt2Mah: controller.getParameterFact(-1, "BATT2_LOW_MAH", false /* reportMissing */)
property Fact _failsafeBatt2Voltage: controller.getParameterFact(-1, "BATT2_LOW_VOLT", false /* reportMissing */)
property Fact _fenceAction: controller.getParameterFact(-1, "FENCE_ACTION")
property Fact _fenceAltMax: controller.getParameterFact(-1, "FENCE_ALT_MAX")
@ -66,135 +80,193 @@ SetupPage { @@ -66,135 +80,193 @@ SetupPage {
spacing: _margins / 2
QGCLabel {
id: failsafeLabel
text: qsTr("Failsafe Triggers")
text: qsTr("Battery Failsafe Triggers")
font.family: ScreenTools.demiboldFontFamily
}
Rectangle {
id: failsafeSettings
width: throttleEnableCombo.x + throttleEnableCombo.width + _margins
height: mahField.y + mahField.height + _margins
width: batteryFailsafeColumn.x + batteryFailsafeColumn.width + _margins
height: batteryFailsafeColumn.y + batteryFailsafeColumn.height + _margins
color: ggcPal.windowShade
QGCLabel {
id: gcsEnableLabel
Column {
id: batteryFailsafeColumn
anchors.margins: _margins
anchors.top: parent.top
anchors.left: parent.left
anchors.baseline: gcsEnableCombo.baseline
text: qsTr("Ground Station failsafe:")
}
spacing: _margins
GridLayout {
id: gridLayout
columnSpacing: _margins
rowSpacing: _margins
columns: 2
QGCLabel { text: qsTr("Battery low action:") }
FactComboBox {
fact: _failsafeBattLowAct
indexModel: false
Layout.fillWidth: true
}
FactComboBox {
id: gcsEnableCombo
anchors.topMargin: _margins
anchors.leftMargin: _margins
anchors.left: gcsEnableLabel.right
anchors.top: parent.top
width: voltageField.width
fact: _failsafeGCSEnable
indexModel: false
}
QGCLabel {
text: qsTr("Battery critical action:")
visible: _failsafeBattCritActAvailable
}
FactComboBox {
fact: _failsafeBattCritAct
visible: _failsafeBattCritActAvailable
indexModel: false
Layout.fillWidth: true
}
QGCLabel {
id: throttleEnableLabel
anchors.margins: _margins
anchors.left: parent.left
anchors.baseline: throttleEnableCombo.baseline
text: qsTr("Throttle failsafe:")
}
QGCCheckBox {
text: qsTr("Voltage threshold:")
checked: _failsafeBattVoltage.value != 0
onClicked: _failsafeBattVoltage.value = checked ? 10.5 : 0
}
FactTextField {
fact: _failsafeBattVoltage
showUnits: true
Layout.fillWidth: true
}
QGCComboBox {
id: throttleEnableCombo
anchors.topMargin: _margins
anchors.left: gcsEnableCombo.left
anchors.top: gcsEnableCombo.bottom
width: voltageField.width
model: [qsTr("Disabled"), qsTr("Always RTL"),
qsTr("Continue with Mission in Auto Mode"), qsTr("Always Land")]
currentIndex: _failsafeThrEnable.value
onActivated: _failsafeThrEnable.value = index
}
QGCCheckBox {
text: qsTr("MAH threshold:")
checked: _failsafeBattMah.value != 0
onClicked: _failsafeBattMah.value = checked ? 600 : 0
}
FactTextField {
fact: _failsafeBattMah
showUnits: true
Layout.fillWidth: true
}
} // GridLayout
} // Column
} // Rectangle
} // Column - Battery Failsafe Settings
QGCLabel {
id: throttlePWMLabel
anchors.margins: _margins
anchors.left: parent.left
anchors.baseline: throttlePWMField.baseline
text: qsTr("PWM threshold:")
}
Column {
spacing: _margins / 2
visible: _batt2MonitorEnabled && _failsafeBatt2LowActAvailable
FactTextField {
id: throttlePWMField
anchors.topMargin: _margins / 2
anchors.left: gcsEnableCombo.left
anchors.top: throttleEnableCombo.bottom
fact: _failsafeThrValue
showUnits: true
}
QGCLabel {
text: qsTr("Battery2 Failsafe Triggers")
font.family: ScreenTools.demiboldFontFamily
}
QGCLabel {
id: batteryEnableLabel
Rectangle {
id: failsafeSettings
width: battery2FailsafeColumn.x + battery2FailsafeColumn.width + _margins
height: battery2FailsafeColumn.y + battery2FailsafeColumn.height + _margins
color: ggcPal.windowShade
Column {
id: battery2FailsafeColumn
anchors.margins: _margins
anchors.top: parent.top
anchors.left: parent.left
anchors.baseline: batteryEnableCombo.baseline
text: qsTr("Battery failsafe:")
}
spacing: _margins
GridLayout {
columnSpacing: _margins
rowSpacing: _margins
columns: 2
visible: _batt2MonitorEnabled && _failsafeBatt2LowActAvailable
QGCLabel { text: qsTr("Battery low action:") }
FactComboBox {
fact: _failsafeBatt2LowAct
indexModel: false
Layout.fillWidth: true
}
QGCComboBox {
id: batteryEnableCombo
anchors.topMargin: _margins
anchors.left: gcsEnableCombo.left
anchors.top: throttlePWMField.bottom
width: voltageField.width
model: [qsTr("Disabled"), qsTr("Land"), qsTr("Return to Launch")]
currentIndex: _failsafeBattEnable.value
QGCLabel {
text: qsTr("Battery critical action:")
}
FactComboBox {
fact: _failsafeBatt2CritAct
indexModel: false
Layout.fillWidth: true
}
onActivated: _failsafeBattEnable.value = index
}
QGCCheckBox {
text: qsTr("Voltage threshold:")
checked: _failsafeBatt2Voltage.value != 0
onClicked: _failsafeBatt2Voltage.value = checked ? 10.5 : 0
}
FactTextField {
fact: _failsafeBatt2Voltage
showUnits: true
Layout.fillWidth: true
}
QGCCheckBox {
id: voltageLabel
anchors.margins: _margins
anchors.left: parent.left
anchors.baseline: voltageField.baseline
text: qsTr("Voltage threshold:")
checked: _failsafeBattVoltage.value != 0
QGCCheckBox {
text: qsTr("MAH threshold:")
checked: _failsafeBatt2Mah.value != 0
onClicked: _failsafeBatt2Mah.value = checked ? 600 : 0
}
FactTextField {
fact: _failsafeBatt2Mah
showUnits: true
Layout.fillWidth: true
}
} // GridLayout
} // Column
} // Rectangle
} // Column - Battery2 Failsafe Settings
onClicked: _failsafeBattVoltage.value = checked ? 10.5 : 0
}
Column {
spacing: _margins / 2
FactTextField {
id: voltageField
anchors.topMargin: _margins / 2
anchors.left: gcsEnableCombo.left
anchors.top: batteryEnableCombo.bottom
fact: _failsafeBattVoltage
showUnits: true
}
QGCLabel {
text: qsTr("General Failsafe Triggers")
font.family: ScreenTools.demiboldFontFamily
}
QGCCheckBox {
id: mahLabel
Rectangle {
width: generalFailsafeColumn.x + generalFailsafeColumn.width + _margins
height: generalFailsafeColumn.y + generalFailsafeColumn.height + _margins
color: ggcPal.windowShade
Column {
id: generalFailsafeColumn
anchors.margins: _margins
anchors.top: parent.top
anchors.left: parent.left
anchors.baseline: mahField.baseline
text: qsTr("MAH threshold:")
checked: _failsafeBattMah.value != 0
spacing: _margins
GridLayout {
columnSpacing: _margins
rowSpacing: _margins
columns: 2
QGCLabel { text: qsTr("Ground Station failsafe:") }
FactComboBox {
fact: _failsafeGCSEnable
indexModel: false
Layout.fillWidth: true
}
onClicked: _failsafeBattMah.value = checked ? 600 : 0
}
QGCLabel { text: qsTr("Throttle failsafe:") }
QGCComboBox {
model: [qsTr("Disabled"), qsTr("Always RTL"),
qsTr("Continue with Mission in Auto Mode"), qsTr("Always Land")]
currentIndex: _failsafeThrEnable.value
Layout.fillWidth: true
FactTextField {
id: mahField
anchors.topMargin: _margins / 2
anchors.left: gcsEnableCombo.left
anchors.top: voltageField.bottom
fact: _failsafeBattMah
showUnits: true
}
onActivated: _failsafeThrEnable.value = index
}
QGCLabel { text: qsTr("PWM threshold:") }
FactTextField {
fact: _failsafeThrValue
showUnits: true
Layout.fillWidth: true
}
} // GridLayout
} // Column
} // Rectangle - Failsafe Settings
} // Column - Failsafe Settings
} // Column - General Failsafe Settings
Column {
spacing: _margins / 2

4
src/AutoPilotPlugins/APM/APMSafetyComponentPlane.qml

@ -34,8 +34,8 @@ SetupPage { @@ -34,8 +34,8 @@ SetupPage {
QGCPalette { id: palette; colorGroupEnabled: true }
property Fact _failsafeBattMah: controller.getParameterFact(-1, "FS_BATT_MAH")
property Fact _failsafeBattVoltage: controller.getParameterFact(-1, "FS_BATT_VOLTAGE")
property Fact _failsafeBattMah: controller.getParameterFact(-1, "r.BATT_LOW_MAH")
property Fact _failsafeBattVoltage: controller.getParameterFact(-1, "r.BATT_LOW_VOLT")
property Fact _failsafeThrEnable: controller.getParameterFact(-1, "THR_FAILSAFE")
property Fact _failsafeThrValue: controller.getParameterFact(-1, "THR_FS_VALUE")
property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABL")

86
src/AutoPilotPlugins/APM/APMSafetyComponentSummaryCopter.qml

@ -14,7 +14,7 @@ FactPanel { @@ -14,7 +14,7 @@ FactPanel {
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
FactPanelController { id: controller; factPanel: panel }
property Fact _failsafeBattEnable: controller.getParameterFact(-1, "FS_BATT_ENABLE")
property Fact _failsafeBattLowAct: controller.getParameterFact(-1, "r.BATT_FS_LOW_ACT")
property Fact _failsafeThrEnable: controller.getParameterFact(-1, "FS_THR_ENABLE")
property Fact _fenceAction: controller.getParameterFact(-1, "FENCE_ACTION")
@ -28,60 +28,14 @@ FactPanel { @@ -28,60 +28,14 @@ FactPanel {
property Fact _armingCheck: controller.getParameterFact(-1, "ARMING_CHECK")
property string _failsafeBattEnableText
property string _failsafeThrEnableText
property bool _failsafeBattCritActAvailable: controller.parameterExists(-1, "BATT_FS_CRT_ACT")
property bool _failsafeBatt2LowActAvailable: controller.parameterExists(-1, "BATT2_FS_LOW_ACT")
property bool _failsafeBatt2CritActAvailable: controller.parameterExists(-1, "BATT2_FS_CRT_ACT")
Component.onCompleted: {
setFailsafeBattEnableText()
setFailsafeThrEnableText()
}
Connections {
target: _failsafeBattEnable
onValueChanged: setFailsafeBattEnableText()
}
Connections {
target: _failsafeThrEnable
onValueChanged: setFailsafeThrEnableText()
}
function setFailsafeThrEnableText() {
switch (_failsafeThrEnable.value) {
case 0:
_failsafeThrEnableText = qsTr("Disabled")
break
case 1:
_failsafeThrEnableText = qsTr("Always RTL")
break
case 2:
_failsafeThrEnableText = qsTr("Continue with Mission in Auto Mode")
break
case 3:
_failsafeThrEnableText = qsTr("Always Land")
break
default:
_failsafeThrEnableText = qsTr("Unknown")
}
}
function setFailsafeBattEnableText() {
switch (_failsafeBattEnable.value) {
case 0:
_failsafeBattEnableText = qsTr("Disabled")
break
case 1:
_failsafeBattEnableText = qsTr("Land")
break
case 2:
_failsafeBattEnableText = qsTr("Return to Launch")
break
default:
_failsafeThrEnableText = qsTr("Unknown")
}
}
property Fact _failsafeBattCritAct: controller.getParameterFact(-1, "BATT_FS_CRT_ACT", false /* reportMissing */)
property Fact _batt2Monitor: controller.getParameterFact(-1, "BATT2_MONITOR", false /* reportMissing */)
property Fact _failsafeBatt2LowAct: controller.getParameterFact(-1, "BATT2_FS_LOW_ACT", false /* reportMissing */)
property Fact _failsafeBatt2CritAct: controller.getParameterFact(-1, "BATT2_FS_CRT_ACT", false /* reportMissing */)
Column {
anchors.fill: parent
@ -93,12 +47,30 @@ FactPanel { @@ -93,12 +47,30 @@ FactPanel {
VehicleSummaryRow {
labelText: qsTr("Throttle failsafe:")
valueText: _failsafeThrEnableText
valueText: _failsafeBattLowAct.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Batt low failsafe:")
valueText: _failsafeBattLowAct.enumStringValue
}
VehicleSummaryRow {
labelText: qsTr("Batt critical failsafe:")
valueText: _failsafeBattCritActAvailable ? _failsafeBattCritAct.enumStringValue : ""
visible: _failsafeBattCritActAvailable
}
VehicleSummaryRow {
labelText: qsTr("Batt2 low failsafe:")
valueText: _failsafeBatt2LowActAvailable ? _failsafeBatt2LowAct.enumStringValue : ""
visible: _failsafeBatt2LowActAvailable
}
VehicleSummaryRow {
labelText: qsTr("Battery failsafe:")
valueText: _failsafeBattEnableText
labelText: qsTr("Batt2 critical failsafe:")
valueText: _failsafeBatt2CritActAvailable ? _failsafeBatt2CritAct.enumStringValue : ""
visible: _failsafeBatt2CritActAvailable
}
VehicleSummaryRow {

4
src/AutoPilotPlugins/APM/APMSensorsComponentSummary.qml

@ -34,7 +34,7 @@ FactPanel { @@ -34,7 +34,7 @@ FactPanel {
model: 3
VehicleSummaryRow {
labelText: qsTr("Compass ") + (index + 1) + ":"
labelText: qsTr("Compass ") + (index + 1) + ""
valueText: sensorParams.rgCompassAvailable[index] ?
(sensorParams.rgCompassCalibrated[index] ?
(sensorParams.rgCompassPrimary[index] ? "Primary" : "Secondary") +
@ -47,7 +47,7 @@ FactPanel { @@ -47,7 +47,7 @@ FactPanel {
}
VehicleSummaryRow {
labelText: qsTr("Accelerometer(s):")
labelText: qsTr("Accelerometer(s)")
valueText: controller.accelSetupNeeded ? qsTr("Setup required") : qsTr("Ready")
}
}

6
src/AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml

@ -45,17 +45,17 @@ FactPanel { @@ -45,17 +45,17 @@ FactPanel {
anchors.fill: parent
VehicleSummaryRow {
id: nameRow;
labelText: qsTr("Frame Type:")
labelText: qsTr("Frame Type")
valueText: frameName()
}
VehicleSummaryRow {
labelText: qsTr("Firmware Version:")
labelText: qsTr("Firmware Version")
valueText: activeVehicle.firmwareMajorVersion == -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + " " + activeVehicle.firmwareVersionTypeString
}
VehicleSummaryRow {
labelText: qsTr("Git Revision:")
labelText: qsTr("Git Revision")
valueText: activeVehicle.gitHash == -1 ? qsTr("Unknown") : activeVehicle.gitHash
}
}

56
src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml

@ -39,13 +39,16 @@ SetupPage { @@ -39,13 +39,16 @@ SetupPage {
property real _hoverTuneMax: _throttleMidExists ? 800 : 1
property real _hoverTuneStep: _throttleMidExists ? 10 : 0.01
property Fact _rcFeel: controller.getParameterFact(-1, "RC_FEEL_RP")
property Fact _rateRollP: controller.getParameterFact(-1, "r.ATC_RAT_RLL_P")
property Fact _rateRollI: controller.getParameterFact(-1, "r.ATC_RAT_RLL_I")
property Fact _ratePitchP: controller.getParameterFact(-1, "r.ATC_RAT_PIT_P")
property Fact _ratePitchI: controller.getParameterFact(-1, "r.ATC_RAT_PIT_I")
property Fact _rateClimbP: controller.getParameterFact(-1, "ACCEL_Z_P")
property Fact _rateClimbI: controller.getParameterFact(-1, "ACCEL_Z_I")
property bool _rcFeelAvailable: controller.parameterExists(-1, "RC_FEEL")
property bool _atcInputTCAvailable: controller.parameterExists(-1, "ATC_INPUT_TC")
property Fact _rcFeel: controller.getParameterFact(-1, "RC_FEEL", false)
property Fact _atcInputTC: controller.getParameterFact(-1, "ATC_INPUT_TC", false)
property Fact _rateRollP: controller.getParameterFact(-1, "r.ATC_RAT_RLL_P")
property Fact _rateRollI: controller.getParameterFact(-1, "r.ATC_RAT_RLL_I")
property Fact _ratePitchP: controller.getParameterFact(-1, "r.ATC_RAT_PIT_P")
property Fact _ratePitchI: controller.getParameterFact(-1, "r.ATC_RAT_PIT_I")
property Fact _rateClimbP: controller.getParameterFact(-1, "r.PSC_ACCZ_P")
property Fact _rateClimbI: controller.getParameterFact(-1, "r.PSC_ACCZ_I")
property Fact _ch7Opt: controller.getParameterFact(-1, "CH7_OPT")
property Fact _ch8Opt: controller.getParameterFact(-1, "CH8_OPT")
@ -78,7 +81,12 @@ SetupPage { @@ -78,7 +81,12 @@ SetupPage {
throttleHover.value = _hoverTuneParam.value
rollPitch.value = _rateRollP.value
climb.value = _rateClimbP.value
rcFeel.value = _rcFeel.value
if (_rcFeelAvailable) {
rcFeel.value = _rcFeel.value
}
if (_atcInputTCAvailable) {
atcInputTC.value = _atcInputTC.value
}
_loadComplete = true
calcAutoTuneChannel()
@ -240,6 +248,7 @@ SetupPage { @@ -240,6 +248,7 @@ SetupPage {
Column {
anchors.left: parent.left
anchors.right: parent.right
visible: _rcFeelAvailable
QGCLabel {
text: qsTr("RC Roll/Pitch Feel")
@ -266,6 +275,37 @@ SetupPage { @@ -266,6 +275,37 @@ SetupPage {
}
}
}
Column {
anchors.left: parent.left
anchors.right: parent.right
visible: _atcInputTCAvailable
QGCLabel {
text: qsTr("RC Roll/Pitch Feel")
font.family: ScreenTools.demiboldFontFamily
}
QGCLabel {
text: qsTr("Slide to the left for soft control, slide to the right for crisp control")
}
Slider {
id: atcInputTC
anchors.left: parent.left
anchors.right: parent.right
minimumValue: _atcInputTC.min
maximumValue: _atcInputTC.max
stepSize: _atcInputTC.increment
tickmarksEnabled: true
onValueChanged: {
if (_loadComplete) {
_atcInputTC.value = value
}
}
}
}
}
} // Rectangle - Basic tuning

4
src/AutoPilotPlugins/AutoPilotPlugin.cc

@ -13,8 +13,6 @@ @@ -13,8 +13,6 @@
#include "AutoPilotPlugin.h"
#include "QGCApplication.h"
#include "ParameterManager.h"
#include "UAS.h"
#include "FirmwarePlugin.h"
AutoPilotPlugin::AutoPilotPlugin(Vehicle* vehicle, QObject* parent)
@ -28,7 +26,7 @@ AutoPilotPlugin::AutoPilotPlugin(Vehicle* vehicle, QObject* parent) @@ -28,7 +26,7 @@ AutoPilotPlugin::AutoPilotPlugin(Vehicle* vehicle, QObject* parent)
AutoPilotPlugin::~AutoPilotPlugin()
{
}
void AutoPilotPlugin::_recalcSetupComplete(void)

1
src/AutoPilotPlugins/AutoPilotPlugin.h

@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
#include "FactSystem.h"
#include "Vehicle.h"
class ParameterManager;
class Vehicle;
class FirmwarePlugin;

16
src/AutoPilotPlugins/Common/ESP8266ComponentSummary.qml

@ -30,38 +30,38 @@ FactPanel { @@ -30,38 +30,38 @@ FactPanel {
Column {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Firmware Version:")
labelText: qsTr("Firmware Version")
valueText: esp8266.version
}
VehicleSummaryRow {
labelText: qsTr("WiFi Mode:")
labelText: qsTr("WiFi Mode")
valueText: wifiMode ? (wifiMode.value === 0 ? "AP Mode" : "Station Mode") : "AP Mode"
}
VehicleSummaryRow {
labelText: qsTr("WiFi Channel:")
labelText: qsTr("WiFi Channel")
valueText: wifiChannel ? wifiChannel.valueString : ""
visible: wifiMode ? wifiMode.value === 0 : true
}
VehicleSummaryRow {
labelText: qsTr("WiFi AP SSID:")
labelText: qsTr("WiFi AP SSID")
valueText: esp8266.wifiSSID
}
VehicleSummaryRow {
labelText: qsTr("WiFi AP Password:")
labelText: qsTr("WiFi AP Password")
valueText: esp8266.wifiPassword
}
/* Too much info makes it all crammed
VehicleSummaryRow {
labelText: qsTr("WiFi STA SSID:")
labelText: qsTr("WiFi STA SSID")
valueText: esp8266.wifiSSIDSta
}
VehicleSummaryRow {
labelText: qsTr("WiFi STA Password:")
labelText: qsTr("WiFi STA Password")
valueText: esp8266.wifiPasswordSta
}
*/
VehicleSummaryRow {
labelText: qsTr("UART Baud Rate:")
labelText: qsTr("UART Baud Rate")
valueText: uartBaud ? uartBaud.valueString : ""
}
}

58
src/AutoPilotPlugins/Common/SetupPage.qml

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.FactSystem 1.0
@ -23,21 +24,26 @@ import QGroundControl.Controllers 1.0 @@ -23,21 +24,26 @@ import QGroundControl.Controllers 1.0
QGCView {
id: setupView
viewPanel: setupPanel
enabled: !_shouldDisableWhenArmed
enabled: !_disableDueToArmed && !_disableDueToFlying
property alias pageComponent: pageLoader.sourceComponent
property string pageName: vehicleComponent ? vehicleComponent.name : ""
property string pageDescription: vehicleComponent ? vehicleComponent.description : ""
property real availableWidth: width - pageLoader.x
property real availableHeight: height - pageLoader.y
property bool showAdvanced: false
property alias advanced: advancedCheckBox.checked
property bool _vehicleArmed: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle.armed : false
property bool _shouldDisableWhenArmed: _vehicleArmed ? (vehicleComponent ? !vehicleComponent.allowSetupWhileArmed : false) : false
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _vehicleArmed: _activeVehicle ? _activeVehicle.armed : false
property bool _vehicleFlying: _activeVehicle ? _activeVehicle.flying : false
property bool _disableDueToArmed: vehicleComponent ? (!vehicleComponent.allowSetupWhileArmed && _vehicleArmed) : false
property bool _disableDueToFlying: vehicleComponent ? (!vehicleComponent.allowSetupWhileFlying && _vehicleFlying) : false
property string _disableReason: _disableDueToArmed ? qsTr("armed") : qsTr("flying")
property real _margins: ScreenTools.defaultFontPixelHeight * 0.5
property string _pageTitle: qsTr("%1 Setup").arg(pageName)
QGCPalette { id: qgcPal; colorGroupEnabled: setupPanel.enabled }
QGCViewPanel {
@ -50,35 +56,49 @@ QGCView { @@ -50,35 +56,49 @@ QGCView {
contentHeight: pageLoader.y + pageLoader.item.height
clip: true
Column {
id: headingColumn
width: setupPanel.width
RowLayout {
id: headingRow
anchors.left: parent.left
anchors.right: parent.right
spacing: _margins
layoutDirection: Qt.RightToLeft
QGCLabel {
font.pointSize: ScreenTools.largeFontPointSize
text: _shouldDisableWhenArmed ? _pageTitle + "<font color=\"red\">" + qsTr(" (Disabled while the vehicle is armed)") + "</font>" : _pageTitle
visible: !ScreenTools.isShortScreen
QGCCheckBox {
id: advancedCheckBox
text: qsTr("Advanced")
visible: showAdvanced
}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: pageDescription
visible: !ScreenTools.isShortScreen
Column {
spacing: _margins
Layout.fillWidth: true
QGCLabel {
font.pointSize: ScreenTools.largeFontPointSize
text: !setupView.enabled ? _pageTitle + "<font color=\"red\">" + qsTr(" (Disabled while the vehicle is %1)").arg(_disableReason) + "</font>" : _pageTitle
visible: !ScreenTools.isShortScreen
}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: pageDescription
visible: !ScreenTools.isShortScreen
}
}
}
Loader {
id: pageLoader
anchors.topMargin: _margins
anchors.top: headingColumn.bottom
anchors.top: headingRow.bottom
}
// Overlay to display when vehicle is armed and this setup page needs
// to be disabled
Rectangle {
visible: _shouldDisableWhenArmed
visible: !setupView.enabled
anchors.fill: pageLoader
color: "black"
opacity: 0.5

8
src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml

@ -23,20 +23,20 @@ FactPanel { @@ -23,20 +23,20 @@ FactPanel {
Column {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("System ID:")
labelText: qsTr("System ID")
valueText: sysIdFact ? sysIdFact.valueString : ""
}
VehicleSummaryRow {
labelText: qsTr("Airframe type:")
labelText: qsTr("Airframe type")
valueText: autoStartSet ? controller.currentAirframeType : qsTr("Setup required")
}
VehicleSummaryRow {
labelText: qsTr("Vehicle:")
labelText: qsTr("Vehicle")
valueText: autoStartSet ? controller.currentVehicleName : qsTr("Setup required")
}
VehicleSummaryRow {
labelText: qsTr("Firmware Version:")
labelText: qsTr("Firmware Version")
valueText: activeVehicle.firmwareMajorVersion === -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + activeVehicle.firmwareVersionTypeString
}
}

5
src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml

@ -329,6 +329,11 @@ @@ -329,6 +329,11 @@
<maintainer>Michael Schaeuble</maintainer>
<type>Quadrotor x</type>
</airframe>
<airframe id="4014" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="S500">
<class>Copter</class>
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type>
</airframe>
<airframe id="4020" maintainer="Thomas Gubler &lt;thomas@px4.io&gt;" name="Hobbyking Micro PCB">
<class>Copter</class>
<maintainer>Thomas Gubler &lt;thomas@px4.io&gt;</maintainer>

18
src/AutoPilotPlugins/PX4/CameraComponent.qml

@ -121,14 +121,14 @@ SetupPage { @@ -121,14 +121,14 @@ SetupPage {
}
QGCLabel {
anchors.baseline: camTrigCombo.baseline
Layout.alignment: Qt.AlignVCenter
text: qsTr("Trigger mode")
}
FactComboBox {
id: camTrigCombo
fact: _camTriggerMode
indexModel: false
enabled: !_rebooting
Layout.alignment: Qt.AlignVCenter
Layout.minimumWidth: _editFieldWidth
onActivated: {
applyAndRestart.visible = true
@ -136,14 +136,14 @@ SetupPage { @@ -136,14 +136,14 @@ SetupPage {
}
QGCLabel {
anchors.baseline: camInterfaceCombo.baseline
Layout.alignment: Qt.AlignVCenter
text: qsTr("Trigger interface")
}
FactComboBox {
id: camInterfaceCombo
fact: _camTriggerInterface
indexModel: false
enabled: !_rebooting && (_camTriggerInterface ? true : false)
Layout.alignment: Qt.AlignVCenter
Layout.minimumWidth: _editFieldWidth
onActivated: {
applyAndRestart.visible = true
@ -152,7 +152,7 @@ SetupPage { @@ -152,7 +152,7 @@ SetupPage {
QGCLabel {
text: qsTr("Time Interval")
anchors.baseline: timeIntervalField.baseline
Layout.alignment: Qt.AlignVCenter
color: qgcPal.text
visible: timeIntervalField.visible
}
@ -161,12 +161,13 @@ SetupPage { @@ -161,12 +161,13 @@ SetupPage {
fact: controller.getParameterFact(-1, "TRIG_INTERVAL", false)
showUnits: true
Layout.minimumWidth: _editFieldWidth
Layout.alignment: Qt.AlignVCenter
visible: _camTriggerMode.value === 2
}
QGCLabel {
text: qsTr("Distance Interval")
anchors.baseline: trigDistField.baseline
Layout.alignment: Qt.AlignVCenter
color: qgcPal.text
visible: trigDistField.visible
}
@ -174,6 +175,7 @@ SetupPage { @@ -174,6 +175,7 @@ SetupPage {
id: trigDistField
fact: controller.getParameterFact(-1, "TRIG_DISTANCE", false)
showUnits: true
Layout.alignment: Qt.AlignVCenter
Layout.minimumWidth: _editFieldWidth
visible: _camTriggerMode.value === 3
}
@ -199,8 +201,8 @@ SetupPage { @@ -199,8 +201,8 @@ SetupPage {
}
Row {
spacing: _margins
anchors.horizontalCenter: parent.horizontalCenter
spacing: _margins
Layout.alignment: Qt.AlignHCenter
GridLayout {
rows: 2

12
src/AutoPilotPlugins/PX4/CameraComponentSummary.qml

@ -25,36 +25,36 @@ FactPanel { @@ -25,36 +25,36 @@ FactPanel {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Trigger interface:")
labelText: qsTr("Trigger interface")
valueText: _camTriggerInterface ? _camTriggerInterface.enumStringValue : ""
}
VehicleSummaryRow {
labelText: qsTr("Trigger mode:")
labelText: qsTr("Trigger mode")
valueText: _camTriggerMode ? _camTriggerMode.enumStringValue : ""
}
VehicleSummaryRow {
visible: _timeInterval && _camTriggerMode.value === 2
labelText: qsTr("Time interval:")
labelText: qsTr("Time interval")
valueText: _timeInterval ? _timeInterval.value : ""
}
VehicleSummaryRow {
visible: _distanceInterval && _camTriggerMode.value === 3
labelText: qsTr("Distance interval:")
labelText: qsTr("Distance interval")
valueText: _distanceInterval ? _distanceInterval.value : ""
}
VehicleSummaryRow {
visible: _auxPins
labelText: qsTr("AUX pins:")
labelText: qsTr("AUX pins")
valueText: _auxPins ? _auxPins.value : ""
}
VehicleSummaryRow {
visible: _camTriggerPol
labelText: qsTr("AUX pin polarity:")
labelText: qsTr("AUX pin polarity")
valueText: _camTriggerPol ? (_camTriggerPol.value ? "High (3.3V)" : "Low (0V)") : ""
}

12
src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml

@ -29,13 +29,13 @@ FactPanel { @@ -29,13 +29,13 @@ FactPanel {
id: simple
Column {
VehicleSummaryRow {
labelText: qsTr("Mode switch:")
labelText: qsTr("Mode switch")
valueText: _rcMapFltmode.value === 0 ? qsTr("Setup required") : _rcMapFltmode.enumStringValue
}
Repeater {
model: 6
VehicleSummaryRow {
labelText: qsTr("Flight Mode %1 :").arg(index + 1)
labelText: qsTr("Flight Mode %1 ").arg(index + 1)
valueText: controller.getParameterFact(-1, "COM_FLTMODE" + (index + 1)).enumStringValue
}
}
@ -49,19 +49,19 @@ FactPanel { @@ -49,19 +49,19 @@ FactPanel {
property Fact loiterSwFact: controller.getParameterFact(-1, "RC_MAP_LOITER_SW")
property Fact returnSwFact: controller.getParameterFact(-1, "RC_MAP_RETURN_SW")
VehicleSummaryRow {
labelText: qsTr("Mode switch:")
labelText: qsTr("Mode switch")
valueText: _rcMapModeSw.value === 0 ? qsTr("Setup required") : _rcMapModeSw.valueString
}
VehicleSummaryRow {
labelText: qsTr("Position Ctl switch:")
labelText: qsTr("Position Ctl switch")
valueText: posCtlSwFact.value === 0 ? qsTr("Disabled") : posCtlSwFact.valueString
}
VehicleSummaryRow {
labelText: qsTr("Loiter switch:")
labelText: qsTr("Loiter switch")
valueText: loiterSwFact.value === 0 ? qsTr("Disabled") : loiterSwFact.valueString
}
VehicleSummaryRow {
labelText: qsTr("Return switch:")
labelText: qsTr("Return switch")
valueText: returnSwFact.value === 0 ? qsTr("Disabled") : returnSwFact.valueString
}
}

14
src/AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml

@ -26,38 +26,38 @@ FactPanel { @@ -26,38 +26,38 @@ FactPanel {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Roll:")
labelText: qsTr("Roll")
valueText: mapRollFact ? (mapRollFact.value === 0 ? qsTr("Setup required") : mapRollFact.valueString) : ""
}
VehicleSummaryRow {
labelText: qsTr("Pitch:")
labelText: qsTr("Pitch")
valueText: mapPitchFact ? (mapPitchFact.value === 0 ? qsTr("Setup required") : mapPitchFact.valueString) : ""
}
VehicleSummaryRow {
labelText: qsTr("Yaw:")
labelText: qsTr("Yaw")
valueText: mapYawFact ? (mapYawFact.value === 0 ? qsTr("Setup required") : mapYawFact.valueString) : ""
}
VehicleSummaryRow {
labelText: qsTr("Throttle:")
labelText: qsTr("Throttle")
valueText: mapThrottleFact ? (mapThrottleFact.value === 0 ? qsTr("Setup required") : mapThrottleFact.valueString) : ""
}
VehicleSummaryRow {
labelText: qsTr("Flaps:")
labelText: qsTr("Flaps")
valueText: mapFlapsFact ? (mapFlapsFact.value === 0 ? qsTr("Disabled") : mapFlapsFact.valueString) : ""
visible: !controller.vehicle.multiRotor
}
VehicleSummaryRow {
labelText: qsTr("Aux1:")
labelText: qsTr("Aux1")
valueText: mapAux1Fact ? (mapAux1Fact.value === 0 ? qsTr("Disabled") : mapAux1Fact.valueString) : ""
}
VehicleSummaryRow {
labelText: qsTr("Aux2:")
labelText: qsTr("Aux2")
valueText: mapAux2Fact ? (mapAux2Fact.value === 0 ? qsTr("Disabled") : mapAux2Fact.valueString) : ""
}
}

1
src/AutoPilotPlugins/PX4/PX4TuningComponent.h

@ -32,6 +32,7 @@ public: @@ -32,6 +32,7 @@ public:
QUrl setupSource(void) const final;
QUrl summaryQmlSource(void) const final;
bool allowSetupWhileArmed(void) const final { return true; }
bool allowSetupWhileFlying(void) const final { return true; }
private:
const QString _name;

137
src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml

@ -7,11 +7,16 @@ @@ -7,11 +7,16 @@
*
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtCharts 2.2
import QtQuick.Layouts 1.2
import QtQuick 2.3
import QtQuick.Controls 1.2
import QGroundControl.Controls 1.0
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0
SetupPage {
id: tuningPage
@ -20,47 +25,97 @@ SetupPage { @@ -20,47 +25,97 @@ SetupPage {
Component {
id: pageComponent
FactSliderPanel {
width: availableWidth
qgcViewPanel: tuningPage.viewPanel
Column {
width: availableWidth
sliderModel: ListModel {
ListElement {
title: qsTr("Hover Throttle")
description: qsTr("Adjust throttle so hover is at mid-throttle. Slide to the left if hover is lower than throttle center. Slide to the right if hover is higher than throttle center.")
param: "MPC_THR_HOVER"
min: 20
max: 80
step: 1
}
Component.onCompleted: {
showAdvanced = !ScreenTools.isMobile
}
ListElement {
title: qsTr("Manual minimum throttle")
description: qsTr("Slide to the left to start the motors with less idle power. Slide to the right if descending in manual flight becomes unstable.")
param: "MPC_MANTHR_MIN"
min: 0
max: 15
step: 1
}
FactPanelController {
id: controller
factPanel: tuningPage.viewPanel
}
ListElement {
title: qsTr("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.")
param: "MC_ROLL_TC"
min: 0.15
max: 0.25
step: 0.01
}
// Standard tuning page
FactSliderPanel {
width: availableWidth
qgcViewPanel: tuningPage.viewPanel
visible: !advanced
sliderModel: ListModel {
ListElement {
title: qsTr("Hover Throttle")
description: qsTr("Adjust throttle so hover is at mid-throttle. Slide to the left if hover is lower than throttle center. Slide to the right if hover is higher than throttle center.")
param: "MPC_THR_HOVER"
min: 20
max: 80
step: 1
}
ListElement {
title: qsTr("Pitch sensitivity")
description: qsTr("Slide to the left to make pitch control faster and more accurate. Slide to the right if pitch oscillates or is too twitchy.")
param: "MC_PITCH_TC"
min: 0.15
max: 0.25
step: 0.01
ListElement {
title: qsTr("Manual minimum throttle")
description: qsTr("Slide to the left to start the motors with less idle power. Slide to the right if descending in manual flight becomes unstable.")
param: "MPC_MANTHR_MIN"
min: 0
max: 15
step: 1
}
/*
These seem to have disappeared from PX4 firmware!
ListElement {
title: qsTr("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.")
param: "MC_ROLL_TC"
min: 0.15
max: 0.25
step: 0.01
}
ListElement {
title: qsTr("Pitch sensitivity")
description: qsTr("Slide to the left to make pitch control faster and more accurate. Slide to the right if pitch oscillates or is too twitchy.")
param: "MC_PITCH_TC"
min: 0.15
max: 0.25
step: 0.01
}
*/
}
}
}
} // Component
Loader {
anchors.left: parent.left
anchors.right: parent.right
sourceComponent: advanced ? advancePageComponent : undefined
}
Component {
id: advancePageComponent
PIDTuning {
anchors.left: parent.left
anchors.right: parent.right
tuneList: [ qsTr("Roll"), qsTr("Pitch"), qsTr("Yaw") ]
params: [
[ controller.getParameterFact(-1, "MC_ROLL_P"),
controller.getParameterFact(-1, "MC_ROLLRATE_P"),
controller.getParameterFact(-1, "MC_ROLLRATE_I"),
controller.getParameterFact(-1, "MC_ROLLRATE_D"),
controller.getParameterFact(-1, "MC_ROLLRATE_FF") ],
[ controller.getParameterFact(-1, "MC_PITCH_P"),
controller.getParameterFact(-1, "MC_PITCHRATE_P"),
controller.getParameterFact(-1, "MC_PITCHRATE_I"),
controller.getParameterFact(-1, "MC_PITCHRATE_D"),
controller.getParameterFact(-1, "MC_PITCHRATE_FF") ],
[ controller.getParameterFact(-1, "MC_YAW_P"),
controller.getParameterFact(-1, "MC_YAWRATE_P"),
controller.getParameterFact(-1, "MC_YAWRATE_I"),
controller.getParameterFact(-1, "MC_YAWRATE_D"),
controller.getParameterFact(-1, "MC_YAW_FF"),
controller.getParameterFact(-1, "MC_YAWRATE_FF") ] ]
}
} // Component - Advanced Page
} // Column
} // Component - pageComponent
} // SetupPage

106
src/AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml

@ -7,11 +7,16 @@ @@ -7,11 +7,16 @@
*
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtCharts 2.2
import QtQuick.Layouts 1.2
import QtQuick 2.3
import QtQuick.Controls 1.2
import QGroundControl.Controls 1.0
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0
SetupPage {
id: tuningPage
@ -20,47 +25,64 @@ SetupPage { @@ -20,47 +25,64 @@ SetupPage {
Component {
id: pageComponent
FactSliderPanel {
width: availableWidth
qgcViewPanel: tuningPage.viewPanel
Column {
width: availableWidth
sliderModel: ListModel {
ListElement {
title: qsTr("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.")
param: "FW_R_TC"
min: 0.2
max: 0.8
step: 0.01
}
Component.onCompleted: {
showAdvanced = !ScreenTools.isMobile
}
ListElement {
title: qsTr("Pitch sensitivity")
description: qsTr("Slide to the left to make pitch control faster and more accurate. Slide to the right if pitch oscillates or is too twitchy.")
param: "FW_P_TC"
min: 0.2
max: 0.8
step: 0.01
}
FactPanelController {
id: controller
factPanel: tuningPage.viewPanel
}
ListElement {
title: qsTr("Cruise throttle")
description: qsTr("This is the throttle setting required to achieve the desired cruise speed. Most planes need 50-60%.")
param: "FW_THR_CRUISE"
min: 20
max: 80
step: 1
}
// Standard tuning page
FactSliderPanel {
width: availableWidth
qgcViewPanel: tuningPage.viewPanel
visible: !advanced
ListElement {
title: qsTr("Mission mode sensitivity")
description: qsTr("Slide to the left to make position control more accurate and more aggressive. Slide to the right to make flight in mission mode smoother and less twitchy.")
param: "FW_L1_PERIOD"
min: 12
max: 50
step: 0.5
sliderModel: ListModel {
ListElement {
title: qsTr("Cruise throttle")
description: qsTr("This is the throttle setting required to achieve the desired cruise speed. Most planes need 50-60%.")
param: "FW_THR_CRUISE"
min: 20
max: 80
step: 1
}
}
}
}
}
}
Loader {
anchors.left: parent.left
anchors.right: parent.right
sourceComponent: advanced ? advancePageComponent : undefined
}
Component {
id: advancePageComponent
PIDTuning {
anchors.left: parent.left
anchors.right: parent.right
tuneList: [ qsTr("Roll"), qsTr("Pitch"), qsTr("Yaw") ]
params: [
[ controller.getParameterFact(-1, "FW_RR_P"),
controller.getParameterFact(-1, "FW_RR_I"),
controller.getParameterFact(-1, "FW_RR_FF"),
controller.getParameterFact(-1, "FW_R_TC"),],
[ controller.getParameterFact(-1, "FW_PR_P"),
controller.getParameterFact(-1, "FW_PR_I"),
controller.getParameterFact(-1, "FW_PR_FF"),
controller.getParameterFact(-1, "FW_P_TC") ],
[ controller.getParameterFact(-1, "FW_YR_P"),
controller.getParameterFact(-1, "FW_YR_I"),
controller.getParameterFact(-1, "FW_YR_FF") ] ]
}
} // Component - Advanced Page
} // Column
} // Component - pageComponent
} // SetupPage

20
src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml

@ -27,24 +27,6 @@ SetupPage { @@ -27,24 +27,6 @@ SetupPage {
sliderModel: ListModel {
ListElement {
title: qsTr("Hover Roll sensitivity")
description: qsTr("Slide to the left to make roll control during hover faster and more accurate. Slide to the right if roll oscillates or is too twitchy.")
param: "MC_ROLL_TC"
min: 0.15
max: 0.25
step: 0.01
}
ListElement {
title: qsTr("Hover Pitch sensitivity")
description: qsTr("Slide to the left to make pitch control during hover faster and more accurate. Slide to the right if pitch oscillates or is too twitchy.")
param: "MC_PITCH_TC"
min: 0.15
max: 0.25
step: 0.01
}
ListElement {
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.")
param: "FW_R_TC"
@ -81,7 +63,7 @@ SetupPage { @@ -81,7 +63,7 @@ SetupPage {
}
ListElement {
title: qsTr("Hoever manual minimum throttle")
title: qsTr("Hover manual minimum throttle")
description: qsTr("Slide to the left to start the motors with less idle power. Slide to the right if descending in manual flight becomes unstable.")
param: "MPC_MANTHR_MIN"
min: 0

23
src/AutoPilotPlugins/PX4/PowerComponent.h

@ -24,18 +24,19 @@ class PowerComponent : public VehicleComponent @@ -24,18 +24,19 @@ class PowerComponent : public VehicleComponent
public:
PowerComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent = NULL);
// Virtuals from VehicleComponent
virtual QStringList setupCompleteChangedTriggerList(void) const;
// Virtuals from VehicleComponent
virtual QString name (void) const;
virtual QString description (void) const;
virtual QString iconResource (void) const;
virtual bool requiresSetup (void) const;
virtual bool setupComplete (void) const;
virtual QUrl setupSource (void) const;
virtual QUrl summaryQmlSource (void) const;
// Overrides from VehicleComponent
QStringList setupCompleteChangedTriggerList(void) const override;
// Overrides from VehicleComponent
QString name (void) const override;
QString description (void) const override;
QString iconResource (void) const override;
bool requiresSetup (void) const override;
bool setupComplete (void) const override;
QUrl setupSource (void) const override;
QUrl summaryQmlSource (void) const override;
bool allowSetupWhileArmed (void) const override { return true; }
private:
const QString _name;
QVariantList _summaryItems;

32
src/AutoPilotPlugins/PX4/PowerComponent.qml

@ -348,9 +348,9 @@ SetupPage { @@ -348,9 +348,9 @@ SetupPage {
} // QGCGroupBox - Battery settings
QGCGroupBox {
anchors.left: batteryGroup.left
anchors.right: batteryGroup.right
title: qsTr("ESC PWM Minimum and Maximum Calibration")
Layout.maximumWidth: batteryGroup.width
Layout.fillWidth: true
title: qsTr("ESC PWM Minimum and Maximum Calibration")
ColumnLayout {
anchors.left: parent.left
@ -383,10 +383,10 @@ SetupPage { @@ -383,10 +383,10 @@ SetupPage {
}
QGCGroupBox {
anchors.left: batteryGroup.left
anchors.right: batteryGroup.right
title: qsTr("UAVCAN Bus Configuration")
visible: showUAVCAN.checked
Layout.maximumWidth: batteryGroup.width
Layout.fillWidth: true
title: qsTr("UAVCAN Bus Configuration")
visible: showUAVCAN.checked
Row {
id: uavCanConfigRow
@ -407,10 +407,10 @@ SetupPage { @@ -407,10 +407,10 @@ SetupPage {
}
QGCGroupBox {
anchors.left: batteryGroup.left
anchors.right: batteryGroup.right
title: qsTr("UAVCAN Motor Index and Direction Assignment")
visible: showUAVCAN.checked
Layout.maximumWidth: batteryGroup.width
Layout.fillWidth: true
title: qsTr("UAVCAN Motor Index and Direction Assignment")
visible: showUAVCAN.checked
ColumnLayout {
anchors.left: parent.left
@ -456,10 +456,10 @@ SetupPage { @@ -456,10 +456,10 @@ SetupPage {
}
QGCGroupBox {
anchors.left: batteryGroup.left
anchors.right: batteryGroup.right
title: qsTr("Advanced Power Settings")
visible: showAdvanced.checked
Layout.maximumWidth: batteryGroup.width
Layout.fillWidth: true
title: qsTr("Advanced Power Settings")
visible: showAdvanced.checked
ColumnLayout {
anchors.left: parent.left
@ -487,7 +487,7 @@ SetupPage { @@ -487,7 +487,7 @@ SetupPage {
text: qsTr("Batteries show less voltage at high throttle. Enter the difference in Volts between idle throttle and full ") +
qsTr("throttle, divided by the number of battery cells. Leave at the default if unsure. ") +
highlightPrefix + qsTr("If this value is set too high, the battery might be deep discharged and damaged.") + highlightSuffix
Layout.fillWidth: true
Layout.maximumWidth: ScreenTools.defaultFontPixelWidth * 60
}
Row {

6
src/AutoPilotPlugins/PX4/PowerComponentSummary.qml

@ -36,17 +36,17 @@ FactPanel { @@ -36,17 +36,17 @@ FactPanel {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Battery Full:")
labelText: qsTr("Battery Full")
valueText: batVChargedFact ? batVChargedFact.valueString + " " + batVChargedFact.units : ""
}
VehicleSummaryRow {
labelText: qsTr("Battery Empty:")
labelText: qsTr("Battery Empty")
valueText: batVEmptyFact ? batVEmptyFact.valueString + " " + batVEmptyFact.units : ""
}
VehicleSummaryRow {
labelText: qsTr("Number of Cells:")
labelText: qsTr("Number of Cells")
valueText: batCellsFact ? batCellsFact.valueString : ""
}
}

54
src/AutoPilotPlugins/PX4/SafetyComponentSummary.qml

@ -14,46 +14,64 @@ FactPanel { @@ -14,46 +14,64 @@ FactPanel {
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
FactPanelController { id: controller; factPanel: panel }
property Fact returnAltFact: controller.getParameterFact(-1, "RTL_RETURN_ALT")
property Fact descendAltFact: controller.getParameterFact(-1, "RTL_DESCEND_ALT")
property Fact landDelayFact: controller.getParameterFact(-1, "RTL_LAND_DELAY")
property Fact commRCLossFact: controller.getParameterFact(-1, "COM_RC_LOSS_T")
property Fact lowBattAction: controller.getParameterFact(-1, "COM_LOW_BAT_ACT")
property Fact rcLossAction: controller.getParameterFact(-1, "NAV_RCL_ACT")
property Fact dataLossAction: controller.getParameterFact(-1, "NAV_DLL_ACT")
property Fact returnAltFact: controller.getParameterFact(-1, "RTL_RETURN_ALT")
property Fact _descendAltFact: controller.getParameterFact(-1, "RTL_DESCEND_ALT")
property Fact landDelayFact: controller.getParameterFact(-1, "RTL_LAND_DELAY")
property Fact commRCLossFact: controller.getParameterFact(-1, "COM_RC_LOSS_T")
property Fact lowBattAction: controller.getParameterFact(-1, "COM_LOW_BAT_ACT")
property Fact rcLossAction: controller.getParameterFact(-1, "NAV_RCL_ACT")
property Fact dataLossAction: controller.getParameterFact(-1, "NAV_DLL_ACT")
property Fact _rtlLandDelayFact: controller.getParameterFact(-1, "RTL_LAND_DELAY")
property int _rtlLandDelayValue: _rtlLandDelayFact.value
Column {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("RTL min alt:")
valueText: returnAltFact ? returnAltFact.valueString + " " + returnAltFact.units : ""
labelText: qsTr("Low Battery Failsafe")
valueText: lowBattAction ? lowBattAction.enumStringValue : ""
}
VehicleSummaryRow {
labelText: qsTr("RTL home alt:")
valueText: descendAltFact ? descendAltFact.valueString + " " + descendAltFact.units : ""
labelText: qsTr("RC Loss Failsafe")
valueText: rcLossAction ? rcLossAction.enumStringValue : ""
}
VehicleSummaryRow {
labelText: qsTr("RC loss RTL:")
labelText: qsTr("RC Loss Timeout")
valueText: commRCLossFact ? commRCLossFact.valueString + " " + commRCLossFact.units : ""
}
VehicleSummaryRow {
labelText: qsTr("RC loss action:")
valueText: rcLossAction ? rcLossAction.enumStringValue : ""
labelText: qsTr("Data Link Loss Failsafe")
valueText: dataLossAction ? dataLossAction.enumStringValue : ""
}
VehicleSummaryRow {
labelText: qsTr("Link loss action:")
valueText: dataLossAction ? dataLossAction.enumStringValue : ""
labelText: qsTr("RTL Climb To")
valueText: returnAltFact ? returnAltFact.valueString + " " + returnAltFact.units : ""
}
VehicleSummaryRow {
labelText: qsTr("Low battery action:")
valueText: lowBattAction ? lowBattAction.enumStringValue : ""
labelText: qsTr("RTL, Then")
valueText: _rtlLandDelayValue === 0 ?
qsTr("Land immediately") :
(_rtlLandDelayValue < 0 ?
qsTr("Loiter and do not land") :
qsTr("Loiter and land after specified time"))
}
VehicleSummaryRow {
labelText: qsTr("Loiter Alt")
valueText: _descendAltFact.valueString + " " + _descendAltFact.units
visible: _rtlLandDelayValue !== 0
}
VehicleSummaryRow {
labelText: qsTr("Land Delay")
valueText: _rtlLandDelayValue + " " + _rtlLandDelayFact.units
visible: _rtlLandDelayValue > 0
}
}
}

15
src/AutoPilotPlugins/PX4/SensorsComponent.cc

@ -20,11 +20,14 @@ const char* SensorsComponent::_airspeedBreakerParam = "CBRK_AIRSPD_CHK"; @@ -20,11 +20,14 @@ const char* SensorsComponent::_airspeedBreakerParam = "CBRK_AIRSPD_CHK";
const char* SensorsComponent::_airspeedDisabledParam = "FW_ARSP_MODE";
const char* SensorsComponent::_airspeedCalParam = "SENS_DPRES_OFF";
const char* SensorsComponent::_magEnabledParam = "SYS_HAS_MAG";
const char* SensorsComponent::_magCalParam = "CAL_MAG0_ID";
SensorsComponent::SensorsComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) :
VehicleComponent(vehicle, autopilot, parent),
_name(tr("Sensors"))
{
_deviceIds << QStringLiteral("CAL_MAG0_ID") << QStringLiteral("CAL_GYRO0_ID") << QStringLiteral("CAL_ACC0_ID");
_deviceIds << QStringLiteral("CAL_GYRO0_ID") << QStringLiteral("CAL_ACC0_ID");
}
QString SensorsComponent::name(void) const
@ -54,6 +57,14 @@ bool SensorsComponent::setupComplete(void) const @@ -54,6 +57,14 @@ bool SensorsComponent::setupComplete(void) const
return false;
}
}
bool magEnabled = true;
if (_vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, _magEnabledParam)) {
magEnabled = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _magEnabledParam)->rawValue().toBool();
}
if (magEnabled && _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _magCalParam)->rawValue().toFloat() == 0.0f) {
return false;
}
if (_vehicle->fixedWing() || _vehicle->vtol()) {
if (!_vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _airspeedDisabledParam)->rawValue().toBool() &&
@ -70,7 +81,7 @@ QStringList SensorsComponent::setupCompleteChangedTriggerList(void) const @@ -70,7 +81,7 @@ QStringList SensorsComponent::setupCompleteChangedTriggerList(void) const
{
QStringList triggers;
triggers << _deviceIds;
triggers << _deviceIds << _magCalParam << _magEnabledParam;
if (_vehicle->fixedWing() || _vehicle->vtol()) {
triggers << _airspeedCalParam << _airspeedBreakerParam;
}

3
src/AutoPilotPlugins/PX4/SensorsComponent.h

@ -44,6 +44,9 @@ private: @@ -44,6 +44,9 @@ private:
static const char* _airspeedDisabledParam;
static const char* _airspeedBreakerParam;
static const char* _airspeedCalParam;
static const char* _magEnabledParam;
static const char* _magCalParam;
};
#endif

95
src/AutoPilotPlugins/PX4/SensorsComponentController.cc

@ -7,10 +7,6 @@ @@ -7,10 +7,6 @@
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "SensorsComponentController.h"
#include "QGCMAVLink.h"
#include "UAS.h"
@ -22,46 +18,48 @@ @@ -22,46 +18,48 @@
QGC_LOGGING_CATEGORY(SensorsComponentControllerLog, "SensorsComponentControllerLog")
SensorsComponentController::SensorsComponentController(void) :
_statusLog(NULL),
_progressBar(NULL),
_compassButton(NULL),
_gyroButton(NULL),
_accelButton(NULL),
_airspeedButton(NULL),
_levelButton(NULL),
_cancelButton(NULL),
_setOrientationsButton(NULL),
_showOrientationCalArea(false),
_gyroCalInProgress(false),
_magCalInProgress(false),
_accelCalInProgress(false),
_orientationCalDownSideDone(false),
_orientationCalUpsideDownSideDone(false),
_orientationCalLeftSideDone(false),
_orientationCalRightSideDone(false),
_orientationCalNoseDownSideDone(false),
_orientationCalTailDownSideDone(false),
_orientationCalDownSideVisible(false),
_orientationCalUpsideDownSideVisible(false),
_orientationCalLeftSideVisible(false),
_orientationCalRightSideVisible(false),
_orientationCalNoseDownSideVisible(false),
_orientationCalTailDownSideVisible(false),
_orientationCalDownSideInProgress(false),
_orientationCalUpsideDownSideInProgress(false),
_orientationCalLeftSideInProgress(false),
_orientationCalRightSideInProgress(false),
_orientationCalNoseDownSideInProgress(false),
_orientationCalTailDownSideInProgress(false),
_orientationCalDownSideRotate(false),
_orientationCalUpsideDownSideRotate(false),
_orientationCalLeftSideRotate(false),
_orientationCalRightSideRotate(false),
_orientationCalNoseDownSideRotate(false),
_orientationCalTailDownSideRotate(false),
_unknownFirmwareVersion(false),
_waitingForCancel(false)
SensorsComponentController::SensorsComponentController(void)
: _statusLog (NULL)
, _progressBar (NULL)
, _compassButton (NULL)
, _gyroButton (NULL)
, _accelButton (NULL)
, _airspeedButton (NULL)
, _levelButton (NULL)
, _cancelButton (NULL)
, _setOrientationsButton (NULL)
, _showOrientationCalArea (false)
, _gyroCalInProgress (false)
, _magCalInProgress (false)
, _accelCalInProgress (false)
, _airspeedCalInProgress (false)
, _levelCalInProgress (false)
, _orientationCalDownSideDone (false)
, _orientationCalUpsideDownSideDone (false)
, _orientationCalLeftSideDone (false)
, _orientationCalRightSideDone (false)
, _orientationCalNoseDownSideDone (false)
, _orientationCalTailDownSideDone (false)
, _orientationCalDownSideVisible (false)
, _orientationCalUpsideDownSideVisible (false)
, _orientationCalLeftSideVisible (false)
, _orientationCalRightSideVisible (false)
, _orientationCalNoseDownSideVisible (false)
, _orientationCalTailDownSideVisible (false)
, _orientationCalDownSideInProgress (false)
, _orientationCalUpsideDownSideInProgress (false)
, _orientationCalLeftSideInProgress (false)
, _orientationCalRightSideInProgress (false)
, _orientationCalNoseDownSideInProgress (false)
, _orientationCalTailDownSideInProgress (false)
, _orientationCalDownSideRotate (false)
, _orientationCalUpsideDownSideRotate (false)
, _orientationCalLeftSideRotate (false)
, _orientationCalRightSideRotate (false)
, _orientationCalNoseDownSideRotate (false)
, _orientationCalTailDownSideRotate (false)
, _unknownFirmwareVersion (false)
, _waitingForCancel (false)
{
}
@ -165,7 +163,9 @@ void SensorsComponentController::_stopCalibration(SensorsComponentController::St @@ -165,7 +163,9 @@ void SensorsComponentController::_stopCalibration(SensorsComponentController::St
switch (code) {
case StopCalibrationSuccess:
_orientationCalAreaHelpText->setProperty("text", tr("Calibration complete"));
emit resetStatusTextArea();
if (!_airspeedCalInProgress && !_levelCalInProgress) {
emit resetStatusTextArea();
}
if (_magCalInProgress) {
emit setCompassRotations();
}
@ -186,6 +186,7 @@ void SensorsComponentController::_stopCalibration(SensorsComponentController::St @@ -186,6 +186,7 @@ void SensorsComponentController::_stopCalibration(SensorsComponentController::St
_magCalInProgress = false;
_accelCalInProgress = false;
_gyroCalInProgress = false;
_airspeedCalInProgress = false;
}
void SensorsComponentController::calibrateGyro(void)
@ -336,6 +337,10 @@ void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, in @@ -336,6 +337,10 @@ void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, in
emit orientationCalSidesVisibleChanged();
emit orientationCalSidesInProgressChanged();
_updateAndEmitShowOrientationCalArea(true);
} else if (text == "airspeed") {
_airspeedCalInProgress = true;
} else if (text == "level") {
_levelCalInProgress = true;
}
return;
}

4
src/AutoPilotPlugins/PX4/SensorsComponentController.h

@ -131,7 +131,9 @@ private: @@ -131,7 +131,9 @@ private:
bool _gyroCalInProgress;
bool _magCalInProgress;
bool _accelCalInProgress;
bool _airspeedCalInProgress;
bool _levelCalInProgress;
bool _orientationCalDownSideDone;
bool _orientationCalUpsideDownSideDone;
bool _orientationCalLeftSideDone;

10
src/AutoPilotPlugins/PX4/SensorsComponentSummary.qml

@ -29,29 +29,29 @@ FactPanel { @@ -29,29 +29,29 @@ FactPanel {
anchors.fill: parent
VehicleSummaryRow {
labelText: qsTr("Compass 0:")
labelText: qsTr("Compass 0")
valueText: mag0IdFact ? (mag0IdFact.value === 0 ? qsTr("Setup required") : qsTr("Ready")) : ""
}
VehicleSummaryRow {
labelText: qsTr("Compass 1:")
labelText: qsTr("Compass 1")
visible: mag1IdFact.value !== 0
valueText: qsTr("Ready")
}
VehicleSummaryRow {
labelText: qsTr("Compass 2:")
labelText: qsTr("Compass 2")
visible: mag2IdFact.value !== 0
valueText: qsTr("Ready")
}
VehicleSummaryRow {
labelText: qsTr("Gyro:")
labelText: qsTr("Gyro")
valueText: gyro0IdFact ? (gyro0IdFact.value === 0 ? qsTr("Setup required") : qsTr("Ready")) : ""
}
VehicleSummaryRow {
labelText: qsTr("Accelerometer:")
labelText: qsTr("Accelerometer")
valueText: accel0IdFact ? (accel0IdFact.value === 0 ? qsTr("Setup required") : qsTr("Ready")) : ""
}
}

2
src/AutoPilotPlugins/PX4/SensorsComponentSummaryFixedWing.qml

@ -25,7 +25,7 @@ FactPanel { @@ -25,7 +25,7 @@ FactPanel {
property Fact airspeedDisabledFact: controller.getParameterFact(-1, "FW_ARSP_MODE")
property Fact airspeedBreakerFact: controller.getParameterFact(-1, "CBRK_AIRSPD_CHK")
property bool _airspeedVisible: airspeedDisabledFact.value === false && airspeedBreakerFact.value !== 162128
property bool _airspeedVisible: airspeedDisabledFact.value == 0 && airspeedBreakerFact.value !== 162128
property bool _airspeedCalRequired: _airspeedVisible && dpressOffFact.value === 0
Column {

27
src/AutoPilotPlugins/PX4/SensorsSetup.qml

@ -140,9 +140,7 @@ Item { @@ -140,9 +140,7 @@ Item {
onWaitingForCancelChanged: {
if (controller.waitingForCancel) {
showMessage(qsTr("Calibration Cancel"), qsTr("Waiting for Vehicle to response to Cancel. This may take a few seconds."), 0)
} else {
hideDialog()
showDialog(waitForCancelDialogComponent, qsTr("Calibration Cancel"), qgcView.showDialogDefaultWidth, 0)
}
}
}
@ -155,6 +153,24 @@ Item { @@ -155,6 +153,24 @@ Item {
}
Component {
id: waitForCancelDialogComponent
QGCViewMessage {
message: qsTr("Waiting for Vehicle to response to Cancel. This may take a few seconds.")
Connections {
target: controller
onWaitingForCancelChanged: {
if (!controller.waitingForCancel) {
hideDialog()
}
}
}
}
}
Component {
id: preCalibrationDialogComponent
QGCViewDialog {
@ -349,11 +365,12 @@ Item { @@ -349,11 +365,12 @@ Item {
spacing: ScreenTools.defaultFontPixelHeight / 2
IndicatorButton {
property bool _hasMag: controller.parameterExists(-1, "SYS_HAS_MAG") ? controller.getParameterFact(-1, "SYS_HAS_MAG").value !== 0 : true
id: compassButton
width: _buttonWidth
text: qsTr("Compass")
indicatorGreen: cal_mag0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationCompass && showSensorCalibrationCompass
visible: _hasMag && QGroundControl.corePlugin.options.showSensorCalibrationCompass && showSensorCalibrationCompass
onClicked: {
preCalibrationDialogType = "compass"
@ -410,7 +427,7 @@ Item { @@ -410,7 +427,7 @@ Item {
width: _buttonWidth
text: qsTr("Airspeed")
visible: (controller.vehicle.fixedWing || controller.vehicle.vtol) &&
controller.getParameterFact(-1, "FW_ARSP_MODE").value === false &&
controller.getParameterFact(-1, "FW_ARSP_MODE").value == 0 &&
controller.getParameterFact(-1, "CBRK_AIRSPD_CHK").value !== 162128 &&
QGroundControl.corePlugin.options.showSensorCalibrationAirspeed &&
showSensorCalibrationAirspeed

2
src/Camera/QGCCameraControl.cc

@ -790,7 +790,7 @@ QGCCameraControl::_loadSettings(const QDomNodeList nodeList) @@ -790,7 +790,7 @@ QGCCameraControl::_loadSettings(const QDomNodeList nodeList)
QVariant typedValue;
QString errorString;
if (metaData->convertAndValidateRaw(attr, true /* convertOnly */, typedValue, errorString)) {
metaData->setIncrement(typedValue.toDouble());
metaData->setRawIncrement(typedValue.toDouble());
} else {
qWarning() << "Invalid step value for" << factName
<< " type:" << metaData->type()

56
src/FactSystem/Fact.cc

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
****************************************************************************/
#include "Fact.h"
#include "FactValueSliderListModel.h"
#include "QGCMAVLink.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
@ -18,13 +19,14 @@ @@ -18,13 +19,14 @@
static const char* kMissingMetadata = "Meta data pointer missing";
Fact::Fact(QObject* parent)
: QObject(parent)
, _componentId(-1)
, _rawValue(0)
, _type(FactMetaData::valueTypeInt32)
, _metaData(NULL)
, _sendValueChangedSignals(true)
: QObject (parent)
, _componentId (-1)
, _rawValue (0)
, _type (FactMetaData::valueTypeInt32)
, _metaData (NULL)
, _sendValueChangedSignals (true)
, _deferredValueChangeSignal(false)
, _valueSliderModel (NULL)
{
FactMetaData* metaData = new FactMetaData(_type, this);
setMetaData(metaData);
@ -34,14 +36,15 @@ Fact::Fact(QObject* parent) @@ -34,14 +36,15 @@ Fact::Fact(QObject* parent)
}
Fact::Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent)
: QObject(parent)
, _name(name)
, _componentId(componentId)
, _rawValue(0)
, _type(type)
, _metaData(NULL)
, _sendValueChangedSignals(true)
: QObject (parent)
, _name (name)
, _componentId (componentId)
, _rawValue (0)
, _type (type)
, _metaData (NULL)
, _sendValueChangedSignals (true)
, _deferredValueChangeSignal(false)
, _valueSliderModel (NULL)
{
FactMetaData* metaData = new FactMetaData(_type, this);
setMetaData(metaData);
@ -57,9 +60,8 @@ Fact::Fact(FactMetaData* metaData, QObject* parent) @@ -57,9 +60,8 @@ Fact::Fact(FactMetaData* metaData, QObject* parent)
, _metaData (NULL)
, _sendValueChangedSignals (true)
, _deferredValueChangeSignal(false)
, _valueSliderModel (NULL)
{
// Allow core plugin a chance to override the default value
qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(*metaData);
setMetaData(metaData, true /* setDefaultFromMetaData */);
}
@ -78,7 +80,7 @@ const Fact& Fact::operator=(const Fact& other) @@ -78,7 +80,7 @@ const Fact& Fact::operator=(const Fact& other)
_type = other._type;
_sendValueChangedSignals = other._sendValueChangedSignals;
_deferredValueChangeSignal = other._deferredValueChangeSignal;
_valueSliderModel = NULL;
if (_metaData && other._metaData) {
*_metaData = *other._metaData;
} else {
@ -633,10 +635,20 @@ QString Fact::enumOrValueString(void) @@ -633,10 +635,20 @@ QString Fact::enumOrValueString(void)
return QString();
}
double Fact::increment(void) const
double Fact::rawIncrement(void) const
{
if (_metaData) {
return _metaData->increment();
return _metaData->rawIncrement();
} else {
qWarning() << kMissingMetadata << name();
}
return std::numeric_limits<double>::quiet_NaN();
}
double Fact::cookedIncrement(void) const
{
if (_metaData) {
return _metaData->cookedIncrement();
} else {
qWarning() << kMissingMetadata << name();
}
@ -682,3 +694,11 @@ bool Fact::volatileValue(void) const @@ -682,3 +694,11 @@ bool Fact::volatileValue(void) const
return false;
}
}
FactValueSliderListModel* Fact::valueSliderModel(void)
{
if (!_valueSliderModel) {
_valueSliderModel = new FactValueSliderListModel(*this);
}
return _valueSliderModel;
}

11
src/FactSystem/Fact.h

@ -20,6 +20,9 @@ @@ -20,6 +20,9 @@
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QAbstractListModel>
class FactValueSliderListModel;
/// @brief A Fact is used to hold a single value within the system.
class Fact : public QObject
@ -66,7 +69,7 @@ public: @@ -66,7 +69,7 @@ public:
Q_PROPERTY(bool valueEqualsDefault READ valueEqualsDefault NOTIFY valueChanged)
Q_PROPERTY(QString valueString READ cookedValueString NOTIFY valueChanged)
Q_PROPERTY(QString enumOrValueString READ enumOrValueString NOTIFY valueChanged)
Q_PROPERTY(double increment READ increment CONSTANT)
Q_PROPERTY(double increment READ cookedIncrement CONSTANT)
Q_PROPERTY(bool typeIsString READ typeIsString CONSTANT)
Q_PROPERTY(bool typeIsBool READ typeIsBool CONSTANT)
Q_PROPERTY(bool hasControl READ hasControl CONSTANT)
@ -115,7 +118,8 @@ public: @@ -115,7 +118,8 @@ public:
bool valueEqualsDefault (void) const;
bool rebootRequired (void) const;
QString enumOrValueString (void); // This is not const, since an unknown value can modify the enum lists
double increment (void) const;
double rawIncrement (void) const;
double cookedIncrement (void) const;
bool typeIsString (void) const { return type() == FactMetaData::valueTypeString; }
bool typeIsBool (void) const { return type() == FactMetaData::valueTypeBool; }
bool hasControl (void) const;
@ -123,6 +127,8 @@ public: @@ -123,6 +127,8 @@ public:
bool writeOnly (void) const;
bool volatileValue (void) const;
Q_INVOKABLE FactValueSliderListModel* valueSliderModel(void);
/// Returns the values as a string with full 18 digit precision if float/double.
QString rawValueStringFullPrecision(void) const;
@ -192,6 +198,7 @@ protected: @@ -192,6 +198,7 @@ protected:
FactMetaData* _metaData;
bool _sendValueChangedSignals;
bool _deferredValueChangeSignal;
FactValueSliderListModel* _valueSliderModel;
};
#endif

5
src/FactSystem/FactControls/FactCheckBox.qml

@ -8,7 +8,8 @@ import QGroundControl.Controls 1.0 @@ -8,7 +8,8 @@ import QGroundControl.Controls 1.0
QGCCheckBox {
property Fact fact: Fact { }
property variant checkedValue: 1
property variant uncheckedValue: 0
checkedState: fact ?
(fact.typeIsBool ?
(fact.value === false ? Qt.Unchecked : Qt.Checked) :
@ -17,5 +18,5 @@ QGCCheckBox { @@ -17,5 +18,5 @@ QGCCheckBox {
text: qsTr("Label")
onClicked: fact.value = checked ? 1 : 0
onClicked: fact.value = (checked ? checkedValue : uncheckedValue)
}

2
src/FactSystem/FactControls/FactPanelController.cc

@ -88,6 +88,8 @@ void FactPanelController::_reportMissingParameter(int componentId, const QString @@ -88,6 +88,8 @@ void FactPanelController::_reportMissingParameter(int componentId, const QString
QString missingParam = QString("%1:%2").arg(componentId).arg(name);
qCWarning(FactPanelControllerLog) << "Missing parameter:" << missingParam;
// If missing parameters a reported from the constructor of a derived class we
// will not have access to _factPanel yet. Just record list of missing facts
// in that case instead of notify. Once _factPanel is available they will be

5
src/FactSystem/FactControls/FactTextField.qml

@ -20,16 +20,11 @@ QGCTextField { @@ -20,16 +20,11 @@ QGCTextField {
property string _validateString
// At this point all Facts are numeric
inputMethodHints: ((fact && fact.typeIsString) || ScreenTools.isiOS) ?
Qt.ImhNone : // iOS numeric keyboard has no done button, we can't use it
Qt.ImhFormattedNumbersOnly // Forces use of virtual numeric keyboard
onEditingFinished: {
if (ScreenTools.isMobile) {
// Toss focus on mobile after Done on virtual keyboard. Prevent strange interactions.
focus = false
}
if (typeof qgcView !== 'undefined' && qgcView) {
var errorString = fact.validate(text, false /* convertOnly */)
if (errorString === "") {

144
src/FactSystem/FactControls/FactValueSlider.qml

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
Rectangle {
height: _itemHeight
width: _totalSlots * _itemWidth
color: qgcPal.textField
property Fact fact: undefined
property int digitCount: 4 ///< The number of digits to show for each value
property int incrementSlots: 1 ///< The number of visible slots to left/right of center value
property int _totalDigitCount: digitCount + 1 + fact.units.length
property real _margins: (ScreenTools.implicitTextFieldHeight - ScreenTools.defaultFontPixelHeight) / 2
property real _increment: fact.increment
property real _value: fact.value
property int _decimalPlaces: fact.decimalPlaces
property string _units: fact.units
property real _prevValue: _value - _increment
property real _nextValue: _value + _increment
property real _itemWidth: (_totalDigitCount * ScreenTools.defaultFontPixelWidth) + (_margins * 2)
property real _itemHeight: ScreenTools.implicitTextFieldHeight
property var _valueModel
property int _totalSlots: (incrementSlots * 2) + 1
property int _currentIndex: _totalSlots / 2
property int _currentRelativeIndex: _currentIndex
property int _prevIncrementSlots: incrementSlots
property int _nextIncrementSlots: incrementSlots
property int _selectionWidth: 3
property var _model: fact.valueSliderModel()
property var _fact: fact
QGCPalette { id: qgcPal; colorGroupEnabled: parent.enabled }
QGCPalette { id: qgcPalDisabled; colorGroupEnabled: false }
function firstVisibleIndex() {
return valueListView.contentX / _itemWidth
}
function recalcRelativeIndex() {
_currentRelativeIndex = _currentIndex - firstVisibleIndex()
_prevIncrementSlots = _currentRelativeIndex
_nextIncrementSlots = _totalSlots - _currentRelativeIndex - 1
}
function reset() {
valueListView.positionViewAtIndex(0, ListView.Beginning)
_currentIndex = _model.resetInitialValue()
valueListView.positionViewAtIndex(_currentIndex, ListView.Center)
recalcRelativeIndex()
}
Component.onCompleted: {
valueListView.maximumFlickVelocity = valueListView.maximumFlickVelocity / 2
reset()
}
Connections {
target: _fact
onValueChanged: reset()
}
Component {
id: editDialogComponent
ParameterEditorDialog {
fact: _fact
}
}
QGCListView {
id: valueListView
anchors.fill: parent
orientation: ListView.Horizontal
snapMode: ListView.SnapToItem
clip: true
model: _model
delegate: QGCLabel {
width: _itemWidth
height: _itemHeight
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: value + " " + _units
color: qgcPal.textFieldText
MouseArea {
anchors.fill: parent
onClicked: {
valueListView.focus = true
if (_currentIndex === index) {
qgcView.showDialog(editDialogComponent, qsTr("Value Details"), qgcView.showDialogDefaultWidth, StandardButton.Save | StandardButton.Cancel)
} else {
_currentIndex = index
valueListView.positionViewAtIndex(_currentIndex, ListView.Center)
recalcRelativeIndex()
fact.value = value
}
}
}
}
onMovementStarted: valueListView.focus = true
onMovementEnded: {
_currentIndex = firstVisibleIndex() + _currentRelativeIndex
fact.value = _model.valueAtModelIndex(_currentIndex)
}
}
Rectangle {
id: leftOverlay
width: _itemWidth * _prevIncrementSlots
height: _itemHeight
color: qgcPal.textField
opacity: 0.5
}
Rectangle {
width: _itemWidth * _nextIncrementSlots
height: _itemHeight
anchors.right: parent.right
color: qgcPal.textField
opacity: 0.5
}
Rectangle {
x: _currentRelativeIndex * _itemWidth - _borderWidth
y: -_borderWidth
width: _itemWidth + (_borderWidth * 2)
height: _itemHeight + (_borderWidth * 2)
border.width: _borderWidth
border.color: qgcPal.brandingBlue
color: "transparent"
readonly property int _borderWidth: 3
}
}

1
src/FactSystem/FactControls/qmldir

@ -8,3 +8,4 @@ FactPanel 1.0 FactPanel.qml @@ -8,3 +8,4 @@ FactPanel 1.0 FactPanel.qml
FactTextField 1.0 FactTextField.qml
FactTextFieldGrid 1.0 FactTextFieldGrid.qml
FactTextFieldRow 1.0 FactTextFieldRow.qml
FactValueSlider 1.0 FactValueSlider.qml

1
src/FactSystem/FactGroup.cc

@ -105,6 +105,7 @@ void FactGroup::_addFact(Fact* fact, const QString& name) @@ -105,6 +105,7 @@ void FactGroup::_addFact(Fact* fact, const QString& name)
fact->setMetaData(_nameToFactMetaDataMap[name]);
}
_nameToFactMap[name] = fact;
_factNames.append(name);
}
void FactGroup::_addFactGroup(FactGroup* factGroup, const QString& name)

4
src/FactSystem/FactGroup.h

@ -38,7 +38,7 @@ public: @@ -38,7 +38,7 @@ public:
/// @return FactGroup for specified name, NULL if not found
Q_INVOKABLE FactGroup* getFactGroup(const QString& name);
QStringList factNames(void) const { return _nameToFactMap.keys(); }
QStringList factNames(void) const { return _factNames; }
QStringList factGroupNames(void) const { return _nameToFactGroupMap.keys(); }
protected:
@ -59,7 +59,7 @@ protected: @@ -59,7 +59,7 @@ protected:
QMap<QString, Fact*> _nameToFactMap;
QMap<QString, FactGroup*> _nameToFactGroupMap;
QMap<QString, FactMetaData*> _nameToFactMetaDataMap;
QStringList _factNames;
};
#endif

106
src/FactSystem/FactMetaData.cc

@ -78,6 +78,7 @@ const char* FactMetaData::_defaultValueJsonKey = "defaultValue"; @@ -78,6 +78,7 @@ const char* FactMetaData::_defaultValueJsonKey = "defaultValue";
const char* FactMetaData::_mobileDefaultValueJsonKey = "mobileDefaultValue";
const char* FactMetaData::_minJsonKey = "min";
const char* FactMetaData::_maxJsonKey = "max";
const char* FactMetaData::_incrementJsonKey = "increment";
const char* FactMetaData::_hasControlJsonKey = "control";
FactMetaData::FactMetaData(QObject* parent)
@ -93,7 +94,7 @@ FactMetaData::FactMetaData(QObject* parent) @@ -93,7 +94,7 @@ FactMetaData::FactMetaData(QObject* parent)
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rebootRequired (false)
, _increment (std::numeric_limits<double>::quiet_NaN())
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
, _writeOnly (false)
@ -116,7 +117,7 @@ FactMetaData::FactMetaData(ValueType_t type, QObject* parent) @@ -116,7 +117,7 @@ FactMetaData::FactMetaData(ValueType_t type, QObject* parent)
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rebootRequired (false)
, _increment (std::numeric_limits<double>::quiet_NaN())
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
, _writeOnly (false)
@ -146,7 +147,7 @@ FactMetaData::FactMetaData(ValueType_t type, const QString name, QObject* parent @@ -146,7 +147,7 @@ FactMetaData::FactMetaData(ValueType_t type, const QString name, QObject* parent
, _rawTranslator (_defaultTranslator)
, _cookedTranslator (_defaultTranslator)
, _rebootRequired (false)
, _increment (std::numeric_limits<double>::quiet_NaN())
, _rawIncrement (std::numeric_limits<double>::quiet_NaN())
, _hasControl (true)
, _readOnly (false)
, _writeOnly (false)
@ -180,7 +181,7 @@ const FactMetaData& FactMetaData::operator=(const FactMetaData& other) @@ -180,7 +181,7 @@ const FactMetaData& FactMetaData::operator=(const FactMetaData& other)
_rawTranslator = other._rawTranslator;
_cookedTranslator = other._cookedTranslator;
_rebootRequired = other._rebootRequired;
_increment = other._increment;
_rawIncrement = other._rawIncrement;
_hasControl = other._hasControl;
_readOnly = other._readOnly;
_writeOnly = other._writeOnly;
@ -615,7 +616,7 @@ void FactMetaData::setBuiltInTranslator(void) @@ -615,7 +616,7 @@ void FactMetaData::setBuiltInTranslator(void)
for (size_t i=0; i<sizeof(_rgBuiltInTranslations)/sizeof(_rgBuiltInTranslations[0]); i++) {
const BuiltInTranslation_s* pBuiltInTranslation = &_rgBuiltInTranslations[i];
if (pBuiltInTranslation->rawUnits == _rawUnits.toLower()) {
if (pBuiltInTranslation->rawUnits.toLower() == _rawUnits.toLower()) {
_cookedUnits = pBuiltInTranslation->cookedUnits;
setTranslators(pBuiltInTranslation->rawTranslator, pBuiltInTranslation->cookedTranslator);
return;
@ -874,13 +875,33 @@ void FactMetaData::_setAppSettingsTranslators(void) @@ -874,13 +875,33 @@ void FactMetaData::_setAppSettingsTranslators(void)
if (!_enumStrings.count() && (type() == valueTypeDouble || type() == valueTypeFloat)) {
for (size_t i=0; i<sizeof(_rgAppSettingsTranslations)/sizeof(_rgAppSettingsTranslations[0]); i++) {
const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i];
if (pAppSettingsTranslation->rawUnits == _rawUnits.toLower() && (
(pAppSettingsTranslation->unitType == UnitTemperature && pAppSettingsTranslation->unitOption == qgcApp()->toolbox()->settingsManager()->unitsSettings()->temperatureUnits()->rawValue().toUInt()) ||
(pAppSettingsTranslation->unitType == UnitSpeed && pAppSettingsTranslation->unitOption == qgcApp()->toolbox()->settingsManager()->unitsSettings()->speedUnits()->rawValue().toUInt()) ||
(pAppSettingsTranslation->unitType == UnitDistance && pAppSettingsTranslation->unitOption == qgcApp()->toolbox()->settingsManager()->unitsSettings()->distanceUnits()->rawValue().toUInt()) ||
(pAppSettingsTranslation->unitType == UnitArea && pAppSettingsTranslation->unitOption == qgcApp()->toolbox()->settingsManager()->unitsSettings()->areaUnits()->rawValue().toUInt())))
{
_cookedUnits = pAppSettingsTranslation->cookedUnits;
if (_rawUnits.toLower() != pAppSettingsTranslation->rawUnits.toLower()) {
continue;
}
UnitsSettings* settings = qgcApp()->toolbox()->settingsManager()->unitsSettings();
uint settingsUnits = 0;
switch (pAppSettingsTranslation->unitType) {
case UnitDistance:
settingsUnits = settings->distanceUnits()->rawValue().toUInt();
break;
case UnitSpeed:
settingsUnits = settings->speedUnits()->rawValue().toUInt();
break;
case UnitArea:
settingsUnits = settings->areaUnits()->rawValue().toUInt();
break;
case UnitTemperature:
settingsUnits = settings->temperatureUnits()->rawValue().toUInt();
break;
default:
break;
}
if (settingsUnits == pAppSettingsTranslation->unitOption) {
_cookedUnits = pAppSettingsTranslation->cookedUnits;
setTranslators(pAppSettingsTranslation->rawTranslator, pAppSettingsTranslation->cookedTranslator);
return;
}
@ -892,8 +913,15 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsDist @@ -892,8 +913,15 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsDist
{
for (size_t i=0; i<sizeof(_rgAppSettingsTranslations)/sizeof(_rgAppSettingsTranslations[0]); i++) {
const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i];
if (pAppSettingsTranslation->rawUnits == rawUnits.toLower() &&
(pAppSettingsTranslation->unitType == UnitDistance && pAppSettingsTranslation->unitOption == qgcApp()->toolbox()->settingsManager()->unitsSettings()->distanceUnits()->rawValue().toUInt())) {
if (rawUnits.toLower() != pAppSettingsTranslation->rawUnits.toLower()) {
continue;
}
uint settingsUnits = qgcApp()->toolbox()->settingsManager()->unitsSettings()->areaUnits()->rawValue().toUInt();
if (pAppSettingsTranslation->unitType == UnitDistance
&& pAppSettingsTranslation->unitOption == settingsUnits) {
return pAppSettingsTranslation;
}
}
@ -904,8 +932,15 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsArea @@ -904,8 +932,15 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsArea
{
for (size_t i=0; i<sizeof(_rgAppSettingsTranslations)/sizeof(_rgAppSettingsTranslations[0]); i++) {
const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i];
if (pAppSettingsTranslation->rawUnits == rawUnits.toLower() &&
(pAppSettingsTranslation->unitType == UnitArea && pAppSettingsTranslation->unitOption == qgcApp()->toolbox()->settingsManager()->unitsSettings()->areaUnits()->rawValue().toUInt())) {
if (rawUnits.toLower() != pAppSettingsTranslation->rawUnits.toLower()) {
continue;
}
uint settingsUnits = qgcApp()->toolbox()->settingsManager()->unitsSettings()->areaUnits()->rawValue().toUInt();
if (pAppSettingsTranslation->unitType == UnitArea
&& pAppSettingsTranslation->unitOption == settingsUnits) {
return pAppSettingsTranslation;
}
}
@ -973,13 +1008,18 @@ QString FactMetaData::appSettingsAreaUnitsString(void) @@ -973,13 +1008,18 @@ QString FactMetaData::appSettingsAreaUnitsString(void)
}
}
double FactMetaData::cookedIncrement(void) const
{
return _rawTranslator(this->rawIncrement()).toDouble();
}
int FactMetaData::decimalPlaces(void) const
{
int actualDecimalPlaces = defaultDecimalPlaces;
int incrementDecimalPlaces = unknownDecimalPlaces;
// First determine decimal places from increment
double increment = _rawTranslator(this->increment()).toDouble();
double increment = _rawTranslator(this->rawIncrement()).toDouble();
if (!qIsNaN(increment)) {
double integralPart;
@ -1024,12 +1064,18 @@ FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QObjec @@ -1024,12 +1064,18 @@ FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QObjec
return new FactMetaData(valueTypeUint32, metaDataParent);
}
// Validate key types
QStringList keys;
QList<QJsonValue::Type> types;
keys << _nameJsonKey << _decimalPlacesJsonKey << _typeJsonKey << _shortDescriptionJsonKey << _longDescriptionJsonKey << _unitsJsonKey << _minJsonKey << _maxJsonKey << _hasControlJsonKey;
types << QJsonValue::String << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Double << QJsonValue::Double << QJsonValue::Bool;
if (!JsonHelper::validateKeyTypes(json, keys, types, errorString)) {
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ _nameJsonKey, QJsonValue::String, true },
{ _typeJsonKey, QJsonValue::String, true },
{ _shortDescriptionJsonKey, QJsonValue::String, false },
{ _longDescriptionJsonKey, QJsonValue::String, false },
{ _unitsJsonKey, QJsonValue::String, false },
{ _decimalPlacesJsonKey, QJsonValue::Double, false },
{ _minJsonKey, QJsonValue::Double, false },
{ _maxJsonKey, QJsonValue::Double, false },
{ _hasControlJsonKey, QJsonValue::Bool, false },
};
if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) {
qWarning() << errorString;
return new FactMetaData(valueTypeUint32, metaDataParent);
}
@ -1095,6 +1141,20 @@ FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QObjec @@ -1095,6 +1141,20 @@ FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QObjec
}
}
if (json.contains(_incrementJsonKey)) {
QVariant typedValue;
QString errorString;
QVariant initialValue = json[_incrementJsonKey].toVariant();
if (metaData->convertAndValidateRaw(initialValue, true /* convertOnly */, typedValue, errorString)) {
metaData->setRawIncrement(typedValue.toDouble());
} else {
qWarning() << "Invalid increment value, name:" << metaData->name()
<< " type:" << metaData->type()
<< " value:" << initialValue
<< " error:" << errorString;
}
}
if (json.contains(_minJsonKey)) {
QVariant typedValue;
QString errorString;

12
src/FactSystem/FactMetaData.h

@ -111,7 +111,8 @@ public: @@ -111,7 +111,8 @@ public:
/// Amount to increment value when used in controls such as spin button or slider with detents.
/// NaN for no increment available.
double increment (void) const { return _increment; }
double rawIncrement (void) const { return _rawIncrement; }
double cookedIncrement (void) const;
Translator rawTranslator (void) const { return _rawTranslator; }
Translator cookedTranslator (void) const { return _cookedTranslator; }
@ -135,7 +136,7 @@ public: @@ -135,7 +136,7 @@ public:
void setShortDescription(const QString& shortDescription) { _shortDescription = shortDescription; }
void setRawUnits (const QString& rawUnits);
void setRebootRequired (bool rebootRequired) { _rebootRequired = rebootRequired; }
void setIncrement (double increment) { _increment = increment; }
void setRawIncrement (double increment) { _rawIncrement = increment; }
void setHasControl (bool bValue) { _hasControl = bValue; }
void setReadOnly (bool bValue) { _readOnly = bValue; }
void setWriteOnly (bool bValue) { _writeOnly = bValue; }
@ -215,7 +216,7 @@ private: @@ -215,7 +216,7 @@ private:
};
struct AppSettingsTranslation_s {
const char* rawUnits;
QString rawUnits;
const char* cookedUnits;
UnitTypes unitType;
uint32_t unitOption;
@ -248,7 +249,7 @@ private: @@ -248,7 +249,7 @@ private:
Translator _rawTranslator;
Translator _cookedTranslator;
bool _rebootRequired;
double _increment;
double _rawIncrement;
bool _hasControl;
bool _readOnly;
bool _writeOnly;
@ -264,7 +265,7 @@ private: @@ -264,7 +265,7 @@ private:
} constants;
struct BuiltInTranslation_s {
const char* rawUnits;
QString rawUnits;
const char* cookedUnits;
Translator rawTranslator;
Translator cookedTranslator;
@ -285,6 +286,7 @@ private: @@ -285,6 +286,7 @@ private:
static const char* _mobileDefaultValueJsonKey;
static const char* _minJsonKey;
static const char* _maxJsonKey;
static const char* _incrementJsonKey;
static const char* _hasControlJsonKey;
};

4
src/FactSystem/FactSystem.h

@ -20,10 +20,6 @@ @@ -20,10 +20,6 @@
/// The components of the FactSystem are a Fact which holds an individual value. FactMetaData holds
/// additional meta data associated with a Fact such as description, min/max ranges and so forth.
/// The FactValidator object is a QML validator which validates input according to the FactMetaData
/// settings. Client code can then use this system to expose sets of Facts to QML code. An example
/// of this is the PX4ParameterMetaData onbject which is part of the PX4 AutoPilot plugin. It exposes
/// the firmware parameters to QML such that you can bind QML ui elements directly to parameters.
class FactSystem : public QGCTool
{

33
src/FactSystem/FactValidator.cc

@ -1,33 +0,0 @@ @@ -1,33 +0,0 @@
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "FactValidator.h"
FactValidator::FactValidator(QObject* parent) :
QValidator(parent)
{
}
void FactValidator::fixup(QString& input) const
{
Q_UNUSED(input);
}
FactValidator::State FactValidator::validate(QString& input, int& pos) const
{
Q_UNUSED(input);
Q_UNUSED(pos);
return Acceptable;
}

56
src/FactSystem/FactValidator.h

@ -1,56 +0,0 @@ @@ -1,56 +0,0 @@
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef FactValidator_H
#define FactValidator_H
#include <QValidator>
class Fact;
/// QML Validator for Facts (Work In Progress)
///
/// The validator uses the FactMetaData to impose restrictions on the input. It is used as follows:
/// @code{.unparsed}
/// TextInput {
/// validator: FactValidator { fact: parameters["RC_MAP_THROTTLE"]; }
/// }
/// @endcode
class FactValidator : public QValidator
{
Q_OBJECT
Q_PROPERTY(Fact* fact READ fact WRITE setFact)
public:
FactValidator(QObject* parent = NULL);
// Property system methods
/// Read accessor for fact property
Fact* fact(void) { return _fact; }
/// Write accessor for fact property
void setFact(Fact* fact) { _fact = fact; }
/// Override from QValidator
virtual void fixup(QString& input) const;
/// Override from QValidator
virtual State validate(QString& input, int& pos) const;
private:
Fact* _fact; ///< Fact that the validator is working on
};
#endif

128
src/FactSystem/FactValueSliderListModel.cc

@ -0,0 +1,128 @@ @@ -0,0 +1,128 @@
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "FactValueSliderListModel.h"
#include <QDebug>
#include <QQmlEngine>
#include <QtMath>
#include <math.h>
const int FactValueSliderListModel::_valueRole = Qt::UserRole;
const int FactValueSliderListModel::_valueIndexRole = Qt::UserRole + 1;
FactValueSliderListModel::FactValueSliderListModel(Fact& fact, QObject* parent)
: QAbstractListModel (parent)
, _fact (fact)
, _cValues (0)
, _firstValueIndexInWindow (0)
, _initialValueIndex (0)
, _cPrevValues (0)
, _cNextValues (0)
, _initialValue (0)
, _initialValueRounded (0)
, _increment (0)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
}
FactValueSliderListModel::~FactValueSliderListModel()
{
}
int FactValueSliderListModel::resetInitialValue(void)
{
if (_cValues > 0) {
// Remove any old rows
beginRemoveRows(QModelIndex(), 0, _cValues - 1);
_cValues = 0;
endRemoveRows();
}
_initialValue = _fact.cookedValue().toDouble();
_initialValueRounded = qRound(_initialValue);
if (qRound(_fact.rawIncrement()) == _fact.rawIncrement()) {
_increment = qRound(_fact.cookedIncrement());
} else {
_increment = _fact.cookedIncrement();
}
_cPrevValues = qMin((_initialValue - _fact.cookedMin().toDouble()), 1000.0) / _increment;
_cNextValues = qMin((_fact.cookedMax().toDouble() - _initialValue), 1000.0) / _increment;
_initialValueIndex = _cPrevValues;
int totalValueCount = _cPrevValues + 1 + _cNextValues;
beginInsertRows(QModelIndex(), 0, totalValueCount - 1);
_cValues = totalValueCount;
endInsertRows();
return _initialValueIndex;
}
int FactValueSliderListModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return _cValues;
}
QVariant FactValueSliderListModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(role);
if (!index.isValid()) {
return QVariant();
}
int valueIndex = index.row();
if (valueIndex >= _cValues) {
return QVariant();
}
if (role == _valueRole) {
double value;
int cIncrementCount = valueIndex - _initialValueIndex;
if (cIncrementCount == 0) {
value = _initialValue;
} else {
value = _initialValueRounded + (cIncrementCount * _increment);
}
double precision = qPow(10, _fact.decimalPlaces());
double atPrecision = qRound(value * precision) / precision;
//qDebug() << value << precision << atPrecision << _fact.decimalPlaces() << _fact.name();
return QVariant(atPrecision);
} else if (role == _valueIndexRole) {
return QVariant::fromValue(valueIndex);
} else {
return QVariant();
}
}
QHash<int, QByteArray> FactValueSliderListModel::roleNames(void) const
{
QHash<int, QByteArray> hash;
hash[_valueRole] = "value";
hash[_valueIndexRole] = "valueIndex";
return hash;
}
double FactValueSliderListModel::valueAtModelIndex(int index)
{
return data(createIndex(index, 0), _valueRole).toDouble();
}
int FactValueSliderListModel::valueIndexAtModelIndex(int index)
{
return data(createIndex(index, 0), _valueIndexRole).toInt();
}

48
src/FactSystem/FactValueSliderListModel.h

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include <QAbstractListModel>
#include "Fact.h"
/// Provides a list model of values for incrementing/decrementing the value of a Fact
class FactValueSliderListModel : public QAbstractListModel
{
Q_OBJECT
public:
FactValueSliderListModel(Fact& fact, QObject* parent = NULL);
~FactValueSliderListModel();
Q_INVOKABLE int resetInitialValue(void);
Q_INVOKABLE double valueAtModelIndex(int index);
Q_INVOKABLE int valueIndexAtModelIndex(int index);
private:
// Overrides from QAbstractListModel
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames(void) const override;
Fact& _fact;
int _cValues;
int _firstValueIndexInWindow;
int _initialValueIndex;
int _cPrevValues;
int _cNextValues;
int _windowSize;
double _initialValue;
double _initialValueRounded;
double _increment;
static const int _valueRole;
static const int _valueIndexRole;
};

8
src/FactSystem/ParameterManager.cc

@ -86,7 +86,7 @@ ParameterManager::ParameterManager(Vehicle* vehicle) @@ -86,7 +86,7 @@ ParameterManager::ParameterManager(Vehicle* vehicle)
_waitingForDefaultComponent = false;
emit parametersReadyChanged(_parametersReady);
emit missingParametersChanged(_missingParameters);
} else {
} else if (!_logReplay){
refreshAllParameters();
}
}
@ -358,7 +358,7 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString @@ -358,7 +358,7 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
// Update param cache. The param cache is only used on PX4 Firmware since ArduPilot and Solo have volatile params
// which invalidate the cache. The Solo also streams param updates in flight for things like gimbal values
// which in turn causes a perf problem with all the param cache updates.
if (_vehicle->px4Firmware()) {
if (!_logReplay && _vehicle->px4Firmware()) {
if (_prevWaitingReadParamIndexCount + _prevWaitingReadParamNameCount != 0 && readWaitingParamCount == 0) {
// All reads just finished, update the cache
_writeLocalParamCache(vehicleId, componentId);
@ -604,6 +604,10 @@ bool ParameterManager::_fillIndexBatchQueue(bool waitingParamTimeout) @@ -604,6 +604,10 @@ bool ParameterManager::_fillIndexBatchQueue(bool waitingParamTimeout)
void ParameterManager::_waitingParamTimeout(void)
{
if (_logReplay) {
return;
}
bool paramsRequested = false;
const int maxBatchSize = 10;
int batchCount = 0;

30
src/FactSystem/ParameterManager.h

@ -7,9 +7,7 @@ @@ -7,9 +7,7 @@
*
****************************************************************************/
#ifndef ParameterManager_H
#define ParameterManager_H
#pragma once
#include <QObject>
#include <QMap>
@ -25,33 +23,26 @@ @@ -25,33 +23,26 @@
#include "QGCMAVLink.h"
#include "Vehicle.h"
/// @file
/// @author Don Gagne <don@thegagnes.com>
Q_DECLARE_LOGGING_CATEGORY(ParameterManagerVerbose1Log)
Q_DECLARE_LOGGING_CATEGORY(ParameterManagerVerbose2Log)
Q_DECLARE_LOGGING_CATEGORY(ParameterManagerDebugCacheFailureLog)
/// Connects to Parameter Manager to load/update Facts
class ParameterManager : public QObject
{
Q_OBJECT
public:
/// @param uas Uas which this set of facts is associated with
ParameterManager(Vehicle* vehicle);
~ParameterManager();
/// true: Parameters are ready for use
Q_PROPERTY(bool parametersReady READ parametersReady NOTIFY parametersReadyChanged)
bool parametersReady(void) { return _parametersReady; }
ParameterManager (Vehicle* vehicle);
~ParameterManager ();
/// true: Parameters are missing from firmware response, false: all parameters received from firmware
Q_PROPERTY(bool missingParameters READ missingParameters NOTIFY missingParametersChanged)
bool missingParameters(void) { return _missingParameters; }
Q_PROPERTY(bool parametersReady READ parametersReady NOTIFY parametersReadyChanged) ///< true: Parameters are ready for use
Q_PROPERTY(bool missingParameters READ missingParameters NOTIFY missingParametersChanged) ///< true: Parameters are missing from firmware response, false: all parameters received from firmware
Q_PROPERTY(double loadProgress READ loadProgress NOTIFY loadProgressChanged)
Q_PROPERTY(double loadProgress READ loadProgress NOTIFY loadProgressChanged)
double loadProgress(void) const { return _loadProgress; }
bool parametersReady (void) const { return _parametersReady; }
bool missingParameters (void) const { return _missingParameters; }
double loadProgress (void) const { return _loadProgress; }
/// @return Directory of parameter caches
static QDir parameterCacheDir();
@ -59,7 +50,6 @@ public: @@ -59,7 +50,6 @@ public:
/// @return Location of parameter cache file
static QString parameterCacheFile(int vehicleId, int componentId);
/// Re-request the full set of parameters from the autopilot
void refreshAllParameters(uint8_t componentID = MAV_COMP_ID_ALL);
@ -217,5 +207,3 @@ private: @@ -217,5 +207,3 @@ private:
static const char* _jsonParamNameKey;
static const char* _jsonParamValueKey;
};
#endif

20
src/FactSystem/SettingsFact.cc

@ -20,19 +20,19 @@ SettingsFact::SettingsFact(QObject* parent) @@ -20,19 +20,19 @@ SettingsFact::SettingsFact(QObject* parent)
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
}
SettingsFact::SettingsFact(QString settingGroup, FactMetaData* metaData, QObject* parent)
: Fact(0, metaData->name(), metaData->type(), parent)
, _settingGroup(settingGroup)
, _visible(true)
SettingsFact::SettingsFact(QString settingsGroup, FactMetaData* metaData, QObject* parent)
: Fact (0, metaData->name(), metaData->type(), parent)
, _settingsGroup(settingsGroup)
, _visible (true)
{
QSettings settings;
if (!_settingGroup.isEmpty()) {
settings.beginGroup(_settingGroup);
if (!_settingsGroup.isEmpty()) {
settings.beginGroup(_settingsGroup);
}
// Allow core plugin a chance to override the default value
_visible = qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(*metaData);
_visible = qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(settingsGroup, *metaData);
setMetaData(metaData);
QVariant rawDefaultValue = metaData->rawDefaultValue();
@ -60,7 +60,7 @@ const SettingsFact& SettingsFact::operator=(const SettingsFact& other) @@ -60,7 +60,7 @@ const SettingsFact& SettingsFact::operator=(const SettingsFact& other)
{
Fact::operator=(other);
_settingGroup = other._settingGroup;
_settingsGroup = other._settingsGroup;
return *this;
}
@ -69,8 +69,8 @@ void SettingsFact::_rawValueChanged(QVariant value) @@ -69,8 +69,8 @@ void SettingsFact::_rawValueChanged(QVariant value)
{
QSettings settings;
if (!_settingGroup.isEmpty()) {
settings.beginGroup(_settingGroup);
if (!_settingsGroup.isEmpty()) {
settings.beginGroup(_settingsGroup);
}
settings.setValue(_name, value);

13
src/FactSystem/SettingsFact.h

@ -7,12 +7,7 @@ @@ -7,12 +7,7 @@
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef SettingsFact_H
#define SettingsFact_H
#pragma once
#include "Fact.h"
@ -23,7 +18,7 @@ class SettingsFact : public Fact @@ -23,7 +18,7 @@ class SettingsFact : public Fact
public:
SettingsFact(QObject* parent = NULL);
SettingsFact(QString settingGroup, FactMetaData* metaData, QObject* parent = NULL);
SettingsFact(QString settingsGroup, FactMetaData* metaData, QObject* parent = NULL);
SettingsFact(const SettingsFact& other, QObject* parent = NULL);
const SettingsFact& operator=(const SettingsFact& other);
@ -37,8 +32,6 @@ private slots: @@ -37,8 +32,6 @@ private slots:
void _rawValueChanged(QVariant value);
private:
QString _settingGroup;
QString _settingsGroup;
bool _visible;
};
#endif

78
src/FirmwarePlugin/APM/APMFirmwarePlugin.cc

@ -366,6 +366,8 @@ bool APMFirmwarePlugin::_handleIncomingStatusText(Vehicle* vehicle, mavlink_mess @@ -366,6 +366,8 @@ bool APMFirmwarePlugin::_handleIncomingStatusText(Vehicle* vehicle, mavlink_mess
supportedMinorNumber = 4;
break;
case MAV_TYPE_QUADROTOR:
// Start TCP video handshake with ARTOO in case it's a Solo running ArduPilot firmware
_soloVideoHandshake(vehicle, false /* originalSoloFirmware */);
case MAV_TYPE_COAXIAL:
case MAV_TYPE_HELICOPTER:
case MAV_TYPE_SUBMARINE:
@ -420,7 +422,7 @@ bool APMFirmwarePlugin::_handleIncomingStatusText(Vehicle* vehicle, mavlink_mess @@ -420,7 +422,7 @@ bool APMFirmwarePlugin::_handleIncomingStatusText(Vehicle* vehicle, mavlink_mess
_setInfoSeverity(message);
// Start TCP video handshake with ARTOO
_soloVideoHandshake(vehicle);
_soloVideoHandshake(vehicle, true /* originalSoloFirmware */);
} else if (messageText.contains(APM_FRAME_REXP)) {
// We need to parse the Frame: message in order to determine whether the motors are coaxial or not
QRegExp frameTypeRegex("^Frame: (\\S*)");
@ -595,6 +597,18 @@ void APMFirmwarePlugin::_adjustCalibrationMessageSeverity(mavlink_message_t* mes @@ -595,6 +597,18 @@ void APMFirmwarePlugin::_adjustCalibrationMessageSeverity(mavlink_message_t* mes
mavlink_msg_statustext_encode_chan(message->sysid, message->compid, 0, message, &statusText);
}
void APMFirmwarePlugin::initializeStreamRates(Vehicle* vehicle)
{
vehicle->requestDataStream(MAV_DATA_STREAM_RAW_SENSORS, 2);
vehicle->requestDataStream(MAV_DATA_STREAM_EXTENDED_STATUS, 2);
vehicle->requestDataStream(MAV_DATA_STREAM_RC_CHANNELS, 2);
vehicle->requestDataStream(MAV_DATA_STREAM_POSITION, 3);
vehicle->requestDataStream(MAV_DATA_STREAM_EXTRA1, 10);
vehicle->requestDataStream(MAV_DATA_STREAM_EXTRA2, 10);
vehicle->requestDataStream(MAV_DATA_STREAM_EXTRA3, 3);
}
void APMFirmwarePlugin::initializeVehicle(Vehicle* vehicle)
{
vehicle->setFirmwarePluginInstanceData(new APMFirmwarePluginInstanceData);
@ -632,13 +646,7 @@ void APMFirmwarePlugin::initializeVehicle(Vehicle* vehicle) @@ -632,13 +646,7 @@ void APMFirmwarePlugin::initializeVehicle(Vehicle* vehicle)
}
} else {
// Streams are not started automatically on APM stack
vehicle->requestDataStream(MAV_DATA_STREAM_RAW_SENSORS, 2);
vehicle->requestDataStream(MAV_DATA_STREAM_EXTENDED_STATUS, 2);
vehicle->requestDataStream(MAV_DATA_STREAM_RC_CHANNELS, 2);
vehicle->requestDataStream(MAV_DATA_STREAM_POSITION, 3);
vehicle->requestDataStream(MAV_DATA_STREAM_EXTRA1, 10);
vehicle->requestDataStream(MAV_DATA_STREAM_EXTRA2, 10);
vehicle->requestDataStream(MAV_DATA_STREAM_EXTRA3, 3);
initializeStreamRates(vehicle);
}
}
@ -744,14 +752,16 @@ bool APMFirmwarePlugin::isGuidedMode(const Vehicle* vehicle) const @@ -744,14 +752,16 @@ bool APMFirmwarePlugin::isGuidedMode(const Vehicle* vehicle) const
return vehicle->flightMode() == "Guided";
}
void APMFirmwarePlugin::_soloVideoHandshake(Vehicle* vehicle)
void APMFirmwarePlugin::_soloVideoHandshake(Vehicle* vehicle, bool originalSoloFirmware)
{
Q_UNUSED(vehicle);
QTcpSocket* socket = new QTcpSocket();
socket->connectToHost(_artooIP, _artooVideoHandshakePort);
QObject::connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error), this, &APMFirmwarePlugin::_artooSocketError);
if (originalSoloFirmware) {
QObject::connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error), this, &APMFirmwarePlugin::_artooSocketError);
}
}
void APMFirmwarePlugin::_artooSocketError(QAbstractSocket::SocketError socketError)
@ -781,6 +791,8 @@ QString APMFirmwarePlugin::internalParameterMetaDataFile(Vehicle* vehicle) @@ -781,6 +791,8 @@ QString APMFirmwarePlugin::internalParameterMetaDataFile(Vehicle* vehicle)
return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.4.xml");
case 5:
return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.5.xml");
case 6:
return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.6.xml");
default:
if (minorVersion < 3) {
return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.3.xml");
@ -951,7 +963,6 @@ bool APMFirmwarePlugin::_guidedModeTakeoff(Vehicle* vehicle, double altitudeRel) @@ -951,7 +963,6 @@ bool APMFirmwarePlugin::_guidedModeTakeoff(Vehicle* vehicle, double altitudeRel)
return false;
}
// FIXME: Is this needed?
if (!_armVehicleAndValidate(vehicle)) {
qgcApp()->showMessage(tr("Unable to takeoff: Vehicle failed to arm."));
return false;
@ -966,36 +977,35 @@ bool APMFirmwarePlugin::_guidedModeTakeoff(Vehicle* vehicle, double altitudeRel) @@ -966,36 +977,35 @@ bool APMFirmwarePlugin::_guidedModeTakeoff(Vehicle* vehicle, double altitudeRel)
return true;
}
// FIXME: Review for a better way to do this
void APMFirmwarePlugin::startMission(Vehicle* vehicle)
{
double currentAlt = vehicle->altitudeRelative()->rawValue().toDouble();
if (!vehicle->flying()) {
if (_guidedModeTakeoff(vehicle, qQNaN())) {
if (vehicle->flying()) {
// Vehicle already in the air, we just need to switch to auto
if (!_setFlightModeAndValidate(vehicle, "Auto")) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle failed to change to Auto mode."));
}
return;
}
// Wait for vehicle to get off ground before switching to auto (10 seconds)
bool didTakeoff = false;
for (int i=0; i<100; i++) {
if (vehicle->altitudeRelative()->rawValue().toDouble() >= currentAlt + 1.0) {
didTakeoff = true;
break;
}
QGC::SLEEP::msleep(100);
qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
}
if (!vehicle->armed()) {
// First switch to flight mode we can arm from
if (!_setFlightModeAndValidate(vehicle, "Guided")) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle failed to change to Guided mode."));
return;
}
if (!didTakeoff) {
qgcApp()->showMessage(tr("Unable to start mission. Vehicle takeoff failed."));
return;
}
} else {
if (!_armVehicleAndValidate(vehicle)) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle failed to arm."));
return;
}
}
if (!_setFlightModeAndValidate(vehicle, missionFlightMode())) {
qgcApp()->showMessage(tr("Unable to start mission. Vehicle failed to change to auto."));
return;
if (vehicle->fixedWing()) {
if (!_setFlightModeAndValidate(vehicle, "Auto")) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle failed to change to Auto mode."));
return;
}
} else {
vehicle->sendMavCommand(vehicle->defaultComponentId(), MAV_CMD_MISSION_START, true /*show error */);
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save