Commit abfc1233 authored by Andreas Bircher's avatar Andreas Bircher

Merge branch 'pull_upstream' into feature/offlineElevationData

Conflicts:
	src/Terrain.cc
	src/Terrain.h
parents 0f7c1a13 e7914214
......@@ -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.1\msvc2015\bin;%PATH%
- set PATH=C:\Qt\Tools\QtCreator\bin;C:\Qt\5.9.4\msvc2015\bin;%PATH%
- mkdir %LOCALAPPDATA%\QtProject && copy test\qtlogging.ini %LOCALAPPDATA%\QtProject\
- ps: |
Write-Host "Installing GStreamer..." -ForegroundColor Cyan
......@@ -35,7 +35,7 @@ install:
Write-Host "Installed" -ForegroundColor Green
build_script:
- mkdir %SHADOW_BUILD_DIR% && cd %SHADOW_BUILD_DIR% && C:\Qt\5.9.1\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.4\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
......
......@@ -4,8 +4,6 @@ language: cpp
env:
global:
- CCACHE_CPP2=1
- CCACHE_DISABLE=1
- JOBS=4
- QT_FATAL_WARNINGS=1
- SHADOW_BUILD_DIR=/tmp/shadow_build_dir
......@@ -28,18 +26,18 @@ matrix:
env: SPEC=android-g++ CONFIG=installer
sudo: false
- os: osx
osx_image: xcode8.3
osx_image: xcode9.2
env: SPEC=macx-clang CONFIG=installer
sudo: required
- os: osx
osx_image: xcode9.2
env: SPEC=macx-ios-clang CONFIG=release
sudo: false
# OSX builds pared back to installer only since travis sucks so bad we can't afford more than one'
# - os: osx
# osx_image: xcode8
# env: SPEC=macx-clang CONFIG=debug
# sudo: required
# - os: osx
# osx_image: xcode8
# env: SPEC=macx-ios-clang CONFIG=release
# sudo: false
android:
components:
......@@ -50,7 +48,6 @@ android:
addons:
apt:
packages:
- ccache
- espeak
- libespeak-dev
- libgstreamer-plugins-base1.0-dev
......@@ -60,25 +57,12 @@ addons:
- libudev-dev
- wget
cache:
directories:
- $HOME/.ccache
before_install:
# fetch entire git repo to properly determine the version
- if [ "${CONFIG}" = "installer" ]; then
cd ${TRAVIS_BUILD_DIR} && git fetch --unshallow && git fetch --all --tags;
fi
# install ccache for osx/ios
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
wget --quiet https://s3.amazonaws.com/px4-travis/toolchain/macos/ccache &&
chmod +x ccache && sudo mv ccache /usr/local/bin;
fi
# setup ccache
#- ccache -M 500MB && ccache -z
# compile threads
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
export JOBS=$((`cat /proc/cpuinfo | grep -c ^processor`+1));
......@@ -89,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.1-linux-min.tar.bz2 &&
tar jxf Qt5.9.1-linux-min.tar.bz2 -C /tmp &&
export PATH=/tmp/Qt5.9-linux/5.9.1/gcc_64/bin:$PATH &&
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 &&
export DISPLAY=:99.0 &&
sh -e /etc/init.d/xvfb start
;
......@@ -99,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.1-android-min.tar.bz2 &&
tar jxf Qt5.9.1-android-min.tar.bz2 -C /tmp &&
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/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 &&
......@@ -109,35 +93,53 @@ 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/5.9.1/android_armv7/bin:`pwd`/android-ndk-r10e:$PATH && echo $PATH
export PATH=/tmp/Qt5.9-android_armv7/5.9.3/android_armv7/bin:`pwd`/android-ndk-r10e:$PATH && echo $PATH
;
fi
# osx dependencies: qt, gstreamer, gstreamer-devel
# 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.1-mac-clang-min.tar.bz2 &&
tar jxf Qt5.9.1-mac-clang-min.tar.bz2 -C /tmp &&
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
;
fi
- if [[ "${SPEC}" = "macx-clang" && "${TRAVIS_PULL_REQUEST}" = "false" ]]; then
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/gstreamer-1.0-1.5.2-x86_64.pkg &&
sudo installer -verboseR -pkg gstreamer-1.0-1.5.2-x86_64.pkg -target / &&
sudo installer -verboseR -pkg gstreamer-1.0-1.5.2-x86_64.pkg -target /
;
fi
- if [[ "${SPEC}" = "macx-clang" && "${TRAVIS_PULL_REQUEST}" = "false" ]]; then
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/gstreamer-1.0-devel-1.5.2-x86_64.pkg &&
sudo installer -verboseR -pkg gstreamer-1.0-devel-1.5.2-x86_64.pkg -target / &&
sudo installer -verboseR -pkg gstreamer-1.0-devel-1.5.2-x86_64.pkg -target /
;
fi
- if [[ "${SPEC}" = "macx-clang" && "${TRAVIS_PULL_REQUEST}" = "false" ]]; then
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/osx-gstreamer.tar.bz2 &&
sudo tar jxf osx-gstreamer.tar.bz2 -C /Library/Frameworks &&
export QT_DIR=Qt5.9-mac-clang/5.9.1/clang_64 &&
sudo tar jxf osx-gstreamer.tar.bz2 -C /Library/Frameworks
;
fi
- if [ "${SPEC}" = "macx-clang" ]; then
export QT_DIR=Qt5.9-clang_64/5.9.3/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
;
fi
# ios dependencies: qt, TODO: add gstreamer
# ios dependencies: qt
- if [ "${SPEC}" = "macx-ios-clang" ]; then
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.9.3-ios-min.tar.bz2
;
fi
- if [ "${SPEC}" = "macx-ios-clang" ]; then
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.8.0-ios-min.tar.bz2 &&
tar jxf Qt5.8.0-ios-min.tar.bz2 -C /tmp &&
tar jxf Qt5.9.3-ios-min.tar.bz2 -C /tmp &&
export IOS_CCACHE_CC=`/usr/bin/xcrun -sdk iphoneos -find clang` &&
export IOS_CCACHE_CXX=`/usr/bin/xcrun -sdk iphoneos -find clang++` &&
export PATH=/tmp/Qt5.8-ios/5.8/ios/bin:$PATH &&
tools/patch_qt_for_xcode8.sh
export PATH=/tmp/Qt5.9-ios/5.9.3/ios/bin:$PATH
;
fi
......
......@@ -2,9 +2,103 @@ pipeline {
agent any
stages {
stage('build') {
steps {
sh 'git status'
parallel {
stage('Linux Debug') {
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'debug'
QMAKE_VER = "5.9.2/gcc_64/bin/qmake"
}
agent {
docker {
image 'mavlink/qgc-build-linux'
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'
}
}
stage('Linux Release') {
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'release'
QMAKE_VER = "5.9.2/gcc_64/bin/qmake"
}
agent {
docker {
image 'mavlink/qgc-build-linux'
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'
}
}
stage('OSX Debug') {
agent {
node {
label 'mac'
}
}
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'debug'
QMAKE_VER = "5.9.3/clang_64/bin/qmake"
}
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`sysctl -n hw.ncpu`'
sh 'ccache -s'
}
}
stage('OSX Release') {
agent {
node {
label 'mac'
}
}
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'release'
QMAKE_VER = "5.9.3/clang_64/bin/qmake"
}
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`sysctl -n hw.ncpu`'
sh 'ccache -s'
}
}
}
}
}
}
\ No newline at end of file
environment {
CCACHE_CPP2 = '1'
CCACHE_DIR = '/tmp/ccache'
QT_FATAL_WARNINGS = '1'
}
}
......@@ -83,7 +83,7 @@ linux {
DEFINES += NO_SERIAL_LINK
DEFINES += QGC_DISABLE_UVC
QMAKE_IOS_DEPLOYMENT_TARGET = 8.0
QMAKE_IOS_TARGETED_DEVICE_FAMILY = 1,2 # Universal
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 1,2 # Universal
QMAKE_LFLAGS += -Wl,-no_pie
} else {
error("Unsupported build platform, only Linux, Windows, Android and Mac (Mac OS and iOS) are supported")
......@@ -235,7 +235,9 @@ ReleaseBuild {
DEFINES += QT_NO_DEBUG QT_MESSAGELOGCONTEXT
CONFIG += force_debug_info # Enable debugging symbols on release builds
!iOSBuild {
CONFIG += ltcg # Turn on link time code generation
!AndroidBuild {
CONFIG += ltcg # Turn on link time code generation
}
}
WindowsBuild {
......
......@@ -7,20 +7,53 @@ WindowsBuild {
#
# [REQUIRED] Add support for the MAVLink communications protocol.
# Mavlink dialect is hardwired to arudpilotmega for now. The reason being
#
# By default MAVLink dialect is hardwired to arudpilotmega. The reason being
# the current codebase supports both PX4 and APM flight stack. PX4 flight stack
# only usese common mavlink specifications, whereas APM flight stack uses custom
# mavlink specifications which add to common. So by using the adupilotmega dialect
# only uses common MAVLink specifications, whereas APM flight stack uses custom
# MAVLink specifications which adds to common. So by using the adupilotmega dialect
# QGC can support both in the same codebase.
#
# Once the mavlink helper routines include support for multiple dialects within
# a single compiled codebase this hardwiring of dialect can go away. But until then
# this "workaround" is needed.
MAVLINKPATH_REL = libs/mavlink/include/mavlink/v2.0
MAVLINKPATH = $$BASEDIR/$$MAVLINKPATH_REL
MAVLINK_CONF = ardupilotmega
DEFINES += MAVLINK_NO_DATA
# In the mean time, it’s possible to define a completely different dialect by defining the
# location and name below.
# check for user defined settings in user_config.pri if not already set as qmake argument
isEmpty(MAVLINKPATH_REL) {
exists(user_config.pri):infile(user_config.pri, MAVLINKPATH_REL) {
MAVLINKPATH_REL = $$fromfile(user_config.pri, MAVLINKPATH_REL)
message($$sprintf("Using user-supplied relativ mavlink path '%1' specified in user_config.pri", $$MAVLINKPATH_REL))
} else {
MAVLINKPATH_REL = libs/mavlink/include/mavlink/v2.0
}
}
isEmpty(MAVLINKPATH) {
exists(user_config.pri):infile(user_config.pri, MAVLINKPATH) {
MAVLINKPATH = $$fromfile(user_config.pri, MAVLINKPATH)
message($$sprintf("Using user-supplied mavlink path '%1' specified in user_config.pri", $$MAVLINKPATH))
} else {
MAVLINKPATH = $$BASEDIR/$$MAVLINKPATH_REL
}
}
isEmpty(MAVLINK_CONF) {
exists(user_config.pri):infile(user_config.pri, MAVLINK_CONF) {
MAVLINK_CONF = $$fromfile(user_config.pri, MAVLINK_CONF)
message($$sprintf("Using user-supplied mavlink dialect '%1' specified in user_config.pri", $$MAVLINK_CONF))
} else {
MAVLINK_CONF = ardupilotmega
}
}
# If defined, all APM specific MAVLink messages are disabled
contains (CONFIG, QGC_DISABLE_APM_MAVLINK) {
message("Disable APM MAVLink support")
DEFINES += NO_ARDUPILOT_DIALECT
}
# First we select the dialect, checking for valid user selection
# Users can override all other settings by specifying MAVLINK_CONF as an argument to qmake
......
......@@ -26,13 +26,14 @@ installer {
# We cd to release directory so we can run macdeployqt without a path to the
# qgroundcontrol.app file. If you specify a path to the .app file the symbolic
# links to plugins will not be created correctly.
QMAKE_POST_LINK += && mkdir -p $${DESTDIR}/package
QMAKE_POST_LINK += && cd $${DESTDIR} && $$dirname(QMAKE_QMAKE)/macdeployqt $${TARGET}.app -appstore-compliant -verbose=2 -qmldir=$${BASEDIR}/src
# macdeploy is missing some relocations once in a while. "Fix" it:
QMAKE_POST_LINK += && python $$BASEDIR/tools/osxrelocator.py $${TARGET}.app/Contents @rpath @executable_path/../Frameworks -r > /dev/null 2>&1
# Create package
QMAKE_POST_LINK += && cd $${OUT_PWD}
QMAKE_POST_LINK += && hdiutil create -verbose -stretch 4g -layout SPUD -srcfolder $${DESTDIR}/$${TARGET}.app -volname $${TARGET} $${DESTDIR}/package/$${TARGET}.dmg
QMAKE_POST_LINK += && hdiutil create /tmp/tmp.dmg -ov -volname "$${TARGET}-$${MAC_VERSION}" -fs HFS+ -srcfolder "$${DESTDIR}/"
QMAKE_POST_LINK += && mkdir -p $${DESTDIR}/package
QMAKE_POST_LINK += && hdiutil convert /tmp/tmp.dmg -format UDBZ -o $${DESTDIR}/package/$${TARGET}.dmg
QMAKE_POST_LINK += && rm /tmp/tmp.dmg
}
WindowsBuild {
QMAKE_POST_LINK += $$escape_expand(\\n) cd $$BASEDIR_WIN && $$quote("\"C:\\Program Files \(x86\)\\NSIS\\makensis.exe\"" /DINSTALLER_ICON="\"$${QGC_INSTALLER_ICON}\"" /DHEADER_BITMAP="\"$${QGC_INSTALLER_HEADER_BITMAP}\"" /DAPPNAME="\"$${QGC_APP_NAME}\"" /DEXENAME="\"$${TARGET}\"" /DORGNAME="\"$${QGC_ORG_NAME}\"" /DDESTDIR=$${DESTDIR} /NOCD "\"/XOutFile $${DESTDIR_WIN}\\$${TARGET}-installer.exe\"" "$$BASEDIR_WIN\\deploy\\qgroundcontrol_installer.nsi")
......
......@@ -40,7 +40,7 @@ WindowsBuild {
# Perform platform specific setup
#
iOSBuild | MacBuild {
MacBuild {
# Update version info in bundle
QMAKE_POST_LINK += && /usr/libexec/PlistBuddy -c \"Set :CFBundleShortVersionString $${MAC_VERSION}\" $$DESTDIR/$${TARGET}.app/Contents/Info.plist
QMAKE_POST_LINK += && /usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $${MAC_BUILD}\" $$DESTDIR/$${TARGET}.app/Contents/Info.plist
......@@ -146,7 +146,8 @@ LinuxBuild {
platforminputcontexts \
platforms \
position \
sqldrivers
sqldrivers \
texttospeech
!contains(DEFINES, __rasp_pi2__) {
QT_PLUGIN_LIST += xcbglintegrations
......
# QGroundControl Ground Control Station
## Open Source Micro Air Vehicle Ground Control Station
[![Releases](https://img.shields.io/github/release/mavlink/QGroundControl.svg)](https://github.com/mavlink/QGroundControl/releases)
[![Travis Build Status](https://travis-ci.org/mavlink/qgroundcontrol.svg?branch=master)](https://travis-ci.org/mavlink/qgroundcontrol)
[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/crxcm4qayejuvh6c/branch/master?svg=true)](https://ci.appveyor.com/project/mavlink/qgroundcontrol)
[![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)
The license terms are set in the COPYING.md file.
* Project:
<http://qgroundcontrol.com>
* Files:
<http://github.com/mavlink/qgroundcontrol>
* Credits:
<http://qgroundcontrol.org/credits>
Website: <http://qgroundcontrol.com>
## Obtaining source code
Source code for QGroundControl is kept on GitHub: https://github.com/mavlink/qgroundcontrol.
```
git clone --recursive https://github.com/mavlink/qgroundcontrol.git
......@@ -36,24 +25,25 @@ https://docs.qgroundcontrol.com/en/
#### 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.1 ONLY
* 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.
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.1**. You will also need to install the Qt Speech package.
* 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 espeak libespeak-dev libudev-dev libsdl2-dev
* Fedora: sudo dnf install espeak espeak-devel SDL2-devel SDL2 systemd-devel
* Arch Linux: pacman -Sy espeak
* Ubuntu: sudo apt-get install speech-dispatcher libudev-dev libsdl2-dev libgstreamer1.0-0 gstreamer1.0-plugins-base libgstreamer-plugins-base1.0-dev gstreamer1.0*
* 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)
......@@ -61,10 +51,10 @@ You need to install Qt as described below instead of using pre-built packages fr
* Launch Qt Creator and open the `qgroundcontrol.pro` project.
* Select the appropriate kit for your needs:
* OSX: Desktop Qt 5.9.1 clang 64 bit
* Ubuntu: Desktop Qt 5.9.1 GCC bit
* Windows: Desktop Qt 5.9.1 MSVC2015 32bit
* Android: Android for armeabi-v7a (GCC 4.9, Qt 5.9.1)
* 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
......
......@@ -9,9 +9,10 @@
<file alias="MavCmdInfoVTOL.json">src/MissionManager/UnitTest/MavCmdInfoVTOL.json</file>
<file alias="MissionPlanner.waypoints">src/MissionManager/UnitTest/MissionPlanner.waypoints</file>
<file alias="OldFileFormat.mission">src/MissionManager/UnitTest/OldFileFormat.mission</file>
<file alias="GoodPolygon.kml">src/MissionManager/UnitTest/GoodPolygon.kml</file>
<file alias="MissingPolygonNode.kml">src/MissionManager/UnitTest/MissingPolygonNode.kml</file>
<file alias="BadXml.kml">src/MissionManager/UnitTest/BadXml.kml</file>
<file alias="BadCoordinatesNode.kml">src/MissionManager/UnitTest/BadCoordinatesNode.kml</file>
<file alias="PolygonAreaTest.kml">src/MissionManager/UnitTest/PolygonAreaTest.kml</file>
<file alias="PolygonGood.kml">src/MissionManager/UnitTest/PolygonGood.kml</file>
<file alias="PolygonMissingNode.kml">src/MissionManager/UnitTest/PolygonMissingNode.kml</file>
<file alias="PolygonBadXml.kml">src/MissionManager/UnitTest/PolygonBadXml.kml</file>
<file alias="PolygonBadCoordinatesNode.kml">src/MissionManager/UnitTest/PolygonBadCoordinatesNode.kml</file>
</qresource>
</RCC>
......@@ -15,7 +15,7 @@ Vagrant.configure(2) do |config|
config.vm.provider "virtualbox"
config.vm.provider "vmware_fusion"
config.vm.box = "boxcutter/ubuntu1604"
config.vm.box = "ubuntu/xenial64"
config.vm.provider :docker do |docker, override|
override.vm.box = "tknerr/baseimage-ubuntu-16.04"
end
......
<?xml version="1.0"?>
<manifest package="org.mavlink.qgroundcontrol" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="3.0.0-243-gd759437" android:versionCode="300243" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:icon="@drawable/icon" android:debuggable="true">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:icon="@drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.mavlink.qgroundcontrol.QGCActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="sensorLandscape" android:launchMode="singleTask" android:keepScreenOn="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
......@@ -59,6 +59,7 @@
<!-- 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" />
<!-- 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 -->
......
#!/bin/bash -x
if [[ $# -eq 0 ]]; then
echo 'MakeQtTravisTarball.sh QtDirectory QtFullVersion QtBaseVersion BuildType'
exit 1
fi
QT_DIRECTORY=$1
if [ ! -d ${QT_DIRECTORY} ]; then
echo 'Specify directory for Qt Directory.'
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_BUILD_TYPE=$4
if [ ! -d ${QT_DIRECTORY}/${QT_FULL_VERSION}/${QT_BUILD_TYPE} ]; then
echo 'Qt build type directory not found'
exit 1
fi
mkdir -p Qt${QT_BASE_VERSION}-${QT_BUILD_TYPE}/${QT_FULL_VERSION}/${QT_BUILD_TYPE}
cp -r ${QT_DIRECTORY}/${QT_FULL_VERSION}/${QT_BUILD_TYPE} Qt${QT_BASE_VERSION}-${QT_BUILD_TYPE}/${QT_FULL_VERSION}
rm -rf Qt${QT_BASE_VERSION}-${QT_BUILD_TYPE}/${QT_FULL_VERSION}/${QT_BUILD_TYPE}/doc
tar -jcvf Qt${QT_FULL_VERSION}-${QT_BUILD_TYPE}-min.tar.bz2 Qt${QT_BASE_VERSION}-${QT_BUILD_TYPE}/
......@@ -34,10 +34,9 @@ mkdir -p ${APPDIR}
cd ${TMPDIR}
wget -c --quiet http://ftp.us.debian.org/debian/pool/main/u/udev/udev_175-7.2_amd64.deb
wget -c --quiet http://ftp.us.debian.org/debian/pool/main/e/espeak/espeak_1.46.02-2_amd64.deb
wget -c --quiet http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/speech-dispatcher_0.8.8-1_amd64.deb
wget -c --quiet http://ftp.us.debian.org/debian/pool/main/libs/libsdl2/libsdl2-2.0-0_2.0.2%2bdfsg1-6_amd64.deb
cd ${APPDIR}
find ../ -name *.deb -exec dpkg -x {} . \;
......
Subproject commit 5be9f5bf6002d58199cafafb5d416929fb8d8bcd
Subproject commit 3ddcbdfcd360c846246d8905d877add3488c8363
#!/bin/bash
# This is set to find lupdate in my particular installation. You will need to set the path
# where you have Qt installed.
QT_PATH=~/Applications/Qt/5.7/clang_64/bin
QT_PATH=~/Applications/Qt/5.9.1/clang_64/bin
$QT_PATH/lupdate ../src -ts qgc.ts
This diff is collapsed.
......@@ -109,6 +109,7 @@
<file alias="compassInstrumentDial.svg">src/FlightMap/Images/compassInstrumentDial.svg</file>
<file alias="crossHair.svg">src/FlightMap/Images/crossHair.svg</file>
<file alias="PiP.svg">src/FlightMap/Images/PiP.svg</file>
<file alias="pipHide.svg">src/FlightMap/Images/pipHide.svg</file>
<file alias="pipResize.svg">src/FlightMap/Images/pipResize.svg</file>
<file alias="rollDialWhite.svg">src/FlightMap/Images/rollDialWhite.svg</file>
<file alias="rollPointerWhite.svg">src/FlightMap/Images/rollPointerWhite.svg</file>
......
......@@ -7,14 +7,16 @@
# License terms set in COPYING.md
# -------------------------------------------------
QMAKE_PROJECT_DEPTH = 0 # undocumented qmake flag to force absolute paths in make files
exists($${OUT_PWD}/qgroundcontrol.pro) {
error("You must use shadow build (e.g. mkdir build; cd build; qmake ../qgroundcontrol.pro).")
}
message(Qt version $$[QT_VERSION])
!equals(QT_MAJOR_VERSION, 5) | !greaterThan(QT_MINOR_VERSION, 6) {
error("Unsupported Qt version, 5.7+ is required")
!equals(QT_MAJOR_VERSION, 5) | !greaterThan(QT_MINOR_VERSION, 8) {
error("Unsupported Qt version, 5.9+ is required")
}
include(QGCCommon.pri)
......@@ -43,8 +45,6 @@ MacBuild {
}
iOSBuild {
BUNDLE.files = $$files($$PWD/ios/AppIcon*.png) $$PWD/ios/QGCLaunchScreen.xib
QMAKE_BUNDLE_DATA += BUNDLE
LIBS += -framework AVFoundation
#-- Info.plist (need an "official" one for the App Store)
ForAppStore {
......@@ -63,6 +63,8 @@ iOSBuild {
QMAKE_INFO_PLIST = $${BASEDIR}/ios/iOS-Info.plist
OTHER_FILES += $${BASEDIR}/ios/iOS-Info.plist
}
BUNDLE.files = $$files($$PWD/ios/AppIcon*.png) $$PWD/ios/QGCLaunchScreen.xib $$QMAKE_INFO_PLIST
QMAKE_BUNDLE_DATA += BUNDLE
#-- TODO: Add iTunesArtwork
}
......@@ -207,8 +209,7 @@ contains(DEFINES, ENABLE_VERBOSE_OUTPUT) {
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, ENABLE_VERBOSE_OUTPUT) {
message("Enable verbose compiler output (manual override from user_config.pri)")
} else {
CONFIG += \
silent
CONFIG += silent
}
QT += \
......@@ -233,10 +234,12 @@ QT += \
multimedia
}
!MobileBuild {
QT += \
printsupport \
serialport \
AndroidBuild || iOSBuild {
# Android and iOS don't unclude these
} else {
QT += \
printsupport \
serialport \
}
contains(DEFINES, QGC_ENABLE_BLUETOOTH) {
......@@ -412,7 +415,9 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/FactSystem/FactSystemTestGeneric.h \
src/FactSystem/FactSystemTestPX4.h \
src/FactSystem/ParameterManagerTest.h \
src/MissionManager/CameraCalcTest.h \
src/MissionManager/CameraSectionTest.h \
src/MissionManager/CorridorScanComplexItemTest.h \
src/MissionManager/MissionCommandTreeTest.h \
src/MissionManager/MissionControllerManagerTest.h \
src/MissionManager/MissionControllerTest.h \
......@@ -421,10 +426,13 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/MissionSettingsTest.h \
src/MissionManager/PlanMasterControllerTest.h \
src/MissionManager/QGCMapPolygonTest.h \
src/MissionManager/QGCMapPolylineTest.h \
src/MissionManager/SectionTest.h \
src/MissionManager/SimpleMissionItemTest.h \
src/MissionManager/SpeedSectionTest.h \
src/MissionManager/StructureScanComplexItemTest.h \
src/MissionManager/SurveyMissionItemTest.h \
src/MissionManager/TransectStyleComplexItemTest.h \
src/MissionManager/VisualMissionItemTest.h \
src/qgcunittest/FileDialogTest.h \
src/qgcunittest/FileManagerTest.h \
......@@ -448,7 +456,9 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/FactSystem/FactSystemTestGeneric.cc \
src/FactSystem/FactSystemTestPX4.cc \
src/FactSystem/ParameterManagerTest.cc \
src/MissionManager/CameraCalcTest.cc \
src/MissionManager/CameraSectionTest.cc \
src/MissionManager/CorridorScanComplexItemTest.cc \
src/MissionManager/MissionCommandTreeTest.cc \
src/MissionManager/MissionControllerManagerTest.cc \
src/MissionManager/MissionControllerTest.cc \
......@@ -457,10 +467,13 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/MissionSettingsTest.cc \
src/MissionManager/PlanMasterControllerTest.cc \
src/MissionManager/QGCMapPolygonTest.cc \
src/MissionManager/QGCMapPolylineTest.cc \
src/MissionManager/SectionTest.cc \
src/MissionManager/SimpleMissionItemTest.cc \
src/MissionManager/SpeedSectionTest.cc \
src/MissionManager/StructureScanComplexItemTest.cc \
src/MissionManager/SurveyMissionItemTest.cc \
src/MissionManager/TransectStyleComplexItemTest.cc \
src/MissionManager/VisualMissionItemTest.cc \
src/qgcunittest/FileDialogTest.cc \
src/qgcunittest/FileManagerTest.cc \
......@@ -483,8 +496,9 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
HEADERS += \
src/AnalyzeView/ExifParser.h \
src/AnalyzeView/ULogParser.h \
src/AnalyzeView/LogDownloadController.h \
src/AnalyzeView/PX4LogParser.h \
src/AnalyzeView/ULogParser.h \
src/Audio/AudioOutput.h \
src/Camera/QGCCameraControl.h \
src/Camera/QGCCameraIO.h \
......@@ -503,6 +517,7 @@ HEADERS += \
src/MissionManager/CameraSection.h \
src/MissionManager/CameraSpec.h \
src/MissionManager/ComplexMissionItem.h \
src/MissionManager/CorridorScanComplexItem.h \
src/MissionManager/FixedWingLandingComplexItem.h \
src/MissionManager/GeoFenceController.h \
src/MissionManager/GeoFenceManager.h \
......@@ -521,6 +536,7 @@ HEADERS += \
src/MissionManager/QGCFencePolygon.h \
src/MissionManager/QGCMapCircle.h \
src/MissionManager/QGCMapPolygon.h \
src/MissionManager/QGCMapPolyline.h \
src/MissionManager/RallyPoint.h \
src/MissionManager/RallyPointController.h \
src/MissionManager/RallyPointManager.h \
......@@ -529,6 +545,7 @@ HEADERS += \
src/MissionManager/SpeedSection.h \
src/MissionManager/StructureScanComplexItem.h \
src/MissionManager/SurveyMissionItem.h \
src/MissionManager/TransectStyleComplexItem.h \
src/MissionManager/VisualMissionItem.h \
src/PositionManager/PositionManager.h \
src/PositionManager/SimulatedPosition.h \
......@@ -549,6 +566,7 @@ HEADERS += \
src/QGCToolbox.h \
src/QmlControls/AppMessages.h \
src/QmlControls/CoordinateVector.h \
src/QmlControls/EditPositionDialogController.h \
src/QmlControls/MavlinkQmlSingleton.h \
src/QmlControls/ParameterEditorController.h \
src/QmlControls/QGCFileDialogController.h \
......@@ -583,7 +601,7 @@ HEADERS += \
src/uas/UAS.h \
src/uas/UASInterface.h \
src/uas/UASMessageHandler.h \
src/AnalyzeView/LogDownloadController.h \
src/UTM.h \
AndroidBuild {
HEADERS += \
......@@ -676,8 +694,9 @@ AndroidBuild {
SOURCES += \
src/AnalyzeView/ExifParser.cc \
src/AnalyzeView/ULogParser.cc \
src/AnalyzeView/LogDownloadController.cc \
src/AnalyzeView/PX4LogParser.cc \
src/AnalyzeView/ULogParser.cc \
src/Audio/AudioOutput.cc \
src/Camera/QGCCameraControl.cc \
src/Camera/QGCCameraIO.cc \
......@@ -694,6 +713,7 @@ SOURCES += \
src/MissionManager/CameraSection.cc \
src/MissionManager/CameraSpec.cc \
src/MissionManager/ComplexMissionItem.cc \
src/MissionManager/CorridorScanComplexItem.cc \
src/MissionManager/FixedWingLandingComplexItem.cc \
src/MissionManager/GeoFenceController.cc \
src/MissionManager/GeoFenceManager.cc \
......@@ -712,6 +732,7 @@ SOURCES += \
src/MissionManager/QGCFencePolygon.cc \
src/MissionManager/QGCMapCircle.cc \
src/MissionManager/QGCMapPolygon.cc \
src/MissionManager/QGCMapPolyline.cc \
src/MissionManager/RallyPoint.cc \
src/MissionManager/RallyPointController.cc \
src/MissionManager/RallyPointManager.cc \
......@@ -719,6 +740,7 @@ SOURCES += \
src/MissionManager/SpeedSection.cc \
src/MissionManager/StructureScanComplexItem.cc \
src/MissionManager/SurveyMissionItem.cc \
src/MissionManager/TransectStyleComplexItem.cc \
src/MissionManager/VisualMissionItem.cc \
src/PositionManager/PositionManager.cpp \
src/PositionManager/SimulatedPosition.cc \
......@@ -738,6 +760,7 @@ SOURCES += \
src/QGCToolbox.cc \
src/QmlControls/AppMessages.cc \
src/QmlControls/CoordinateVector.cc \
src/QmlControls/EditPositionDialogController.cc \
src/QmlControls/ParameterEditorController.cc \
src/QmlControls/QGCFileDialogController.cc \
src/QmlControls/QGCImageProvider.cc \
......@@ -770,7 +793,7 @@ SOURCES += \
src/main.cc \
src/uas/UAS.cc \
src/uas/UASMessageHandler.cc \
src/AnalyzeView/LogDownloadController.cc \
src/UTM.cpp \
DebugBuild {
SOURCES += \
......
This diff is collapsed.
......@@ -110,7 +110,7 @@ AnalyzePage {
}
QGCLabel {
text: geoController.saveDirectory != "" ? geoController.saveDirectory : "/TAGGED folder in your image folder"
text: geoController.saveDirectory !== "" ? geoController.saveDirectory : "/TAGGED folder in your image folder"
anchors.verticalCenter: parent.verticalCenter
}
}
......
......@@ -21,6 +21,7 @@
#include "QGCMapEngine.h"
#include "ParameterManager.h"
#include "Vehicle.h"
#include "SettingsManager.h"
#include <QDebug>
#include <QSettings>
......@@ -511,7 +512,7 @@ LogDownloadController::download(QString path)
QString dir = path;
#if defined(__mobile__)
if(dir.isEmpty()) {
dir = QDir::homePath();
dir = qgcApp()->toolbox()->settingsManager()->appSettings()->logSavePath();
}
#else
if(dir.isEmpty()) {
......
......@@ -57,7 +57,7 @@ void LogDownloadTest::downloadTest(void)
}
_multiSpyLogDownloadController->clearAllSignals();
QString downloadFile = QDir(downloadTo).filePath("log_0_UnknownDate.px4log");
QString downloadFile = QDir(downloadTo).filePath("log_0_UnknownDate.ulg");
QVERIFY(UnitTest::fileCompare(downloadFile, _mockLink->logDownloadFile()));
QFile::remove(downloadFile);
......
......@@ -11,6 +11,7 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QGroundControl 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
......@@ -32,6 +33,8 @@ SetupPage {
QGCPalette { id: palette; colorGroupEnabled: true }
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _oldFW: !(_activeVehicle.firmwareMajorVersion > 3 || _activeVehicle.firmwareMinorVersion > 5 || _activeVehicle.firmwarePatchVersion >= 2)
property Fact _rc5Function: controller.getParameterFact(-1, "r.SERVO5_FUNCTION")
property Fact _rc6Function: controller.getParameterFact(-1, "r.SERVO6_FUNCTION")
property Fact _rc7Function: controller.getParameterFact(-1, "r.SERVO7_FUNCTION")
......@@ -42,7 +45,8 @@ SetupPage {
property Fact _rc12Function: controller.getParameterFact(-1, "r.SERVO12_FUNCTION")
property Fact _rc13Function: controller.getParameterFact(-1, "r.SERVO13_FUNCTION")
property Fact _rc14Function: controller.getParameterFact(-1, "r.SERVO14_FUNCTION")
property Fact _stepSize: controller.getParameterFact(-1, "JS_LIGHTS_STEP")
property Fact _stepSize: _oldFW ? controller.getParameterFact(-1, "JS_LIGHTS_STEP") : null // v3.5.1 and prior
property Fact _numSteps: _oldFW ? null : controller.getParameterFact(-1, "JS_LIGHTS_STEPS") // v3.5.2 and up
readonly property real _margins: ScreenTools.defaultFontPixelHeight
readonly property int _rcFunctionDisabled: 0
......@@ -88,22 +92,30 @@ SetupPage {
}
function calcCurrentStep() {
var i = 1
for(i; i <= 10; i++) {
var stepSize = (1900-1100)/i
if(_stepSize.value >= stepSize) {
_stepSize.value = stepSize;
break;
if (_oldFW) {
var i = 1
for(i; i <= 10; i++) {
var stepSize = (1900-1100)/i
if(_stepSize.value >= stepSize) {
_stepSize.value = stepSize;
break;
}
}
if (_stepSize.value < 80) {
_stepSize.value = 80;
}
lightsLoader.lightsSteps = i
} else {
lightsLoader.lightsSteps = _numSteps.value
}
if (_stepSize.value < 80) {
_stepSize.value = 80;
}
lightsLoader.lightsSteps = i
}
function calcStepSize(steps) {
_stepSize.value = (1900-1100)/steps
if (_oldFW) {
_stepSize.value = (1900-1100)/steps
} else {
_numSteps.value = steps
}
}
// Whenever any SERVO#_FUNCTION parameters chagnes we need to go looking for light output channels again
......
......@@ -29,6 +29,7 @@ SetupPage {
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")
......@@ -239,6 +240,18 @@ SetupPage {
QGCLabel {
Layout.row: 2
Layout.column: 0
text: qsTr("Minimum arming voltage:")
}
FactTextField {
id: armVoltField
width: _fieldWidth
fact: armVoltMin
}
QGCLabel {
Layout.row: 3
Layout.column: 0
text: qsTr("Power sensor:")
}
......@@ -260,7 +273,7 @@ SetupPage {
}
QGCLabel {
Layout.row: 3
Layout.row: 4
Layout.column: 0
text: qsTr("Current pin:")
visible: _showAdvanced
......@@ -274,7 +287,7 @@ SetupPage {
}
QGCLabel {
Layout.row: 4
Layout.row: 5
Layout.column: 0
text: qsTr("Voltage pin:")
visible: _showAdvanced
......@@ -288,7 +301,7 @@ SetupPage {
}
QGCLabel {
Layout.row: 5
Layout.row: 6
Layout.column: 0
text: qsTr("Voltage multiplier:")
visible: _showAdvanced
......
......@@ -22,7 +22,6 @@ import QGroundControl.ScreenTools 1.0
SetupPage {
id: safetyPage
pageComponent: safetyPageComponent
visibleWhileArmed: true
Component {
id: safetyPageComponent
......
......@@ -12,6 +12,7 @@ import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
......@@ -22,12 +23,9 @@ import QGroundControl.Controllers 1.0
SetupPage {
id: subFramePage
pageComponent: subFramePageComponent
property var _flatParamList: ListModel {
ListElement {
name: "Blue Robotics BlueROV2"
file: "Sub/bluerov2-3_5.params"
}
}
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _oldFW: !(_activeVehicle.firmwareMajorVersion > 3 || _activeVehicle.firmwareMinorVersion > 5 || _activeVehicle.firmwarePatchVersion >= 2)
APMAirframeComponentController { id: controller; factPanel: subFramePage.viewPanel }
......@@ -194,18 +192,16 @@ SetupPage {
spacing : _margins
layoutDirection: Qt.Vertical;
Repeater {
id: airframePicker
model: _flatParamList
delegate: QGCButton {
width: parent.width
text: name
onClicked : {
controller.loadParameters(file)
hideDialog()
}
QGCButton {
width: parent.width
text: "Blue Robotics BlueROV2"
property var file: _oldFW ? "Sub/bluerov2-3_5.params" : "Sub/bluerov2-3_5_2.params"
onClicked : {
console.log(_oldFW)
console.log(_activeVehicle.firmwarePatchVersion)
controller.loadParameters(file)
hideDialog()
}
}
}
......
......@@ -61,6 +61,17 @@ bool AutoPilotPlugin::setupComplete(void)
void AutoPilotPlugin::parametersReadyPreChecks(void)
{
_recalcSetupComplete();
// Connect signals in order to keep setupComplete up to date
foreach(const QVariant componentVariant, vehicleComponents()) {
VehicleComponent* component = qobject_cast<VehicleComponent*>(qvariant_cast<QObject *>(componentVariant));
if (component) {
connect(component, &VehicleComponent::setupCompleteChanged, this, &AutoPilotPlugin::_recalcSetupComplete);
} else {
qWarning() << "AutoPilotPlugin::_recalcSetupComplete Incorrectly typed VehicleComponent";
}
}
if (!_setupComplete) {
qgcApp()->showMessage(tr("One or more vehicle components require setup prior to flight."));
......
......@@ -66,7 +66,7 @@ protected:
FirmwarePlugin* _firmwarePlugin;
bool _setupComplete;
private:
private slots:
void _recalcSetupComplete(void);
};
......
......@@ -55,7 +55,7 @@ SetupPage {
property real _lastValue: 0
onTriggered: {
if (_lastValue != slider.value) {
if (_lastValue !== slider.value) {
controller.vehicle.motorTest(index + 1, slider.value, 1)
}
}
......
......@@ -379,7 +379,7 @@ SetupPage {
text: qsTr("Calibrate")
onClicked: {
if (text == qsTr("Calibrate")) {
if (text === qsTr("Calibrate")) {
showDialog(zeroTrimsDialogComponent, dialogTitle, radioPage.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel)
} else {
controller.nextButtonClicked()
......
......@@ -123,23 +123,23 @@ RadioComponentController::~RadioComponentController()
/// @brief Returns the state machine entry for the specified state.
const RadioComponentController::stateMachineEntry* RadioComponentController::_getStateMachineEntry(int step) const
{
static const char* msgBeginPX4 = "Lower the Throttle stick all the way down as shown in diagram.\n\n"
static const char* msgBeginPX4 = QT_TR_NOOP("Lower the Throttle stick all the way down as shown in diagram.\n\n"
"It is recommended to disconnect all motors for additional safety, however, the system is designed to not arm during the calibration.\n\n"
"Click Next to continue";
static const char* msgBeginAPM = "Lower the Throttle stick all the way down as shown in diagram.\nReset all transmitter trims to center.\n\n"
"Click Next to continue");
static const char* msgBeginAPM = QT_TR_NOOP("Lower the Throttle stick all the way down as shown in diagram.\nReset all transmitter trims to center.\n\n"
"Please ensure all motor power is disconnected AND all props are removed from the vehicle.\n\n"
"Click Next to continue";
static const char* msgThrottleUp = "Move the Throttle stick all the way up and hold it there...";
static const char* msgThrottleDown = "Move the Throttle stick all the way down and leave it there...";
static const char* msgYawLeft = "Move the Yaw stick all the way to the left and hold it there...";
static const char* msgYawRight = "Move the Yaw stick all the way to the right and hold it there...";
static const char* msgRollLeft = "Move the Roll stick all the way to the left and hold it there...";
static const char* msgRollRight = "Move the Roll stick all the way to the right and hold it there...";
static const char* msgPitchDown = "Move the Pitch stick all the way down and hold it there...";
static const char* msgPitchUp = "Move the Pitch stick all the way up and hold it there...";
static const char* msgPitchCenter = "Allow the Pitch stick to move back to center...";
static const char* msgSwitchMinMax = "Move all the transmitter switches and/or dials back and forth to their extreme positions.";
static const char* msgComplete = "All settings have been captured. Click Next to write the new parameters to your board.";
"Click Next to continue");
static const char* msgThrottleUp = QT_TR_NOOP("Move the Throttle stick all the way up and hold it there...");
static const char* msgThrottleDown = QT_TR_NOOP("Move the Throttle stick all the way down and leave it there...");
static const char* msgYawLeft = QT_TR_NOOP("Move the Yaw stick all the way to the left and hold it there...");
static const char* msgYawRight = QT_TR_NOOP("Move the Yaw stick all the way to the right and hold it there...");
static const char* msgRollLeft = QT_TR_NOOP("Move the Roll stick all the way to the left and hold it there...");
static const char* msgRollRight = QT_TR_NOOP("Move the Roll stick all the way to the right and hold it there...");
static const char* msgPitchDown = QT_TR_NOOP("Move the Pitch stick all the way down and hold it there...");
static const char* msgPitchUp = QT_TR_NOOP("Move the Pitch stick all the way up and hold it there...");
static const char* msgPitchCenter = QT_TR_NOOP("Allow the Pitch stick to move back to center...");
static const char* msgSwitchMinMax = QT_TR_NOOP("Move all the transmitter switches and/or dials back and forth to their extreme positions.");
static const char* msgComplete = QT_TR_NOOP("All settings have been captured. Click Next to write the new parameters to your board.");
static const stateMachineEntry rgStateMachinePX4[] = {
//Function
......@@ -206,9 +206,9 @@ void RadioComponentController::_advanceState(void)
/// @brief Sets up the state machine according to the current step from _currentStep.
void RadioComponentController::_setupCurrentState(void)
{
static const char* msgBeginAPMRover = "Center the Throttle stick as shown in diagram.\nReset all transmitter trims to center.\n\n"
static const char* msgBeginAPMRover = QT_TR_NOOP("Center the Throttle stick as shown in diagram.\nReset all transmitter trims to center.\n\n"
"Please ensure all motor power is disconnected from the vehicle.\n\n"
"Click Next to continue";
"Click Next to continue");
const stateMachineEntry* state = _getStateMachineEntry(_currentStep);
const char* instructions = state->instructions;
......
......@@ -21,8 +21,9 @@ import QGroundControl.Controllers 1.0
/// Base view control for all Setup pages
QGCView {
id: setupView
viewPanel: setupPanel
id: setupView
viewPanel: setupPanel
enabled: !_shouldDisableWhenArmed
property alias pageComponent: pageLoader.sourceComponent
property string pageName: vehicleComponent ? vehicleComponent.name : ""
......@@ -30,53 +31,15 @@ QGCView {
property real availableWidth: width - pageLoader.x
property real availableHeight: height - pageLoader.y
property real _margins: ScreenTools.defaultFontPixelHeight / 2
property bool _vehicleArmed: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle.armed : false
property bool _shouldDisableWhenArmed: _vehicleArmed ? (vehicleComponent ? !vehicleComponent.allowSetupWhileArmed : false) : false
property bool visibleWhileArmed: false
property real _margins: ScreenTools.defaultFontPixelHeight * 0.5
property string _pageTitle: qsTr("%1 Setup").arg(pageName)
property bool vehicleArmed: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle.armed : false
onVehicleArmedChanged: {
if (visibleWhileArmed) {
return
}
if (vehicleArmed) {
disabledWhileArmed.visible = true
setupView.viewPanel.enabled = false
} else {
disabledWhileArmed.visible = false
setupView.viewPanel.enabled = true
}
}
QGCPalette { id: qgcPal; colorGroupEnabled: setupPanel.enabled }
// Overlay to display when vehicle is armed and the setup page needs
// to be disabled
Item {
id: disabledWhileArmed
visible: false
z: 9999
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "black"
opacity: 0.5
}
QGCLabel {
anchors.margins: defaultTextWidth * 2
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pointSize: ScreenTools.largeFontPointSize
color: "red"
text: "Setup disabled while the vehicle is armed"
}
}
QGCViewPanel {
id: setupPanel
anchors.fill: parent
......@@ -88,13 +51,13 @@ QGCView {
clip: true
Column {
id: headingColumn
width: setupPanel.width
spacing: _margins
id: headingColumn
width: setupPanel.width
spacing: _margins
QGCLabel {
font.pointSize: ScreenTools.largeFontPointSize
text: pageName + " " + qsTr("Setup")
text: _shouldDisableWhenArmed ? _pageTitle + "<font color=\"red\">" + qsTr(" (Disabled while the vehicle is armed)") + "</font>" : _pageTitle
visible: !ScreenTools.isShortScreen
}
......@@ -112,6 +75,14 @@ QGCView {
anchors.topMargin: _margins
anchors.top: headingColumn.bottom
}
// Overlay to display when vehicle is armed and this setup page needs
// to be disabled
Rectangle {
visible: _shouldDisableWhenArmed
anchors.fill: pageLoader
color: "black"
opacity: 0.5
}
}
}
}
......@@ -202,12 +202,12 @@ Your vehicle will also be restarted in order to complete the process.")
QGCCheckBox {
// Although this item is invisible we still use it to manage state
id: airframeCheckBox
checked: modelData.name == controller.currentAirframeType
checked: modelData.name === controller.currentAirframeType
exclusiveGroup: airframeTypeExclusive
visible: false
onCheckedChanged: {
if (checked && combo.currentIndex != -1) {
if (checked && combo.currentIndex !== -1) {
console.log("check box change", combo.currentIndex)
controller.autostartId = modelData.airframes[combo.currentIndex].autostartId
}
......
......@@ -125,8 +125,8 @@ void AirframeComponentController::_rebootAfterStackUnwind(void)
QGC::SLEEP::usleep(500);
qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
}
qgcApp()->toolbox()->linkManager()->disconnectAll();
qgcApp()->restoreOverrideCursor();
qgcApp()->toolbox()->linkManager()->disconnectAll();
}
AirframeType::AirframeType(const QString& name, const QString& imageResource, QObject* parent) :
......
......@@ -37,7 +37,7 @@ FactPanel {
VehicleSummaryRow {
labelText: qsTr("Firmware Version:")
valueText: activeVehicle.firmwareMajorVersion == -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + activeVehicle.firmwareVersionTypeString
valueText: activeVehicle.firmwareMajorVersion === -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + activeVehicle.firmwareVersionTypeString
}
}
}
......@@ -354,9 +354,9 @@
<maintainer>James Goppert &lt;james.goppert@gmail.com&gt;</maintainer>
<type>Quadrotor x</type>
</airframe>
<airframe id="4070" maintainer="Lucas de Marchi" name="Intel Aero Ready to Fly Drone">
<airframe id="4070" maintainer="Beat Kueng &lt;beat@px4.io&gt;" name="Intel Aero Ready to Fly Drone">
<class>Copter</class>
<maintainer>Lucas de Marchi</maintainer>
<maintainer>Beat Kueng &lt;beat@px4.io&gt;</maintainer>
<type>Quadrotor x</type>
</airframe>
<airframe id="4080" maintainer="Anton Matosov &lt;anton.matosov@gmail.com&gt;" name="ZMR250 Racer">
......@@ -589,15 +589,6 @@
<output name="MAIN4">throttle</output>
</airframe>
</airframe_group>
<airframe_group image="AirframeUnknown" name="custom">
<airframe id="20000" maintainer="Julian Oes &lt;julian@oes.ch&gt;&#10;This startup can be used on Pixhawk/Pixfalcon/Pixracer for the&#10;passthrough of RC input and PWM output." name="Passthrough mode for Snapdragon">
<class>Tool</class>
<maintainer>Julian Oes &lt;julian@oes.ch&gt;
This startup can be used on Pixhawk/Pixfalcon/Pixracer for the
passthrough of RC input and PWM output.</maintainer>
<type>custom</type>
</airframe>
</airframe_group>
<airframe_group image="VTOLPlane" name="Standard VTOL">
<airframe id="13000" maintainer="" name="Generic Quadplane VTOL">
<class>VTOL</class>
......
......@@ -18,7 +18,7 @@ FactPanel {
property Fact _nullFact
property Fact _rcMapFltmode: controller.parameterExists(-1, "RC_MAP_FLTMODE") ? controller.getParameterFact(-1, "RC_MAP_FLTMODE") : _nullFact
property Fact _rcMapModeSw: controller.getParameterFact(-1, "RC_MAP_MODE_SW")
property bool _simpleMode: _rcMapFltmode.value > 0 || _rcMapModeSw.value == 0
property bool _simpleMode: _rcMapFltmode.value > 0 || _rcMapModeSw.value === 0
Loader {
anchors.fill: parent
......
......@@ -66,16 +66,16 @@ const QVariantList& PX4AutoPilotPlugin::vehicleComponents(void)
_airframeComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_airframeComponent));
_radioComponent = new PX4RadioComponent(_vehicle, this);
_radioComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_radioComponent));
if (!_vehicle->hilMode()) {
_sensorsComponent = new SensorsComponent(_vehicle, this);
_sensorsComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_sensorsComponent));
}
_radioComponent = new PX4RadioComponent(_vehicle, this);
_radioComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_radioComponent));
_flightModesComponent = new FlightModesComponent(_vehicle, this);
_flightModesComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_flightModesComponent));
......
......@@ -44,6 +44,7 @@ public:
const QVariantList& vehicleComponents(void) override;
void parametersReadyPreChecks(void) override;
QString prerequisiteSetup(VehicleComponent* component) const override;
protected:
bool _incorrectParameterVersion; ///< true: parameter version incorrect, setup not allowed
PX4AirframeLoader* _airframeFacts;
......@@ -58,6 +59,7 @@ protected:
MotorComponent* _motorComponent;
PX4TuningComponent* _tuningComponent;
SyslinkComponent* _syslinkComponent;
private:
QVariantList _components;
};
......
......@@ -39,7 +39,7 @@ SetupPage {
property bool _rcMapFltmodeExists: controller.parameterExists(-1, "RC_MAP_FLTMODE")
property Fact _rcMapFltmode: _rcMapFltmodeExists ? controller.getParameterFact(-1, "RC_MAP_FLTMODE") : _nullFact
property Fact _rcMapModeSw: controller.getParameterFact(-1, "RC_MAP_MODE_SW")
property bool _simpleMode: _rcMapFltmodeExists ? _rcMapFltmode.value > 0 || _rcMapModeSw.value == 0 : false
property bool _simpleMode: _rcMapFltmodeExists ? _rcMapFltmode.value > 0 || _rcMapModeSw.value === 0 : false
FactPanelController {
id: controller
......
......@@ -145,7 +145,7 @@ Item {
QGCLabel {
anchors.baseline: returnCombo.baseline
text: qsTr("Return switch:")
color: parent.fact.value == 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
color: parent.fact.value === 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
}
FactComboBox {
......@@ -164,7 +164,7 @@ Item {
QGCLabel {
anchors.baseline: killCombo.baseline
text: qsTr("Kill switch:")
color: parent.fact.value == 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
color: parent.fact.value === 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
}
FactComboBox {
......@@ -183,7 +183,7 @@ Item {
QGCLabel {
anchors.baseline: offboardCombo.baseline
text: qsTr("Offboard switch:")
color: parent.fact.value == 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
color: parent.fact.value === 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
}
FactComboBox {
......@@ -203,7 +203,7 @@ Item {
QGCLabel {
anchors.baseline: vtolCombo.baseline
text: qsTr("VTOL mode switch:")
color: parent.fact.value == 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
color: parent.fact.value === 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
}
FactComboBox {
......
......@@ -43,24 +43,24 @@ SetupPage {
readonly property string highlightPrefix: "<font color=\"" + qgcPal.warningText + "\">"
readonly property string highlightSuffix: "</font>"
function getBatteryImage()
{
switch(battNumCells.value) {
case 1: return "/qmlimages/PowerComponentBattery_01cell.svg";
case 2: return "/qmlimages/PowerComponentBattery_02cell.svg"
case 3: return "/qmlimages/PowerComponentBattery_03cell.svg"
case 4: return "/qmlimages/PowerComponentBattery_04cell.svg"
case 5: return "/qmlimages/PowerComponentBattery_05cell.svg"
case 6: return "/qmlimages/PowerComponentBattery_06cell.svg"
default: return "/qmlimages/PowerComponentBattery_01cell.svg";
}
}
ColumnLayout {
id: innerColumn
anchors.horizontalCenter: parent.horizontalCenter
spacing: ScreenTools.defaultFontPixelHeight
function getBatteryImage()
{
switch(battNumCells.value) {
case 1: return "/qmlimages/PowerComponentBattery_01cell.svg";
case 2: return "/qmlimages/PowerComponentBattery_02cell.svg"
case 3: return "/qmlimages/PowerComponentBattery_03cell.svg"
case 4: return "/qmlimages/PowerComponentBattery_04cell.svg"
case 5: return "/qmlimages/PowerComponentBattery_05cell.svg"
case 6: return "/qmlimages/PowerComponentBattery_06cell.svg"
default: return "/qmlimages/PowerComponentBattery_01cell.svg";
}
}
function drawArrowhead(ctx, x, y, radians)
{
ctx.save();
......@@ -143,7 +143,7 @@ SetupPage {
onClicked: {
var measuredVoltageValue = parseFloat(measuredVoltage.text)
if (measuredVoltageValue == 0 || isNaN(measuredVoltageValue)) {
if (measuredVoltageValue === 0 || isNaN(measuredVoltageValue)) {
return
}
var newVoltageDivider = (measuredVoltageValue * battVoltageDivider.value) / controller.vehicle.battery.voltage.value
......@@ -201,7 +201,7 @@ SetupPage {
onClicked: {
var measuredCurrentValue = parseFloat(measuredCurrent.text)
if (measuredCurrentValue == 0) {
if (measuredCurrentValue === 0) {
return
}
var newAmpsPerVolt = (measuredCurrentValue * battAmpsPerVolt.value) / controller.vehicle.battery.current.value
......@@ -379,7 +379,7 @@ SetupPage {
QGCCheckBox {
id: showUAVCAN
text: qsTr("Show UAVCAN Settings")
checked: uavcanEnable.rawValue != 0
checked: uavcanEnable ? uavcanEnable.rawValue !== 0 : false
}
QGCGroupBox {
......
......@@ -167,10 +167,10 @@ SetupPage {
columns: 3
Image {
mipmap: true
fillMode: Image.PreserveAspectFit
source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/LowBatteryLight.svg" : "/qmlimages/LowBattery.svg"
Layout.rowSpan: 3
mipmap: true
fillMode: Image.PreserveAspectFit
source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/LowBatteryLight.svg" : "/qmlimages/LowBattery.svg"
Layout.rowSpan: 4
Layout.maximumWidth: _imageWidth
Layout.maximumHeight: _imageHeight
width: _imageWidth
......@@ -204,6 +204,15 @@ SetupPage {
fact: controller.getParameterFact(-1, "BAT_CRIT_THR")
Layout.minimumWidth: _editFieldWidth
}
QGCLabel {
text: qsTr("Battery Emergency Level:")
Layout.fillWidth: true
}
FactTextField {
fact: controller.getParameterFact(-1, "BAT_EMERGEN_THR")
Layout.minimumWidth: _editFieldWidth
}
}
Item { width: 1; height: _margins; Layout.columnSpan: 3 }
......
......@@ -16,8 +16,9 @@
#include "QGCQmlWidgetHolder.h"
#include "SensorsComponentController.h"
const char* SensorsComponent::_airspeedBreaker = "CBRK_AIRSPD_CHK";
const char* SensorsComponent::_airspeedCal = "SENS_DPRES_OFF";
const char* SensorsComponent::_airspeedBreakerParam = "CBRK_AIRSPD_CHK";
const char* SensorsComponent::_airspeedDisabledParam = "FW_ARSP_MODE";
const char* SensorsComponent::_airspeedCalParam = "SENS_DPRES_OFF";
SensorsComponent::SensorsComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) :
VehicleComponent(vehicle, autopilot, parent),
......@@ -55,10 +56,10 @@ bool SensorsComponent::setupComplete(void) const
}
if (_vehicle->fixedWing() || _vehicle->vtol()) {
if (_vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _airspeedBreaker)->rawValue().toInt() != 162128) {
if (_vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _airspeedCal)->rawValue().toFloat() == 0.0f) {
return false;
}
if (!_vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _airspeedDisabledParam)->rawValue().toBool() &&
_vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _airspeedBreakerParam)->rawValue().toInt() != 162128 &&
_vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _airspeedCalParam)->rawValue().toFloat() == 0.0f) {
return false;
}
}
......@@ -71,7 +72,7 @@ QStringList SensorsComponent::setupCompleteChangedTriggerList(void) const
triggers << _deviceIds;
if (_vehicle->fixedWing() || _vehicle->vtol()) {
triggers << _airspeedCal << _airspeedBreaker;
triggers << _airspeedCalParam << _airspeedBreakerParam;
}
return triggers;
......
......@@ -41,8 +41,9 @@ private:
QVariantList _summaryItems;
QStringList _deviceIds;
static const char* _airspeedBreaker;
static const char* _airspeedCal;
static const char* _airspeedDisabledParam;
static const char* _airspeedBreakerParam;
static const char* _airspeedCalParam;
};
#endif
......@@ -18,10 +18,15 @@ FactPanel {
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
FactPanelController { id: controller; factPanel: panel }
property Fact mag0IdFact: controller.getParameterFact(-1, "CAL_MAG0_ID")
property Fact gyro0IdFact: controller.getParameterFact(-1, "CAL_GYRO0_ID")
property Fact accel0IdFact: controller.getParameterFact(-1, "CAL_ACC0_ID")
property Fact dpressOffFact: controller.getParameterFact(-1, "SENS_DPRES_OFF")
property Fact mag0IdFact: controller.getParameterFact(-1, "CAL_MAG0_ID")
property Fact gyro0IdFact: controller.getParameterFact(-1, "CAL_GYRO0_ID")
property Fact accel0IdFact: controller.getParameterFact(-1, "CAL_ACC0_ID")
property Fact dpressOffFact: controller.getParameterFact(-1, "SENS_DPRES_OFF")
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 _airspeedCalRequired: _airspeedVisible && dpressOffFact.value === 0
Column {
anchors.fill: parent
......@@ -42,8 +47,9 @@ FactPanel {
}
VehicleSummaryRow {
labelText: qsTr("Airspeed:")
valueText: dpressOffFact ? (dpressOffFact.value === 0 ? qsTr("Setup required") : qsTr("Ready")) : ""
labelText: qsTr("Airspeed:")
visible: _airspeedVisible
valueText: _airspeedCalRequired ? qsTr("Setup required") : qsTr("Ready")
}
}
}
......@@ -42,9 +42,9 @@ Item {
readonly property string boardRotationText: qsTr("If the orientation is in the direction of flight, select ROTATION_NONE.")
readonly property string compassRotationText: qsTr("If the orientation is in the direction of flight, select ROTATION_NONE.")
readonly property string compassHelp: qsTr("For Compass calibration you will need to rotate your vehicle through a number of positions. Click Ok to start calibration.")
readonly property string gyroHelp: qsTr("For Gyroscope calibration you will need to place your vehicle on a surface and leave it still. Click Ok to start calibration.")
readonly property string accelHelp: qsTr("For Accelerometer calibration you will need to place your vehicle on all six sides on a perfectly level surface and hold it still in each orientation for a few seconds. Click Ok to start calibration.")
readonly property string compassHelp: qsTr("For Compass calibration you will need to rotate your vehicle through a number of positions.\n\nClick Ok to start calibration.")
readonly property string gyroHelp: qsTr("For Gyroscope calibration you will need to place your vehicle on a surface and leave it still.\n\nClick Ok to start calibration.")
readonly property string accelHelp: qsTr("For Accelerometer calibration you will need to place your vehicle on all six sides on a perfectly level surface and hold it still in each orientation for a few seconds.\n\nClick Ok to start calibration.")
readonly property string levelHelp: qsTr("To level the horizon you need to place the vehicle in its level flight position and press OK.")
readonly property string airspeedHelp: qsTr("For Airspeed calibration you will need to keep your airspeed sensor out of any wind and then blow across the sensor. Do not touch the sensor or obstruct any holes during the calibration.")
......@@ -177,15 +177,10 @@ Item {
Column {
anchors.fill: parent
spacing: ScreenTools.defaultFontPixelWidth / 2
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: preCalibrationDialogHelp
}
spacing: ScreenTools.defaultFontPixelHeight
Column {
width: parent.width
spacing: 5
visible: !_sensorsHaveFixedOrientation
......@@ -194,14 +189,13 @@ Item {
width: parent.width
wrapMode: Text.WordWrap
visible: (preCalibrationDialogType != "airspeed") && (preCalibrationDialogType != "gyro")
text: boardRotationText
text: qsTr("Set autopilot orientation before calibrating.")
}
Column {
visible: boardRotationHelp.visible
QGCLabel {
text: qsTr("Autopilot Orientation:")
}
QGCLabel { text: qsTr("Autopilot Orientation:") }
FactComboBox {
id: boardRotationCombo
......@@ -211,6 +205,12 @@ Item {
}
}
}
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: preCalibrationDialogHelp
}
}
}
}
......@@ -352,7 +352,7 @@ Item {
id: compassButton
width: _buttonWidth
text: qsTr("Compass")
indicatorGreen: cal_mag0_id.value != 0
indicatorGreen: cal_mag0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationCompass && showSensorCalibrationCompass
onClicked: {
......@@ -366,7 +366,7 @@ Item {
id: gyroButton
width: _buttonWidth
text: qsTr("Gyroscope")
indicatorGreen: cal_gyro0_id.value != 0
indicatorGreen: cal_gyro0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationGyro && showSensorCalibrationGyro
onClicked: {
......@@ -380,7 +380,7 @@ Item {
id: accelButton
width: _buttonWidth
text: qsTr("Accelerometer")
indicatorGreen: cal_acc0_id.value != 0
indicatorGreen: cal_acc0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationAccel && showSensorCalibrationAccel
onClicked: {
......@@ -394,8 +394,8 @@ Item {
id: levelButton
width: _buttonWidth
text: qsTr("Level Horizon")
indicatorGreen: sens_board_x_off.value != 0 || sens_board_y_off != 0 | sens_board_z_off != 0
enabled: cal_acc0_id.value != 0 && cal_gyro0_id.value != 0
indicatorGreen: sens_board_x_off.value !== 0 || sens_board_y_off.value !== 0 | sens_board_z_off.value !== 0
enabled: cal_acc0_id.value !== 0 && cal_gyro0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationLevel && showSensorCalibrationLevel
onClicked: {
......@@ -410,10 +410,11 @@ Item {
width: _buttonWidth
text: qsTr("Airspeed")
visible: (controller.vehicle.fixedWing || controller.vehicle.vtol) &&
controller.getParameterFact(-1, "CBRK_AIRSPD_CHK").value != 162128 &&
controller.getParameterFact(-1, "FW_ARSP_MODE").value === false &&
controller.getParameterFact(-1, "CBRK_AIRSPD_CHK").value !== 162128 &&
QGroundControl.corePlugin.options.showSensorCalibrationAirspeed &&
showSensorCalibrationAirspeed
indicatorGreen: sens_dpres_off.value != 0
indicatorGreen: sens_dpres_off.value !== 0
onClicked: {
preCalibrationDialogType = "airspeed"
......
......@@ -40,6 +40,7 @@ static const char* kParameterrange = "parameterrange";
static const char* kParameterranges = "parameterranges";
static const char* kParameters = "parameters";
static const char* kReadOnly = "readonly";
static const char* kWriteOnly = "writeonly";
static const char* kRoption = "roption";
static const char* kStep = "step";
static const char* kStrings = "strings";
......@@ -659,6 +660,13 @@ QGCCameraControl::_loadSettings(const QDomNodeList nodeList)
//-- Is it read only?
bool readOnly = false;
read_attribute(parameterNode, kReadOnly, readOnly);
//-- Is it write only?
bool writeOnly = false;
read_attribute(parameterNode, kWriteOnly, writeOnly);
//-- It can't be both
if(readOnly && writeOnly) {
qCritical() << QString("Parameter %1 cannot be both read only and write only").arg(factName);
}
//-- Param type
bool unknownType;
FactMetaData::ValueType_t factType = FactMetaData::stringToType(type, unknownType);
......@@ -689,6 +697,7 @@ QGCCameraControl::_loadSettings(const QDomNodeList nodeList)
metaData->setLongDescription(description);
metaData->setHasControl(control);
metaData->setReadOnly(readOnly);
metaData->setWriteOnly(writeOnly);
//-- Options (enums)
QDomElement optionElem = parameterNode.toElement();
QDomNodeList optionsRoot = optionElem.elementsByTagName(kOptions);
......@@ -797,7 +806,7 @@ QGCCameraControl::_loadSettings(const QDomNodeList nodeList)
metaData->setRawUnits(attr);
}
}
qCDebug(CameraControlLog) << "New parameter:" << factName;
qCDebug(CameraControlLog) << "New parameter:" << factName << (readOnly ? "ReadOnly" : "Writable") << (writeOnly ? "WriteOnly" : "Readable");
_nameToFactMetaDataMap[factName] = metaData;
Fact* pFact = new Fact(_compID, factName, factType, this);
QQmlEngine::setObjectOwnership(pFact, QQmlEngine::CppOwnership);
......
......@@ -202,16 +202,16 @@ protected:
virtual void _setCameraMode (CameraMode mode);
protected slots:
void _initWhenReady ();
void _requestCameraSettings ();
void _requestAllParameters ();
void _requestParamUpdates ();
void _requestCaptureStatus ();
void _requestStorageInfo ();
void _downloadFinished ();
void _mavCommandResult (int vehicleId, int component, int command, int result, bool noReponseFromVehicle);
void _dataReady (QByteArray data);
void _paramDone ();
virtual void _initWhenReady ();
virtual void _requestCameraSettings ();
virtual void _requestAllParameters ();
virtual void _requestParamUpdates ();
virtual void _requestCaptureStatus ();
virtual void _requestStorageInfo ();
virtual void _downloadFinished ();
virtual void _mavCommandResult (int vehicleId, int component, int command, int result, bool noReponseFromVehicle);
virtual void _dataReady (QByteArray data);
virtual void _paramDone ();
private:
bool _handleLocalization (QByteArray& bytes);
......
......@@ -28,8 +28,13 @@ QGCCameraParamIO::QGCCameraParamIO(QGCCameraControl *control, Fact* fact, Vehicl
_paramWriteTimer.setInterval(3000);
_paramRequestTimer.setSingleShot(true);
_paramRequestTimer.setInterval(3500);
if(_fact->writeOnly()) {
//-- Write mode is always "done" as it won't ever read
_done = true;
} else {
connect(&_paramRequestTimer, &QTimer::timeout, this, &QGCCameraParamIO::_paramRequestTimeout);
}
connect(&_paramWriteTimer, &QTimer::timeout, this, &QGCCameraParamIO::_paramWriteTimeout);
connect(&_paramRequestTimer, &QTimer::timeout, this, &QGCCameraParamIO::_paramRequestTimeout);
connect(_fact, &Fact::rawValueChanged, this, &QGCCameraParamIO::_factChanged);
connect(_fact, &Fact::_containerRawValueChanged, this, &QGCCameraParamIO::_containerRawValueChanged);
_pMavlink = qgcApp()->toolbox()->mavlinkProtocol();
......@@ -38,31 +43,42 @@ QGCCameraParamIO::QGCCameraParamIO(QGCCameraControl *control, Fact* fact, Vehicl
switch (_fact->type()) {
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeBool:
_mavParamType = MAV_PARAM_TYPE_UINT8;
_mavParamType = MAV_PARAM_EXT_TYPE_UINT8;
break;
case FactMetaData::valueTypeInt8:
_mavParamType = MAV_PARAM_TYPE_INT8;
_mavParamType = MAV_PARAM_EXT_TYPE_INT8;
break;
case FactMetaData::valueTypeUint16:
_mavParamType = MAV_PARAM_TYPE_UINT16;
_mavParamType = MAV_PARAM_EXT_TYPE_UINT16;
break;
case FactMetaData::valueTypeInt16:
_mavParamType = MAV_PARAM_TYPE_INT16;
_mavParamType = MAV_PARAM_EXT_TYPE_INT16;
break;
case FactMetaData::valueTypeUint32:
_mavParamType = MAV_PARAM_TYPE_UINT32;
_mavParamType = MAV_PARAM_EXT_TYPE_UINT32;
break;
case FactMetaData::valueTypeUint64:
_mavParamType = MAV_PARAM_EXT_TYPE_UINT64;
break;
case FactMetaData::valueTypeInt64:
_mavParamType = MAV_PARAM_EXT_TYPE_INT64;
break;
case FactMetaData::valueTypeFloat:
_mavParamType = MAV_PARAM_TYPE_REAL32;
_mavParamType = MAV_PARAM_EXT_TYPE_REAL32;
break;
case FactMetaData::valueTypeDouble:
_mavParamType = MAV_PARAM_EXT_TYPE_REAL64;
break;
//-- String and custom are the same for now
case FactMetaData::valueTypeString:
case FactMetaData::valueTypeCustom:
_mavParamType = (MAV_PARAM_TYPE)11; // MAV_PARAM_TYPE_CUSTOM;
_mavParamType = MAV_PARAM_EXT_TYPE_CUSTOM;
break;
default:
qWarning() << "Unsupported fact type" << _fact->type() << "for" << _fact->name();
// Fall through
case FactMetaData::valueTypeInt32:
_mavParamType = MAV_PARAM_TYPE_INT32;
_mavParamType = MAV_PARAM_EXT_TYPE_INT32;
break;
}
}
......@@ -71,9 +87,11 @@ QGCCameraParamIO::QGCCameraParamIO(QGCCameraControl *control, Fact* fact, Vehicl
void
QGCCameraParamIO::setParamRequest()
{
_paramRequestReceived = false;
_requestRetries = 0;
_paramRequestTimer.start();
if(!_fact->writeOnly()) {
_paramRequestReceived = false;
_requestRetries = 0;
_paramRequestTimer.start();
}
}
//-----------------------------------------------------------------------------
......@@ -136,9 +154,20 @@ QGCCameraParamIO::_sendParameter()
case FactMetaData::valueTypeUint32:
union_value.param_uint32 = (uint32_t)_fact->rawValue().toUInt();
break;
case FactMetaData::valueTypeInt64:
union_value.param_int64 = (int64_t)_fact->rawValue().toLongLong();
break;
case FactMetaData::valueTypeUint64:
union_value.param_uint64 = (uint64_t)_fact->rawValue().toULongLong();
break;
case FactMetaData::valueTypeFloat:
union_value.param_float = _fact->rawValue().toFloat();
break;
case FactMetaData::valueTypeDouble:
union_value.param_double = _fact->rawValue().toDouble();
break;
//-- String and custom are the same for now
case FactMetaData::valueTypeString:
case FactMetaData::valueTypeCustom:
{
QByteArray custom = _fact->rawValue().toByteArray();
......@@ -250,28 +279,34 @@ QGCCameraParamIO::_valueFromMessage(const char* value, uint8_t param_type)
param_ext_union_t u;
memcpy(u.bytes, value, MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN);
switch (param_type) {
case MAV_PARAM_TYPE_REAL32:
case MAV_PARAM_EXT_TYPE_REAL32:
var = QVariant(u.param_float);
break;
case MAV_PARAM_TYPE_UINT8:
case MAV_PARAM_EXT_TYPE_UINT8:
var = QVariant(u.param_uint8);
break;
case MAV_PARAM_TYPE_INT8:
case MAV_PARAM_EXT_TYPE_INT8:
var = QVariant(u.param_int8);
break;
case MAV_PARAM_TYPE_UINT16:
case MAV_PARAM_EXT_TYPE_UINT16:
var = QVariant(u.param_uint16);
break;
case MAV_PARAM_TYPE_INT16:
case MAV_PARAM_EXT_TYPE_INT16:
var = QVariant(u.param_int16);
break;
case MAV_PARAM_TYPE_UINT32:
case MAV_PARAM_EXT_TYPE_UINT32:
var = QVariant(u.param_uint32);
break;
case MAV_PARAM_TYPE_INT32:
case MAV_PARAM_EXT_TYPE_INT32:
var = QVariant(u.param_int32);
break;
case 11: //MAV_PARAM_TYPE_CUSTOM:
case MAV_PARAM_EXT_TYPE_UINT64:
var = QVariant((qulonglong)u.param_uint64);
break;
case MAV_PARAM_EXT_TYPE_INT64:
var = QVariant((qlonglong)u.param_int64);
break;
case MAV_PARAM_EXT_TYPE_CUSTOM:
var = QVariant(QByteArray(value, MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN));
break;
default:
......@@ -303,6 +338,14 @@ QGCCameraParamIO::_paramRequestTimeout()
void
QGCCameraParamIO::paramRequest(bool reset)
{
//-- If it's write only, we don't request it.
if(_fact->writeOnly()) {
if(!_done) {
_done = true;
_control->_paramDone();
}
return;
}
if(reset) {
_requestRetries = 0;
_forceUIUpdate = true;
......
......@@ -19,6 +19,9 @@ MAVPACKED(
typedef struct {
union {
float param_float;
double param_double;
int64_t param_int64;
uint64_t param_uint64;
int32_t param_int32;
uint32_t param_uint32;
int16_t param_int16;
......@@ -67,7 +70,7 @@ private:
QTimer _paramRequestTimer;
bool _done;
bool _updateOnSet;
MAV_PARAM_TYPE _mavParamType;
MAV_PARAM_EXT_TYPE _mavParamType;
MAVLinkProtocol* _pMavlink;
bool _forceUIUpdate;
};
......
......@@ -25,28 +25,28 @@ public:
QGCCameraManager(Vehicle* vehicle);
virtual ~QGCCameraManager();
Q_PROPERTY(QmlObjectListModel* cameras READ cameras NOTIFY camerasChanged)
Q_PROPERTY(QmlObjectListModel* cameras READ cameras NOTIFY camerasChanged)
//-- Return a list of cameras provided by this vehicle
virtual QmlObjectListModel* cameras () { return &_cameras; }
virtual QmlObjectListModel* cameras () { return &_cameras; }
signals:
void camerasChanged ();
void camerasChanged ();
protected slots:
void _vehicleReady (bool ready);
void _mavlinkMessageReceived (const mavlink_message_t& message);
virtual void _vehicleReady (bool ready);
virtual void _mavlinkMessageReceived (const mavlink_message_t& message);
protected:
QGCCameraControl* _findCamera (int id);
void _requestCameraInfo (int compID);
void _handleHeartbeat (const mavlink_message_t& message);
void _handleCameraInfo (const mavlink_message_t& message);
void _handleStorageInfo (const mavlink_message_t& message);
void _handleCameraSettings (const mavlink_message_t& message);
void _handleParamAck (const mavlink_message_t& message);
void _handleParamValue (const mavlink_message_t& message);
void _handleCaptureStatus (const mavlink_message_t& message);
virtual QGCCameraControl* _findCamera (int id);
virtual void _requestCameraInfo (int compID);
virtual void _handleHeartbeat (const mavlink_message_t& message);
virtual void _handleCameraInfo (const mavlink_message_t& message);
virtual void _handleStorageInfo (const mavlink_message_t& message);
virtual void _handleCameraSettings (const mavlink_message_t& message);
virtual void _handleParamAck (const mavlink_message_t& message);
virtual void _handleParamValue (const mavlink_message_t& message);
virtual void _handleCaptureStatus (const mavlink_message_t& message);
protected:
Vehicle* _vehicle;
......
......@@ -7,12 +7,10 @@
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "Fact.h"
#include "QGCMAVLink.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
#include <QtQml>
#include <QQmlEngine>
......@@ -50,6 +48,21 @@ Fact::Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObjec
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
}
Fact::Fact(FactMetaData* metaData, QObject* parent)
: QObject(parent)
, _name (metaData->name())
, _componentId (0)
, _rawValue (0)
, _type (metaData->type())
, _metaData (NULL)
, _sendValueChangedSignals (true)
, _deferredValueChangeSignal(false)
{
// Allow core plugin a chance to override the default value
qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(*metaData);
setMetaData(metaData, true /* setDefaultFromMetaData */);
}
Fact::Fact(const Fact& other, QObject* parent)
: QObject(parent)
{
......@@ -148,9 +161,11 @@ void Fact::_containerSetRawValue(const QVariant& value)
if(_rawValue != value) {
_rawValue = value;
_sendValueChangedSignal(cookedValue());
emit vehicleUpdated(_rawValue);
emit rawValueChanged(_rawValue);
}
// This always need to be signalled in order to support forceSetRawValue usage and waiting for vehicleUpdated signal
emit vehicleUpdated(_rawValue);
}
QString Fact::name(void) const
......@@ -484,6 +499,16 @@ int Fact::decimalPlaces(void) const
}
}
QString Fact::category(void) const
{
if (_metaData) {
return _metaData->category();
} else {
qWarning() << kMissingMetadata << name();
return QString();
}
}
QString Fact::group(void) const
{
if (_metaData) {
......@@ -637,3 +662,23 @@ bool Fact::readOnly(void) const
return false;
}
}
bool Fact::writeOnly(void) const
{
if (_metaData) {
return _metaData->writeOnly();
} else {
qWarning() << kMissingMetadata << name();
return false;
}
}
bool Fact::volatileValue(void) const
{
if (_metaData) {
return _metaData->volatileValue();
} else {
qWarning() << kMissingMetadata << name();
return false;
}
}
......@@ -31,6 +31,10 @@ public:
Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent = NULL);
Fact(const Fact& other, QObject* parent = NULL);
/// Creates a Fact using the name and type from metaData. Also calls QGCCorePlugin::adjustSettingsMetaData allowing
/// custom builds to override the metadata.
Fact(FactMetaData* metaData, QObject* parent = NULL);
const Fact& operator=(const Fact& other);
Q_PROPERTY(int componentId READ componentId CONSTANT)
......@@ -44,6 +48,7 @@ public:
Q_PROPERTY(QStringList enumStrings READ enumStrings NOTIFY enumsChanged)
Q_PROPERTY(QString enumStringValue READ enumStringValue WRITE setEnumStringValue NOTIFY valueChanged)
Q_PROPERTY(QVariantList enumValues READ enumValues NOTIFY enumsChanged)
Q_PROPERTY(QString category READ category CONSTANT)
Q_PROPERTY(QString group READ group CONSTANT)
Q_PROPERTY(QString longDescription READ longDescription CONSTANT)
Q_PROPERTY(QVariant max READ cookedMax CONSTANT)
......@@ -66,6 +71,8 @@ public:
Q_PROPERTY(bool typeIsBool READ typeIsBool CONSTANT)
Q_PROPERTY(bool hasControl READ hasControl CONSTANT)
Q_PROPERTY(bool readOnly READ readOnly CONSTANT)
Q_PROPERTY(bool writeOnly READ writeOnly CONSTANT)
Q_PROPERTY(bool volatileValue READ volatileValue CONSTANT)
/// Convert and validate value
/// @param convertOnly true: validate type conversion only, false: validate against meta data as well
......@@ -87,6 +94,7 @@ public:
QStringList enumStrings (void) const;
QString enumStringValue (void); // This is not const, since an unknown value can modify the enum lists
QVariantList enumValues (void) const;
QString category (void) const;
QString group (void) const;
QString longDescription (void) const;
QVariant rawMax (void) const;
......@@ -112,6 +120,8 @@ public:
bool typeIsBool (void) const { return type() == FactMetaData::valueTypeBool; }
bool hasControl (void) const;
bool readOnly (void) const;
bool writeOnly (void) const;
bool volatileValue (void) const;
/// Returns the values as a string with full 18 digit precision if float/double.
QString rawValueStringFullPrecision(void) const;
......
......@@ -33,10 +33,12 @@ Flow {
checked: fact.value & fact.bitmaskValues[index]
onClicked: {
var i;
var otherCheckbox;
if (checked) {
if (firstEntryIsAll && index == 0) {
for (var i=1; i<repeater.count; i++) {
var otherCheckbox = repeater.itemAt(i)
for (i = 1; i < repeater.count; i++) {
otherCheckbox = repeater.itemAt(i)
fact.value &= ~fact.bitmaskValues[i]
otherCheckbox.checked = false
otherCheckbox.enabled = false
......@@ -45,8 +47,8 @@ Flow {
fact.value |= fact.bitmaskValues[index]
} else {
if (firstEntryIsAll && index == 0) {
for (var i=1; i<repeater.count; i++) {
var otherCheckbox = repeater.itemAt(i)
for (i = 1; i < repeater.count; i++) {
otherCheckbox = repeater.itemAt(i)
otherCheckbox.enabled = true
}
}
......
......@@ -8,16 +8,14 @@ import QGroundControl.Controls 1.0
QGCCheckBox {
property Fact fact: Fact { }
property variant checkedValue: 1
property variant uncheckedValue: 0
checkedState: fact ?
(fact.typeIsBool ?
(fact.value === true ? Qt.Checked : Qt.Unchecked) :
(fact.value === checkedValue ? Qt.Checked : Qt.Unchecked)) :
(fact.value === false ? Qt.Unchecked : Qt.Checked) :
(fact.value === 0 ? Qt.Unchecked : Qt.Checked)) :
Qt.Unchecked
text: qsTr("Label")
onClicked: fact.value = checked ? checkedValue : uncheckedValue
onClicked: fact.value = checked ? 1 : 0
}
......@@ -12,7 +12,7 @@ QGCComboBox {
model: fact ? fact.enumStrings : null
currentIndex: indexModel ? fact.value : fact.enumIndex
currentIndex: fact ? (indexModel ? fact.value : fact.enumIndex) : 0
onActivated: {
if (indexModel) {
......
......@@ -32,7 +32,7 @@ QGCTextField {
}
if (typeof qgcView !== 'undefined' && qgcView) {
var errorString = fact.validate(text, false /* convertOnly */)
if (errorString == "") {
if (errorString === "") {
fact.value = text
} else {
_validateString = text
......
......@@ -48,8 +48,8 @@ protected:
int _updateRateMSecs; ///< Update rate for Fact::valueChanged signals, 0: immediate update
private slots:
void _updateAllValues(void);
protected slots:
virtual void _updateAllValues(void);
private:
void _setupTimer();
......
This diff is collapsed.
......@@ -27,7 +27,7 @@
class FactMetaData : public QObject
{
Q_OBJECT
public:
typedef enum {
valueTypeUint8,
......@@ -36,6 +36,8 @@ public:
valueTypeInt16,
valueTypeUint32,
valueTypeInt32,
valueTypeUint64,
valueTypeInt64,
valueTypeFloat,
valueTypeDouble,
valueTypeString,
......@@ -45,7 +47,7 @@ public:
} ValueType_t;
typedef QVariant (*Translator)(const QVariant& from);
FactMetaData(QObject* parent = NULL);
FactMetaData(ValueType_t type, QObject* parent = NULL);
FactMetaData(ValueType_t type, const QString name, QObject* parent = NULL);
......@@ -76,6 +78,9 @@ public:
/// Returns the string for distance units which has configued by user
static QString appSettingsAreaUnitsString(void);
static const QString defaultCategory ();
static const QString defaultGroup ();
int decimalPlaces (void) const;
QVariant rawDefaultValue (void) const;
QVariant cookedDefaultValue (void) const { return _rawTranslator(rawDefaultValue()); }
......@@ -84,6 +89,7 @@ public:
QVariantList bitmaskValues (void) const { return _bitmaskValues; }
QStringList enumStrings (void) const { return _enumStrings; }
QVariantList enumValues (void) const { return _enumValues; }
QString category (void) const { return _category; }
QString group (void) const { return _group; }
QString longDescription (void) const { return _longDescription;}
QVariant rawMax (void) const { return _rawMax; }
......@@ -100,6 +106,8 @@ public:
bool rebootRequired (void) const { return _rebootRequired; }
bool hasControl (void) const { return _hasControl; }
bool readOnly (void) const { return _readOnly; }
bool writeOnly (void) const { return _writeOnly; }
bool volatileValue (void) const { return _volatile; }
/// Amount to increment value when used in controls such as spin button or slider with detents.
/// NaN for no increment available.
......@@ -118,6 +126,7 @@ public:
void setRawDefaultValue (const QVariant& rawDefaultValue);
void setBitmaskInfo (const QStringList& strings, const QVariantList& values);
void setEnumInfo (const QStringList& strings, const QVariantList& values);
void setCategory (const QString& category) { _category = category; }
void setGroup (const QString& group) { _group = group; }
void setLongDescription (const QString& longDescription) { _longDescription = longDescription;}
void setRawMax (const QVariant& rawMax);
......@@ -129,6 +138,8 @@ public:
void setIncrement (double increment) { _increment = increment; }
void setHasControl (bool bValue) { _hasControl = bValue; }
void setReadOnly (bool bValue) { _readOnly = bValue; }
void setWriteOnly (bool bValue) { _writeOnly = bValue; }
void setVolatileValue (bool bValue);
void setTranslators(Translator rawTranslator, Translator cookedTranslator);
......@@ -193,15 +204,23 @@ private:
static QVariant _normToPercent(const QVariant& normalized);
static QVariant _centimetersToInches(const QVariant& centimeters);
static QVariant _inchesToCentimeters(const QVariant& inches);
static QVariant _celsiusToFarenheit(const QVariant& celsius);
static QVariant _farenheitToCelsius(const QVariant& farenheit);
enum UnitTypes {
UnitDistance = 0,
UnitArea,
UnitSpeed,
UnitTemperature
};
struct AppSettingsTranslation_s {
const char* rawUnits;
const char* cookedUnits;
bool speed;
uint32_t speedOrDistanceUnits;
Translator rawTranslator;
Translator cookedTranslator;
const char* rawUnits;
const char* cookedUnits;
UnitTypes unitType;
uint32_t unitOption;
Translator rawTranslator;
Translator cookedTranslator;
};
static const AppSettingsTranslation_s* _findAppSettingsDistanceUnitsTranslation(const QString& rawUnits);
......@@ -215,6 +234,7 @@ private:
QVariantList _bitmaskValues;
QStringList _enumStrings;
QVariantList _enumValues;
QString _category;
QString _group;
QString _longDescription;
QVariant _rawMax;
......@@ -231,6 +251,8 @@ private:
double _increment;
bool _hasControl;
bool _readOnly;
bool _writeOnly;
bool _volatile;
// Exact conversion constants
static const struct UnitConsts_s {
......
This diff is collapsed.
......@@ -30,6 +30,7 @@
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
......@@ -84,7 +85,7 @@ public:
/// @param name Parameter name
Fact* getParameter(int componentId, const QString& name);
const QMap<int, QMap<QString, QStringList> >& getGroupMap(void);
const QMap<QString, QMap<QString, QStringList> >& getCategoryMap(void);
/// Returns error messages from loading
QString readParametersFromStream(QTextStream& stream);
......@@ -137,11 +138,13 @@ protected:
private:
static QVariant _stringToTypedVariant(const QString& string, FactMetaData::ValueType_t type, bool failOk = false);
int _actualComponentId(int componentId);
void _setupGroupMap(void);
void _setupCategoryMap(void);
void _readParameterRaw(int componentId, const QString& paramName, int paramIndex);
void _writeParameterRaw(int componentId, const QString& paramName, const QVariant& value);
void _writeLocalParamCache(int vehicleId, int componentId);
void _tryCacheHashLoad(int vehicleId, int componentId, QVariant hash_value);
void _loadMetaData(void);
void _clearMetaData(void);
void _addMetaDataToDefaultComponent(void);
QString _remapParamNameToVersion(const QString& paramName);
void _loadOfflineEditingParams(void);
......@@ -151,18 +154,14 @@ private:
MAV_PARAM_TYPE _factTypeToMavType(FactMetaData::ValueType_t factType);
FactMetaData::ValueType_t _mavTypeToFactType(MAV_PARAM_TYPE mavType);
void _saveToEEPROM(void);
void _checkInitialLoadComplete(void);
/// First mapping is by component id
/// Second mapping is parameter name, to Fact* in QVariant
QMap<int, QVariantMap> _mapParameterName2Variant;
QMap<int, QMap<int, QString> > _mapParameterId2Name;
/// First mapping is by component id
/// Second mapping is group name, to Fact
QMap<int, QMap<QString, QStringList> > _mapGroup2ParameterName;
// Category map of default component parameters
QMap<QString /* category */, QMap<QString /* group */, QStringList /* parameter names */> > _categoryMap;
double _loadProgress; ///< Parameter load progess, [0.0,1.0]
bool _parametersReady; ///< true: parameter load complete
......@@ -170,11 +169,19 @@ private:
bool _initialLoadComplete; ///< true: Initial load of all parameters complete, whether successful or not
bool _waitingForDefaultComponent; ///< true: last chance wait for default component params
bool _saveRequired; ///< true: _saveToEEPROM should be called
bool _metaDataAddedToFacts; ///< true: FactMetaData has been adde to the default component facts
bool _logReplay; ///< true: running with log replay link
QString _versionParam; ///< Parameter which contains parameter set version
int _parameterSetMajorVersion; ///< Version for parameter set, -1 if not known
QObject* _parameterMetaData; ///< Opaque data from FirmwarePlugin::loadParameterMetaDataCall
typedef QPair<int /* FactMetaData::ValueType_t */, QVariant /* Fact::rawValue */> ParamTypeVal;
typedef QMap<QString /* parameter name */, ParamTypeVal> CacheMapName2ParamTypeVal;
QMap<int /* component id */, bool> _debugCacheCRC; ///< true: debug cache crc failure
QMap<int /* component id */, CacheMapName2ParamTypeVal> _debugCacheMap;
QMap<int /* component id */, QMap<QString /* param name */, bool /* seen */>> _debugCacheParamSeen;
// Wait counts from previous parameter update cycle
int _prevWaitingReadParamIndexCount;
int _prevWaitingReadParamNameCount;
......
......@@ -911,6 +911,23 @@ void APMFirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle, double altitudeRel)
_guidedModeTakeoff(vehicle, altitudeRel);
}
double APMFirmwarePlugin::minimumTakeoffAltitude(Vehicle* vehicle)
{
double minTakeoffAlt = 0;
QString takeoffAltParam(vehicle->vtol() ? QStringLiteral("Q_RTL_ALT") : QStringLiteral("PILOT_TKOFF_ALT"));
float paramDivisor = vehicle->vtol() ? 1.0 : 100.0; // PILOT_TAKEOFF_ALT is in centimeters
if (vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, takeoffAltParam)) {
minTakeoffAlt = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, takeoffAltParam)->rawValue().toDouble() / paramDivisor;
}
if (minTakeoffAlt == 0) {
minTakeoffAlt = FirmwarePlugin::minimumTakeoffAltitude(vehicle);
}
return minTakeoffAlt;
}
bool APMFirmwarePlugin::_guidedModeTakeoff(Vehicle* vehicle, double altitudeRel)
{
if (!vehicle->multiRotor() && !vehicle->vtol()) {
......@@ -924,20 +941,7 @@ bool APMFirmwarePlugin::_guidedModeTakeoff(Vehicle* vehicle, double altitudeRel)
return false;
}
QString takeoffAltParam(vehicle->vtol() ? QStringLiteral("Q_RTL_ALT") : QStringLiteral("PILOT_TKOFF_ALT"));
float paramDivisor = vehicle->vtol() ? 1.0 : 100.0; // PILOT_TAKEOFF_ALT is in centimeters
float takeoffAltRel = 0;
if (vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, takeoffAltParam)) {
Fact* takeoffAltFact = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, takeoffAltParam);
takeoffAltRel = takeoffAltFact->rawValue().toDouble();
}
if (takeoffAltRel <= 0) {
takeoffAltRel = 2.5;
} else {
takeoffAltRel /= paramDivisor; // centimeters -> meters
}
double takeoffAltRel = minimumTakeoffAltitude(vehicle);
if (!qIsNaN(altitudeRel) && altitudeRel > takeoffAltRel) {
takeoffAltRel = altitudeRel;
}
......
......@@ -78,6 +78,7 @@ public:
void setGuidedMode (Vehicle* vehicle, bool guidedMode) override;
void guidedModeTakeoff (Vehicle* vehicle, double altitudeRel) override;
void guidedModeGotoLocation (Vehicle* vehicle, const QGeoCoordinate& gotoCoord) override;
double minimumTakeoffAltitude (Vehicle* vehicle) override;
void startMission (Vehicle* vehicle) override;
QStringList flightModes (Vehicle* vehicle) override;
QString flightMode (uint8_t base_mode, uint32_t custom_mode) const override;
......
......@@ -1336,7 +1336,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 2" name="ArduCopter:FLTMODE2" documentation="Flight mode when Channel 5 pwm is &gt;1230, &lt;= 1360" user="Standard">
......@@ -1359,7 +1359,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 3" name="ArduCopter:FLTMODE3" documentation="Flight mode when Channel 5 pwm is &gt;1360, &lt;= 1490" user="Standard">
......@@ -1382,7 +1382,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 4" name="ArduCopter:FLTMODE4" documentation="Flight mode when Channel 5 pwm is &gt;1490, &lt;= 1620" user="Standard">
......@@ -1405,7 +1405,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 5" name="ArduCopter:FLTMODE5" documentation="Flight mode when Channel 5 pwm is &gt;1620, &lt;= 1749" user="Standard">
......@@ -1428,7 +1428,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 6" name="ArduCopter:FLTMODE6" documentation="Flight mode when Channel 5 pwm is &gt;=1750" user="Standard">
......@@ -1451,7 +1451,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Simple mode bitmask" name="ArduCopter:SIMPLE" documentation="Bitmask which holds which flight modes use simple heading mode (eg bit 0 = 1 means Flight Mode 0 uses simple mode)" user="Advanced">
......
......@@ -1094,7 +1094,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 2" name="ArduCopter:FLTMODE2" documentation="Flight mode when Channel 5 pwm is &gt;1230, &lt;= 1360" user="Standard">
......@@ -1117,7 +1117,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 3" name="ArduCopter:FLTMODE3" documentation="Flight mode when Channel 5 pwm is &gt;1360, &lt;= 1490" user="Standard">
......@@ -1140,7 +1140,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 4" name="ArduCopter:FLTMODE4" documentation="Flight mode when Channel 5 pwm is &gt;1490, &lt;= 1620" user="Standard">
......@@ -1163,7 +1163,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 5" name="ArduCopter:FLTMODE5" documentation="Flight mode when Channel 5 pwm is &gt;1620, &lt;= 1749" user="Standard">
......@@ -1186,7 +1186,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 6" name="ArduCopter:FLTMODE6" documentation="Flight mode when Channel 5 pwm is &gt;=1750" user="Standard">
......@@ -1209,7 +1209,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Simple mode bitmask" name="ArduCopter:SIMPLE" documentation="Bitmask which holds which flight modes use simple heading mode (eg bit 0 = 1 means Flight Mode 0 uses simple mode)" user="Advanced">
......
......@@ -1013,7 +1013,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 2" name="ArduCopter:FLTMODE2" documentation="Flight mode when Channel 5 pwm is &gt;1230, &lt;= 1360" user="Standard">
......@@ -1036,7 +1036,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 3" name="ArduCopter:FLTMODE3" documentation="Flight mode when Channel 5 pwm is &gt;1360, &lt;= 1490" user="Standard">
......@@ -1059,7 +1059,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 4" name="ArduCopter:FLTMODE4" documentation="Flight mode when Channel 5 pwm is &gt;1490, &lt;= 1620" user="Standard">
......@@ -1082,7 +1082,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 5" name="ArduCopter:FLTMODE5" documentation="Flight mode when Channel 5 pwm is &gt;1620, &lt;= 1749" user="Standard">
......@@ -1105,7 +1105,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 6" name="ArduCopter:FLTMODE6" documentation="Flight mode when Channel 5 pwm is &gt;=1750" user="Standard">
......@@ -1128,7 +1128,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Simple mode bitmask" name="ArduCopter:SIMPLE" documentation="Bitmask which holds which flight modes use simple heading mode (eg bit 0 = 1 means Flight Mode 0 uses simple mode)" user="Advanced">
......
......@@ -1013,7 +1013,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 2" name="ArduCopter:FLTMODE2" documentation="Flight mode when Channel 5 pwm is &gt;1230, &lt;= 1360" user="Standard">
......@@ -1036,7 +1036,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 3" name="ArduCopter:FLTMODE3" documentation="Flight mode when Channel 5 pwm is &gt;1360, &lt;= 1490" user="Standard">
......@@ -1059,7 +1059,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 4" name="ArduCopter:FLTMODE4" documentation="Flight mode when Channel 5 pwm is &gt;1490, &lt;= 1620" user="Standard">
......@@ -1082,7 +1082,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 5" name="ArduCopter:FLTMODE5" documentation="Flight mode when Channel 5 pwm is &gt;1620, &lt;= 1749" user="Standard">
......@@ -1105,7 +1105,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Flight Mode 6" name="ArduCopter:FLTMODE6" documentation="Flight mode when Channel 5 pwm is &gt;=1750" user="Standard">
......@@ -1128,7 +1128,7 @@
<value code="18">Throw</value>
<value code="19">Avoid_ADSB</value>
<value code="20">Guided_NoGPS</value>
<value code="21">SafeRTL</value>
<value code="21">SmartRTL</value>
</values>
</param>
<param humanName="Simple mode bitmask" name="ArduCopter:SIMPLE" documentation="Bitmask which holds which flight modes use simple heading mode (eg bit 0 = 1 means Flight Mode 0 uses simple mode)" user="Advanced">
......
......@@ -44,11 +44,13 @@ QVariant APMParameterMetaData::_stringToTypedVariant(const QString& string,
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
case FactMetaData::valueTypeUint64:
convertTo = QVariant::UInt;
break;
case FactMetaData::valueTypeInt8:
case FactMetaData::valueTypeInt16:
case FactMetaData::valueTypeInt32:
case FactMetaData::valueTypeInt64:
convertTo = QVariant::Int;
break;
case FactMetaData::valueTypeFloat:
......@@ -233,14 +235,18 @@ void APMParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
QString group = name.split('_').first();
group = group.remove(QRegExp("[0-9]*$")); // remove any numbers from the end
QString category = xml.attributes().value("user").toString();
if (category.isEmpty()) {
category = QStringLiteral("Advanced");
}
QString shortDescription = xml.attributes().value("humanName").toString();
QString longDescription = xml.attributes().value("documentation").toString();
QString userLevel = xml.attributes().value("user").toString();
qCDebug(APMParameterMetaDataVerboseLog) << "Found parameter name:" << name
<< "short Desc:" << shortDescription
<< "longDescription:" << longDescription
<< "user level: " << userLevel
<< "category: " << category
<< "group: " << group;
Q_ASSERT(!rawMetaData);
......@@ -254,6 +260,7 @@ void APMParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
}
qCDebug(APMParameterMetaDataVerboseLog) << "inserting metadata for field" << name;
rawMetaData->name = name;
rawMetaData->category = category;
rawMetaData->group = group;
rawMetaData->shortDescription = shortDescription;
rawMetaData->longDescription = longDescription;
......@@ -301,7 +308,7 @@ void APMParameterMetaData::correctGroupMemberships(ParameterNametoFactMetaDataMa
foreach(const QString& groupName, groupMembers.keys()) {
if (groupMembers[groupName].count() == 1) {
foreach(const QString& parameter, groupMembers.value(groupName)) {
parameterToFactMetaDataMap[parameter]->group = "others";
parameterToFactMetaDataMap[parameter]->group = FactMetaData::defaultGroup();
}
}
}
......@@ -434,6 +441,7 @@ void APMParameterMetaData::addMetaDataToFact(Fact* fact, MAV_TYPE vehicleType)
}
metaData->setName(rawMetaData->name);
metaData->setCategory(rawMetaData->category);
metaData->setGroup(rawMetaData->group);
metaData->setRebootRequired(rawMetaData->rebootRequired);
......@@ -525,12 +533,14 @@ void APMParameterMetaData::addMetaDataToFact(Fact* fact, MAV_TYPE vehicleType)
break;
case FactMetaData::valueTypeInt32:
case FactMetaData::valueTypeInt64:
typedBitSet = QVariant((int)bitSet);
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
case FactMetaData::valueTypeUint64:
typedBitSet = QVariant(bitSet);
break;
......
......@@ -32,6 +32,7 @@ public:
{ }
QString name;
QString category;
QString group;
QString shortDescription;
QString longDescription;
......
......@@ -41,7 +41,7 @@ APMCopterMode::APMCopterMode(uint32_t mode, bool settable) :
enumToString.insert(THROW, "Throw");
enumToString.insert(AVOID_ADSB,"Avoid ADSB");
enumToString.insert(GUIDED_NOGPS,"Guided No GPS");
enumToString.insert(SAFE_RTL,"Safe RTL");
enumToString.insert(SAFE_RTL,"Smart RTL");
setEnumToStringMapping(enumToString);
......@@ -145,6 +145,9 @@ ArduCopterFirmwarePlugin::ArduCopterFirmwarePlugin(void)
remapV3_5["SERVO13_REVERSED"] = QStringLiteral("RC13_REVERSED");
remapV3_5["SERVO14_REVERSED"] = QStringLiteral("RC14_REVERSED");
remapV3_5["ARMING_VOLT_MIN"] = QStringLiteral("ARMING_MIN_VOLT");
remapV3_5["ARMING_VOLT2_MIN"] = QStringLiteral("ARMING_MIN_VOLT2");
_remapParamNameIntialized = true;
}
}
......
......@@ -110,6 +110,9 @@ ArduPlaneFirmwarePlugin::ArduPlaneFirmwarePlugin(void)
remapV3_8["SERVO13_REVERSED"] = QStringLiteral("RC13_REVERSED");
remapV3_8["SERVO14_REVERSED"] = QStringLiteral("RC14_REVERSED");
remapV3_8["ARMING_VOLT_MIN"] = QStringLiteral("ARMING_MIN_VOLT");
remapV3_8["ARMING_VOLT2_MIN"] = QStringLiteral("ARMING_MIN_VOLT2");
_remapParamNameIntialized = true;
}
}
......
......@@ -59,7 +59,8 @@ public:
QString pauseFlightMode (void) const override { return QString("Loiter"); }
QString offlineEditingParamFile (Vehicle* vehicle) final { Q_UNUSED(vehicle); return QStringLiteral(":/FirmwarePlugin/APM/Plane.OfflineEditing.params"); }
QString autoDisarmParameter (Vehicle* vehicle) final { Q_UNUSED(vehicle); return QStringLiteral("LAND_DISARMDELAY"); }
int remapParamNameHigestMinorVersionNumber (int majorVersionNumber) const final;
int remapParamNameHigestMinorVersionNumber (int majorVersionNumber) const final;
const FirmwarePlugin::remapParamNameMajorVersionMap_t& paramNameRemapMajorVersionMap(void) const final { return _remapParamName; }
private:
static bool _remapParamNameIntialized;
......
......@@ -89,6 +89,9 @@ ArduRoverFirmwarePlugin::ArduRoverFirmwarePlugin(void)
remapV3_2["SERVO13_REVERSED"] = QStringLiteral("RC13_REVERSED");
remapV3_2["SERVO14_REVERSED"] = QStringLiteral("RC14_REVERSED");
remapV3_2["ARMING_VOLT_MIN"] = QStringLiteral("ARMING_MIN_VOLT");
remapV3_2["ARMING_VOLT2_MIN"] = QStringLiteral("ARMING_MIN_VOLT2");
_remapParamNameIntialized = true;
}
}
......
......@@ -110,16 +110,53 @@ ArduSubFirmwarePlugin::ArduSubFirmwarePlugin(void):
remapV3_5["FENCE_ALT_MIN"] = QStringLiteral("FENCE_DEPTH_MAX");
FirmwarePlugin::remapParamNameMap_t& remapV3_6 = _remapParamName[3][6];
remapV3_6["ARMING_VOLT_MIN"] = QStringLiteral("ARMING_MIN_VOLT");
remapV3_6["ARMING_VOLT2_MIN"] = QStringLiteral("ARMING_MIN_VOLT2");
_remapParamNameIntialized = true;
}
_nameToFactGroupMap.insert("APMSubInfo", &_infoFactGroup);
}
QList<MAV_CMD> ArduSubFirmwarePlugin::supportedMissionCommands(void)
{
QList<MAV_CMD> list;
list << MAV_CMD_NAV_WAYPOINT
<< MAV_CMD_NAV_RETURN_TO_LAUNCH
<< MAV_CMD_NAV_LAND
<< MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT
<< MAV_CMD_NAV_SPLINE_WAYPOINT
<< MAV_CMD_NAV_GUIDED_ENABLE
<< MAV_CMD_NAV_DELAY
<< MAV_CMD_CONDITION_DELAY << MAV_CMD_CONDITION_DISTANCE << MAV_CMD_CONDITION_YAW
<< MAV_CMD_DO_SET_MODE
<< MAV_CMD_DO_JUMP
<< MAV_CMD_DO_CHANGE_SPEED
<< MAV_CMD_DO_SET_HOME
<< MAV_CMD_DO_SET_RELAY << MAV_CMD_DO_REPEAT_RELAY
<< MAV_CMD_DO_SET_SERVO << MAV_CMD_DO_REPEAT_SERVO
<< MAV_CMD_DO_LAND_START
<< MAV_CMD_DO_SET_ROI
<< MAV_CMD_DO_DIGICAM_CONFIGURE << MAV_CMD_DO_DIGICAM_CONTROL
<< MAV_CMD_DO_MOUNT_CONTROL
<< MAV_CMD_DO_SET_CAM_TRIGG_DIST
<< MAV_CMD_DO_FENCE_ENABLE
<< MAV_CMD_DO_INVERTED_FLIGHT
<< MAV_CMD_DO_GRIPPER
<< MAV_CMD_DO_GUIDED_LIMITS
<< MAV_CMD_DO_AUTOTUNE_ENABLE;
return list;
}
int ArduSubFirmwarePlugin::remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const
{
// Remapping supports up to 3.5
return majorVersionNumber == 3 ? 5 : Vehicle::versionNotSetValue;
// Remapping supports up to 3.6
return majorVersionNumber == 3 ? 6 : Vehicle::versionNotSetValue;
}
int ArduSubFirmwarePlugin::manualControlReservedButtonCount(void)
......@@ -178,6 +215,8 @@ void ArduSubFirmwarePlugin::_handleNamedValueFloat(mavlink_message_t* message)
_infoFactGroup.getFact("lights 2")->setRawValue(value.value * 100);
} else if (name == "PilotGain") {
_infoFactGroup.getFact("pilot gain")->setRawValue(value.value * 100);
} else if (name == "InputHold") {
_infoFactGroup.getFact("input hold")->setRawValue(value.value);
}
}
......@@ -186,6 +225,14 @@ void ArduSubFirmwarePlugin::_handleMavlinkMessage(mavlink_message_t* message)
switch (message->msgid) {
case (MAVLINK_MSG_ID_NAMED_VALUE_FLOAT):
_handleNamedValueFloat(message);
break;
case (MAVLINK_MSG_ID_RANGEFINDER):
{
mavlink_rangefinder_t msg;
mavlink_msg_rangefinder_decode(message, &msg);
_infoFactGroup.getFact("rangefinder distance")->setRawValue(msg.distance);
break;
}
}
}
......@@ -199,32 +246,41 @@ QMap<QString, FactGroup*>* ArduSubFirmwarePlugin::factGroups(void) {
return &_nameToFactGroupMap;
}
const char* APMSubmarineFactGroup::_camTiltFactName = "camera tilt";
const char* APMSubmarineFactGroup::_tetherTurnsFactName = "tether turns";
const char* APMSubmarineFactGroup::_lightsLevel1FactName = "lights 1";
const char* APMSubmarineFactGroup::_lightsLevel2FactName = "lights 2";
const char* APMSubmarineFactGroup::_pilotGainFactName = "pilot gain";
const char* APMSubmarineFactGroup::_camTiltFactName = "camera tilt";
const char* APMSubmarineFactGroup::_tetherTurnsFactName = "tether turns";
const char* APMSubmarineFactGroup::_lightsLevel1FactName = "lights 1";
const char* APMSubmarineFactGroup::_lightsLevel2FactName = "lights 2";
const char* APMSubmarineFactGroup::_pilotGainFactName = "pilot gain";
const char* APMSubmarineFactGroup::_inputHoldFactName = "input hold";
const char* APMSubmarineFactGroup::_rangefinderDistanceFactName = "rangefinder distance";
APMSubmarineFactGroup::APMSubmarineFactGroup(QObject* parent)
: FactGroup(300, ":/json/Vehicle/SubmarineFact.json", parent)
, _camTiltFact (0, _camTiltFactName, FactMetaData::valueTypeDouble)
, _tetherTurnsFact (0, _tetherTurnsFactName, FactMetaData::valueTypeDouble)
, _lightsLevel1Fact (0, _lightsLevel1FactName, FactMetaData::valueTypeDouble)
, _lightsLevel2Fact (0, _lightsLevel2FactName, FactMetaData::valueTypeDouble)
, _pilotGainFact (0, _pilotGainFactName, FactMetaData::valueTypeDouble)
{
_addFact(&_camTiltFact, _camTiltFactName);
_addFact(&_tetherTurnsFact, _tetherTurnsFactName);
_addFact(&_lightsLevel1Fact, _lightsLevel1FactName);
_addFact(&_lightsLevel2Fact, _lightsLevel2FactName);
_addFact(&_pilotGainFact, _pilotGainFactName);
, _camTiltFact (0, _camTiltFactName, FactMetaData::valueTypeDouble)
, _tetherTurnsFact (0, _tetherTurnsFactName, FactMetaData::valueTypeDouble)
, _lightsLevel1Fact (0, _lightsLevel1FactName, FactMetaData::valueTypeDouble)
, _lightsLevel2Fact (0, _lightsLevel2FactName, FactMetaData::valueTypeDouble)
, _pilotGainFact (0, _pilotGainFactName, FactMetaData::valueTypeDouble)
, _inputHoldFact (0, _inputHoldFactName, FactMetaData::valueTypeDouble)
, _rangefinderDistanceFact (0, _rangefinderDistanceFactName, FactMetaData::valueTypeDouble)
{
_addFact(&_camTiltFact, _camTiltFactName);
_addFact(&_tetherTurnsFact, _tetherTurnsFactName);
_addFact(&_lightsLevel1Fact, _lightsLevel1FactName);
_addFact(&_lightsLevel2Fact, _lightsLevel2FactName);
_addFact(&_pilotGainFact, _pilotGainFactName);
_addFact(&_inputHoldFact, _inputHoldFactName);
_addFact(&_rangefinderDistanceFact, _rangefinderDistanceFactName);
// Start out as not available "--.--"
_camTiltFact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_tetherTurnsFact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_lightsLevel1Fact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_lightsLevel2Fact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_pilotGainFact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_camTiltFact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_tetherTurnsFact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_lightsLevel1Fact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_lightsLevel2Fact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_pilotGainFact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_inputHoldFact.setRawValue (std::numeric_limits<float>::quiet_NaN());
_rangefinderDistanceFact.setRawValue (std::numeric_limits<float>::quiet_NaN());
}
QString ArduSubFirmwarePlugin::vehicleImageOpaque(const Vehicle* vehicle) const
......
......@@ -35,23 +35,29 @@ class APMSubmarineFactGroup : public FactGroup
public:
APMSubmarineFactGroup(QObject* parent = NULL);
Q_PROPERTY(Fact* camTilt READ camTilt CONSTANT)
Q_PROPERTY(Fact* tetherTurns READ tetherTurns CONSTANT)
Q_PROPERTY(Fact* lightsLevel1 READ lightsLevel1 CONSTANT)
Q_PROPERTY(Fact* lightsLevel2 READ lightsLevel2 CONSTANT)
Q_PROPERTY(Fact* pilotGain READ pilotGain CONSTANT)
Fact* camTilt (void) { return &_camTiltFact; }
Fact* tetherTurns (void) { return &_tetherTurnsFact; }
Fact* lightsLevel1 (void) { return &_lightsLevel1Fact; }
Fact* lightsLevel2 (void) { return &_lightsLevel2Fact; }
Fact* pilotGain (void) { return &_pilotGainFact; }
Q_PROPERTY(Fact* camTilt READ camTilt CONSTANT)
Q_PROPERTY(Fact* tetherTurns READ tetherTurns CONSTANT)
Q_PROPERTY(Fact* lightsLevel1 READ lightsLevel1 CONSTANT)
Q_PROPERTY(Fact* lightsLevel2 READ lightsLevel2 CONSTANT)
Q_PROPERTY(Fact* pilotGain READ pilotGain CONSTANT)
Q_PROPERTY(Fact* inputHold READ inputHold CONSTANT)
Q_PROPERTY(Fact* rangefinderDistance READ rangefinderDistance CONSTANT)
Fact* camTilt (void) { return &_camTiltFact; }
Fact* tetherTurns (void) { return &_tetherTurnsFact; }
Fact* lightsLevel1 (void) { return &_lightsLevel1Fact; }
Fact* lightsLevel2 (void) { return &_lightsLevel2Fact; }
Fact* pilotGain (void) { return &_pilotGainFact; }
Fact* inputHold (void) { return &_inputHoldFact; }
Fact* rangefinderDistance (void) { return &_rangefinderDistanceFact; }
static const char* _camTiltFactName;
static const char* _tetherTurnsFactName;
static const char* _lightsLevel1FactName;
static const char* _lightsLevel2FactName;
static const char* _pilotGainFactName;
static const char* _inputHoldFactName;
static const char* _rangefinderDistanceFactName;
static const char* _settingsGroup;
......@@ -61,6 +67,8 @@ private:
Fact _lightsLevel1Fact;
Fact _lightsLevel2Fact;
Fact _pilotGainFact;
Fact _inputHoldFact;
Fact _rangefinderDistanceFact;
};
class APMSubMode : public APMCustomMode
......@@ -100,6 +108,8 @@ class ArduSubFirmwarePlugin : public APMFirmwarePlugin
public:
ArduSubFirmwarePlugin(void);
QList<MAV_CMD> supportedMissionCommands(void);
// Overrides from FirmwarePlugin
int manualControlReservedButtonCount(void) final;
......
......@@ -51,9 +51,9 @@
}
},
{
"id": 201,
"comment": "MAV_CMD_DO_SET_ROI",
"paramRemove": "2,3"
"id": 201,
"comment": "MAV_CMD_DO_SET_ROI",
"paramRemove": "1,2,3"
},
{
"id": 205,
......
......@@ -335,6 +335,7 @@ const QVariantList &FirmwarePlugin::toolBarIndicators(const Vehicle* vehicle)
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/RCRSSIIndicator.qml")));
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/BatteryIndicator.qml")));
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/ModeIndicator.qml")));
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/VTOLModeIndicator.qml")));
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/ArmedIndicator.qml")));
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/GPSRTKIndicator.qml")));
}
......@@ -348,6 +349,18 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
if (_cameraList.size() == 0) {
CameraMetaData* metaData;
metaData = new CameraMetaData(tr("Sony NEX-5R 20mm"), //http://www.sony.co.uk/electronics/interchangeable-lens-cameras/ilce-qx1-body-kit/specifications
23.2, //http://www.sony.com/electronics/camera-lenses/sel16f28/specifications
15.4,
4912,
3264,
20,
true,
false,
1,
this);
_cameraList.append(QVariant::fromValue(metaData));
metaData = new CameraMetaData(tr("Sony ILCE-QX1"), //http://www.sony.co.uk/electronics/interchangeable-lens-cameras/ilce-qx1-body-kit/specifications
23.2, //http://www.sony.com/electronics/camera-lenses/sel16f28/specifications
15.4,
......@@ -455,6 +468,42 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
0, // minTriggerInterval
this);
_cameraList.append(QVariant::fromValue(metaData));
metaData = new CameraMetaData(tr("Parrot Sequioa RGB"),
6.17, // sensorWidth
4.63, // sendsorHeight
4608, // imageWidth
3456, // imageHeight
4.9, // focalLength
true, // landscape
false, // fixedOrientation
1, // minTriggerInterval
this);
_cameraList.append(QVariant::fromValue(metaData));
metaData = new CameraMetaData(tr("Parrot Sequioa Monochrome"),
4.8, // sensorWidth
3.6, // sendsorHeight
1280, // imageWidth
960, // imageHeight
4.0, // focalLength
true, // landscape
false, // fixedOrientation
0.8, // minTriggerInterval
this);
_cameraList.append(QVariant::fromValue(metaData));
metaData = new CameraMetaData(tr("GoPro Hero 4"),
6.17, // sensorWidth
4.55, // sendsorHeight
4000, // imageWidth
3000, // imageHeight
2.98, // focalLength
true, // landscape
false, // fixedOrientation
0, // minTriggerInterval
this);
_cameraList.append(QVariant::fromValue(metaData));
}
return _cameraList;
......@@ -583,4 +632,9 @@ QGCCameraControl* FirmwarePlugin::createCameraControl(const mavlink_camera_infor
return NULL;
}
uint32_t FirmwarePlugin::highLatencyCustomModeTo32Bits(uint16_t hlCustomMode)
{
// Standard implementation assumes no special handling. Upper part of 32 bit value is not used.
return hlCustomMode;
}
......@@ -43,11 +43,10 @@ public:
/// Set of optional capabilites which firmware may support
typedef enum {
SetFlightModeCapability = 1 << 0, ///< FirmwarePlugin::setFlightMode method is supported
MavCmdPreflightStorageCapability = 1 << 1, ///< MAV_CMD_PREFLIGHT_STORAGE is supported
PauseVehicleCapability = 1 << 2, ///< Vehicle supports pausing at current location
GuidedModeCapability = 1 << 3, ///< Vehicle supports guided mode commands
OrbitModeCapability = 1 << 4, ///< Vehicle supports orbit mode
TakeoffVehicleCapability = 1 << 5, ///< Vehicle supports guided takeoff
PauseVehicleCapability = 1 << 1, ///< Vehicle supports pausing at current location
GuidedModeCapability = 1 << 2, ///< Vehicle supports guided mode commands
OrbitModeCapability = 1 << 3, ///< Vehicle supports orbit mode
TakeoffVehicleCapability = 1 << 4, ///< Vehicle supports guided takeoff
} FirmwareCapabilities;
/// Maps from on parameter name to another
......@@ -130,6 +129,9 @@ public:
/// Command vehicle to takeoff from current location to a firmware specific height.
virtual void guidedModeTakeoff(Vehicle* vehicle, double takeoffAltRel);
/// @return The minimum takeoff altitude (relative) for guided takeoff.
virtual double minimumTakeoffAltitude(Vehicle* vehicle) { Q_UNUSED(vehicle); return 10; }
/// Command the vehicle to start the mission
virtual void startMission(Vehicle* vehicle);
......@@ -215,6 +217,11 @@ public:
/// call deleteParameterMetaData when no longer needed.
virtual QObject* loadParameterMetaData(const QString& metaDataFile) { Q_UNUSED(metaDataFile); return NULL; }
/// Returns the FactMetaData associated with the parameter name
/// @param opaqueParameterMetaData Opaque pointer returned from loadParameterMetaData
/// @param name Parameter name
virtual FactMetaData* getMetaDataForFact(QObject* parameterMetaData, const QString& name, MAV_TYPE vehicleType) { Q_UNUSED(parameterMetaData); Q_UNUSED(name); Q_UNUSED(vehicleType); return NULL; }
/// Adds the parameter meta data to the Fact
/// @param opaqueParameterMetaData Opaque pointer returned from loadParameterMetaData
virtual void addMetaDataToFact(QObject* parameterMetaData, Fact* fact, MAV_TYPE vehicleType) { Q_UNUSED(parameterMetaData); Q_UNUSED(fact); Q_UNUSED(vehicleType); return; }
......@@ -257,6 +264,7 @@ public:
virtual QString vehicleImageCompass(const Vehicle* vehicle) const;
/// Allows the core plugin to override the toolbar indicators
/// signals toolbarIndicatorsChanged
/// @return A list of QUrl with the indicators (see MainToolBarIndicators.qml)
virtual const QVariantList& toolBarIndicators(const Vehicle* vehicle);
......@@ -295,9 +303,15 @@ public:
/// Returns true if the vehicle is a VTOL
virtual bool isVtol(const Vehicle* vehicle) const;
/// Convert from HIGH_LATENCY2.custom_mode value to correct 32 bit value.
virtual uint32_t highLatencyCustomModeTo32Bits(uint16_t hlCustomMode);
// FIXME: Hack workaround for non pluginize FollowMe support
static const QString px4FollowMeFlightMode;
signals:
void toolbarIndicatorsChanged(void);
protected:
// Arms the vehicle with validation and retries
// @return: true - vehicle armed, false - vehicle failed to arm
......
......@@ -13,6 +13,11 @@
"id": 21,
"comment": "MAV_CMD_NAV_LAND",
"paramRemove": "1"
},
{
"id": 201,
"comment": "MAV_CMD_DO_SET_ROI",
"paramRemove": "1,2,3"
}
]
}
......@@ -227,7 +227,7 @@ int PX4FirmwarePlugin::manualControlReservedButtonCount(void)
bool PX4FirmwarePlugin::isCapable(const Vehicle *vehicle, FirmwareCapabilities capabilities)
{
int available = MavCmdPreflightStorageCapability | SetFlightModeCapability | PauseVehicleCapability | GuidedModeCapability;
int available = SetFlightModeCapability | PauseVehicleCapability | GuidedModeCapability;
if (vehicle->multiRotor() || vehicle->vtol()) {
available |= TakeoffVehicleCapability;
}
......@@ -247,6 +247,19 @@ bool PX4FirmwarePlugin::sendHomePositionToVehicle(void)
return false;
}
FactMetaData* PX4FirmwarePlugin::getMetaDataForFact(QObject* parameterMetaData, const QString& name, MAV_TYPE vehicleType)
{
PX4ParameterMetaData* px4MetaData = qobject_cast<PX4ParameterMetaData*>(parameterMetaData);
if (px4MetaData) {
return px4MetaData->getMetaDataForFact(name, vehicleType);
} else {
qWarning() << "Internal error: pointer passed to PX4FirmwarePlugin::getMetaDataForFact not PX4ParameterMetaData";
}
return NULL;
}
void PX4FirmwarePlugin::addMetaDataToFact(QObject* parameterMetaData, Fact* fact, MAV_TYPE vehicleType)
{
PX4ParameterMetaData* px4MetaData = qobject_cast<PX4ParameterMetaData*>(parameterMetaData);
......@@ -258,6 +271,11 @@ void PX4FirmwarePlugin::addMetaDataToFact(QObject* parameterMetaData, Fact* fact
}
}
void PX4FirmwarePlugin::getParameterMetaDataVersionInfo(const QString& metaDataFile, int& majorVersion, int& minorVersion)
{
return PX4ParameterMetaData::getParameterMetaDataVersionInfo(metaDataFile, majorVersion, minorVersion);
}
QList<MAV_CMD> PX4FirmwarePlugin::supportedMissionCommands(void)
{
QList<MAV_CMD> list;
......@@ -272,7 +290,7 @@ QList<MAV_CMD> PX4FirmwarePlugin::supportedMissionCommands(void)
<< MAV_CMD_DO_SET_SERVO
<< MAV_CMD_DO_CHANGE_SPEED
<< MAV_CMD_DO_LAND_START
<< MAV_CMD_DO_SET_ROI
<< MAV_CMD_DO_SET_ROI_LOCATION << MAV_CMD_DO_SET_ROI_WPNEXT_OFFSET << MAV_CMD_DO_SET_ROI_NONE
<< MAV_CMD_DO_MOUNT_CONFIGURE
<< MAV_CMD_DO_MOUNT_CONTROL
<< MAV_CMD_SET_CAMERA_MODE
......@@ -384,24 +402,30 @@ void PX4FirmwarePlugin::_mavCommandResult(int vehicleId, int component, int comm
}
}
void PX4FirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle, double takeoffAltRel)
double PX4FirmwarePlugin::minimumTakeoffAltitude(Vehicle* vehicle)
{
QString takeoffAltParam("MIS_TAKEOFF_ALT");
if (vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, takeoffAltParam)) {
return vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, takeoffAltParam)->rawValue().toDouble();
} else {
return FirmwarePlugin::minimumTakeoffAltitude(vehicle);
}
}
void PX4FirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle, double takeoffAltRel)
{
double vehicleAltitudeAMSL = vehicle->altitudeAMSL()->rawValue().toDouble();
if (qIsNaN(vehicleAltitudeAMSL)) {
qgcApp()->showMessage(tr("Unable to takeoff, vehicle position not known."));
return;
}
if (!vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, takeoffAltParam)) {
qgcApp()->showMessage(tr("Unable to takeoff, MIS_TAKEOFF_ALT parameter missing."));
return;
}
double takeoffAltRelFromVehicle = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, takeoffAltParam)->rawValue().toDouble();
double takeoffAltRelFromVehicle = minimumTakeoffAltitude(vehicle);
double takeoffAltAMSL = qMax(takeoffAltRel, takeoffAltRelFromVehicle) + vehicleAltitudeAMSL;
qDebug() << takeoffAltRel << takeoffAltRelFromVehicle << takeoffAltAMSL << vehicleAltitudeAMSL;
connect(vehicle, &Vehicle::mavCommandResult, this, &PX4FirmwarePlugin::_mavCommandResult);
vehicle->sendMavCommand(vehicle->defaultComponentId(),
MAV_CMD_NAV_TAKEOFF,
......@@ -566,4 +590,11 @@ QGCCameraControl* PX4FirmwarePlugin::createCameraControl(const mavlink_camera_in
return new QGCCameraControl(info, vehicle, compID, parent);
}
uint32_t PX4FirmwarePlugin::highLatencyCustomModeTo32Bits(uint16_t hlCustomMode)
{
union px4_custom_mode px4_cm;
px4_cm.data = 0;
px4_cm.custom_mode_hl = hlCustomMode;
return px4_cm.data;
}
......@@ -49,16 +49,18 @@ public:
void guidedModeOrbit (Vehicle* vehicle, const QGeoCoordinate& centerCoord = QGeoCoordinate(), double radius = NAN, double velocity = NAN, double altitude = NAN) override;
void guidedModeGotoLocation (Vehicle* vehicle, const QGeoCoordinate& gotoCoord) override;
void guidedModeChangeAltitude (Vehicle* vehicle, double altitudeRel) override;
double minimumTakeoffAltitude (Vehicle* vehicle) override;
void startMission (Vehicle* vehicle) override;
bool isGuidedMode (const Vehicle* vehicle) const override;
int manualControlReservedButtonCount(void) override;
void initializeVehicle (Vehicle* vehicle) override;
bool sendHomePositionToVehicle (void) override;
void addMetaDataToFact (QObject* parameterMetaData, Fact* fact, MAV_TYPE vehicleType) override;
FactMetaData* getMetaDataForFact (QObject* parameterMetaData, const QString& name, MAV_TYPE vehicleType) override;
QString missionCommandOverrides (MAV_TYPE vehicleType) const override;
QString getVersionParam (void) override { return QString("SYS_PARAM_VER"); }
QString internalParameterMetaDataFile (Vehicle* vehicle) override { Q_UNUSED(vehicle); return QString(":/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml"); }
void getParameterMetaDataVersionInfo (const QString& metaDataFile, int& majorVersion, int& minorVersion) override { PX4ParameterMetaData::getParameterMetaDataVersionInfo(metaDataFile, majorVersion, minorVersion); }
void getParameterMetaDataVersionInfo (const QString& metaDataFile, int& majorVersion, int& minorVersion) override;
QObject* loadParameterMetaData (const QString& metaDataFile) final;
bool adjustIncomingMavlinkMessage (Vehicle* vehicle, mavlink_message_t* message) override;
QString offlineEditingParamFile(Vehicle* vehicle) override { Q_UNUSED(vehicle); return QStringLiteral(":/FirmwarePlugin/PX4/PX4.OfflineEditing.params"); }
......@@ -68,6 +70,7 @@ public:
QString autoDisarmParameter (Vehicle* vehicle) override { Q_UNUSED(vehicle); return QStringLiteral("COM_DISARM_LAND"); }
QGCCameraManager* createCameraManager (Vehicle* vehicle) override;
QGCCameraControl* createCameraControl (const mavlink_camera_information_t* info, Vehicle* vehicle, int compID, QObject* parent = NULL) override;
uint32_t highLatencyCustomModeTo32Bits (uint16_t hlCustomMode) override;
protected:
typedef struct {
......
......@@ -44,11 +44,13 @@ QVariant PX4ParameterMetaData::_stringToTypedVariant(const QString& string, Fact
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
case FactMetaData::valueTypeUint64:
convertTo = QVariant::UInt;
break;
case FactMetaData::valueTypeInt8:
case FactMetaData::valueTypeInt16:
case FactMetaData::valueTypeInt32:
case FactMetaData::valueTypeInt64:
convertTo = QVariant::Int;
break;
case FactMetaData::valueTypeFloat:
......@@ -181,6 +183,25 @@ void PX4ParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
QString type = xml.attributes().value("type").toString();
QString strDefault = xml.attributes().value("default").toString();
QString category = xml.attributes().value("category").toString();
if (category.isEmpty()) {
category = QStringLiteral("Standard");
}
bool volatileValue = false;
bool readOnly = false;
QString volatileStr = xml.attributes().value("volatile").toString();
if (volatileStr.compare(QStringLiteral("true")) == 0) {
volatileValue = true;
readOnly = true;
}
if (!volatileValue) {
QString readOnlyStr = xml.attributes().value("readonly").toString();
if (readOnlyStr.compare(QStringLiteral("true")) == 0) {
readOnly = true;
}
}
qCDebug(PX4ParameterMetaDataLog) << "Found parameter name:" << name << " type:" << type << " default:" << strDefault;
// Convert type from string to FactMetaData::ValueType_t
......@@ -196,7 +217,7 @@ void PX4ParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
metaData = new FactMetaData(foundType);
Q_CHECK_PTR(metaData);
if (_mapParameterName2FactMetaData.contains(name)) {
// We can't trust the meta dafa since we have dups
// We can't trust the meta data since we have dups
qCWarning(PX4ParameterMetaDataLog) << "Duplicate parameter found:" << name;
badMetaData = true;
// Reset to default meta data
......@@ -204,7 +225,10 @@ void PX4ParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
} else {
_mapParameterName2FactMetaData[name] = metaData;
metaData->setName(name);
metaData->setCategory(category);
metaData->setGroup(factGroup);
metaData->setReadOnly(readOnly);
metaData->setVolatileValue(volatileValue);
if (xml.attributes().hasAttribute("default") && !strDefault.isEmpty()) {
QVariant varDefault;
......@@ -243,7 +267,7 @@ void PX4ParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
qCDebug(PX4ParameterMetaDataLog) << "Min:" << text;
QVariant varMin;
if (metaData->convertAndValidateRaw(text, true /* convertOnly */, varMin, errorString)) {
if (metaData->convertAndValidateRaw(text, false /* convertOnly */, varMin, errorString)) {
metaData->setRawMin(varMin);
} else {
qCWarning(PX4ParameterMetaDataLog) << "Invalid min value, name:" << metaData->name() << " type:" << metaData->type() << " min:" << text << " error:" << errorString;
......@@ -254,7 +278,7 @@ void PX4ParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
qCDebug(PX4ParameterMetaDataLog) << "Max:" << text;
QVariant varMax;
if (metaData->convertAndValidateRaw(text, true /* convertOnly */, varMax, errorString)) {
if (metaData->convertAndValidateRaw(text, false /* convertOnly */, varMax, errorString)) {
metaData->setRawMax(varMax);
} else {
qCWarning(PX4ParameterMetaDataLog) << "Invalid max value, name:" << metaData->name() << " type:" << metaData->type() << " max:" << text << " error:" << errorString;
......@@ -381,6 +405,17 @@ void PX4ParameterMetaData::loadParameterFactMetaDataFile(const QString& metaData
}
}
FactMetaData* PX4ParameterMetaData::getMetaDataForFact(const QString& name, MAV_TYPE vehicleType)
{
Q_UNUSED(vehicleType)
if (_mapParameterName2FactMetaData.contains(name)) {
return _mapParameterName2FactMetaData[name];
} else {
return NULL;
}
}
void PX4ParameterMetaData::addMetaDataToFact(Fact* fact, MAV_TYPE vehicleType)
{
Q_UNUSED(vehicleType)
......
......@@ -33,8 +33,9 @@ class PX4ParameterMetaData : public QObject
public:
PX4ParameterMetaData(void);
void loadParameterFactMetaDataFile (const QString& metaDataFile);
void addMetaDataToFact (Fact* fact, MAV_TYPE vehicleType);
void loadParameterFactMetaDataFile (const QString& metaDataFile);
FactMetaData* getMetaDataForFact (const QString& name, MAV_TYPE vehicleType);
void addMetaDataToFact (Fact* fact, MAV_TYPE vehicleType);
static void getParameterMetaDataVersionInfo(const QString& metaDataFile, int& majorVersion, int& minorVersion);
......
......@@ -71,7 +71,11 @@ union px4_custom_mode {
uint8_t main_mode;
uint8_t sub_mode;
};
uint32_t data;
struct {
uint16_t reserved_hl;
uint16_t custom_mode_hl;
};
uint32_t data;
float data_float;
};
......
......@@ -16,6 +16,7 @@ import QtLocation 5.3
import QtPositioning 5.3
import QtMultimedia 5.5
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
import QGroundControl 1.0
import QGroundControl.FlightDisplay 1.0
......@@ -43,8 +44,6 @@ QGCView {
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _videoReceiver: QGroundControl.videoManager.videoReceiver
property bool _recordingVideo: _videoReceiver && _videoReceiver.recording
property bool _mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true
property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false
property real _savedZoomLevel: 0
......@@ -94,6 +93,20 @@ QGCView {
QGroundControl.saveBoolGlobalSetting(_PIPVisibleKey, state)
}
function isInstrumentRight() {
if(QGroundControl.corePlugin.options.instrumentWidget) {
if(QGroundControl.corePlugin.options.instrumentWidget.source.toString().length) {
switch(QGroundControl.corePlugin.options.instrumentWidget.widgetPosition) {
case CustomInstrumentWidget.POS_TOP_LEFT:
case CustomInstrumentWidget.POS_BOTTOM_LEFT:
case CustomInstrumentWidget.POS_CENTER_LEFT:
return false;
}
}
}
return true;
}
PlanMasterController {
id: masterController
Component.onCompleted: start(false /* editMode */)
......@@ -184,6 +197,24 @@ QGCView {
}
}
Window {
id: videoWindow
width: !_mainIsMap ? _panel.width : _pipSize
height: !_mainIsMap ? _panel.height : _pipSize * (9/16)
visible: false
Item {
id: videoItem
anchors.fill: parent
}
onClosing: {
_flightVideo.state = "unpopup"
videoWindow.visible = false
}
}
QGCMapPalette { id: mapPal; lightColors: _mainIsMap ? _flightMap.isSatelliteMap : true }
QGCViewPanel {
......@@ -244,7 +275,11 @@ QGCView {
name: "pipMode"
PropertyChanges {
target: _flightVideo
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.margins: ScreenTools.defaultFontPixelHeight
}
PropertyChanges {
target: _flightVideoPipControl
inPopup: false
}
},
State {
......@@ -253,10 +288,53 @@ QGCView {
target: _flightVideo
anchors.margins: 0
}
PropertyChanges {
target: _flightVideoPipControl
inPopup: false
}
},
State {
name: "popup"
StateChangeScript {
script: QGroundControl.videoManager.stopVideo()
}
ParentChange {
target: _flightVideo
parent: videoItem
x: 0
y: 0
width: videoWindow.width
height: videoWindow.height
}
PropertyChanges {
target: _flightVideoPipControl
inPopup: true
}
},
State {
name: "unpopup"
StateChangeScript {
script: QGroundControl.videoManager.stopVideo()
}
ParentChange {
target: _flightVideo
parent: _panel
}
PropertyChanges {
target: _flightVideo
anchors.left: _panel.left
anchors.bottom: _panel.bottom
anchors.margins: ScreenTools.defaultFontPixelHeight
}
PropertyChanges {
target: _flightVideoPipControl
inPopup: false
}
}
]
//-- Video Streaming
FlightDisplayViewVideo {
id: videoStreaming
anchors.fill: parent
visible: QGroundControl.videoManager.isGStreamer
}
......@@ -277,9 +355,10 @@ QGCView {
anchors.left: _panel.left
anchors.bottom: _panel.bottom
anchors.margins: ScreenTools.defaultFontPixelHeight
visible: QGroundControl.videoManager.hasVideo && !QGroundControl.videoManager.fullScreen
visible: QGroundControl.videoManager.hasVideo && !QGroundControl.videoManager.fullScreen && _flightVideo.state != "popup"
isHidden: !_isPipVisible
isDark: isBackgroundDark
enablePopup: _mainIsMap
onActivated: {
_mainIsMap = !_mainIsMap
setStates()
......@@ -287,6 +366,10 @@ QGCView {
onHideIt: {
setPipVisibility(!state)
}
onPopup: {
videoWindow.visible = true
_flightVideo.state = "popup"
}
onNewWidth: {
_pipSize = newWidth
}
......@@ -346,63 +429,6 @@ QGCView {
property var qgcView: root
}
// Button to start/stop video recording
Item {
z: _flightVideoPipControl.z + 1
anchors.margins: ScreenTools.defaultFontPixelHeight / 2
anchors.bottom: _flightVideo.bottom
anchors.right: _flightVideo.right
height: ScreenTools.defaultFontPixelHeight * 2
width: height
visible: _videoReceiver && _videoReceiver.videoRunning && QGroundControl.settingsManager.videoSettings.showRecControl.rawValue && _flightVideo.visible && !_isCamera && !QGroundControl.videoManager.fullScreen
opacity: 0.75
readonly property string recordBtnBackground: "BackgroundName"
Rectangle {
id: recordBtnBackground
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height