diff --git a/.appveyor.yml b/.appveyor.yml index a096bf9a6f7fb06af87d48a2fd50eb5a5b57f6cd..a506d864576ac06371f8754cf3e277b4b4e7a402 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,17 +14,9 @@ environment: install: - git submodule update --init --recursive - - call "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86 - - set PATH=C:\Qt\Tools\QtCreator\bin;C:\Qt\5.5\msvc2013\bin;%PATH% + - call "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 + - set PATH=C:\Qt\Tools\QtCreator\bin;C:\Qt\5.8\msvc2015\bin;%PATH% - mkdir %LOCALAPPDATA%\QtProject && copy test\qtlogging.ini %LOCALAPPDATA%\QtProject\ - - ps: | - Write-Host "Installing NSIS..." -ForegroundColor Cyan - $exePath = "$($env:USERPROFILE)\nsis-3.0rc1-setup.exe" - Write-Host "Downloading..." - (New-Object Net.WebClient).DownloadFile('https://storage.googleapis.com/appveyor-download-cache/nsis/nsis-3.0rc1-setup.exe', $exePath) - Write-Host "Installing..." - cmd /c start /wait $exePath /S - Write-Host "Installed" -ForegroundColor Green - ps: | Write-Host "Installing GStreamer..." -ForegroundColor Cyan $msiPath = "$($env:USERPROFILE)\gstreamer-1.0-x86-1.5.2.msi" @@ -43,7 +35,7 @@ install: Write-Host "Installed" -ForegroundColor Green build_script: - - mkdir %SHADOW_BUILD_DIR% && cd %SHADOW_BUILD_DIR% && C:\Qt\5.5\msvc2013\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.8\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 diff --git a/.travis.yml b/.travis.yml index 75f8b0e181c2a65052b0e8837f7bc2873bec58b2..bbb2485ea7c884a5d49063e88e30a78fb0921a95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,18 +27,19 @@ matrix: language: android env: SPEC=android-g++ CONFIG=installer sudo: false - - os: osx - osx_image: xcode8 - env: SPEC=macx-clang CONFIG=debug - sudo: required - os: osx osx_image: xcode8 env: SPEC=macx-clang CONFIG=installer sudo: required - - os: osx - osx_image: xcode8 - 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: @@ -88,9 +89,9 @@ before_install: install: # linux dependencies: qt - if [ "${SPEC}" = "linux-g++-64" ]; then - wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.5.1-linux-min.tar.bz2 && - tar jxf Qt5.5.1-linux-min.tar.bz2 -C /tmp && - export PATH=/tmp/Qt/5.5/gcc_64/bin:$PATH && + wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.8.0-linux-min.tar.bz2 && + tar jxf Qt5.8.0-linux-min.tar.bz2 -C /tmp && + export PATH=/tmp/Qt5.8-linux/5.8/gcc_64/bin:$PATH && export DISPLAY=:99.0 && sh -e /etc/init.d/xvfb start ; @@ -98,8 +99,8 @@ install: # android dependencies: qt, gstreamer, android-ndk - if [ "${SPEC}" = "android-g++" ]; then - wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.5.1-linux-min.tar.bz2 && - tar jxf Qt5.5.1-linux-min.tar.bz2 -C /tmp && + wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.8.0-android-min.tar.bz2 && + tar jxf Qt5.8.0-android-min.tar.bz2 -C /tmp && wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/gstreamer-1.0-android-armv7-1.5.2.tar.bz2 && mkdir -p ${TRAVIS_BUILD_DIR}/gstreamer-1.0-android-armv7-1.5.2 && tar jxf gstreamer-1.0-android-armv7-1.5.2.tar.bz2 -C ${TRAVIS_BUILD_DIR}/gstreamer-1.0-android-armv7-1.5.2 && @@ -108,35 +109,34 @@ 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/Qt/5.5/android_armv7/bin:`pwd`/android-ndk-r10e:$PATH + export PATH=/tmp/Qt5.8-android/5.8/android_armv7/bin:`pwd`/android-ndk-r10e:$PATH && echo $PATH ; fi # osx dependencies: qt, gstreamer, gstreamer-devel - if [ "${SPEC}" = "macx-clang" ]; then - wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.5.1-mac-clang-min.tar.bz2 && - tar jxf Qt5.5.1-mac-clang-min.tar.bz2 -C /tmp && + wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.8.0-mac-clang-min.tar.bz2 && + tar jxf Qt5.8.0-mac-clang-min.tar.bz2 -C /tmp && wget 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 / && wget 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 / && wget 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.5-mac-clang/5.5/clang_64 && + export QT_DIR=Qt5.8-mac-clang/5.8/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 && - tools/patch_qt_for_xcode8.sh + export PATH=/tmp/$QT_DIR/bin:$PATH ; fi # ios dependencies: qt, TODO: add gstreamer - if [ "${SPEC}" = "macx-ios-clang" ]; then - wget https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.5.1-ios-min.tar.bz2 && - tar jxf Qt5.5.1-ios-min.tar.bz2 -C /tmp && + wget 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 && 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/ios/bin:$PATH && + export PATH=/tmp/Qt5.8-ios/5.8/ios/bin:$PATH && tools/patch_qt_for_xcode8.sh ; fi @@ -174,12 +174,14 @@ script: #- ccache -s # unit tests linux/osx - - if [[ "${SPEC}" = "linux-g++-64" && "${CONFIG}" = "debug" ]]; then - mkdir -p ~/.config/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/.config/QtProject/ && - ./debug/QGroundControl --unittest; - elif [[ "${SPEC}" = "macx-clang" && "${CONFIG}" = "debug" ]]; then - mkdir -p ~/Library/Preferences/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/Library/Preferences/QtProject/ && - ./debug/qgroundcontrol.app/Contents/MacOS/QGroundControl --unittest; + - if [ "${TRAVIS_BRANCH}" != "master" ]; then + if [[ "${SPEC}" = "linux-g++-64" && "${CONFIG}" = "debug" ]]; then + mkdir -p ~/.config/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/.config/QtProject/ && + ./debug/QGroundControl --unittest; + elif [[ "${SPEC}" = "macx-clang" && "${CONFIG}" = "debug" ]]; then + mkdir -p ~/Library/Preferences/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/Library/Preferences/QtProject/ && + ./debug/qgroundcontrol.app/Contents/MacOS/QGroundControl --unittest; + fi fi after_success: diff --git a/QGCCommon.pri b/QGCCommon.pri index e10d5ea8551ec9c0be169f22ea3fcac577adfde1..732b99a00a9855b0421b42dcc63693616c55b2f2 100644 --- a/QGCCommon.pri +++ b/QGCCommon.pri @@ -38,7 +38,6 @@ linux { equals(ANDROID_TARGET_ARCH, x86) { CONFIG += Androidx86Build DEFINES += __androidx86__ - DEFINES += QGC_DISABLE_UVC message("Android x86 build") } else { message("Android Arm build") @@ -47,7 +46,7 @@ linux { error("Unsuported Linux toolchain, only GCC 32- or 64-bit is supported") } } else : win32 { - win32-msvc2010 | win32-msvc2012 | win32-msvc2013 { + win32-msvc2010 | win32-msvc2012 | win32-msvc2013 | win32-msvc2015 { message("Windows build") CONFIG += WindowsBuild DEFINES += __STDC_LIMIT_MACROS @@ -77,9 +76,11 @@ linux { error("Unsupported Qt version, 5.5.x or greater is required for iOS") } message("iOS build") - CONFIG += iOSBuild MobileBuild app_bundle + CONFIG += iOSBuild MobileBuild app_bundle NoSerialBuild + CONFIG -= bitcode DEFINES += __ios__ DEFINES += QGC_NO_GOOGLE_MAPS + DEFINES += NO_SERIAL_LINK QMAKE_IOS_DEPLOYMENT_TARGET = 8.0 QMAKE_IOS_TARGETED_DEVICE_FAMILY = 1,2 # Universal QMAKE_LFLAGS += -Wl,-no_pie @@ -202,8 +203,13 @@ MacBuild | LinuxBuild { } WindowsBuild { + win32-msvc2015 { + QMAKE_CFLAGS -= -Zc:strictStrings + QMAKE_CXXFLAGS -= -Zc:strictStrings + } QMAKE_CFLAGS_RELEASE -= -Zc:strictStrings QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO -= -Zc:strictStrings + QMAKE_CXXFLAGS_RELEASE -= -Zc:strictStrings QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO -= -Zc:strictStrings QMAKE_CXXFLAGS_WARN_ON += /W3 \ @@ -221,7 +227,7 @@ WindowsBuild { # ReleaseBuild { - DEFINES += QT_NO_DEBUG + 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 @@ -239,11 +245,3 @@ ReleaseBuild { QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += /OPT:ICF } } - -# -# Unit Test specific configuration goes here -# - -DebugBuild { - DEFINES += UNITTEST_BUILD -} diff --git a/QGCExternalLibs.pri b/QGCExternalLibs.pri index 0f31a6e155a649fb1adedcbc450a936fa1ad9821..52e5de7fb69d0848634ad8006199e48311da3e98 100644 --- a/QGCExternalLibs.pri +++ b/QGCExternalLibs.pri @@ -65,103 +65,6 @@ DEPENDPATH += libs/qwt INCLUDEPATH += libs/qwt } -# -# [OPTIONAL] XBee wireless support. This is not necessary for basic serial/UART communications. -# It's only required for speaking directly to the Xbee using their proprietary API. -# Unsupported on Mac. -# Installation on Windows is unnecessary, as we just link to our included .dlls directly. -# Installing on Linux involves running `make;sudo make install` in `libs/thirdParty/libxbee` -# Uninstalling from Linux can be done with `sudo make uninstall`. -# -XBEE_DEPENDENT_HEADERS += \ - src/comm/XbeeLinkInterface.h \ - src/comm/XbeeLink.h \ - src/comm/HexSpinBox.h \ - src/ui/XbeeConfigurationWindow.h \ - src/comm/CallConv.h -XBEE_DEPENDENT_SOURCES += \ - src/comm/XbeeLink.cpp \ - src/comm/HexSpinBox.cpp \ - src/ui/XbeeConfigurationWindow.cpp -XBEE_DEFINES = QGC_XBEE_ENABLED - -contains(DEFINES, DISABLE_XBEE) { - message("Skipping support for native XBee API (manual override from command line)") - DEFINES -= DISABLE_XBEE -# Otherwise the user can still disable this feature in the user_config.pri file. -} else:exists(user_config.pri):infile(user_config.pri, DEFINES, DISABLE_XBEE) { - message("Skipping support for native XBee API (manual override from user_config.pri)") -} else:LinuxBuild { - linux-g++-64 { - message("Skipping support for XBee API (64-bit Linux builds not supported)") - } else:exists(/usr/include/xbee.h) { - message("Including support for XBee API") - - HEADERS += $$XBEE_DEPENDENT_HEADERS - SOURCES += $$XBEE_DEPENDENT_SOURCES - DEFINES += $$XBEE_DEFINES - LIBS += -L/usr/lib -lxbee - } else { - warning("Skipping support for XBee API (missing libraries, see README)") - } -} else:WindowsBuild { - message("Including support for XBee API") - HEADERS += $$XBEE_DEPENDENT_HEADERS - SOURCES += $$XBEE_DEPENDENT_SOURCES - DEFINES += $$XBEE_DEFINES - INCLUDEPATH += libs/thirdParty/libxbee - LIBS += -l$$BASEDIR/libs/thirdParty/libxbee/lib/libxbee -} else { - message("Skipping support for XBee API (unsupported platform)") -} - -# -# [OPTIONAL] Opal RT-LAB Library. Provides integration with Opal-RT's RT-LAB simulator. -# -contains(DEFINES, DISABLE_RTLAB) { - message("Skipping support for RT-LAB (manual override from command line)") - DEFINES -= DISABLE_RTLAB -# Otherwise the user can still disable this feature in the user_config.pri file. -} else:exists(user_config.pri):infile(user_config.pri, DEFINES, DISABLE_RTLAB) { - message("Skipping support for RT-LAB (manual override from user_config.pri)") -} else:WindowsBuild { - exists(src/lib/opalrt/OpalApi.h) : exists(C:/OPAL-RT/RT-LAB7.2.4/Common/bin) { - message("Including support for RT-LAB") - - DEFINES += QGC_RTLAB_ENABLED - - INCLUDEPATH += - src/lib/opalrt - libs/lib/opal/include \ - - FORMS += src/ui/OpalLinkSettings.ui - - HEADERS += \ - src/comm/OpalRT.h \ - src/comm/OpalLink.h \ - src/comm/Parameter.h \ - src/comm/QGCParamID.h \ - src/comm/ParameterList.h \ - src/ui/OpalLinkConfigurationWindow.h - - SOURCES += \ - src/comm/OpalRT.cc \ - src/comm/OpalLink.cc \ - src/comm/Parameter.cc \ - src/comm/QGCParamID.cc \ - src/comm/ParameterList.cc \ - src/ui/OpalLinkConfigurationWindow.cc - - LIBS += \ - -LC:/OPAL-RT/RT-LAB7.2.4/Common/bin \ - -lOpalApi - } else { - warning("Skipping support for RT-LAB (missing libraries, see README)") - } -} else { - message("Skipping support for RT-LAB (unsupported platform)") -} - # # [REQUIRED] SDL dependency. Provides joystick/gamepad support. # The SDL is packaged with QGC for the Mac and Windows. Linux support requires installing the SDL diff --git a/QGCInstaller.pri b/QGCInstaller.pri index cce214a04f7878e4b56723650b7c0b622fd0ceb7..e47938565df9f38c653a93c30eec9b3f930fb853 100644 --- a/QGCInstaller.pri +++ b/QGCInstaller.pri @@ -29,7 +29,7 @@ installer { QMAKE_POST_LINK += && mkdir -p $${DESTDIR}/package QMAKE_POST_LINK += && cd $${DESTDIR} && $$dirname(QMAKE_QMAKE)/macdeployqt QGroundControl.app -appstore-compliant -verbose=2 -qmldir=$${BASEDIR}/src QMAKE_POST_LINK += && cd $${OUT_PWD} - QMAKE_POST_LINK += && hdiutil create -verbose -stretch 2g -layout SPUD -srcfolder $${DESTDIR}/QGroundControl.app -volname QGroundControl $${DESTDIR}/package/QGroundControl.dmg + QMAKE_POST_LINK += && hdiutil create -verbose -stretch 3g -layout SPUD -srcfolder $${DESTDIR}/QGroundControl.app -volname QGroundControl $${DESTDIR}/package/QGroundControl.dmg } WindowsBuild { # The pdb moving command are commented out for now since we are including the .pdb in the installer. This makes it much diff --git a/QGCSetup.pri b/QGCSetup.pri index 3cbfb74015b9a243b2f3c48c25379d55a8f26e62..fa0b3e5f678853bd92e5e2dfed4a5997e8e29d5b 100644 --- a/QGCSetup.pri +++ b/QGCSetup.pri @@ -63,7 +63,6 @@ WindowsBuild { ReleaseBuild: DLL_QT_DEBUGCHAR = "" COPY_FILE_LIST = \ $$BASEDIR\\libs\\lib\\sdl2\\msvc\\lib\\x86\\SDL2.dll \ - $$BASEDIR\\libs\\thirdParty\\libxbee\\lib\\libxbee.dll \ $$BASEDIR\\deploy\\libeay32.dll for(COPY_FILE, COPY_FILE_LIST) { @@ -85,6 +84,10 @@ WindowsBuild { QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcp120.dll\" \"$$DESTDIR_WIN\" QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcr120.dll\" \"$$DESTDIR_WIN\" } + else:win32-msvc2015 { + QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcp140.dll\" \"$$DESTDIR_WIN\" + QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\vcruntime140.dll\" \"$$DESTDIR_WIN\" + } else { error("Visual studio version not supported, installation cannot be completed.") } @@ -123,9 +126,9 @@ LinuxBuild { !contains(DEFINES, __rasp_pi2__) { QT_LIB_LIST += \ - libicudata.so.54 \ - libicui18n.so.54 \ - libicuuc.so.54 + libicudata.so.56 \ + libicui18n.so.56 \ + libicuuc.so.56 } for(QT_LIB, QT_LIB_LIST) { diff --git a/README.md b/README.md index 8fb9e497c0d86f3c72a8d74743c334ade013cfb8..cd0d25dd731a5334252a99515b5aed23c2507cb0 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ https://donlakeflyer.gitbooks.io/qgroundcontrol-user-guide/content/ #### 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 not supported due to Qt bug. Currently only workaround is to use XCode 7.3.1) +* 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 2013 compiler](http://www.visualstudio.com/downloads/download-visual-studio-vs#d-express-windows-desktop) * iOS: 8.0 and higher @@ -43,7 +43,8 @@ QGroundControl builds are supported for OSX, Linux, Windows, iOS and Android. QG ###### Install QT You need to install Qt as described below instead of using pre-built packages from say, a Linux distribution because QGroundControl needs access to private Qt headers. * Download the [Qt installer](http://www.qt.io/download-open-source) - * Make sure to install Qt version **5.5.1** NOT 5.4.x, 5.6.x, 5.7.x, etc. + * Make sure to install Qt version **5.5.1** NOT 5.4.x, 5.6.x, 5.7.x, etc. + * If you don't install the full Qt 5.5 make sure you install Qt Location and Qt Quick Controls. * 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: Default installer not quite correct, use [this](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013-5.5.1.exe) instead diff --git a/Vagrantfile b/Vagrantfile index f58cd8766fafa3231264556b5ed7f451e92d81b9..41756cd1510bee7da1b89e1f77e83b51b04f8e03 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -25,7 +25,7 @@ Vagrant.configure(2) do |config| sudo apt-get update -y sudo apt-get dist-upgrade -y sudo apt-get install -y git build-essential - sudo apt-get install -y espeak libespeak-dev libudev-dev libsdl1.2-dev + sudo apt-get install -y espeak libespeak-dev libudev-dev libsdl2-dev sudo apt-get install -y doxygen sudo apt-get install -y gstreamer1.0* libgstreamer1.0* diff --git a/android.pri b/android.pri new file mode 100644 index 0000000000000000000000000000000000000000..eef0ae3f9cae5ca6fcdcf434a98dba2cdb1b0a0d --- /dev/null +++ b/android.pri @@ -0,0 +1,26 @@ +include($$PWD/libs/qtandroidserialport/src/qtandroidserialport.pri) +message("Adding Serial Java Classes") +QT += androidextras +ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android +OTHER_FILES += \ + $$PWD/android/AndroidManifest.xml \ + $$PWD/android/res/xml/device_filter.xml \ + $$PWD/android/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java \ + $$PWD/android/src/com/hoho/android/usbserial/driver/CommonUsbSerialDriver.java \ + $$PWD/android/src/com/hoho/android/usbserial/driver/Cp2102SerialDriver.java \ + $$PWD/android/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java \ + $$PWD/android/src/com/hoho/android/usbserial/driver/ProlificSerialDriver.java \ + $$PWD/android/src/com/hoho/android/usbserial/driver/UsbId.java \ + $$PWD/android/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java \ + $$PWD/android/src/com/hoho/android/usbserial/driver/UsbSerialProber.java \ + $$PWD/android/src/com/hoho/android/usbserial/driver/UsbSerialRuntimeException.java \ + $$PWD/android/src/org/qgroundcontrol/qgchelper/UsbDeviceJNI.java \ + $$PWD/android/src/org/qgroundcontrol/qgchelper/UsbIoManager.java + +DISTFILES += \ + $$PWD/android/gradle/wrapper/gradle-wrapper.jar \ + $$PWD/android/gradlew \ + $$PWD/android/res/values/libs.xml \ + $$PWD/android/build.gradle \ + $$PWD/android/gradle/wrapper/gradle-wrapper.properties \ + $$PWD/android/gradlew.bat diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 24bdd8a1b77f94ef20ecd9c9d2137a99dcbd7f22..f5009b3f46569bf64cbf6223c53cd6a546269da4 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -48,7 +48,7 @@ - + diff --git a/deploy/qgroundcontrol_installer.nsi b/deploy/qgroundcontrol_installer.nsi index 36833d1fe70d0c74abcb9b283eb7af164bd5b8ed..2fee9698a7009ba17675f71ed6f5406a1834e239 100644 --- a/deploy/qgroundcontrol_installer.nsi +++ b/deploy/qgroundcontrol_installer.nsi @@ -41,6 +41,8 @@ Var StartMenuFolder InstallDir $PROGRAMFILES\qgroundcontrol +SetCompressor /SOLID /FINAL lzma + !define MUI_HEADERIMAGE !define MUI_HEADERIMAGE_BITMAP "installheader.bmp"; diff --git a/ios/iOS-Info.plist b/ios/iOS-Info.plist index 1343e18ee0c8f1224bdf0985a8cde51f8aaf7674..a7bde7a2ae5a6ef0e02debe7660e0fcd142bf562 100644 --- a/ios/iOS-Info.plist +++ b/ios/iOS-Info.plist @@ -2,85 +2,87 @@ - CFBundleDisplayName - QGroundControl - CFBundleExecutable - $(EXECUTABLE_NAME) - NSHumanReadableCopyright - Open Source Flight Systems GmbH - Internal Build - CFBundleIconFile - - CFBundleIdentifier - org.QGroundControl.qgc - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 0.0.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - QGCLaunchScreen - UIRequiresFullScreen - - CFBundleInfoDictionaryVersion - 6.0 - ForAppStore - No - NSLocationUsageDescription - Ground Station Location - NSLocationWhenInUseUsageDescription - Ground Station Location - UISupportedInterfaceOrientations - - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - CFBundleIcons - - CFBundlePrimaryIcon - - CFBundleIconFiles - - AppIcon29x29.png - AppIcon29x29@2x.png - AppIcon40x40@2x.png - AppIcon57x57.png - AppIcon57x57@2x.png - AppIcon60x60@2x.png - - - - CFBundleIcons~ipad - - CFBundlePrimaryIcon - - CFBundleIconFiles - - AppIcon29x29.png - AppIcon29x29@2x.png - AppIcon40x40@2x.png - AppIcon57x57.png - AppIcon57x57@2x.png - AppIcon60x60@2x.png - AppIcon29x29~ipad.png - AppIcon29x29@2x~ipad.png - AppIcon40x40~ipad.png - AppIcon40x40@2x~ipad.png - AppIcon50x50~ipad.png - AppIcon50x50@2x~ipad.png - AppIcon72x72~ipad.png - AppIcon72x72@2x~ipad.png - AppIcon76x76~ipad.png - AppIcon76x76@2x~ipad.png - AppIcon83.5x83.5@2x~ipad.png - - - + NSCameraUsageDescription + QGC uses UVC devices for video streaming. + CFBundleDisplayName + QGroundControl + CFBundleExecutable + $(EXECUTABLE_NAME) + NSHumanReadableCopyright + Open Source Flight Systems GmbH - Internal Build + CFBundleIconFile + + CFBundleIdentifier + org.QGroundControl.qgc + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + QGCLaunchScreen + UIRequiresFullScreen + + CFBundleInfoDictionaryVersion + 6.0 + ForAppStore + No + NSLocationUsageDescription + Ground Station Location + NSLocationWhenInUseUsageDescription + Ground Station Location + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CFBundleIcons + + CFBundlePrimaryIcon + + CFBundleIconFiles + + AppIcon29x29.png + AppIcon29x29@2x.png + AppIcon40x40@2x.png + AppIcon57x57.png + AppIcon57x57@2x.png + AppIcon60x60@2x.png + + + + CFBundleIcons~ipad + + CFBundlePrimaryIcon + + CFBundleIconFiles + + AppIcon29x29.png + AppIcon29x29@2x.png + AppIcon40x40@2x.png + AppIcon57x57.png + AppIcon57x57@2x.png + AppIcon60x60@2x.png + AppIcon29x29~ipad.png + AppIcon29x29@2x~ipad.png + AppIcon40x40~ipad.png + AppIcon40x40@2x~ipad.png + AppIcon50x50~ipad.png + AppIcon50x50@2x~ipad.png + AppIcon72x72~ipad.png + AppIcon72x72@2x~ipad.png + AppIcon76x76~ipad.png + AppIcon76x76@2x~ipad.png + AppIcon83.5x83.5@2x~ipad.png + + + diff --git a/libs/mavlink/include/mavlink/v1.0 b/libs/mavlink/include/mavlink/v1.0 index e93ac62981a338a7c823364e7c4ff1077e3f8fc1..13a478092fc9c2faa90c553c362e799ba3bad4e8 160000 --- a/libs/mavlink/include/mavlink/v1.0 +++ b/libs/mavlink/include/mavlink/v1.0 @@ -1 +1 @@ -Subproject commit e93ac62981a338a7c823364e7c4ff1077e3f8fc1 +Subproject commit 13a478092fc9c2faa90c553c362e799ba3bad4e8 diff --git a/libs/mavlink/include/mavlink/v2.0 b/libs/mavlink/include/mavlink/v2.0 index 36f37bde1df2dd36661fbcbd6ed5aaf0424c8269..b5aaac46c4819bab0f80d4d071ae9a8fec439676 160000 --- a/libs/mavlink/include/mavlink/v2.0 +++ b/libs/mavlink/include/mavlink/v2.0 @@ -1 +1 @@ -Subproject commit 36f37bde1df2dd36661fbcbd6ed5aaf0424c8269 +Subproject commit b5aaac46c4819bab0f80d4d071ae9a8fec439676 diff --git a/libs/qwt/qwt_plot_canvas.cpp b/libs/qwt/qwt_plot_canvas.cpp index 0271713a8b50c44478dfcc6335d513e49c37e818..e558a44ee0afdc67ec3d036d6b9b70fad0d3ba07 100644 --- a/libs/qwt/qwt_plot_canvas.cpp +++ b/libs/qwt/qwt_plot_canvas.cpp @@ -937,7 +937,14 @@ void QwtPlotCanvas::drawBorder( QPainter *painter ) else { #if QT_VERSION >= 0x040500 +#if !defined(_MSC_VER) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif QStyleOptionFrameV3 opt; +#if !defined(_MSC_VER) +#pragma GCC diagnostic pop +#endif opt.init(this); int frameShape = frameStyle() & QFrame::Shape_Mask; diff --git a/libs/thirdParty/libxbee/LICENSE b/libs/thirdParty/libxbee/LICENSE deleted file mode 100644 index 94a9ed024d3859793618152ea559a168bbcbb5e2..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/libs/thirdParty/libxbee/README b/libs/thirdParty/libxbee/README deleted file mode 100644 index a5dbbfe0f3bd6fc9a433c4532221a140e283b4d4..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/README +++ /dev/null @@ -1,39 +0,0 @@ -Welcome to libxbee! - -I have proveded sample code in the ./sample directory. Hopefully this will help -get you up and running with libxbee. If you would like samples showing a different -aspect of libxbee, then please do not hesitate to file an 'issue' on the project -site, and I will get to it ASAP: - http://code.google.com/p/libxbee/issues/list - - -Documentation is avaliable via the man page system once you have installed the -library, or as HTML in the 'doc' directory. - $ man libxbee - - -Please note that this project is still in development, so should not be used for -any purpose other than learning/playing/testing etc... Basically don't use it to -make money, and then hold me responsible if it breaks! - -Feel free to contact me directly with any queries: - attie@attie.co.uk - - -For those of you that are planning to use this on an embedded board, I have -included a small makefile (umakefile) that has only the information needed to -compile the library. I suggest you use this instead! - -=== Installation === -To install simply type: - $ make install - -For more information, or if you can't install it, please see the wiki: - http://code.google.com/p/libxbee/wiki/install_libxbee - - -=== Usage === -If you are compiling the object file directly into your executable instead -of making use of the shared library, you must include the following link -flags: - -lpthread -lrt diff --git a/libs/thirdParty/libxbee/api.c b/libs/thirdParty/libxbee/api.c deleted file mode 100644 index ef5923b56848f5c345c2712c7430919c40d676ba..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/api.c +++ /dev/null @@ -1,2433 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -const char *SVN_REV = "$Id: api.c 508 2011-06-12 23:22:34Z attie@attie.co.uk $"; -char svn_rev[128] = "\0"; - -#include "api.h" - -const char *xbee_svn_version(void) { - if (svn_rev[0] == '\0') { - char *t; - sprintf(svn_rev,"r%s",&SVN_REV[11]); - t = strrchr(svn_rev,' '); - if (t) { - t[0] = '\0'; - } - } - return svn_rev; -} - -const char *xbee_build_info(void) { - return "Built on " __DATE__ " @ " __TIME__ " for " HOST_OS; -} - -/* ################################################################# */ -/* ### Memory Handling ############################################# */ -/* ################################################################# */ - -/* malloc wrapper function */ -static void *Xmalloc2(xbee_hnd xbee, size_t size) { - void *t; - t = malloc(size); - if (!t) { - /* uhoh... thats pretty bad... */ - xbee_perror("libxbee:malloc()"); - exit(1); - } - return t; -} - -/* calloc wrapper function */ -static void *Xcalloc2(xbee_hnd xbee, size_t size) { - void *t; - t = calloc(1, size); - if (!t) { - /* uhoh... thats pretty bad... */ - xbee_perror("libxbee:calloc()"); - exit(1); - } - return t; -} - -/* realloc wrapper function */ -static void *Xrealloc2(xbee_hnd xbee, void *ptr, size_t size) { - void *t; - t = realloc(ptr,size); - if (!t) { - /* uhoh... thats pretty bad... */ - fprintf(stderr,"libxbee:realloc(): Returned NULL\n"); - exit(1); - } - return t; -} - -/* free wrapper function (uses the Xfree macro and sets the pointer to NULL after freeing it) */ -static void Xfree2(void **ptr) { - if (!*ptr) return; - free(*ptr); - *ptr = NULL; -} - -/* ################################################################# */ -/* ### Helper Functions ############################################ */ -/* ################################################################# */ - -/* ################################################################# - returns 1 if the packet has data for the digital input else 0 */ -int xbee_hasdigital(xbee_pkt *pkt, int sample, int input) { - int mask = 0x0001; - if (input < 0 || input > 7) return 0; - if (sample >= pkt->samples) return 0; - - mask <<= input; - return !!(pkt->IOdata[sample].IOmask & mask); -} - -/* ################################################################# - returns 1 if the digital input is high else 0 (or 0 if no digital data present) */ -int xbee_getdigital(xbee_pkt *pkt, int sample, int input) { - int mask = 0x0001; - if (!xbee_hasdigital(pkt,sample,input)) return 0; - - mask <<= input; - return !!(pkt->IOdata[sample].IOdigital & mask); -} - -/* ################################################################# - returns 1 if the packet has data for the analog input else 0 */ -int xbee_hasanalog(xbee_pkt *pkt, int sample, int input) { - int mask = 0x0200; - if (input < 0 || input > 5) return 0; - if (sample >= pkt->samples) return 0; - - mask <<= input; - return !!(pkt->IOdata[sample].IOmask & mask); -} - -/* ################################################################# - returns analog input as a voltage if vRef is non-zero, else raw value (or 0 if no analog data present) */ -double xbee_getanalog(xbee_pkt *pkt, int sample, int input, double Vref) { - if (!xbee_hasanalog(pkt,sample,input)) return 0; - - if (Vref) return (Vref / 1023) * pkt->IOdata[sample].IOanalog[input]; - return pkt->IOdata[sample].IOanalog[input]; -} - -/* ################################################################# */ -/* ### XBee Functions ############################################## */ -/* ################################################################# */ - -static void xbee_logf(xbee_hnd xbee, const char *logformat, const char *file, - const int line, const char *function, char *format, ...) { - char buf[128]; - va_list ap; - if (!xbee) return; - if (!xbee->log) return; - va_start(ap,format); - vsnprintf(buf,127,format,ap); - va_end(ap); - fprintf(xbee->log,logformat,file,line,function,buf); -} -void xbee_logitf(char *format, ...) { - char buf[128]; - va_list ap; - va_start(ap,format); - vsnprintf(buf,127,format,ap); - va_end(ap); - xbee_logit(buf); -} -void _xbee_logitf(xbee_hnd xbee, char *format, ...) { - char buf[128]; - va_list ap; - va_start(ap,format); - vsnprintf(buf,127,format,ap); - va_end(ap); - _xbee_logit(xbee, buf); -} -void xbee_logit(char *str) { - _xbee_logit(default_xbee, str); -} -void _xbee_logit(xbee_hnd xbee, char *str) { - if (!xbee) return; - if (!xbee->log) return; - xbee_mutex_lock(xbee->logmutex); - fprintf(xbee->log,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,str); - xbee_mutex_unlock(xbee->logmutex); -} - -/* ################################################################# - xbee_sendAT - INTERNAL - allows for an at command to be send, and the reply to be captured */ -static int xbee_sendAT(xbee_hnd xbee, char *command, char *retBuf, int retBuflen) { - return xbee_sendATdelay(xbee, 0, command, retBuf, retBuflen); -} -static int xbee_sendATdelay(xbee_hnd xbee, int guardTime, char *command, char *retBuf, int retBuflen) { - struct timeval to; - - int ret; - int bufi = 0; - - /* if there is a guardTime given, then use it and a bit more */ - if (guardTime) usleep(guardTime * 1200); - - /* get rid of any pre-command sludge... */ - memset(&to, 0, sizeof(to)); - ret = xbee_select(xbee,&to); - if (ret > 0) { - char t[128]; - while (xbee_read(xbee,t,127)); - } - - /* send the requested command */ - xbee_log("sendATdelay: Sending '%s'", command); - xbee_write(xbee,command, strlen(command)); - - /* if there is a guardTime, then use it */ - if (guardTime) { - usleep(guardTime * 900); - - /* get rid of any post-command sludge... */ - memset(&to, 0, sizeof(to)); - ret = xbee_select(xbee,&to); - if (ret > 0) { - char t[128]; - while (xbee_read(xbee,t,127)); - } - } - - /* retrieve the data */ - memset(retBuf, 0, retBuflen); - memset(&to, 0, sizeof(to)); - if (guardTime) { - /* select on the xbee fd... wait at most 0.2 the guardTime for the response */ - to.tv_usec = guardTime * 200; - } else { - /* or 250ms */ - to.tv_usec = 250000; - } - if ((ret = xbee_select(xbee,&to)) == -1) { - xbee_perror("libxbee:xbee_sendATdelay()"); - exit(1); - } - - if (!ret) { - /* timed out, and there is nothing to be read */ - xbee_log("sendATdelay: No Data to read - Timeout..."); - return 1; - } - - /* check for any dribble... */ - do { - /* if there is actually no space in the retBuf then break out */ - if (bufi >= retBuflen - 1) { - break; - } - - /* read as much data as is possible into retBuf */ - if ((ret = xbee_read(xbee,&retBuf[bufi], retBuflen - bufi - 1)) == 0) { - break; - } - - /* advance the 'end of string' pointer */ - bufi += ret; - - /* wait at most 150ms for any more data */ - memset(&to, 0, sizeof(to)); - to.tv_usec = 150000; - if ((ret = xbee_select(xbee,&to)) == -1) { - xbee_perror("libxbee:xbee_sendATdelay()"); - exit(1); - } - - /* loop while data was read */ - } while (ret); - - if (!bufi) { - xbee_log("sendATdelay: No response..."); - return 1; - } - - /* terminate the string */ - retBuf[bufi] = '\0'; - - xbee_log("sendATdelay: Recieved '%s'",retBuf); - return 0; -} - - -/* ################################################################# - xbee_start - sets up the correct API mode for the xbee - cmdSeq = CC - cmdTime = GT */ -static int xbee_startAPI(xbee_hnd xbee) { - char buf[256]; - - if (xbee->cmdSeq == 0 || xbee->cmdTime == 0) return 1; - - /* setup the command sequence string */ - memset(buf,xbee->cmdSeq,3); - buf[3] = '\0'; - - /* try the command sequence */ - if (xbee_sendATdelay(xbee, xbee->cmdTime, buf, buf, sizeof(buf))) { - /* if it failed... try just entering 'AT' which should return OK */ - if (xbee_sendAT(xbee, "AT\r", buf, 4) || strncmp(buf,"OK\r",3)) return 1; - } else if (strncmp(&buf[strlen(buf)-3],"OK\r",3)) { - /* if data was returned, but it wasn't OK... then something went wrong! */ - return 1; - } - - /* get the current API mode */ - if (xbee_sendAT(xbee, "ATAP\r", buf, 3)) return 1; - buf[1] = '\0'; - xbee->oldAPI = atoi(buf); - - if (xbee->oldAPI != 2) { - /* if it wasnt set to mode 2 already, then set it to mode 2 */ - if (xbee_sendAT(xbee, "ATAP2\r", buf, 4) || strncmp(buf,"OK\r",3)) return 1; - } - - /* quit from command mode, ready for some packets! :) */ - if (xbee_sendAT(xbee, "ATCN\r", buf, 4) || strncmp(buf,"OK\r",3)) return 1; - - return 0; -} - -/* ################################################################# - xbee_end - resets the API mode to the saved value - you must have called xbee_setup[log]API */ -int xbee_end(void) { - return _xbee_end(default_xbee); -} -int _xbee_end(xbee_hnd xbee) { - int ret = 1; - xbee_con *con, *ncon; - xbee_pkt *pkt, *npkt; - xbee_hnd xbeet; - - ISREADYR(0); - xbee_log("Stopping libxbee instance..."); - - /* unlink the instance from list... */ - xbee_log("Unlinking instance from list..."); - xbee_mutex_lock(xbee_hnd_mutex); - if (xbee == default_xbee) { - default_xbee = default_xbee->next; - if (!default_xbee) { - xbee_mutex_destroy(xbee_hnd_mutex); - } - } else { - xbeet = default_xbee; - while (xbeet) { - if (xbeet->next == xbee) { - xbeet->next = xbee->next; - break; - } - xbeet = xbeet->next; - } - } - if (default_xbee) xbee_mutex_unlock(xbee_hnd_mutex); - - /* if the api mode was not 2 to begin with then put it back */ - if (xbee->oldAPI == 2) { - xbee_log("XBee was already in API mode 2, no need to reset"); - ret = 0; - } else { - int to = 5; - - con = _xbee_newcon(xbee,'I',xbee_localAT); - con->callback = NULL; - con->waitforACK = 1; - _xbee_senddata(xbee,con,"AP%c",xbee->oldAPI); - - pkt = NULL; - - while (!pkt && to--) { - pkt = _xbee_getpacketwait(xbee,con); - } - if (pkt) { - ret = pkt->status; - Xfree(pkt); - } - _xbee_endcon(xbee,con); - } - - /* xbee_* functions may no longer run... */ - xbee->xbee_ready = 0; - - /* nullify everything */ - - /* stop listening for data... either after timeout or next char read which ever is first */ - xbee->run = 0; - - xbee_thread_cancel(xbee->listent,0); - xbee_thread_join(xbee->listent); - - xbee_thread_cancel(xbee->threadt,0); - xbee_thread_join(xbee->threadt); - - /* free all connections */ - con = xbee->conlist; - xbee->conlist = NULL; - while (con) { - ncon = con->next; - Xfree(con); - con = ncon; - } - - /* free all packets */ - xbee->pktlast = NULL; - pkt = xbee->pktlist; - xbee->pktlist = NULL; - while (pkt) { - npkt = pkt->next; - Xfree(pkt); - pkt = npkt; - } - - /* destroy mutexes */ - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - - /* close the serial port */ - Xfree(xbee->path); - if (xbee->tty) xbee_close(xbee->tty); - - /* close log and tty */ - if (xbee->log) { - fflush(xbee->log); - xbee_close(xbee->log); - } - xbee_mutex_destroy(xbee->logmutex); - - Xfree(xbee); - - return ret; -} - -/* ################################################################# - xbee_setup - opens xbee serial port & creates xbee listen thread - the xbee must be configured for API mode 2 - THIS MUST BE CALLED BEFORE ANY OTHER XBEE FUNCTION */ -int xbee_setup(char *path, int baudrate) { - return xbee_setuplogAPI(path,baudrate,0,0,0); -} -xbee_hnd _xbee_setup(char *path, int baudrate) { - return _xbee_setuplogAPI(path,baudrate,0,0,0); -} -int xbee_setuplog(char *path, int baudrate, int logfd) { - return xbee_setuplogAPI(path,baudrate,logfd,0,0); -} -xbee_hnd _xbee_setuplog(char *path, int baudrate, int logfd) { - return _xbee_setuplogAPI(path,baudrate,logfd,0,0); -} -int xbee_setupAPI(char *path, int baudrate, char cmdSeq, int cmdTime) { - return xbee_setuplogAPI(path,baudrate,0,cmdSeq,cmdTime); -} -xbee_hnd _xbee_setupAPI(char *path, int baudrate, char cmdSeq, int cmdTime) { - return _xbee_setuplogAPI(path,baudrate,0,cmdSeq,cmdTime); -} -int xbee_setuplogAPI(char *path, int baudrate, int logfd, char cmdSeq, int cmdTime) { - if (default_xbee) return 0; - default_xbee = _xbee_setuplogAPI(path,baudrate,logfd,cmdSeq,cmdTime); - return (default_xbee?0:-1); -} -xbee_hnd _xbee_setuplogAPI(char *path, int baudrate, int logfd, char cmdSeq, int cmdTime) { - int ret; - xbee_hnd xbee = NULL; - - /* create a new instance */ - xbee = Xcalloc(sizeof(struct xbee_hnd)); - xbee->next = NULL; - - xbee_mutex_init(xbee->logmutex); -#ifdef DEBUG - if (!logfd) logfd = 2; -#endif - if (logfd) { - xbee->logfd = dup(logfd); - xbee->log = fdopen(xbee->logfd,"w"); - if (!xbee->log) { - /* errno == 9 is bad file descriptor (probrably not provided) */ - if (errno != 9) xbee_perror("xbee_setup(): Failed opening logfile"); - xbee->logfd = 0; - } else { -#ifdef __GNUC__ /* ---- */ - /* set to line buffer - ensure lines are written to file when complete */ - setvbuf(xbee->log,NULL,_IOLBF,BUFSIZ); -#else /* -------------- */ - /* Win32 is rubbish... so we have to completely disable buffering... */ - setvbuf(xbee->log,NULL,_IONBF,BUFSIZ); -#endif /* ------------- */ - } - } - - xbee_logS("---------------------------------------------------------------------"); - xbee_logI("libxbee Starting..."); - xbee_logI("SVN Info: %s",xbee_svn_version()); - xbee_logI("Build Info: %s",xbee_build_info()); - xbee_logE("---------------------------------------------------------------------"); - - /* setup the connection stuff */ - xbee->conlist = NULL; - - /* setup the packet stuff */ - xbee->pktlist = NULL; - xbee->pktlast = NULL; - xbee->pktcount = 0; - xbee->run = 1; - - /* setup the mutexes */ - if (xbee_mutex_init(xbee->conmutex)) { - xbee_perror("xbee_setup():xbee_mutex_init(conmutex)"); - if (xbee->log) xbee_close(xbee->log); - Xfree(xbee); - return NULL; - } - if (xbee_mutex_init(xbee->pktmutex)) { - xbee_perror("xbee_setup():xbee_mutex_init(pktmutex)"); - if (xbee->log) xbee_close(xbee->log); - xbee_mutex_destroy(xbee->conmutex); - Xfree(xbee); - return NULL; - } - if (xbee_mutex_init(xbee->sendmutex)) { - xbee_perror("xbee_setup():xbee_mutex_init(sendmutex)"); - if (xbee->log) xbee_close(xbee->log); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - Xfree(xbee); - return NULL; - } - - /* take a copy of the XBee device path */ - if ((xbee->path = Xmalloc(sizeof(char) * (strlen(path) + 1))) == NULL) { - xbee_perror("xbee_setup():Xmalloc(path)"); - if (xbee->log) xbee_close(xbee->log); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee); - return NULL; - } - strcpy(xbee->path,path); - if (xbee->log) xbee_log("Opening serial port '%s'...",xbee->path); - - /* call the relevant init function */ - if ((ret = init_serial(xbee,baudrate)) != 0) { - xbee_log("Something failed while opening the serial port..."); - if (xbee->log) xbee_close(xbee->log); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee->path); - Xfree(xbee); - return NULL; - } - - /* when xbee_end() is called, if this is not 2 then ATAP will be set to this value */ - xbee->oldAPI = 2; - xbee->cmdSeq = cmdSeq; - xbee->cmdTime = cmdTime; - if (xbee->cmdSeq && xbee->cmdTime) { - if (xbee_startAPI(xbee)) { - if (xbee->log) { - xbee_log("Couldn't communicate with XBee..."); - xbee_close(xbee->log); - } - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee->path); -#ifdef __GNUC__ /* ---- */ - close(xbee->ttyfd); -#endif /* ------------- */ - xbee_close(xbee->tty); - Xfree(xbee); - return NULL; - } - } - - /* allow the listen thread to start */ - xbee->xbee_ready = -1; - - /* can start xbee_listen thread now */ - if (xbee_thread_create(xbee->listent, xbee_listen_wrapper, xbee)) { - xbee_perror("xbee_setup():xbee_thread_create(listent)"); - if (xbee->log) xbee_close(xbee->log); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee->path); -#ifdef __GNUC__ /* ---- */ - close(xbee->ttyfd); -#endif /* ------------- */ - xbee_close(xbee->tty); - Xfree(xbee); - return NULL; - } - - /* can start xbee_thread_watch thread thread now */ - if (xbee_thread_create(xbee->threadt, xbee_thread_watch, xbee)) { - xbee_perror("xbee_setup():xbee_thread_create(threadt)"); - if (xbee->log) xbee_close(xbee->log); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee->path); -#ifdef __GNUC__ /* ---- */ - close(xbee->ttyfd); -#endif /* ------------- */ - xbee_close(xbee->tty); - Xfree(xbee); - return NULL; - } - - usleep(500); - while (xbee->xbee_ready != -2) { - usleep(500); - xbee_log("Waiting for xbee_listen() to be ready..."); - } - - /* allow other functions to be used! */ - xbee->xbee_ready = 1; - - xbee_log("Linking xbee instance..."); - if (!default_xbee) { - xbee_mutex_init(xbee_hnd_mutex); - xbee_mutex_lock(xbee_hnd_mutex); - default_xbee = xbee; - xbee_mutex_unlock(xbee_hnd_mutex); - } else { - xbee_hnd xbeet; - xbee_mutex_lock(xbee_hnd_mutex); - xbeet = default_xbee; - while (xbeet->next) { - xbeet = xbeet->next; - } - xbeet->next = xbee; - xbee_mutex_unlock(xbee_hnd_mutex); - } - - xbee_log("libxbee: Started!"); - - return xbee; -} - -/* ################################################################# - xbee_con - produces a connection to the specified device and frameID - if a connection had already been made, then this connection will be returned */ -xbee_con *xbee_newcon(unsigned char frameID, xbee_types type, ...) { - xbee_con *ret; - va_list ap; - - /* xbee_vnewcon() wants a va_list... */ - va_start(ap, type); - /* hand it over :) */ - ret = _xbee_vnewcon(default_xbee, frameID, type, ap); - va_end(ap); - return ret; -} -xbee_con *_xbee_newcon(xbee_hnd xbee, unsigned char frameID, xbee_types type, ...) { - xbee_con *ret; - va_list ap; - - /* xbee_vnewcon() wants a va_list... */ - va_start(ap, type); - /* hand it over :) */ - ret = _xbee_vnewcon(xbee, frameID, type, ap); - va_end(ap); - return ret; -} -xbee_con *_xbee_vnewcon(xbee_hnd xbee, unsigned char frameID, xbee_types type, va_list ap) { - xbee_con *con, *ocon; - unsigned char tAddr[8]; - int t; - int i; - - ISREADYR(NULL); - - if (!type || type == xbee_unknown) type = xbee_localAT; /* default to local AT */ - else if (type == xbee_remoteAT) type = xbee_64bitRemoteAT; /* if remote AT, default to 64bit */ - - /* if: 64 bit address expected (2 ints) */ - if ((type == xbee_64bitRemoteAT) || - (type == xbee_64bitData) || - (type == xbee_64bitIO) || - (type == xbee2_data)) { - t = va_arg(ap, int); - tAddr[0] = (t >> 24) & 0xFF; - tAddr[1] = (t >> 16) & 0xFF; - tAddr[2] = (t >> 8) & 0xFF; - tAddr[3] = (t ) & 0xFF; - t = va_arg(ap, int); - tAddr[4] = (t >> 24) & 0xFF; - tAddr[5] = (t >> 16) & 0xFF; - tAddr[6] = (t >> 8) & 0xFF; - tAddr[7] = (t ) & 0xFF; - - /* if: 16 bit address expected (1 int) */ - } else if ((type == xbee_16bitRemoteAT) || - (type == xbee_16bitData) || - (type == xbee_16bitIO)) { - t = va_arg(ap, int); - tAddr[0] = (t >> 8) & 0xFF; - tAddr[1] = (t ) & 0xFF; - tAddr[2] = 0; - tAddr[3] = 0; - tAddr[4] = 0; - tAddr[5] = 0; - tAddr[6] = 0; - tAddr[7] = 0; - - /* otherwise clear the address */ - } else { - memset(tAddr,0,8); - } - - /* lock the connection mutex */ - xbee_mutex_lock(xbee->conmutex); - - /* are there any connections? */ - if (xbee->conlist) { - con = xbee->conlist; - while (con) { - /* if: looking for a modemStatus, and the types match! */ - if ((type == xbee_modemStatus) && - (con->type == type)) { - xbee_mutex_unlock(xbee->conmutex); - return con; - - /* if: looking for a txStatus and frameIDs match! */ - } else if ((type == xbee_txStatus) && - (con->type == type) && - (frameID == con->frameID)) { - xbee_mutex_unlock(xbee->conmutex); - return con; - - /* if: looking for a localAT, and the frameIDs match! */ - } else if ((type == xbee_localAT) && - (con->type == type) && - (frameID == con->frameID)) { - xbee_mutex_unlock(xbee->conmutex); - return con; - - /* if: connection types match, the frameIDs match, and the addresses match! */ - } else if ((type == con->type) && - (frameID == con->frameID) && - (!memcmp(tAddr,con->tAddr,8))) { - xbee_mutex_unlock(xbee->conmutex); - return con; - } - - /* if there are more, move along, dont want to loose that last item! */ - if (con->next == NULL) break; - con = con->next; - } - - /* keep hold of the last connection... we will need to link it up later */ - ocon = con; - } - - /* unlock the connection mutex */ - xbee_mutex_unlock(xbee->conmutex); - - /* create a new connection and set its attributes */ - con = Xcalloc(sizeof(xbee_con)); - con->type = type; - /* is it a 64bit connection? */ - if ((type == xbee_64bitRemoteAT) || - (type == xbee_64bitData) || - (type == xbee_64bitIO) || - (type == xbee2_data)) { - con->tAddr64 = TRUE; - } - con->atQueue = 0; /* queue AT commands? */ - con->txDisableACK = 0; /* disable ACKs? */ - con->txBroadcastPAN = 0; /* broadcast? */ - con->frameID = frameID; - con->waitforACK = 0; - memcpy(con->tAddr,tAddr,8); /* copy in the remote address */ - xbee_mutex_init(con->callbackmutex); - xbee_mutex_init(con->callbackListmutex); - xbee_mutex_init(con->Txmutex); - xbee_sem_init(con->waitforACKsem); - - if (xbee->log) { - switch(type) { - case xbee_localAT: - xbee_log("New local AT connection!"); - break; - case xbee_16bitRemoteAT: - case xbee_64bitRemoteAT: - xbee_logc("New %d-bit remote AT connection! (to: ",(con->tAddr64?64:16)); - for (i=0;i<(con->tAddr64?8:2);i++) { - fprintf(xbee->log,(i?":%02X":"%02X"),tAddr[i]); - } - fprintf(xbee->log,")"); - xbee_logcf(); - break; - case xbee_16bitData: - case xbee_64bitData: - xbee_logc("New %d-bit data connection! (to: ",(con->tAddr64?64:16)); - for (i=0;i<(con->tAddr64?8:2);i++) { - fprintf(xbee->log,(i?":%02X":"%02X"),tAddr[i]); - } - fprintf(xbee->log,")"); - xbee_logcf(); - break; - case xbee_16bitIO: - case xbee_64bitIO: - xbee_logc("New %d-bit IO connection! (to: ",(con->tAddr64?64:16)); - for (i=0;i<(con->tAddr64?8:2);i++) { - fprintf(xbee->log,(i?":%02X":"%02X"),tAddr[i]); - } - fprintf(xbee->log,")"); - xbee_logcf(); - break; - case xbee2_data: - xbee_logc("New Series 2 data connection! (to: "); - for (i=0;i<8;i++) { - fprintf(xbee->log,(i?":%02X":"%02X"),tAddr[i]); - } - fprintf(xbee->log,")"); - xbee_logcf(); - break; - case xbee_txStatus: - xbee_log("New Tx status connection!"); - break; - case xbee_modemStatus: - xbee_log("New modem status connection!"); - break; - case xbee_unknown: - default: - xbee_log("New unknown connection!"); - } - } - - /* lock the connection mutex */ - xbee_mutex_lock(xbee->conmutex); - - /* make it the last in the list */ - con->next = NULL; - /* add it to the list */ - if (xbee->conlist) { - ocon->next = con; - } else { - xbee->conlist = con; - } - - /* unlock the mutex */ - xbee_mutex_unlock(xbee->conmutex); - return con; -} - -/* ################################################################# - xbee_conflush - removes any packets that have been collected for the specified - connection */ -void xbee_purgecon(xbee_con *con) { - _xbee_purgecon(default_xbee, con); -} -void _xbee_purgecon(xbee_hnd xbee, xbee_con *con) { - xbee_pkt *r, *p, *n; - - ISREADYP(); - - /* lock the packet mutex */ - xbee_mutex_lock(xbee->pktmutex); - - /* if: there are packets */ - if ((p = xbee->pktlist) != NULL) { - r = NULL; - /* get all packets for this connection */ - do { - /* does the packet match the connection? */ - if (xbee_matchpktcon(xbee,p,con)) { - /* if it was the first packet */ - if (!r) { - /* move the chain along */ - xbee->pktlist = p->next; - } else { - /* otherwise relink the list */ - r->next = p->next; - } - xbee->pktcount--; - - /* free this packet! */ - n = p->next; - Xfree(p); - /* move on */ - p = n; - } else { - /* move on */ - r = p; - p = p->next; - } - } while (p); - xbee->pktlast = r; - } - - /* unlock the packet mutex */ - xbee_mutex_unlock(xbee->pktmutex); -} - -/* ################################################################# - xbee_endcon - close the unwanted connection - free wrapper function (uses the Xfree macro and sets the pointer to NULL after freeing it) */ -void xbee_endcon2(xbee_con **con, int alreadyUnlinked) { - _xbee_endcon2(default_xbee, con, alreadyUnlinked); -} -void _xbee_endcon2(xbee_hnd xbee, xbee_con **con, int alreadyUnlinked) { - xbee_con *t, *u; - - ISREADYP(); - - /* lock the connection mutex */ - xbee_mutex_lock(xbee->conmutex); - - u = t = xbee->conlist; - while (t && t != *con) { - u = t; - t = t->next; - } - if (!t) { - /* this could be true if comming from the destroySelf signal... */ - if (!alreadyUnlinked) { - /* invalid connection given... */ - if (xbee->log) { - xbee_log("Attempted to close invalid connection..."); - } - /* unlock the connection mutex */ - xbee_mutex_unlock(xbee->conmutex); - return; - } - } else { - /* extract this connection from the list */ - if (t == xbee->conlist) { - xbee->conlist = t->next; - } else { - u->next = t->next; - } - } - - /* unlock the connection mutex */ - xbee_mutex_unlock(xbee->conmutex); - - /* check if a callback thread is running... */ - if (t->callback && xbee_mutex_trylock(t->callbackmutex)) { - /* if it is running... tell it to destroy the connection on completion */ - xbee_log("Attempted to close a connection with active callbacks... " - "Connection will be destroyed when callbacks have completeted..."); - t->destroySelf = 1; - return; - } - - /* remove all packets for this connection */ - _xbee_purgecon(xbee,t); - - /* destroy the callback mutex */ - xbee_mutex_destroy(t->callbackmutex); - xbee_mutex_destroy(t->callbackListmutex); - xbee_mutex_destroy(t->Txmutex); - xbee_sem_destroy(t->waitforACKsem); - - /* free the connection! */ - Xfree(*con); -} - -/* ################################################################# - xbee_senddata - send the specified data to the provided connection */ -int xbee_senddata(xbee_con *con, char *format, ...) { - int ret; - va_list ap; - - /* xbee_vsenddata() wants a va_list... */ - va_start(ap, format); - /* hand it over :) */ - ret = _xbee_vsenddata(default_xbee, con, format, ap); - va_end(ap); - return ret; -} -int _xbee_senddata(xbee_hnd xbee, xbee_con *con, char *format, ...) { - int ret; - va_list ap; - - /* xbee_vsenddata() wants a va_list... */ - va_start(ap, format); - /* hand it over :) */ - ret = _xbee_vsenddata(xbee, con, format, ap); - va_end(ap); - return ret; -} - -int xbee_vsenddata(xbee_con *con, char *format, va_list ap) { - return _xbee_vsenddata(default_xbee, con, format, ap); -} -int _xbee_vsenddata(xbee_hnd xbee, xbee_con *con, char *format, va_list ap) { - unsigned char data[128]; /* max payload is 100 bytes... plus a bit of fluff... */ - int length; - - /* make up the data and keep the length, its possible there are nulls in there */ - length = vsnprintf((char *)data, 128, format, ap); - - /* hand it over :) */ - return _xbee_nsenddata(xbee, con, (char *)data, length); -} - -/* returns: - 1 - if NAC was recieved - 0 - if packet was successfully sent (or just sent if waitforACK is off) - -1 - if there was an error building the packet - -2 - if the connection type was unknown */ -int xbee_nsenddata(xbee_con *con, char *data, int length) { - return _xbee_nsenddata(default_xbee, con, data, length); -} -int _xbee_nsenddata(xbee_hnd xbee, xbee_con *con, char *data, int length) { - t_data *pkt; - int i; - unsigned char buf[128]; /* max payload is 100 bytes... plus a bit for the headers etc... */ - - ISREADYR(-1); - - if (!con) return -1; - if (con->type == xbee_unknown) return -1; - if (length > 127) return -1; - - if (xbee->log) { - xbee_logS("--== TX Packet ============--"); - xbee_logIc("Connection Type: "); - switch (con->type) { - case xbee_unknown: fprintf(xbee->log,"Unknown"); break; - case xbee_localAT: fprintf(xbee->log,"Local AT"); break; - case xbee_remoteAT: fprintf(xbee->log,"Remote AT"); break; - case xbee_16bitRemoteAT: fprintf(xbee->log,"Remote AT (16-bit)"); break; - case xbee_64bitRemoteAT: fprintf(xbee->log,"Remote AT (64-bit)"); break; - case xbee_16bitData: fprintf(xbee->log,"Data (16-bit)"); break; - case xbee_64bitData: fprintf(xbee->log,"Data (64-bit)"); break; - case xbee_16bitIO: fprintf(xbee->log,"IO (16-bit)"); break; - case xbee_64bitIO: fprintf(xbee->log,"IO (64-bit)"); break; - case xbee2_data: fprintf(xbee->log,"Series 2 Data"); break; - case xbee2_txStatus: fprintf(xbee->log,"Series 2 Tx Status"); break; - case xbee_txStatus: fprintf(xbee->log,"Tx Status"); break; - case xbee_modemStatus: fprintf(xbee->log,"Modem Status"); break; - } - xbee_logIcf(); - switch (con->type) { - case xbee_localAT: case xbee_remoteAT: case xbee_txStatus: case xbee_modemStatus: - break; - default: - xbee_logIc("Destination: "); - for (i=0;i<(con->tAddr64?8:2);i++) { - fprintf(xbee->log,(i?":%02X":"%02X"),con->tAddr[i]); - } - xbee_logIcf(); - } - xbee_logI("Length: %d",length); - for (i=0;i 32) && (data[i] < 127)) { - fprintf(xbee->log,"'%c'",data[i]); - } else{ - fprintf(xbee->log," _"); - } - xbee_logIcf(); - } - xbee_logEf(); - } - - /* ########################################## */ - /* if: local AT */ - if (con->type == xbee_localAT) { - /* AT commands are 2 chars long (plus optional parameter) */ - if (length < 2) return -1; - if (length > 32) return -1; - - /* use the command? */ - buf[0] = ((!con->atQueue)?XBEE_LOCAL_ATREQ:XBEE_LOCAL_ATQUE); - buf[1] = con->frameID; - - /* copy in the data */ - for (i=0;itype == xbee_16bitRemoteAT) || - (con->type == xbee_64bitRemoteAT)) { - if (length < 2) return -1; /* at commands are 2 chars long (plus optional parameter) */ - if (length > 32) return -1; - buf[0] = XBEE_REMOTE_ATREQ; - buf[1] = con->frameID; - - /* copy in the relevant address */ - if (con->tAddr64) { - memcpy(&buf[2],con->tAddr,8); - buf[10] = 0xFF; - buf[11] = 0xFE; - } else { - memset(&buf[2],0,8); - memcpy(&buf[10],con->tAddr,2); - } - /* queue the command? */ - buf[12] = ((!con->atQueue)?0x02:0x00); - - /* copy in the data */ - for (i=0;itype == xbee_16bitData) || - (con->type == xbee_64bitData)) { - int offset; - if (length > 100) return -1; - - /* if: 16bit Data */ - if (con->type == xbee_16bitData) { - buf[0] = XBEE_16BIT_DATATX; - offset = 5; - /* copy in the address */ - memcpy(&buf[2],con->tAddr,2); - - /* if: 64bit Data */ - } else { /* 64bit Data */ - buf[0] = XBEE_64BIT_DATATX; - offset = 11; - /* copy in the address */ - memcpy(&buf[2],con->tAddr,8); - } - - /* copy frameID */ - buf[1] = con->frameID; - - /* disable ack? broadcast? */ - buf[offset-1] = ((con->txDisableACK)?0x01:0x00) | ((con->txBroadcastPAN)?0x04:0x00); - - /* copy in the data */ - for (i=0;itype == xbee_64bitIO) || - (con->type == xbee_16bitIO)) { - /* not currently implemented... is it even allowed? */ - if (xbee->log) { - xbee_log("******* TODO ********\n"); - } - - /* ########################################## */ - /* if: Series 2 Data */ - } else if (con->type == xbee2_data) { - if (length > 72) return -1; - - buf[0] = XBEE2_DATATX; - buf[1] = con->frameID; - - /* copy in the relevant address */ - memcpy(&buf[2],con->tAddr,8); - buf[10] = 0xFF; - buf[11] = 0xFE; - - /* Maximum Radius/hops */ - buf[12] = 0x00; - - /* Options */ - buf[13] = 0x00; - - /* copy in the data */ - for (i=0;ipktmutex); - - /* if: there are no packets */ - if ((p = xbee->pktlist) == NULL) { - xbee_mutex_unlock(xbee->pktmutex); - /*if (xbee->log) { - xbee_log("No packets avaliable..."); - }*/ - return NULL; - } - - l = NULL; - q = NULL; - /* get the first avaliable packet for this connection */ - do { - /* does the packet match the connection? */ - if (xbee_matchpktcon(xbee, p, con)) { - q = p; - break; - } - /* move on */ - l = p; - p = p->next; - } while (p); - - /* if: no packet was found */ - if (!q) { - xbee_mutex_unlock(xbee->pktmutex); - if (xbee->log) { - struct timeval tv; - xbee_logS("--== Get Packet ==========--"); - gettimeofday(&tv,NULL); - xbee_logE("Didn't get a packet @ %ld.%06ld",tv.tv_sec,tv.tv_usec); - } - return NULL; - } - - /* if it was the first packet */ - if (l) { - /* relink the list */ - l->next = p->next; - if (!l->next) xbee->pktlast = l; - } else { - /* move the chain along */ - xbee->pktlist = p->next; - if (!xbee->pktlist) { - xbee->pktlast = NULL; - } else if (!xbee->pktlist->next) { - xbee->pktlast = xbee->pktlist; - } - } - xbee->pktcount--; - - /* unlink this packet from the chain! */ - q->next = NULL; - - if (xbee->log) { - struct timeval tv; - xbee_logS("--== Get Packet ==========--"); - gettimeofday(&tv,NULL); - xbee_logI("Got a packet @ %ld.%06ld",tv.tv_sec,tv.tv_usec); - xbee_logE("Packets left: %d",xbee->pktcount); - } - - /* unlock the packet mutex */ - xbee_mutex_unlock(xbee->pktmutex); - - /* and return the packet (must be free'd by caller!) */ - return q; -} - -/* ################################################################# - xbee_matchpktcon - INTERNAL - checks if the packet matches the connection */ -static int xbee_matchpktcon(xbee_hnd xbee, xbee_pkt *pkt, xbee_con *con) { - /* if: the connection type matches the packet type OR - the connection is 16/64bit remote AT, and the packet is a remote AT response */ - if ((pkt->type == con->type) || /* -- */ - ((pkt->type == xbee_remoteAT) && /* -- */ - ((con->type == xbee_16bitRemoteAT) || - (con->type == xbee_64bitRemoteAT)))) { - - - /* if: is a modem status (there can only be 1 modem status connection) */ - if (pkt->type == xbee_modemStatus) return 1; - - /* if: the packet is a txStatus or localAT and the frameIDs match */ - if ((pkt->type == xbee_txStatus) || - (pkt->type == xbee_localAT)) { - if (pkt->frameID == con->frameID) { - return 1; - } - /* if: the packet was sent as a 16bit remoteAT, and the 16bit addresss match */ - } else if ((pkt->type == xbee_remoteAT) && - (con->type == xbee_16bitRemoteAT) && - !memcmp(pkt->Addr16,con->tAddr,2)) { - return 1; - /* if: the packet was sent as a 64bit remoteAT, and the 64bit addresss match */ - } else if ((pkt->type == xbee_remoteAT) && - (con->type == xbee_64bitRemoteAT) && - !memcmp(pkt->Addr64,con->tAddr,8)) { - return 1; - /* if: the packet is 64bit addressed, and the addresses match */ - } else if (pkt->sAddr64 && !memcmp(pkt->Addr64,con->tAddr,8)) { - return 1; - /* if: the packet is 16bit addressed, and the addresses match */ - } else if (!pkt->sAddr64 && !memcmp(pkt->Addr16,con->tAddr,2)) { - return 1; - } else if (con->type == pkt->type && - (con->type == xbee_16bitData || con->type == xbee_64bitData) && - (pkt->isBroadcastADR || pkt->isBroadcastPAN)) { - unsigned char t[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - if ((con->tAddr64 && !memcmp(con->tAddr,t,8)) || - (!con->tAddr64 && !memcmp(con->tAddr,t,2))) { - return 1; - } - } - } - return 0; -} - -/* ################################################################# - xbee_parse_io - INTERNAL - parses the data given into the packet io information */ -static int xbee_parse_io(xbee_hnd xbee, xbee_pkt *p, unsigned char *d, - int maskOffset, int sampleOffset, int sample) { - xbee_sample *s = &(p->IOdata[sample]); - - /* copy in the I/O data mask */ - s->IOmask = (((d[maskOffset]<<8) | d[maskOffset + 1]) & 0x7FFF); - - /* copy in the digital I/O data */ - s->IOdigital = (((d[sampleOffset]<<8) | d[sampleOffset+1]) & 0x01FF); - - /* advance over the digital data, if its there */ - sampleOffset += ((s->IOmask & 0x01FF)?2:0); - - /* copy in the analog I/O data */ - if (s->IOmask & 0x0200) { - s->IOanalog[0] = (((d[sampleOffset]<<8) | d[sampleOffset+1]) & 0x03FF); - sampleOffset+=2; - } - if (s->IOmask & 0x0400) { - s->IOanalog[1] = (((d[sampleOffset]<<8) | d[sampleOffset+1]) & 0x03FF); - sampleOffset+=2; - } - if (s->IOmask & 0x0800) { - s->IOanalog[2] = (((d[sampleOffset]<<8) | d[sampleOffset+1]) & 0x03FF); - sampleOffset+=2; - } - if (s->IOmask & 0x1000) { - s->IOanalog[3] = (((d[sampleOffset]<<8) | d[sampleOffset+1]) & 0x03FF); - sampleOffset+=2; - } - if (s->IOmask & 0x2000) { - s->IOanalog[4] = (((d[sampleOffset]<<8) | d[sampleOffset+1]) & 0x03FF); - sampleOffset+=2; - } - if (s->IOmask & 0x4000) { - s->IOanalog[5] = (((d[sampleOffset]<<8) | d[sampleOffset+1]) & 0x03FF); - sampleOffset+=2; - } - - if (xbee->log) { - if (s->IOmask & 0x0001) - xbee_logI("Digital 0: %c",((s->IOdigital & 0x0001)?'1':'0')); - if (s->IOmask & 0x0002) - xbee_logI("Digital 1: %c",((s->IOdigital & 0x0002)?'1':'0')); - if (s->IOmask & 0x0004) - xbee_logI("Digital 2: %c",((s->IOdigital & 0x0004)?'1':'0')); - if (s->IOmask & 0x0008) - xbee_logI("Digital 3: %c",((s->IOdigital & 0x0008)?'1':'0')); - if (s->IOmask & 0x0010) - xbee_logI("Digital 4: %c",((s->IOdigital & 0x0010)?'1':'0')); - if (s->IOmask & 0x0020) - xbee_logI("Digital 5: %c",((s->IOdigital & 0x0020)?'1':'0')); - if (s->IOmask & 0x0040) - xbee_logI("Digital 6: %c",((s->IOdigital & 0x0040)?'1':'0')); - if (s->IOmask & 0x0080) - xbee_logI("Digital 7: %c",((s->IOdigital & 0x0080)?'1':'0')); - if (s->IOmask & 0x0100) - xbee_logI("Digital 8: %c",((s->IOdigital & 0x0100)?'1':'0')); - if (s->IOmask & 0x0200) - xbee_logI("Analog 0: %d (~%.2fv)",s->IOanalog[0],(3.3/1023)*s->IOanalog[0]); - if (s->IOmask & 0x0400) - xbee_logI("Analog 1: %d (~%.2fv)",s->IOanalog[1],(3.3/1023)*s->IOanalog[1]); - if (s->IOmask & 0x0800) - xbee_logI("Analog 2: %d (~%.2fv)",s->IOanalog[2],(3.3/1023)*s->IOanalog[2]); - if (s->IOmask & 0x1000) - xbee_logI("Analog 3: %d (~%.2fv)",s->IOanalog[3],(3.3/1023)*s->IOanalog[3]); - if (s->IOmask & 0x2000) - xbee_logI("Analog 4: %d (~%.2fv)",s->IOanalog[4],(3.3/1023)*s->IOanalog[4]); - if (s->IOmask & 0x4000) - xbee_logI("Analog 5: %d (~%.2fv)",s->IOanalog[5],(3.3/1023)*s->IOanalog[5]); - } - - return sampleOffset; -} - -/* ################################################################# - xbee_listen_stop - stops the listen thread after the current packet has been processed */ -void xbee_listen_stop(xbee_hnd xbee) { - ISREADYP(); - xbee->run = 0; -} - -/* ################################################################# - xbee_listen_wrapper - INTERNAL - the xbee_listen wrapper. Prints an error when xbee_listen ends */ -static void xbee_listen_wrapper(xbee_hnd xbee) { - int ret; - - /* just falls out if the proper 'go-ahead' isn't given */ - if (xbee->xbee_ready != -1) return; - /* now allow the parent to continue */ - xbee->xbee_ready = -2; - -#ifdef _WIN32 /* ---- */ - /* win32 requires this delay... no idea why */ - usleep(1000000); -#endif /* ----------- */ - - while (xbee->run) { - ret = xbee_listen(xbee); - if (!xbee->run) break; - xbee_log("xbee_listen() returned [%d]... Restarting in 25ms!",ret); - usleep(25000); - } -} - -/* xbee_listen - INTERNAL - the xbee xbee_listen thread - reads data from the xbee and puts it into a linked list to keep the xbee buffers free */ -static int xbee_listen(xbee_hnd xbee) { -#define LISTEN_BUFLEN 1024 - unsigned char c, t, d[LISTEN_BUFLEN]; - unsigned int l, i, chksum, o; - int j; - xbee_pkt *p = NULL, *q; - xbee_con *con; - int hasCon; - - /* do this forever :) */ - while (xbee->run) { - /* clean up any undesired storage */ - if (p) Xfree(p); - - /* wait for a valid start byte */ - if ((c = xbee_getrawbyte(xbee)) != 0x7E) { - if (xbee->log) xbee_log("***** Unexpected byte (0x%02X)... *****",c); - continue; - } - if (!xbee->run) return 0; - - xbee_logSf(); - if (xbee->log) { - struct timeval tv; - xbee_logI("--== RX Packet ===========--"); - gettimeofday(&tv,NULL); - xbee_logI("Got a packet @ %ld.%06ld",tv.tv_sec,tv.tv_usec); - } - - /* get the length */ - l = xbee_getbyte(xbee) << 8; - l += xbee_getbyte(xbee); - - /* check it is a valid length... */ - if (!l) { - if (xbee->log) { - xbee_logI("Recived zero length packet!"); - } - continue; - } - if (l > 100) { - if (xbee->log) { - xbee_logI("Recived oversized packet! Length: %d",l - 1); - } - } - if (l > LISTEN_BUFLEN) { - if (xbee->log) { - xbee_logI("Recived packet larger than buffer! Discarding..."); - } - continue; - } - - if (xbee->log) { - xbee_logI("Length: %d",l - 1); - } - - /* get the packet type */ - t = xbee_getbyte(xbee); - - /* start the checksum */ - chksum = t; - - /* suck in all the data */ - for (i = 0; l > 1 && i < LISTEN_BUFLEN; l--, i++) { - /* get an unescaped byte */ - c = xbee_getbyte(xbee); - d[i] = c; - chksum += c; - if (xbee->log) { - xbee_logIc("%3d | 0x%02X | ",i,c); - if ((c > 32) && (c < 127)) fprintf(xbee->log,"'%c'",c); else fprintf(xbee->log," _ "); - - if ((t == XBEE_LOCAL_AT && i == 4) || - (t == XBEE_REMOTE_AT && i == 14) || - (t == XBEE_64BIT_DATARX && i == 10) || - (t == XBEE_16BIT_DATARX && i == 4) || - (t == XBEE_64BIT_IO && i == 13) || - (t == XBEE_16BIT_IO && i == 7)) { - /* mark the beginning of the 'data' bytes */ - fprintf(xbee->log," <-- data starts"); - } else if (t == XBEE_64BIT_IO) { - if (i == 10) fprintf(xbee->log," <-- sample count"); - else if (i == 11) fprintf(xbee->log," <-- mask (msb)"); - else if (i == 12) fprintf(xbee->log," <-- mask (lsb)"); - } else if (t == XBEE_16BIT_IO) { - if (i == 4) fprintf(xbee->log," <-- sample count"); - else if (i == 5) fprintf(xbee->log," <-- mask (msb)"); - else if (i == 6) fprintf(xbee->log," <-- mask (lsb)"); - } - xbee_logIcf(); - } - } - i--; /* it went up too many times!... */ - - /* add the checksum */ - chksum += xbee_getbyte(xbee); - - /* check if the whole packet was recieved, or something else occured... unlikely... */ - if (l>1) { - if (xbee->log) { - xbee_logE("Didn't get whole packet... :("); - } - continue; - } - - /* check the checksum */ - if ((chksum & 0xFF) != 0xFF) { - if (xbee->log) { - chksum &= 0xFF; - xbee_logE("Invalid Checksum: 0x%02X",chksum); - } - continue; - } - - /* make a new packet */ - p = Xcalloc(sizeof(xbee_pkt)); - q = NULL; - p->datalen = 0; - - /* ########################################## */ - /* if: modem status */ - if (t == XBEE_MODEM_STATUS) { - if (xbee->log) { - xbee_logI("Packet type: Modem Status (0x8A)"); - xbee_logIc("Event: "); - switch (d[0]) { - case 0x00: fprintf(xbee->log,"Hardware reset"); break; - case 0x01: fprintf(xbee->log,"Watchdog timer reset"); break; - case 0x02: fprintf(xbee->log,"Associated"); break; - case 0x03: fprintf(xbee->log,"Disassociated"); break; - case 0x04: fprintf(xbee->log,"Synchronization lost"); break; - case 0x05: fprintf(xbee->log,"Coordinator realignment"); break; - case 0x06: fprintf(xbee->log,"Coordinator started"); break; - } - fprintf(xbee->log,"... (0x%02X)",d[0]); - xbee_logIcf(); - } - p->type = xbee_modemStatus; - - p->sAddr64 = FALSE; - p->dataPkt = FALSE; - p->txStatusPkt = FALSE; - p->modemStatusPkt = TRUE; - p->remoteATPkt = FALSE; - p->IOPkt = FALSE; - - /* modem status can only ever give 1 'data' byte */ - p->datalen = 1; - p->data[0] = d[0]; - - /* ########################################## */ - /* if: local AT response */ - } else if (t == XBEE_LOCAL_AT) { - if (xbee->log) { - xbee_logI("Packet type: Local AT Response (0x88)"); - xbee_logI("FrameID: 0x%02X",d[0]); - xbee_logI("AT Command: %c%c",d[1],d[2]); - xbee_logIc("Status: "); - if (d[3] == 0x00) fprintf(xbee->log,"OK"); - else if (d[3] == 0x01) fprintf(xbee->log,"Error"); - else if (d[3] == 0x02) fprintf(xbee->log,"Invalid Command"); - else if (d[3] == 0x03) fprintf(xbee->log,"Invalid Parameter"); - fprintf(xbee->log," (0x%02X)",d[3]); - xbee_logIcf(); - } - p->type = xbee_localAT; - - p->sAddr64 = FALSE; - p->dataPkt = FALSE; - p->txStatusPkt = FALSE; - p->modemStatusPkt = FALSE; - p->remoteATPkt = FALSE; - p->IOPkt = FALSE; - - p->frameID = d[0]; - p->atCmd[0] = d[1]; - p->atCmd[1] = d[2]; - - p->status = d[3]; - - /* copy in the data */ - p->datalen = i-3; - for (;i>3;i--) p->data[i-4] = d[i]; - - /* ########################################## */ - /* if: remote AT response */ - } else if (t == XBEE_REMOTE_AT) { - if (xbee->log) { - xbee_logI("Packet type: Remote AT Response (0x97)"); - xbee_logI("FrameID: 0x%02X",d[0]); - xbee_logIc("64-bit Address: "); - for (j=0;j<8;j++) { - fprintf(xbee->log,(j?":%02X":"%02X"),d[1+j]); - } - xbee_logIcf(); - xbee_logIc("16-bit Address: "); - for (j=0;j<2;j++) { - fprintf(xbee->log,(j?":%02X":"%02X"),d[9+j]); - } - xbee_logIcf(); - xbee_logI("AT Command: %c%c",d[11],d[12]); - xbee_logIc("Status: "); - if (d[13] == 0x00) fprintf(xbee->log,"OK"); - else if (d[13] == 0x01) fprintf(xbee->log,"Error"); - else if (d[13] == 0x02) fprintf(xbee->log,"Invalid Command"); - else if (d[13] == 0x03) fprintf(xbee->log,"Invalid Parameter"); - else if (d[13] == 0x04) fprintf(xbee->log,"No Response"); - fprintf(xbee->log," (0x%02X)",d[13]); - xbee_logIcf(); - } - p->type = xbee_remoteAT; - - p->sAddr64 = FALSE; - p->dataPkt = FALSE; - p->txStatusPkt = FALSE; - p->modemStatusPkt = FALSE; - p->remoteATPkt = TRUE; - p->IOPkt = FALSE; - - p->frameID = d[0]; - - p->Addr64[0] = d[1]; - p->Addr64[1] = d[2]; - p->Addr64[2] = d[3]; - p->Addr64[3] = d[4]; - p->Addr64[4] = d[5]; - p->Addr64[5] = d[6]; - p->Addr64[6] = d[7]; - p->Addr64[7] = d[8]; - - p->Addr16[0] = d[9]; - p->Addr16[1] = d[10]; - - p->atCmd[0] = d[11]; - p->atCmd[1] = d[12]; - - p->status = d[13]; - - p->samples = 1; - - if (p->status == 0x00 && p->atCmd[0] == 'I' && p->atCmd[1] == 'S') { - /* parse the io data */ - xbee_logI("--- Sample -----------------"); - xbee_parse_io(xbee, p, d, 15, 17, 0); - xbee_logI("----------------------------"); - } else { - /* copy in the data */ - p->datalen = i-13; - for (;i>13;i--) p->data[i-14] = d[i]; - } - - /* ########################################## */ - /* if: TX status */ - } else if (t == XBEE_TX_STATUS) { - if (xbee->log) { - xbee_logI("Packet type: TX Status Report (0x89)"); - xbee_logI("FrameID: 0x%02X",d[0]); - xbee_logIc("Status: "); - if (d[1] == 0x00) fprintf(xbee->log,"Success"); - else if (d[1] == 0x01) fprintf(xbee->log,"No ACK"); - else if (d[1] == 0x02) fprintf(xbee->log,"CCA Failure"); - else if (d[1] == 0x03) fprintf(xbee->log,"Purged"); - fprintf(xbee->log," (0x%02X)",d[1]); - xbee_logIcf(); - } - p->type = xbee_txStatus; - - p->sAddr64 = FALSE; - p->dataPkt = FALSE; - p->txStatusPkt = TRUE; - p->modemStatusPkt = FALSE; - p->remoteATPkt = FALSE; - p->IOPkt = FALSE; - - p->frameID = d[0]; - - p->status = d[1]; - - /* never returns data */ - p->datalen = 0; - - /* check for any connections waiting for a status update */ - /* lock the connection mutex */ - xbee_mutex_lock(xbee->conmutex); - xbee_logI("Looking for a connection that wants a status update..."); - con = xbee->conlist; - while (con) { - if ((con->frameID == p->frameID) && - (con->ACKstatus == 0xFF)) { - xbee_logI("Found @ 0x%08X!",con); - con->ACKstatus = p->status; - xbee_sem_post(con->waitforACKsem); - } - con = con->next; - } - - /* unlock the connection mutex */ - xbee_mutex_unlock(xbee->conmutex); - - /* ########################################## */ - /* if: 16 / 64bit data recieve */ - } else if ((t == XBEE_64BIT_DATARX) || - (t == XBEE_16BIT_DATARX)) { - int offset; - if (t == XBEE_64BIT_DATARX) { /* 64bit */ - offset = 8; - } else { /* 16bit */ - offset = 2; - } - if (xbee->log) { - xbee_logI("Packet type: %d-bit RX Data (0x%02X)",((t == XBEE_64BIT_DATARX)?64:16),t); - xbee_logIc("%d-bit Address: ",((t == XBEE_64BIT_DATARX)?64:16)); - for (j=0;jlog,(j?":%02X":"%02X"),d[j]); - } - xbee_logIcf(); - xbee_logI("RSSI: -%ddB",d[offset]); - if (d[offset + 1] & 0x02) xbee_logI("Options: Address Broadcast"); - if (d[offset + 1] & 0x04) xbee_logI("Options: PAN Broadcast"); - } - p->isBroadcastADR = !!(d[offset+1] & 0x02); - p->isBroadcastPAN = !!(d[offset+1] & 0x04); - p->dataPkt = TRUE; - p->txStatusPkt = FALSE; - p->modemStatusPkt = FALSE; - p->remoteATPkt = FALSE; - p->IOPkt = FALSE; - - if (t == XBEE_64BIT_DATARX) { /* 64bit */ - p->type = xbee_64bitData; - - p->sAddr64 = TRUE; - - p->Addr64[0] = d[0]; - p->Addr64[1] = d[1]; - p->Addr64[2] = d[2]; - p->Addr64[3] = d[3]; - p->Addr64[4] = d[4]; - p->Addr64[5] = d[5]; - p->Addr64[6] = d[6]; - p->Addr64[7] = d[7]; - } else { /* 16bit */ - p->type = xbee_16bitData; - - p->sAddr64 = FALSE; - - p->Addr16[0] = d[0]; - p->Addr16[1] = d[1]; - } - - /* save the RSSI / signal strength - this can be used with printf as: - printf("-%ddB\n",p->RSSI); */ - p->RSSI = d[offset]; - - p->status = d[offset + 1]; - - /* copy in the data */ - p->datalen = i-(offset + 1); - for (;i>offset + 1;i--) p->data[i-(offset + 2)] = d[i]; - - /* ########################################## */ - /* if: 16 / 64bit I/O recieve */ - } else if ((t == XBEE_64BIT_IO) || - (t == XBEE_16BIT_IO)) { - int offset,i2; - if (t == XBEE_64BIT_IO) { /* 64bit */ - p->type = xbee_64bitIO; - - p->sAddr64 = TRUE; - - p->Addr64[0] = d[0]; - p->Addr64[1] = d[1]; - p->Addr64[2] = d[2]; - p->Addr64[3] = d[3]; - p->Addr64[4] = d[4]; - p->Addr64[5] = d[5]; - p->Addr64[6] = d[6]; - p->Addr64[7] = d[7]; - - offset = 8; - p->samples = d[10]; - } else { /* 16bit */ - p->type = xbee_16bitIO; - - p->sAddr64 = FALSE; - - p->Addr16[0] = d[0]; - p->Addr16[1] = d[1]; - - offset = 2; - p->samples = d[4]; - } - if (p->samples > 1) { - p = Xrealloc(p, sizeof(xbee_pkt) + (sizeof(xbee_sample) * (p->samples - 1))); - } - if (xbee->log) { - xbee_logI("Packet type: %d-bit RX I/O Data (0x%02X)",((t == XBEE_64BIT_IO)?64:16),t); - xbee_logIc("%d-bit Address: ",((t == XBEE_64BIT_IO)?64:16)); - for (j = 0; j < offset; j++) { - fprintf(xbee->log,(j?":%02X":"%02X"),d[j]); - } - xbee_logIcf(); - xbee_logI("RSSI: -%ddB",d[offset]); - xbee_logI("Samples: %d",d[offset + 2]); - } - i2 = offset + 5; - - /* never returns data */ - p->datalen = 0; - - p->dataPkt = FALSE; - p->txStatusPkt = FALSE; - p->modemStatusPkt = FALSE; - p->remoteATPkt = FALSE; - p->IOPkt = TRUE; - - /* save the RSSI / signal strength - this can be used with printf as: - printf("-%ddB\n",p->RSSI); */ - p->RSSI = d[offset]; - - p->status = d[offset + 1]; - - /* each sample is split into its own packet here, for simplicity */ - for (o = 0; o < p->samples; o++) { - if (i2 >= i) { - xbee_logI("Invalid I/O data! Actually contained %d samples...",o); - p = Xrealloc(p, sizeof(xbee_pkt) + (sizeof(xbee_sample) * ((o>1)?o:1))); - p->samples = o; - break; - } - xbee_logI("--- Sample %3d -------------", o); - - /* parse the io data */ - i2 = xbee_parse_io(xbee, p, d, offset + 3, i2, o); - } - xbee_logI("----------------------------"); - - /* ########################################## */ - /* if: Series 2 Transmit status */ - } else if (t == XBEE2_TX_STATUS) { - if (xbee->log) { - xbee_logI("Packet type: Series 2 Transmit Status (0x%02X)", t); - xbee_logI("FrameID: 0x%02X",d[0]); - xbee_logI("16-bit Delivery Address: %02X:%02X",d[1],d[2]); - xbee_logI("Transmit Retry Count: %02X",d[3]); - xbee_logIc("Delivery Status: "); - if (d[4] == 0x00) fprintf(xbee->log,"Success"); - else if (d[4] == 0x02) fprintf(xbee->log,"CCA Failure"); - else if (d[4] == 0x15) fprintf(xbee->log,"Invalid Destination"); - else if (d[4] == 0x21) fprintf(xbee->log,"Network ACK Failure"); - else if (d[4] == 0x22) fprintf(xbee->log,"Not Joined to Network"); - else if (d[4] == 0x23) fprintf(xbee->log,"Self-Addressed"); - else if (d[4] == 0x24) fprintf(xbee->log,"Address Not Found"); - else if (d[4] == 0x25) fprintf(xbee->log,"Route Not Found"); - else if (d[4] == 0x74) fprintf(xbee->log,"Data Payload Too Large"); /* ??? */ - fprintf(xbee->log," (0x%02X)",d[4]); - xbee_logIcf(); - - xbee_logIc("Discovery Status: "); - if (d[5] == 0x00) fprintf(xbee->log,"No Discovery Overhead"); - else if (d[5] == 0x01) fprintf(xbee->log,"Address Discovery"); - else if (d[5] == 0x02) fprintf(xbee->log,"Route Discovery"); - else if (d[5] == 0x03) fprintf(xbee->log,"Address & Route Discovery"); - fprintf(xbee->log," (0x%02X)",d[5]); - xbee_logIcf(); - } - - p->type = xbee2_txStatus; - - p->sAddr64 = FALSE; - p->dataPkt = FALSE; - p->txStatusPkt = TRUE; - p->modemStatusPkt = FALSE; - p->remoteATPkt = FALSE; - p->IOPkt = FALSE; - - p->frameID = d[0]; - - p->status = d[4]; - - /* never returns data */ - p->datalen = 0; - - /* ########################################## */ - /* if: Series 2 data recieve */ - } else if (t == XBEE2_DATARX) { - int offset; - offset = 10; - if (xbee->log) { - xbee_logI("Packet type: Series 2 Data Rx (0x%02X)", t); - - xbee_logIc("64-bit Address: "); - for (j=0;j<8;j++) { - fprintf(xbee->log,(j?":%02X":"%02X"),d[j]); - } - xbee_logIcf(); - - xbee_logIc("16-bit Address: "); - for (j=0;j<2;j++) { - fprintf(xbee->log,(j?":%02X":"%02X"),d[j+8]); - } - xbee_logIcf(); - - if (d[offset] & 0x01) xbee_logI("Options: Packet Acknowledged"); - if (d[offset] & 0x02) xbee_logI("Options: Packet was a broadcast packet"); - if (d[offset] & 0x20) xbee_logI("Options: Packet Encrypted"); /* ??? */ - if (d[offset] & 0x40) xbee_logI("Options: Packet from end device"); /* ??? */ - } - p->dataPkt = TRUE; - p->txStatusPkt = FALSE; - p->modemStatusPkt = FALSE; - p->remoteATPkt = FALSE; - p->IOPkt = FALSE; - p->type = xbee2_data; - p->sAddr64 = TRUE; - - p->Addr64[0] = d[0]; - p->Addr64[1] = d[1]; - p->Addr64[2] = d[2]; - p->Addr64[3] = d[3]; - p->Addr64[4] = d[4]; - p->Addr64[5] = d[5]; - p->Addr64[6] = d[6]; - p->Addr64[7] = d[7]; - - p->Addr16[0] = d[8]; - p->Addr16[1] = d[9]; - - p->status = d[offset]; - - /* copy in the data */ - p->datalen = i - (offset + 1); - for (;i>offset;i--) { - p->data[i-(offset + 1)] = d[i]; - } - - /* ########################################## */ - /* if: Unknown */ - } else { - xbee_logE("Packet type: Unknown (0x%02X)",t); - continue; - } - p->next = NULL; - - /* lock the connection mutex */ - xbee_mutex_lock(xbee->conmutex); - - hasCon = 0; - if (p->isBroadcastADR || p->isBroadcastPAN) { - unsigned char t[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - /* if the packet was broadcast, search for a broadcast accepting connection */ - con = xbee->conlist; - while (con) { - if (con->type == p->type && - (con->type == xbee_16bitData || con->type == xbee_64bitData) && - ((con->tAddr64 && !memcmp(con->tAddr,t,8)) || - (!con->tAddr64 && !memcmp(con->tAddr,t,2)))) { - hasCon = 1; - xbee_logI("Found broadcasting connection @ 0x%08X",con); - break; - } - con = con->next; - } - } - if (!hasCon || !con) { - con = xbee->conlist; - while (con) { - if (xbee_matchpktcon(xbee, p, con)) { - hasCon = 1; - break; - } - con = con->next; - } - } - - /* unlock the connection mutex */ - xbee_mutex_unlock(xbee->conmutex); - - /* if the packet doesn't have a connection, don't add it! */ - if (!hasCon) { - xbee_logE("Connectionless packet... discarding!"); - continue; - } - - /* if the connection has a callback function then it is passed the packet - and the packet is not added to the list */ - if (con && con->callback) { - t_callback_list *l, *q; - - xbee_mutex_lock(con->callbackListmutex); - l = con->callbackList; - q = NULL; - while (l) { - q = l; - l = l->next; - } - l = Xcalloc(sizeof(t_callback_list)); - l->pkt = p; - if (!con->callbackList || q == NULL) { - con->callbackList = l; - } else { - q->next = l; - } - xbee_mutex_unlock(con->callbackListmutex); - - xbee_logI("Using callback function!"); - xbee_logI(" info block @ 0x%08X",l); - xbee_logI(" function @ 0x%08X",con->callback); - xbee_logI(" connection @ 0x%08X",con); - xbee_logE(" packet @ 0x%08X",p); - - /* if the callback thread not still running, then start a new one! */ - if (!xbee_mutex_trylock(con->callbackmutex)) { - xbee_thread_t t; - int ret; - t_threadList *p, *q; - t_CBinfo info; - info.xbee = xbee; - info.con = con; - xbee_log("Starting new callback thread!"); - if ((ret = xbee_thread_create(t,xbee_callbackWrapper,&info)) != 0) { - xbee_mutex_unlock(con->callbackmutex); - /* this MAY help with future attempts... */ - xbee_sem_post(xbee->threadsem); - xbee_logS("An error occured while starting thread (%d)... Out of resources?", ret); - xbee_logE("This packet has been lost!"); - continue; - } - xbee_log("Started thread 0x%08X!", t); - xbee_mutex_lock(xbee->threadmutex); - p = xbee->threadList; - q = NULL; - while (p) { - q = p; - p = p->next; - } - p = Xcalloc(sizeof(t_threadList)); - if (q == NULL) { - xbee->threadList = p; - } else { - q->next = p; - } - p->thread = t; - p->next = NULL; - xbee_mutex_unlock(xbee->threadmutex); - } else { - xbee_logE("Using existing callback thread... callback has been scheduled."); - } - /* prevent the packet from being free'd */ - p = NULL; - continue; - } - - /* lock the packet mutex, so we can safely add the packet to the list */ - xbee_mutex_lock(xbee->pktmutex); - - /* if: the list is empty */ - if (!xbee->pktlist) { - /* start the list! */ - xbee->pktlist = p; - } else if (xbee->pktlast) { - /* add the packet to the end */ - xbee->pktlast->next = p; - } else { - /* pktlast wasnt set... look for the end and then set it */ - i = 0; - q = xbee->pktlist; - while (q->next) { - q = q->next; - i++; - } - q->next = p; - xbee->pktcount = i; - } - xbee->pktlast = p; - xbee->pktcount++; - - /* unlock the packet mutex */ - xbee_mutex_unlock(xbee->pktmutex); - - xbee_logI("--========================--"); - xbee_logE("Packets: %d",xbee->pktcount); - - p = q = NULL; - } - return 0; -} - -static void xbee_callbackWrapper(t_CBinfo *info) { - xbee_hnd xbee; - xbee_con *con; - xbee_pkt *pkt; - t_callback_list *temp; - xbee = info->xbee; - con = info->con; - /* dont forget! the callback mutex is already locked... by the parent thread :) */ - xbee_mutex_lock(con->callbackListmutex); - while (con->callbackList) { - /* shift the list along 1 */ - temp = con->callbackList; - con->callbackList = temp->next; - xbee_mutex_unlock(con->callbackListmutex); - /* get the packet */ - pkt = temp->pkt; - - xbee_logS("Starting callback function..."); - xbee_logI(" info block @ 0x%08X",temp); - xbee_logI(" function @ 0x%08X",con->callback); - xbee_logI(" connection @ 0x%08X",con); - xbee_logE(" packet @ 0x%08X",pkt); - Xfree(temp); - if (con->callback) { - con->callback(con,pkt); - xbee_log("Callback complete!"); - if (!con->noFreeAfterCB) Xfree(pkt); - } else { - xbee_pkt *q; - int i; - xbee_log("Callback function was removed! Appending packet to main list..."); - /* lock the packet mutex, so we can safely add the packet to the list */ - xbee_mutex_lock(xbee->pktmutex); - - /* if: the list is empty */ - if (!xbee->pktlist) { - /* start the list! */ - xbee->pktlist = pkt; - } else if (xbee->pktlast) { - /* add the packet to the end */ - xbee->pktlast->next = pkt; - } else { - /* pktlast wasnt set... look for the end and then set it */ - i = 0; - q = xbee->pktlist; - while (q->next) { - q = q->next; - i++; - } - q->next = pkt; - xbee->pktcount = i; - } - xbee->pktlast = pkt; - xbee->pktcount++; - - /* unlock the packet mutex */ - xbee_mutex_unlock(xbee->pktmutex); - } - - xbee_mutex_lock(con->callbackListmutex); - } - xbee_mutex_unlock(con->callbackListmutex); - - xbee_log("Callback thread ending..."); - /* releasing the thread mutex is the last thing we do! */ - xbee_mutex_unlock(con->callbackmutex); - - if (con->destroySelf) { - _xbee_endcon2(xbee,&con,1); - } - xbee_sem_post(xbee->threadsem); -} - -/* ################################################################# - xbee_thread_watch - INTERNAL - watches for dead threads and tidies up */ -static void xbee_thread_watch(xbee_hnd xbee) { - -#ifdef _WIN32 /* ---- */ - /* win32 requires this delay... no idea why */ - usleep(1000000); -#endif /* ----------- */ - - xbee_mutex_init(xbee->threadmutex); - xbee_sem_init(xbee->threadsem); - - while (xbee->run) { - t_threadList *p, *q, *t; - xbee_mutex_lock(xbee->threadmutex); - p = xbee->threadList; - q = NULL; - - while (p) { - t = p; - p = p->next; - if (!(xbee_thread_tryjoin(t->thread))) { - xbee_log("Joined with thread 0x%08X...",t->thread); - if (t == xbee->threadList) { - xbee->threadList = t->next; - } else if (q) { - q->next = t->next; - } - free(t); - } else { - q = t; - } - } - - xbee_mutex_unlock(xbee->threadmutex); - xbee_sem_wait(xbee->threadsem); - usleep(100000); /* 100ms to allow the thread to end before we try to join */ - } - - xbee_mutex_destroy(xbee->threadmutex); - xbee_sem_destroy(xbee->threadsem); -} - - -/* ################################################################# - xbee_getbyte - INTERNAL - waits for an escaped byte of data */ -static unsigned char xbee_getbyte(xbee_hnd xbee) { - unsigned char c; - - /* take a byte */ - c = xbee_getrawbyte(xbee); - /* if its escaped, take another and un-escape */ - if (c == 0x7D) c = xbee_getrawbyte(xbee) ^ 0x20; - - return (c & 0xFF); -} - -/* ################################################################# - xbee_getrawbyte - INTERNAL - waits for a raw byte of data */ -static unsigned char xbee_getrawbyte(xbee_hnd xbee) { - int ret; - unsigned char c = 0x00; - - /* the loop is just incase there actually isnt a byte there to be read... */ - do { - /* wait for a read to be possible */ - if ((ret = xbee_select(xbee,NULL)) == -1) { - xbee_perror("libxbee:xbee_getrawbyte()"); - exit(1); - } - if (!xbee->run) break; - if (ret == 0) continue; - - /* read 1 character */ - if (xbee_read(xbee,&c,1) == 0) { - /* for some reason no characters were read... */ - if (xbee_ferror(xbee) || xbee_feof(xbee)) { - xbee_log("Error or EOF detected"); - fprintf(stderr,"libxbee:xbee_read(): Error or EOF detected\n"); - exit(1); /* this should have something nicer... */ - } - /* no error... try again */ - usleep(10); - continue; - } - } while (0); - - return (c & 0xFF); -} - -/* ################################################################# - _xbee_send_pkt - INTERNAL - sends a complete packet of data */ -static int _xbee_send_pkt(xbee_hnd xbee, t_data *pkt, xbee_con *con) { - int retval = 0; - - /* lock connection mutex */ - xbee_mutex_lock(con->Txmutex); - /* lock the send mutex */ - xbee_mutex_lock(xbee->sendmutex); - - /* write and flush the data */ - xbee_write(xbee,pkt->data,pkt->length); - - /* unlock the mutex */ - xbee_mutex_unlock(xbee->sendmutex); - - xbee_logSf(); - if (xbee->log) { - int i,x,y; - /* prints packet in hex byte-by-byte */ - xbee_logIc("TX Packet:"); - for (i=0,x=0,y=0;ilength;i++,x--) { - if (x == 0) { - fprintf(xbee->log,"\n 0x%04X | ",y); - x = 0x8; - y += x; - } - if (x == 4) { - fprintf(xbee->log," "); - } - fprintf(xbee->log,"0x%02X ",pkt->data[i]); - } - xbee_logIcf(); - } - xbee_logEf(); - - if (con->waitforACK && - ((con->type == xbee_16bitData) || - (con->type == xbee_64bitData))) { - con->ACKstatus = 0xFF; /* waiting */ - xbee_log("Waiting for ACK/NAK response..."); - xbee_sem_wait1sec(con->waitforACKsem); - switch (con->ACKstatus) { - case 0: xbee_log("ACK recieved!"); break; - case 1: xbee_log("NAK recieved..."); break; - case 2: xbee_log("CCA failure..."); break; - case 3: xbee_log("Purged..."); break; - case 255: default: xbee_log("Timeout..."); - } - if (con->ACKstatus) retval = 1; /* error */ - } - - /* unlock connection mutex */ - xbee_mutex_unlock(con->Txmutex); - - /* free the packet */ - Xfree(pkt); - - return retval; -} - -/* ################################################################# - xbee_make_pkt - INTERNAL - adds delimiter field - calculates length and checksum - escapes bytes */ -static t_data *xbee_make_pkt(xbee_hnd xbee, unsigned char *data, int length) { - t_data *pkt; - unsigned int l, i, o, t, x, m; - char d = 0; - - /* check the data given isnt too long - 100 bytes maximum payload + 12 bytes header information */ - if (length > 100 + 12) return NULL; - - /* calculate the length of the whole packet - start, length (MSB), length (LSB), DATA, checksum */ - l = 3 + length + 1; - - /* prepare memory */ - pkt = Xcalloc(sizeof(t_data)); - - /* put start byte on */ - pkt->data[0] = 0x7E; - - /* copy data into packet */ - for (t = 0, i = 0, o = 1, m = 1; i <= length; o++, m++) { - /* if: its time for the checksum */ - if (i == length) d = M8((0xFF - M8(t))); - /* if: its time for the high length byte */ - else if (m == 1) d = M8(length >> 8); - /* if: its time for the low length byte */ - else if (m == 2) d = M8(length); - /* if: its time for the normal data */ - else if (m > 2) d = data[i]; - - x = 0; - /* check for any escapes needed */ - if ((d == 0x11) || /* XON */ - (d == 0x13) || /* XOFF */ - (d == 0x7D) || /* Escape */ - (d == 0x7E)) { /* Frame Delimiter */ - l++; - pkt->data[o++] = 0x7D; - x = 1; - } - - /* move data in */ - pkt->data[o] = ((!x)?d:d^0x20); - if (m > 2) { - i++; - t += d; - } - } - - /* remember the length */ - pkt->length = l; - - return pkt; -} diff --git a/libs/thirdParty/libxbee/api.h b/libs/thirdParty/libxbee/api.h deleted file mode 100644 index 692bd7b165cfb9f8ae746af583da2f2c3317fd17..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/api.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include - -#include - -#include -#include -#include -#include - -#ifdef __GNUC__ /* ---- */ -#include -#include -#define __USE_GNU -#include -#undef __USE_GNU -#include -#else /* -------------- */ -#include -#include -#include -#include -#endif /* ------------- */ - -#ifdef __UMAKEFILE - #define HOST_OS "Embedded" -#elif defined(__GNUC__) - #define HOST_OS "Linux" -#elif defined(_WIN32) - #define HOST_OS "Win32" -#else - #define HOST_OS "UNKNOWN" -#endif - -#define TRUE 1 -#define FALSE 0 - -#define M8(x) (x & 0xFF) - -/* various connection types */ -#define XBEE_LOCAL_AT 0x88 -#define XBEE_LOCAL_ATREQ 0x08 -#define XBEE_LOCAL_ATQUE 0x09 - -#define XBEE_REMOTE_AT 0x97 -#define XBEE_REMOTE_ATREQ 0x17 - -#define XBEE_MODEM_STATUS 0x8A - -/* XBee Series 1 stuff */ -#define XBEE_TX_STATUS 0x89 -#define XBEE_64BIT_DATATX 0x00 -#define XBEE_64BIT_DATARX 0x80 -#define XBEE_16BIT_DATATX 0x01 -#define XBEE_16BIT_DATARX 0x81 -#define XBEE_64BIT_IO 0x82 -#define XBEE_16BIT_IO 0x83 - -/* XBee Series 2 stuff */ -#define XBEE2_DATATX 0x10 -#define XBEE2_DATARX 0x90 -#define XBEE2_TX_STATUS 0x8B - -typedef struct xbee_hnd* xbee_hnd; - -#define __LIBXBEE_API_H -#include "xbee.h" - -typedef struct t_threadList t_threadList; -struct t_threadList { - xbee_thread_t thread; - t_threadList *next; -}; - -struct xbee_hnd { - xbee_file_t tty; -#ifdef __GNUC__ /* ---- */ - int ttyfd; -#else /* -------------- */ - int ttyr; - int ttyw; - int ttyeof; - - OVERLAPPED ttyovrw; - OVERLAPPED ttyovrr; - OVERLAPPED ttyovrs; -#endif /* ------------- */ - - char *path; /* serial port path */ - - xbee_mutex_t logmutex; - FILE *log; - int logfd; - - xbee_mutex_t conmutex; - xbee_con *conlist; - - xbee_mutex_t pktmutex; - xbee_pkt *pktlist; - xbee_pkt *pktlast; - int pktcount; - - xbee_mutex_t sendmutex; - - xbee_thread_t listent; - - xbee_thread_t threadt; - xbee_mutex_t threadmutex; - xbee_sem_t threadsem; - t_threadList *threadList; - - int run; - - int oldAPI; - char cmdSeq; - int cmdTime; - - /* ready flag. - needs to be set to -1 so that the listen thread can begin. */ - volatile int xbee_ready; - - xbee_hnd next; -}; -xbee_hnd default_xbee = NULL; -xbee_mutex_t xbee_hnd_mutex; - -typedef struct t_data t_data; -struct t_data { - unsigned char data[128]; - unsigned int length; -}; - -typedef struct t_LTinfo t_LTinfo; -struct t_LTinfo { - int i; - xbee_hnd xbee; -}; - -typedef struct t_CBinfo t_CBinfo; -struct t_CBinfo { - xbee_hnd xbee; - xbee_con *con; -}; - -typedef struct t_callback_list t_callback_list; -struct t_callback_list { - xbee_pkt *pkt; - t_callback_list *next; -}; - -static void *Xmalloc2(xbee_hnd xbee, size_t size); -static void *Xcalloc2(xbee_hnd xbee, size_t size); -static void *Xrealloc2(xbee_hnd xbee, void *ptr, size_t size); -static void Xfree2(void **ptr); -#define Xmalloc(x) Xmalloc2(xbee,(x)) -#define Xcalloc(x) Xcalloc2(xbee,(x)) -#define Xrealloc(x,y) Xrealloc2(xbee,(x),(y)) -#define Xfree(x) Xfree2((void **)&x) - -/* usage: - xbee_logSf() lock the log - xbee_logEf() unlock the log - - xbee_log() lock print with \n unlock # to print a single line - xbee_logc() lock print with no \n # to print a single line with a custom ending - xbee_logcf() print \n unlock # to end a custom-ended single line - - xbee_logS() lock print with \n # to start a continuous block - xbee_logI() print with \n # to continue a continuous block - xbee_logIc() print with no \n # to continue a continuous block with a custom ending - xbee_logIcf() print \n # to continue a continuous block with ended custom-ended line - xbee_logE() print with \n unlock # to end a continuous block -*/ -static void xbee_logf(xbee_hnd xbee, const char *logformat, const char *file, - const int line, const char *function, char *format, ...); -#define LOG_FORMAT "[%s:%d] %s(): %s" - -#define xbee_logSf() if (xbee->log) { xbee_mutex_lock(xbee->logmutex); } -#define xbee_logEf() if (xbee->log) { xbee_mutex_unlock(xbee->logmutex); } - -#define xbee_log(...) if (xbee->log) { xbee_logSf(); xbee_logf(xbee,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__); xbee_logEf(); } -#define xbee_logc(...) if (xbee->log) { xbee_logSf(); xbee_logf(xbee,LOG_FORMAT ,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__); } -#define xbee_logcf() if (xbee->log) { fprintf(xbee->log, "\n"); xbee_logEf(); } - -#define xbee_logS(...) if (xbee->log) { xbee_logSf(); xbee_logf(xbee,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__); } -#define xbee_logI(...) if (xbee->log) { xbee_logf(xbee,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__); } -#define xbee_logIc(...) if (xbee->log) { xbee_logf(xbee,LOG_FORMAT ,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__); } -#define xbee_logIcf() if (xbee->log) { fprintf(xbee->log, "\n"); } -#define xbee_logE(...) if (xbee->log) { xbee_logf(xbee,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__); xbee_logEf(); } - -#define xbee_perror(str) \ - if (xbee->log) xbee_logI("%s:%s",str,strerror(errno)); \ - perror(str); - -static int xbee_startAPI(xbee_hnd xbee); - -static int xbee_sendAT(xbee_hnd xbee, char *command, char *retBuf, int retBuflen); -static int xbee_sendATdelay(xbee_hnd xbee, int guardTime, char *command, char *retBuf, int retBuflen); - -static int xbee_parse_io(xbee_hnd xbee, xbee_pkt *p, unsigned char *d, - int maskOffset, int sampleOffset, int sample); - -static void xbee_thread_watch(xbee_hnd xbee); -static void xbee_listen_wrapper(xbee_hnd xbee); -static int xbee_listen(xbee_hnd xbee); -static unsigned char xbee_getbyte(xbee_hnd xbee); -static unsigned char xbee_getrawbyte(xbee_hnd xbee); -static int xbee_matchpktcon(xbee_hnd xbee, xbee_pkt *pkt, xbee_con *con); - -static t_data *xbee_make_pkt(xbee_hnd xbee, unsigned char *data, int len); -static int _xbee_send_pkt(xbee_hnd xbee, t_data *pkt, xbee_con *con); -static void xbee_callbackWrapper(t_CBinfo *info); - -/* these functions can be found in the xsys files */ -static int init_serial(xbee_hnd xbee, int baudrate); -static int xbee_select(xbee_hnd xbee, struct timeval *timeout); - -#ifdef __GNUC__ /* ---- */ -#include "xsys/linux.c" -#else /* -------------- */ -#include "xsys\win32.c" -#endif /* ------------- */ - -#ifndef Win32Message -#define Win32Message() -#endif - -#define ISREADY(a) if (!xbee || !xbee->xbee_ready) { \ - if (stderr) fprintf(stderr,"libxbee: Run xbee_setup() first!...\n"); \ - Win32Message(); \ - a; \ - } -#define ISREADYP() ISREADY(return) -#define ISREADYR(a) ISREADY(return a) diff --git a/libs/thirdParty/libxbee/doc/man/man3/libxbee.3.html b/libs/thirdParty/libxbee/doc/man/man3/libxbee.3.html deleted file mode 100644 index 57b7f6a0c5721c77483ac1c30a3cd7c266aa78c3..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/libxbee.3.html +++ /dev/null @@ -1,127 +0,0 @@ -Manpage of LIBXBEE - -

LIBXBEE

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -libxbee -  -

DESCRIPTION

- -libxbee is a C library to aid the use of Series 1 Digi XBee radios running in API mode (AP=2). -

-I have tried to keep flexibility to a maximum. -By allowing connections to individual nodes to be created you don't have to address each packet, -or filter through incomming packets to get at the one you are after. This is all taken care of -for you by -libxbee! - -

-libxbee is still in development, so if you find any bugs or have any enhancement requests, please -feel free to submit an issue on the project page: - -

-http://code.google.com/p/libxbee/
-
- - -or contact me (Attie) directly: - -
-attie@attie.co.uk
-
- - -  -

MAN PAGES

- -Documentation is avaliable via the following man pages, or by example in the 'sample' folder in the SVN repository - -

-xbee_pkt(3) - libxbee's packet structure - -xbee_con(3) - libxbee's connection structure - -

-xbee_setup(3) - function to setup libxbee (and its variants) - -xbee_end(3) - function to end the libxbee session and close any open handles - -

-xbee_logit(3) - function that allows the user to add to the xbee log output - -

-xbee_newcon(3) - function to create a new connection - -xbee_flushcon(3) - function to flush packets from a connection - -xbee_endcon(3) - function to end a connection - -

-xbee_senddata(3) - function to send data to a remote XBee (and its variants) - -xbee_getpacket(3) - function to get a packet from a connection (and its variants) - -

-xbee_hasdigital(3) - function to check if digital sample is in the packet - -xbee_getdigital(3) - function to get digital sample from the packet - -

-xbee_hasanalog(3) - function to check if analog sample is in the packet - -xbee_getanalog(3) - function to get the analog sample from the packet - - - -  -

SEE ALSO

- -xbee_pkt(3), - -xbee_con(3), - -xbee_setup(3), - -xbee_end(3), - -xbee_logit(3), - -xbee_newcon(3), - -xbee_flushcon(3), - -xbee_endcon(3), - -xbee_senddata(3), - -xbee_getpacket(3), - -xbee_hasdigital(3), - -xbee_getdigital(3), - -xbee_hasanalog(3), - -xbee_getanalog(3) - -

- -


- 

Index

-
-
NAME
-
DESCRIPTION
-
MAN PAGES
-
SEE ALSO
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_con.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_con.3.html deleted file mode 100644 index 9990d7f2e37d9187140c87fa43d681fce26a4aa7..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_con.3.html +++ /dev/null @@ -1,26 +0,0 @@ -Manpage of LIBXBEE - -

LIBXBEE

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -libxbee -

-This page has not been written yet... -

- -


- 

Index

-
-
NAME
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_end.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_end.3.html deleted file mode 100644 index 7eaa6c27017f7865a490d9b428ed84d979714c5a..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_end.3.html +++ /dev/null @@ -1,27 +0,0 @@ -Manpage of LIBXBEE - -

LIBXBEE

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -libxbee -

-This page has not been written yet... -

-

- -


- 

Index

-
-
NAME
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_endcon.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_endcon.3.html deleted file mode 100644 index d7250a3cc42a2399be2d2f7f85d3a820517256e7..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_endcon.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_endcon.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_flushcon.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_flushcon.3.html deleted file mode 100644 index 1d046d7921238a0569928b2322d5518b29e7a0dd..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_flushcon.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_flushcon.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_getanalog.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_getanalog.3.html deleted file mode 100644 index 1883c3262e23af1b6162b3d2c44c983d0cf53eb7..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_getanalog.3.html +++ /dev/null @@ -1,140 +0,0 @@ -Manpage of XBEE_GETPACKET - -

XBEE_GETPACKET

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -xbee_hasanalog, xbee_getanalog -  -

SYNOPSIS

- -#include <xbee.h> - -

-int xbee_hasanalog(xbee_pkt *pkt,int sample, int input); - -

-double xbee_getanalog(xbee_pkt *pkt,int sample, int input, double Vref); - - -  -

DESCRIPTION

- -The -xbee_hasanalog() - -function will check the packet for the presence of an analog sample on the specified input. -

-The -xbee_getanalog() - -function will read the packet and return the sample value for the specified analog input. -

-They both take 3 arguments, with the same purposes. -

-The argument -pkt - -points to a packet that was previously retrieved with -xbee_getpacket() - -

-The argument -sample - -selects the sample within the packet to use. -

-The argument -input - -specifies which input you are interested in testing. -

-xbee_getanalog() - -also takes a fourth argument that allows you to provide a -Vref - -value. This allows the function to convert the raw ADC value into a voltage for you. -  -

RETURN VALUE

- -The -xbee_hasanalog() - -function will return -1 - -if the provided packet has sample data for the specified input, otherwise -0. - -

-The -xbee_getanalog() - -function will return the raw ADC value (0 - 1023) if the provided packet has sample data for the specified input and Vref was given as zero. -If Vref was non-zero, then the return value will be the voltage read. -A --1 - -will be returned if the packet does not contain sample data. -

-  -

EXAMPLE

- -To read sample data from previously made connection: - -
-#include <xbee.h>
-xbee_pkt *pkt;
-double Vref = 3.3;
-if ((pkt = xbee_getpacket(con)) != NULL) {
-  if (xbee_hasanalog(pkt,0,0)) {
-    printf("A0 read %fv,xbee_getanalog(pkt,0,0,Vref));
-  } else {
-    printf("No A0 data);
-  }
-  free(pkt);
-}
-
- - -  -

AUTHOR

- -Attie Grande <attie@attie.co.uk> -  -

SEE ALSO

- -libxbee(3), - -xbee_pkt(3), - -xbee_getpacket(3), - -xbee_hasdigital(3), - -xbee_getdigital(3) - -

- -


- 

Index

-
-
NAME
-
SYNOPSIS
-
DESCRIPTION
-
RETURN VALUE
-
EXAMPLE
-
AUTHOR
-
SEE ALSO
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_getdigital.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_getdigital.3.html deleted file mode 100644 index 2df9136221c30ff8335915a7d73f6ee5f91111bf..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_getdigital.3.html +++ /dev/null @@ -1,134 +0,0 @@ -Manpage of XBEE_GETPACKET - -

XBEE_GETPACKET

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -xbee_hasdigital, xbee_getdigital -  -

SYNOPSIS

- -#include <xbee.h> - -

-int xbee_hasdigital(xbee_pkt *pkt, int sample, int input); - -

-int xbee_getdigital(xbee_pkt *pkt, int sample, int input); - - -  -

DESCRIPTION

- -The -xbee_hasdigital() - -function will check the packet for the presence of a given sample on the specified input. -

-The -xbee_getdigital() - -function will read the packet and return the sample value for the specified input. -

-They both take 3 arguments, with the same purposes. -

-The argument -pkt - -points to a packet that was previously retrieved with -xbee_getpacket() - -

-The argument -sample - -selects the sample within the packet to use. -

-The argument -input - -specifies which input you are interested in testing. -  -

RETURN VALUE

- -The -xbee_hasdigital() - -function will return -1 - -if the provided packet has sample data for the specified input, otherwise -0. - -

-The -xbee_getdigital() - -function will return -1 - -if the provided packet has sample data for the specified input and the sample was HIGH. -A -0 - -will be returned if the sample was LOW, or the packet does not contain sample data. -

-  -

EXAMPLE

- -To read sample data from previously made connection: - -
-#include <xbee.h>
-xbee_pkt *pkt;
-if ((pkt = xbee_getpacket(con)) != NULL) {
-  if (xbee_hasdigital(pkt,0,0)) {
-    printf("D0 read %d,xbee_getdigital(pkt,0));
-  } else {
-    printf("No D0 data);
-  }
-  free(pkt);
-}
-
- - -  -

AUTHOR

- -Attie Grande <attie@attie.co.uk> -  -

SEE ALSO

- -libxbee(3), - -xbee_pkt(3), - -xbee_getpacket(3), - -xbee_hasanalog(3), - -xbee_getanalog(3) - -

- -


- 

Index

-
-
NAME
-
SYNOPSIS
-
DESCRIPTION
-
RETURN VALUE
-
EXAMPLE
-
AUTHOR
-
SEE ALSO
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_getpacket.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_getpacket.3.html deleted file mode 100644 index 45063f77369f1abf8072bb1d7e39dfcda77574d4..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_getpacket.3.html +++ /dev/null @@ -1,130 +0,0 @@ -Manpage of XBEE_GETPACKET - -

XBEE_GETPACKET

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -xbee_getpacket -  -

SYNOPSIS

- -#include <xbee.h> - -

-xbee_pkt *xbee_getpacket(xbee_con *con); - -

-xbee_pkt *xbee_getpacketwait(xbee_con *con); - - -  -

DESCRIPTION

- -The -xbee_getpacket() - -function will return the next avaliable packet for the provided connection. -It takes 1 argument. -

-The argument -con - -points to a connection made previously with -xbee_newcon(). - -

-The -xbee_getpacketwait() - -function behaves the same, but will wait for an internally specified time for a packet to arrive (currently around 1 second). -  -

RETURN VALUE

- -Upon successful return, this function returns the packet, having unlinked it from the internal list of packets. -You must keep hold of the packet until you are finished with it, and then you must -free() - -it to prevent memory leaks. -

-If a packet was not avaliable for the provided connection, a -NULL - -is returned. -

-If an error occured a -NULL - -is also returned (though unlikely). -

-For more information on the structure of the packet, please see -xbee_pkt(3) - -

-For information on using callback functions with connections instead, please see -xbee_con(3) - -  -

EXAMPLE

- -To recieve a packet from a previously made connection: - -
-#include <xbee.h>
-xbee_pkt *pkt;
-if ((pkt = xbee_getpacket(con)) != NULL) {
-  /* process packet... */
-  free(pkt);
-}
-
- - -  -

AUTHOR

- -Attie Grande <attie@attie.co.uk> -  -

SEE ALSO

- -libxbee(3), - -xbee_setup(3), - -xbee_newcon(3), - -xbee_senddata(3), - -xbee_pkt(3), - -xbee_con(3), - -xbee_hasDigital(3), - -xbee_getDigital(3), - -xbee_hasAnalog(3), - -xbee_getAnalog(3) - -

- -


- 

Index

-
-
NAME
-
SYNOPSIS
-
DESCRIPTION
-
RETURN VALUE
-
EXAMPLE
-
AUTHOR
-
SEE ALSO
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_hasanalog.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_hasanalog.3.html deleted file mode 100644 index e2c495c41a0ee5bd289201f4d5cfced40434af68..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_hasanalog.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_hasanalog.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_hasdigital.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_hasdigital.3.html deleted file mode 100644 index 9774f408171e5530962325df7512425f27aff02c..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_hasdigital.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_hasdigital.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_logit.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_logit.3.html deleted file mode 100644 index 7eaa6c27017f7865a490d9b428ed84d979714c5a..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_logit.3.html +++ /dev/null @@ -1,27 +0,0 @@ -Manpage of LIBXBEE - -

LIBXBEE

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -libxbee -

-This page has not been written yet... -

-

- -


- 

Index

-
-
NAME
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_newcon.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_newcon.3.html deleted file mode 100644 index 32f085b2685782320a34654812647c3898b51a46..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_newcon.3.html +++ /dev/null @@ -1,201 +0,0 @@ -Manpage of XBEE_NEWCON - -

XBEE_NEWCON

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -xbee_newcon -  -

SYNOPSIS

- -#include <xbee.h> - -

-xbee_con *xbee_newcon(unsigned char frameID, xbee_types type, ...); - -

-void xbee_flushcon(xbee_con *con); - -

-void xbee_endcon(xbee_con *con); - - -  -

DESCRIPTION

- -The -xbee_newcon() - -function will setup a new connection with the specified settings. -It takes at least 2 arguments, and possibly up to 4 depending on the -type. - -

-NOTE: - -Packets will only be collected when they match an active connection. -You must setup a connection in order to recieve packets. -

-The argument -frameID - -allows similar functionality to that of TCP/IP port numbers. This is 1 character (or 8-bit integer) that -identifies where the data is coming from or going to. - -The -type - -specifies the type of connection you would like. The following types are avaliable: -

-
xbee_localAT - -
-communicates AT commands with the local XBee -
xbee_txStatus - -
-recieves transmit status information from the local XBee -
xbee_modemStatus - -
-recieves modem status information from the local XBee -
xbee_16bitRemoteAT - -
-communicates AT commands with a remote node (using 16-bit addressing) -
xbee_64bitRemoteAT - -
-communicates AT commands with a remote node (using 64-bit addressing) -
xbee_16bitData - -
-sends/recieves data through a remote node (using 16-bit addressing) -
xbee_64bitData - -
-sends/recieves data through a remote node (using 64-bit addressing) -
xbee_16bitIO - -
-sends/recieves I/O data through a remote node (using 16-bit addressing) -
xbee_64bitIO - -
-sends/recieves I/O data through a remote node (using 64-bit addressing) -
-

- -If you are using -xbee_localAT, xbee_txStatus or xbee_modemStatus - -then only the -frameID - -and -type - -arguments are required. -

-If you are using any 16-bit connection, you must also specify 1 right aligned integer, -containing the 16-bit address (e.g. 0x1234). -

-If you are using any 64-bit connection, you must also specify 2 integers containing the -64-bit address, first the high 32-bits, then the low 32-bits. -

-The -xbee_flushcon() - -function is very basic. It removes any packets that have been collected in the buffer for the specified connection. -

-The -xbee_endcon() - -function is used to end a connection. This will stop collecting packets for the given connection, and remove any packets from the buffer. -  -

RETURN VALUE

- -A pointer to the connection is returned. A connection can only be made once, using the same -type - -, -frameID - -and address (if needed). The second call using the same parameters will return the same -connection. -

-For information on using callback functions for packet handling please see -xbee_con(3) - -  -

EXAMPLE

- -To create a local AT connection: - -
-#include <xbee.h>
-xbee_con *con;
-con = xbee_newcon('A', xbee_localAT);
-
- - -

-To create a 16-bit Data connection: - -

-#include <xbee.h>
-xbee_con *con;
-con = xbee_newcon('A', xbee_16bitData, 0x1234);
-
- - -

-To create a 64-bit Data connection: - -

-#include <xbee.h>
-xbee_con *con;
-con = xbee_newcon('A', xbee_64bitData, 0x0013A200, 0x40081826);
-
- - -  -

AUTHOR

- -Attie Grande <attie@attie.co.uk> -  -

SEE ALSO

- -libxbee(3), - -xbee_setup(3), - -xbee_getpacket(3), - -xbee_con(3), - -xbee_senddata(3) - -

- -


- 

Index

-
-
NAME
-
SYNOPSIS
-
DESCRIPTION
-
RETURN VALUE
-
EXAMPLE
-
AUTHOR
-
SEE ALSO
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_nsenddata.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_nsenddata.3.html deleted file mode 100644 index 3da3c6f217e80896fd86b61a576a2a7285721c2e..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_nsenddata.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_nsenddata.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_pkt.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_pkt.3.html deleted file mode 100644 index 1859405aa7a94fb1384c2d2ba38b0ca6c4fb89df..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_pkt.3.html +++ /dev/null @@ -1,107 +0,0 @@ -Manpage of XBEE_PKT - -

XBEE_PKT

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -xbee_pkt -  -

SYNOPSIS

- -#include <xbee.h> - - -  -

DESCRIPTION

- -This is the packet structure. If you want to get more advanced information from connections (such as RSSI) then this is where it lives. -

- -

-struct xbee_pkt {
-  unsigned char frameID;          /* AT        Status    */
-  unsigned char atCmd[2];         /* AT                  */
-  unsigned char status;           /* AT  Data  Status    */ /* status / options */
-  unsigned char Addr64[8];        /* AT  Data            */
-  unsigned char Addr16[2];        /* AT  Data            */
-  unsigned char data[128];        /* AT  Data            */
-  unsigned char RSSI;             /*     Data            */
-  unsigned int datalen;
-
-  /* X  A5 A4 A3 A2 A1 A0 D8    D7 D6 D5 D4 D3 D2 D1 D0 */
-  unsigned short IOmask;          /*                  IO */
-
-  /* X  X  X  X  X  X  X  D8    D7 D6 D5 D4 D3 D2 D1 D0 */
-  unsigned short IOdata;          /*                  IO */
-
-  /* X  X  X  X  X  D  D  D     D  D  D  D  D  D  D  D  */
-  unsigned short IOanalog[6];     /*                  IO */
-};
-typedef struct xbee_pkt xbee_pkt;
-
- - -

-Most of these fields are fairly self explanatory, however some need attention brought to them -and others need explaining. I will touch on the most important here: -

-
atCmd - -
-This is the 2 character identifier for the AT command response you just recieved. -Of course if you didnt setup an AT connection, you should never see, or try to see data here. -
Addr64 and Addr16 - -
-These contain the address of the XBee that you recieved the packet from. You should really know this -because you setup the connection. However remote AT packets will contain both 16 and 64 bit -addresses. -
data - -
-This is the data you just recieved. Either the AT reponse, or the data from the remote XBee node. -
datalen - -
-Would you be suprised if I told you this is how much data there is?... Dont try and -printf() - -the -data - -as it isn't null terminated. Use this for processing instead. - - -
-  -

AUTHOR

- -Attie Grande <attie@attie.co.uk> -  -

SEE ALSO

- -libxbee(3), - -xbee_getpacket(3) - -

- -


- 

Index

-
-
NAME
-
SYNOPSIS
-
DESCRIPTION
-
AUTHOR
-
SEE ALSO
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_senddata.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_senddata.3.html deleted file mode 100644 index 31baf1c73b44dcb38a0471d1cb3fb5495a53b321..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_senddata.3.html +++ /dev/null @@ -1,129 +0,0 @@ -Manpage of XBEE_SENDDATA - -

XBEE_SENDDATA

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -xbee_senddata, xbee_vsenddata -  -

SYNOPSIS

- -#include <xbee.h> - -

-int xbee_senddata(xbee_con *con, char *format, ...); - -

-int xbee_nsenddata(xbee_con *con, char *data, int length); - -

-#include <stdarg.h> - -

-int xbee_vsenddata(xbee_con *con, char *format, va_list ap); - - -  -

DESCRIPTION

- -The -xbee_senddata() - -function will send data via a provided connection. -It takes at least 2 arguments, and possibly more depending on the format string. -

-The argument -con - -points to a connection made previously with -xbee_newcon(). - -

-The -format - -string and any following parameters are passed to -sprintf() - -within these functions. -Please see the -printf(3) - -man page for more information. -

-If you are using -xbee_nsenddata() - -you must provide a character array of the data, and the data's length. -

-If you are using -xbee_vsenddata() - -you must provide a va_list. See -stdarg(3). - -  -

RETURN VALUE

- -Upon successful completion, these functions return 0. -

-If an invalid packet or connection was provided, -1 is returned. -

-If an unknown error occured, -2 is returned. -

-If -con - -has -waitforACK - -enabled, then these functions return 1 when an ACK was not recieved within 1 second. -  -

EXAMPLE

- -To send the string "Hello World!" through a previously made connection: - -
-#include <xbee.h>
-xbee_senddata(con,"Hello World!");
-
- - -  -

AUTHOR

- -Attie Grande <attie@attie.co.uk> -  -

SEE ALSO

- -libxbee(3), - -xbee_setup(3), - -xbee_newcon(3), - -xbee_getpacket(3) - -

- -


- 

Index

-
-
NAME
-
SYNOPSIS
-
DESCRIPTION
-
RETURN VALUE
-
EXAMPLE
-
AUTHOR
-
SEE ALSO
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_setup.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_setup.3.html deleted file mode 100644 index 5b69945a51c1bff7c75d9d21909791f5f934c41e..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_setup.3.html +++ /dev/null @@ -1,142 +0,0 @@ -Manpage of XBEE_SETUP - -

XBEE_SETUP

-Section: Linux Programmer's Manual (3)
Updated: 2009-11-01
Index -Return to Main Contents
- -  -

NAME

- -xbee_setup -  -

SYNOPSIS

- -#include <xbee.h> - -

-int xbee_setup(char *path, int baudrate); - -

-int xbee_setuplog(char *path, int baudrate, int logfd); - -

-int xbee_setupAPI(char *path, char cmdSeq, int cmdTime); - -

-int xbee_setuplogAPI(char *path, int baudrate, int logfd, char cmdSeq, int cmdTime); - - -  -

DESCRIPTION

- -

-A VERSION OF THIS FUNCTION MUST BE CALLED BEFORE ANY OTHER libxbee FUNCTION! - -The -xbee_setup() - -function will setup libxbee so that it can handle an XBee. -It takes 2 arguments. -

-The argument -path - -is the path to the serial port that the XBee is connected to (e.g. /dev/ttyUSB0). -

-The -baudrate - -is the baud rate that the local XBee is configured to run at. The following are avaliable: - -

-1200
-2400
-4800
-9600
-19200
-38400
-57600
-115200 - this is potentially unstable (read the XBee manual to find out why...)
-
- - -

-Using -xbee_setuplog() - -is exactly the same, but instead you give an open file descriptor. All log messages will be written to this file (you can use stderr or stdout if you want!). -

-Using -xbee_setupAPI() - -is exactly the same, but instead you provide the 'Command Sequence' character and the 'Guard Time' that your local XBee has been configured with. -libxbee will then place your XBee in API mode 2, and when you call xbee_end() it will return your XBee to its previous API mode. -

-Using -xbee_setuplogAPI() - -is simply a combination of -xbee_setuplog() - -and -xbee_setupAPI() - -  -

RETURN VALUE

- -If any error occures, --1 - -is returned. Otherwise -0 - -is returned. -  -

EXAMPLE

- -To setup libxbee to use /dev/ttyUSB0 at 57600 baud: - -
-#include <xbee.h>
-if (xbee_setup("/dev/ttyUSB0",57600) == -1) {
-  printf("Oh no...);
-  exit(1);
-}
-
- - -  -

AUTHOR

- -Attie Grande <attie@attie.co.uk> -  -

SEE ALSO

- -libxbee(3), - -xbee_newcon(3), - -xbee_getpacket(3), - -xbee_senddata(3) - -

- -


- 

Index

-
-
NAME
-
SYNOPSIS
-
DESCRIPTION
-
RETURN VALUE
-
EXAMPLE
-
AUTHOR
-
SEE ALSO
-
-
-This document was created by -man2html, -using the manual pages.
-Time: 00:08:23 GMT, March 30, 2011 - - diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_setupAPI.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_setupAPI.3.html deleted file mode 100644 index 158f1857c92583be548fb5d24e1ea8b856284f74..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_setupAPI.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_setupAPI.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_setuplog.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_setuplog.3.html deleted file mode 100644 index 16accc571339096d89bb449e201a3f56a72e7dc0..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_setuplog.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_setuplog.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_setuplogAPI.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_setuplogAPI.3.html deleted file mode 100644 index 801cbfaf90d574643d8ed624b7c0838e340df80c..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_setuplogAPI.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_setuplogAPI.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/doc/man/man3/xbee_vsenddata.3.html b/libs/thirdParty/libxbee/doc/man/man3/xbee_vsenddata.3.html deleted file mode 100644 index 5a9b7d948c5ed228bbc005c20bb87dab963cea2f..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/doc/man/man3/xbee_vsenddata.3.html +++ /dev/null @@ -1,4 +0,0 @@ -Invalid Manpage - -

Invalid Manpage

-The requested file ./man/man3/xbee_vsenddata.3 is not a valid (unformatted) man page. diff --git a/libs/thirdParty/libxbee/lib/libxbee.dll b/libs/thirdParty/libxbee/lib/libxbee.dll deleted file mode 100644 index cf1af098e6c3a5fb130ab8d248fe873fe594db94..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/lib/libxbee.dll and /dev/null differ diff --git a/libs/thirdParty/libxbee/lib/libxbee.exp b/libs/thirdParty/libxbee/lib/libxbee.exp deleted file mode 100644 index 1ab830676fc609ead5c1aaab15a204bc98345123..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/lib/libxbee.exp and /dev/null differ diff --git a/libs/thirdParty/libxbee/lib/libxbee.lib b/libs/thirdParty/libxbee/lib/libxbee.lib deleted file mode 100644 index 7b42cadbaede1530f4c126e5c81306195d19784e..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/lib/libxbee.lib and /dev/null differ diff --git a/libs/thirdParty/libxbee/lib/libxbee.map b/libs/thirdParty/libxbee/lib/libxbee.map deleted file mode 100644 index 6adaef145b7bdce3eef1a1b1ea8c52935cd4ec32..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/lib/libxbee.map +++ /dev/null @@ -1,897 +0,0 @@ - libxbee - - Timestamp is 4e2eb2df (Tue Jul 26 14:28:15 2011) - - Preferred load address is 10000000 - - Start Length Name Class - 0001:00000000 00019a38H .text CODE - 0002:00000000 00000188H .idata$5 DATA - 0002:00000188 00000004H .CRT$XCA DATA - 0002:0000018c 00000004H .CRT$XCZ DATA - 0002:00000190 00000004H .CRT$XIA DATA - 0002:00000194 00000010H .CRT$XIC DATA - 0002:000001a4 00000004H .CRT$XIZ DATA - 0002:000001a8 00000004H .CRT$XPA DATA - 0002:000001ac 00000004H .CRT$XPX DATA - 0002:000001b0 00000004H .CRT$XPXA DATA - 0002:000001b4 00000004H .CRT$XPZ DATA - 0002:000001b8 00000004H .CRT$XTA DATA - 0002:000001bc 00000004H .CRT$XTZ DATA - 0002:000001c0 000022c0H .rdata DATA - 0002:00002480 0000000cH .rdata$sxdata DATA - 0002:0000248c 00000004H .rtc$IAA DATA - 0002:00002490 00000000H .rtc$IMZ DATA - 0002:00002490 00000004H .rtc$IZZ DATA - 0002:00002494 00000004H .rtc$TAA DATA - 0002:00002498 00000000H .rtc$TMZ DATA - 0002:00002498 00000004H .rtc$TZZ DATA - 0002:000024a0 0000049cH .xdata$x DATA - 0002:0000293c 0000003cH .idata$2 DATA - 0002:00002978 00000014H .idata$3 DATA - 0002:0000298c 00000188H .idata$4 DATA - 0002:00002b14 000006baH .idata$6 DATA - 0002:000031d0 000005a5H .edata DATA - 0003:00000000 000052f0H .data DATA - 0003:00005300 00001f44H .bss DATA - 0004:00000000 00000058H .rsrc$01 DATA - 0004:00000060 00000400H .rsrc$02 DATA - - Address Publics by Value Rva+Base Lib:Object - - 0000:00000000 __except_list 00000000 - 0000:00000003 ___safe_se_handler_count 00000003 - 0000:00000000 ___ImageBase 10000000 - 0001:00000000 _ver@16 10001000 f api.obj - 0001:000000b0 _xbee_UNLOADALL@0 100010b0 f api.obj - 0001:000000e0 _DllMain@12 100010e0 f api.obj - 0001:00000120 _DllCanUnloadNow@0 10001120 f api.obj - 0001:00000140 _RegWriteKey@24 10001140 f api.obj - 0001:00000210 _DllRegisterServer@0 10001210 f api.obj - 0001:000004b0 _DllUnregisterServer@0 100014b0 f api.obj - 0001:00000670 _xbee_write@12 10001670 f api.obj - 0001:00000720 _xbee_read@12 10001720 f api.obj - 0001:000007d0 _xbee_free@4 100017d0 f api.obj - 0001:00000800 _gettimeofday@8 10001800 f api.obj - 0001:000008a0 _xbee_setupDebugAPI@20 100018a0 f api.obj - 0001:000009b0 _xbee_setupDebug@12 100019b0 f api.obj - 0001:000009e0 _xbee_newcon_simple@8 100019e0 f api.obj - 0001:00000a00 _xbee_newcon_16bit@12 10001a00 f api.obj - 0001:00000a30 _xbee_newcon_64bit@16 10001a30 f api.obj - 0001:00000a60 _xbee_enableACKwait@4 10001a60 f api.obj - 0001:00000a80 _xbee_disableACKwait@4 10001a80 f api.obj - 0001:00000aa0 _xbee_enableDestroySelf@4 10001aa0 f api.obj - 0001:00000ac0 _xbee_callback@8 10001ac0 f api.obj - 0001:00000c70 _xbee_runCallback@12 10001c70 f api.obj - 0001:00000ca0 _xbee_enableCallbacks@8 10001ca0 f api.obj - 0001:00000df0 _xbee_attachCallback@4 10001df0 f api.obj - 0001:00000ea0 _xbee_detachCallback@4 10001ea0 f api.obj - 0001:00000f50 _xbee_svn_version@0 10001f50 f api.obj - 0001:00000fc0 _xbee_build_info@0 10001fc0 f api.obj - 0001:00000fd0 _xbee_hasdigital@12 10001fd0 f api.obj - 0001:00001030 _xbee_getdigital@12 10002030 f api.obj - 0001:00001090 _xbee_hasanalog@12 10002090 f api.obj - 0001:000010f0 _xbee_getanalog@20 100020f0 f api.obj - 0001:00001270 _xbee_logitf 10002270 f api.obj - 0001:00001320 __xbee_logitf 10002320 f api.obj - 0001:000013d0 _xbee_logit@4 100023d0 f api.obj - 0001:000013f0 __xbee_logit@8 100023f0 f api.obj - 0001:00001470 _xbee_end@0 10002470 f api.obj - 0001:00001490 __xbee_end@4 10002490 f api.obj - 0001:00001a30 _xbee_setup@8 10002a30 f api.obj - 0001:00001a60 __xbee_setup@8 10002a60 f api.obj - 0001:00001a90 _xbee_setuplog@12 10002a90 f api.obj - 0001:00001ac0 __xbee_setuplog@12 10002ac0 f api.obj - 0001:00001af0 _xbee_setupAPI@16 10002af0 f api.obj - 0001:00001b20 __xbee_setupAPI@16 10002b20 f api.obj - 0001:00001b50 _xbee_setuplogAPI@20 10002b50 f api.obj - 0001:00001ba0 __xbee_setuplogAPI@20 10002ba0 f api.obj - 0001:00003820 _xbee_newcon 10004820 f api.obj - 0001:00003870 __xbee_newcon 10004870 f api.obj - 0001:000038c0 __xbee_vnewcon@16 100048c0 f api.obj - 0001:000043f0 _xbee_purgecon@4 100053f0 f api.obj - 0001:00004410 __xbee_purgecon@8 10005410 f api.obj - 0001:00004590 _xbee_endcon2@8 10005590 f api.obj - 0001:000045c0 __xbee_endcon2@12 100055c0 f api.obj - 0001:00004880 _xbee_senddata 10005880 f api.obj - 0001:000048d0 __xbee_senddata 100058d0 f api.obj - 0001:00004920 _xbee_vsenddata@12 10005920 f api.obj - 0001:00004950 __xbee_vsenddata@16 10005950 f api.obj - 0001:00004a00 _xbee_nsenddata@12 10005a00 f api.obj - 0001:00004a30 __xbee_nsenddata@16 10005a30 f api.obj - 0001:000053a0 _xbee_getpacketwait@4 100063a0 f api.obj - 0001:000053c0 __xbee_getpacketwait@8 100063c0 f api.obj - 0001:00005440 _xbee_getpacket@4 10006440 f api.obj - 0001:00005460 __xbee_getpacket@8 10006460 f api.obj - 0001:00005ab0 _xbee_listen_stop@4 10006ab0 f api.obj - 0001:0000a47f _sprintf 1000b47f f LIBCMT:sprintf.obj - 0001:0000a503 @__security_check_cookie@4 1000b503 f LIBCMT:secchk.obj - 0001:0000a512 __RTC_CheckEsp 1000b512 f LIBCMT:_stack_.obj - 0001:0000a535 @_RTC_CheckStackVars@8 1000b535 f LIBCMT:_stack_.obj - 0001:0000a591 _free 1000b591 f LIBCMT:free.obj - 0001:0000a5cb __ftime64_s 1000b5cb f LIBCMT:ftime64.obj - 0001:0000a73b __ftime64 1000b73b f LIBCMT:ftime64.obj - 0001:0000a746 __get_errno_from_oserr 1000b746 f LIBCMT:dosmap.obj - 0001:0000a788 __errno 1000b788 f LIBCMT:dosmap.obj - 0001:0000a79b ___doserrno 1000b79b f LIBCMT:dosmap.obj - 0001:0000a7ae __dosmaperr 1000b7ae f LIBCMT:dosmap.obj - 0001:0000af05 __open 1000bf05 f LIBCMT:open.obj - 0001:0000afc0 _strrchr 1000bfc0 f LIBCMT:strrchr.obj - 0001:0000aff0 __cfltcvt_init 1000bff0 f LIBCMT:_fpinit_.obj - 0001:0000b050 __fpmath 1000c050 f LIBCMT:_fpinit_.obj - 0001:0000b069 _fprintf 1000c069 f LIBCMT:fprintf.obj - 0001:0000b175 __flush 1000c175 f LIBCMT:fflush.obj - 0001:0000b1dd __fflush_nolock 1000c1dd f LIBCMT:fflush.obj - 0001:0000b2ff _fflush 1000c2ff f LIBCMT:fflush.obj - 0001:0000b352 __flushall 1000c352 f LIBCMT:fflush.obj - 0001:0000b35b __fclose_nolock 1000c35b f LIBCMT:fclose.obj - 0001:0000b3c8 _fclose 1000c3c8 f LIBCMT:fclose.obj - 0001:0000b43c ___iob_func 1000c43c f LIBCMT:_file.obj - 0001:0000b442 ___initstdio 1000c442 f LIBCMT:_file.obj - 0001:0000b4f3 ___endstdio 1000c4f3 f LIBCMT:_file.obj - 0001:0000b513 __lock_file 1000c513 f LIBCMT:_file.obj - 0001:0000b554 __lock_file2 1000c554 f LIBCMT:_file.obj - 0001:0000b586 __unlock_file 1000c586 f LIBCMT:_file.obj - 0001:0000b5c2 __unlock_file2 1000c5c2 f LIBCMT:_file.obj - 0001:0000b600 _strcpy 1000c600 f LIBCMT:strcat.obj - 0001:0000b610 _strcat 1000c610 f LIBCMT:strcat.obj - 0001:0000b700 _strlen 1000c700 f LIBCMT:strlen.obj - 0001:0000b78b _setvbuf 1000c78b f LIBCMT:setvbuf.obj - 0001:0000b881 __get_sys_err_msg 1000c881 f i LIBCMT:perror.obj - 0001:0000b8a9 _perror 1000c8a9 f LIBCMT:perror.obj - 0001:0000b937 _strerror 1000c937 f LIBCMT:strerror.obj - 0001:0000b9a1 ___crtCorExitProcess 1000c9a1 f LIBCMT:crt0dat.obj - 0001:0000b9cc ___crtExitProcess 1000c9cc f LIBCMT:crt0dat.obj - 0001:0000b9e4 __lockexit 1000c9e4 f LIBCMT:crt0dat.obj - 0001:0000b9ed __unlockexit 1000c9ed f LIBCMT:crt0dat.obj - 0001:0000b9f6 __init_pointers 1000c9f6 f LIBCMT:crt0dat.obj - 0001:0000ba29 __initterm_e 1000ca29 f LIBCMT:crt0dat.obj - 0001:0000ba4d __cinit 1000ca4d f LIBCMT:crt0dat.obj - 0001:0000bc24 _exit 1000cc24 f LIBCMT:crt0dat.obj - 0001:0000bc3a __exit 1000cc3a f LIBCMT:crt0dat.obj - 0001:0000bc50 __cexit 1000cc50 f LIBCMT:crt0dat.obj - 0001:0000bc5f __amsg_exit 1000cc5f f LIBCMT:crt0dat.obj - 0001:0000bc7d _malloc 1000cc7d f LIBCMT:malloc.obj - 0001:0000bd11 _calloc 1000cd11 f LIBCMT:calloc.obj - 0001:0000bd51 _atol 1000cd51 f LIBCMT:atox.obj - 0001:0000bd67 _atoi 1000cd67 f LIBCMT:atox.obj - 0001:0000bd72 _strncmp 1000cd72 f LIBCMT:strncmp.obj - 0001:0000be40 _memset 1000ce40 f LIBCMT:memset.obj - 0001:0000bec0 _memcpy 1000cec0 f LIBCMT:memcpy.obj - 0001:0000c221 _memcmp 1000d221 f LIBCMT:memcmp.obj - 0001:0000d775 _realloc 1000e775 f LIBCMT:realloc.obj - 0001:0000d822 __CRT_INIT@12 1000e822 f LIBCMT:dllcrt0.obj - 0001:0000da7c __DllMainCRTStartup@12 1000ea7c f LIBCMT:dllcrt0.obj - 0001:0000da9f __flsbuf 1000ea9f f LIBCMT:_flsbuf.obj - 0001:0000dc03 ??0_LocaleUpdate@@QAE@PAUlocaleinfo_struct@@@Z 1000ec03 f i LIBCMT:output.obj - 0001:0000dd0a __output_l 1000ed0a f LIBCMT:output.obj - 0001:0000e8b6 __initp_misc_invarg 1000f8b6 f LIBCMT:invarg.obj - 0001:0000e8c5 __call_reportfault 1000f8c5 f LIBCMT:invarg.obj - 0001:0000e9ee __invoke_watson 1000f9ee f LIBCMT:invarg.obj - 0001:0000ea13 __invalid_parameter 1000fa13 f LIBCMT:invarg.obj - 0001:0000ea40 __invalid_parameter_noinfo 1000fa40 f LIBCMT:invarg.obj - 0001:0000ea50 ___report_gsfailure 1000fa50 f LIBCMT:gs_report.obj - 0001:0000ee0e ?_RTC_Failure@@YAXPAXH@Z 1000fe0e f LIBCMT:_error_.obj - 0001:0000ee49 ?_RTC_StackFailure@@YAXPAXPBD@Z 1000fe49 f LIBCMT:_error_.obj - 0001:0000ef3c ?_RTC_GetErrorFunc@@YAP6AHHPBDH00ZZPBX@Z 1000ff3c f LIBCMT:_userapi_.obj - 0001:0000ef42 ?_RTC_GetErrorFuncW@@YAP6AHHPB_WH00ZZPBX@Z 1000ff42 f LIBCMT:_userapi_.obj - 0001:0000ef48 __heap_init 1000ff48 f LIBCMT:heapinit.obj - 0001:0000ef66 __heap_term 1000ff66 f LIBCMT:heapinit.obj - 0001:0000ef7a __get_daylight 1000ff7a f LIBCMT:timeset.obj - 0001:0000efa7 __get_dstbias 1000ffa7 f LIBCMT:timeset.obj - 0001:0000efd4 __get_timezone 1000ffd4 f LIBCMT:timeset.obj - 0001:0000f001 ___daylight 10010001 f LIBCMT:timeset.obj - 0001:0000f007 ___dstbias 10010007 f LIBCMT:timeset.obj - 0001:0000f00d ___timezone 1001000d f LIBCMT:timeset.obj - 0001:0000f013 ___tzname 10010013 f LIBCMT:timeset.obj - 0001:0000f32c ___tzset 1001032c f LIBCMT:tzset.obj - 0001:0000f380 __aullrem 10010380 f LIBCMT:ullrem.obj - 0001:0000f400 __aulldiv 10010400 f LIBCMT:ulldiv.obj - 0001:0000f468 __encoded_null 10010468 f LIBCMT:tidtable.obj - 0001:0000f471 ___crtTlsAlloc@4 10010471 f LIBCMT:tidtable.obj - 0001:0000f47a ___set_flsgetvalue 1001047a f LIBCMT:tidtable.obj - 0001:0000f4ae __mtterm 100104ae f LIBCMT:tidtable.obj - 0001:0000f4eb __initptd 100104eb f LIBCMT:tidtable.obj - 0001:0000f59f __getptd_noexit 1001059f f LIBCMT:tidtable.obj - 0001:0000f618 __getptd 10010618 f LIBCMT:tidtable.obj - 0001:0000f632 __freefls@4 10010632 f LIBCMT:tidtable.obj - 0001:0000f761 __freeptd 10010761 f LIBCMT:tidtable.obj - 0001:0000f7cf __mtinit 100107cf f LIBCMT:tidtable.obj - 0001:0000f94a __set_osfhnd 1001094a f LIBCMT:osfinfo.obj - 0001:0000f9cb __free_osfhnd 100109cb f LIBCMT:osfinfo.obj - 0001:0000fa51 __get_osfhandle 10010a51 f LIBCMT:osfinfo.obj - 0001:0000faba ___lock_fhandle 10010aba f LIBCMT:osfinfo.obj - 0001:0000fb59 __unlock_fhandle 10010b59 f LIBCMT:osfinfo.obj - 0001:0000fb80 __alloc_osfhnd 10010b80 f LIBCMT:osfinfo.obj - 0001:0000fd19 __write_nolock 10010d19 f LIBCMT:write.obj - 0001:00010416 __write 10011416 f LIBCMT:write.obj - 0001:000104ea __lseeki64_nolock 100114ea f LIBCMT:lseeki64.obj - 0001:0001056f __lseeki64 1001156f f LIBCMT:lseeki64.obj - 0001:00010659 __chsize_nolock 10011659 f LIBCMT:chsize.obj - 0001:0001080f __read_nolock 1001180f f LIBCMT:read.obj - 0001:00010dc6 __close_nolock 10011dc6 f LIBCMT:close.obj - 0001:00010e62 __close 10011e62 f LIBCMT:close.obj - 0001:00010f26 __lseek_nolock 10011f26 f LIBCMT:lseek.obj - 0001:00010f9b __ioinit 10011f9b f LIBCMT:ioinit.obj - 0001:000111e0 __ioterm 100121e0 f LIBCMT:ioinit.obj - 0001:00011233 __setmode_nolock 10012233 f LIBCMT:setmode.obj - 0001:000112ee __get_fmode 100122ee f LIBCMT:setmode.obj - 0001:00011320 __SEH_prolog4 10012320 f LIBCMT:sehprolg4.obj - 0001:00011365 __SEH_epilog4 10012365 f LIBCMT:sehprolg4.obj - 0001:00011380 __except_handler4 10012380 f LIBCMT:chandler4.obj - 0001:0001150f __forcdecpt_l 1001250f f LIBCMT:cvt.obj - 0001:00011583 __cropzeros_l 10012583 f LIBCMT:cvt.obj - 0001:00011605 __positive 10012605 f LIBCMT:cvt.obj - 0001:00011621 __fassign_l 10012621 f LIBCMT:cvt.obj - 0001:00011663 __fassign 10012663 f LIBCMT:cvt.obj - 0001:0001169c __forcdecpt 1001269c f LIBCMT:cvt.obj - 0001:000116af __cropzeros 100126af f LIBCMT:cvt.obj - 0001:00011823 __cftoe_l 10012823 f LIBCMT:cvt.obj - 0001:000118ea __cftoe 100128ea f LIBCMT:cvt.obj - 0001:0001190a __cftoa_l 1001290a f LIBCMT:cvt.obj - 0001:00011d83 __cftof_l 10012d83 f LIBCMT:cvt.obj - 0001:00011e44 __cftog_l 10012e44 f LIBCMT:cvt.obj - 0001:00011f31 __cfltcvt_l 10012f31 f LIBCMT:cvt.obj - 0001:00011fb9 __cfltcvt 10012fb9 f LIBCMT:cvt.obj - 0001:00011fdc __initp_misc_cfltcvt_tab 10012fdc f LIBCMT:cmiscdat.obj - 0001:00011fff __setdefaultprecision 10012fff f LIBCMT:fp8.obj - 0001:00012027 __stbuf 10013027 f LIBCMT:_sftbuf.obj - 0001:000120c3 __ftbuf 100130c3 f LIBCMT:_sftbuf.obj - 0001:000120f7 __fileno 100130f7 f LIBCMT:fileno.obj - 0001:0001211d __vsnprintf_l 1001311d f LIBCMT:vsnprint.obj - 0001:000121c9 __vsnprintf 100131c9 f LIBCMT:vsnprint.obj - 0001:000121c9 _vsnprintf 100131c9 f LIBCMT:vsnprint.obj - 0001:000121e6 __commit 100131e6 f LIBCMT:commit.obj - 0001:000122bf __mtinitlocks 100132bf f LIBCMT:mlock.obj - 0001:00012309 __mtdeletelocks 10013309 f LIBCMT:mlock.obj - 0001:00012360 __unlock 10013360 f LIBCMT:mlock.obj - 0001:00012377 __mtinitlocknum 10013377 f LIBCMT:mlock.obj - 0001:00012439 __lock 10013439 f LIBCMT:mlock.obj - 0001:0001246c __freebuf 1001346c f LIBCMT:_freebuf.obj - 0001:0001249d __malloc_crt 1001349d f LIBCMT:crtheap.obj - 0001:000124e2 __calloc_crt 100134e2 f LIBCMT:crtheap.obj - 0001:0001252e __realloc_crt 1001352e f LIBCMT:crtheap.obj - 0001:0001257c __recalloc_crt 1001357c f LIBCMT:crtheap.obj - 0001:000125ce __fcloseall 100135ce f LIBCMT:closeall.obj - 0001:0001266a ___sys_nerr 1001366a f LIBCMT:syserr.obj - 0001:00012670 ___sys_errlist 10013670 f LIBCMT:syserr.obj - 0001:00012676 _strcpy_s 10013676 f LIBCMT:strcpy_s.obj - 0001:000126d5 _strncpy_s 100136d5 f LIBCMT:strncpy_s.obj - 0001:0001278a ?terminate@@YAXXZ 1001378a f LIBCMT:hooks.obj - 0001:000127c3 __initp_eh_hooks 100137c3 f LIBCMT:hooks.obj - 0001:000127d4 __initp_misc_winsig 100137d4 f LIBCMT:winsig.obj - 0001:00012829 ___get_sigabrt 10013829 f LIBCMT:winsig.obj - 0001:00012836 _raise 10013836 f LIBCMT:winsig.obj - 0001:000129d9 __initp_misc_rand_s 100139d9 f LIBCMT:rand_s.obj - 0001:000129e8 __initp_misc_purevirt 100139e8 f LIBCMT:inithelp.obj - 0001:000129f7 __initp_heap_handler 100139f7 f LIBCMT:handler.obj - 0001:00012a06 __callnewh 10013a06 f LIBCMT:handler.obj - 0001:00012ae4 ___onexitinit 10013ae4 f LIBCMT:onexit.obj - 0001:00012b15 __onexit 10013b15 f LIBCMT:onexit.obj - 0001:00012b51 _atexit 10013b51 f LIBCMT:onexit.obj - 0001:00012b68 __RTC_Initialize 10013b68 f LIBCMT:_initsect_.obj - 0001:00012b8e __RTC_Terminate 10013b8e f LIBCMT:_initsect_.obj - 0001:00012bc0 __ValidateImageBase 10013bc0 f LIBCMT:pesect.obj - 0001:00012c00 __FindPESection 10013c00 f LIBCMT:pesect.obj - 0001:00012c50 __IsNonwritableInCurrentImage 10013c50 f LIBCMT:pesect.obj - 0001:00012d0c __GET_RTERRMSG 10013d0c f LIBCMT:crt0msg.obj - 0001:00012d32 __NMSG_WRITE 10013d32 f LIBCMT:crt0msg.obj - 0001:00012ee1 __FF_MSGBANNER 10013ee1 f LIBCMT:crt0msg.obj - 0001:00012f1a __calloc_impl 10013f1a f LIBCMT:calloc_impl.obj - 0001:000131c7 _strtol 100141c7 f LIBCMT:strtol.obj - 0001:000131f2 __VEC_memzero 100141f2 f LIBCMT:p4_memset.obj - 0001:000132ac ___sse2_available_init 100142ac f LIBCMT:cpu_disp.obj - 0001:000132bc __VEC_memcpy 100142bc f LIBCMT:p4_memcpy.obj - 0001:000133bf __setenvp 100143bf f LIBCMT:stdenvp.obj - 0001:00013635 __setargv 10014635 f LIBCMT:stdargv.obj - 0001:000136f0 ___crtGetEnvironmentStringsA 100146f0 f LIBCMT:a_env.obj - 0001:00013787 __XcptFilter 10014787 f LIBCMT:winxfltr.obj - 0001:000138d1 ___CppXcptFilter 100148d1 f LIBCMT:winxfltr.obj - 0001:000138f1 ___security_init_cookie 100148f1 f LIBCMT:gs_support.obj - 0001:0001398c __getbuf 1001498c f LIBCMT:_getbuf.obj - 0001:000139d5 __isatty 100149d5 f LIBCMT:isatty.obj - 0001:00013c4e ___updatetmbcinfo 10014c4e f LIBCMT:mbctype.obj - 0001:00013d6e __setmbcp_nolock 10014d6e f LIBCMT:mbctype.obj - 0001:00013f57 __setmbcp 10014f57 f LIBCMT:mbctype.obj - 0001:000140f1 ___initmbctable 100150f1 f LIBCMT:mbctype.obj - 0001:0001410f ___addlocaleref 1001510f f LIBCMT:localref.obj - 0001:0001419e ___removelocaleref 1001519e f LIBCMT:localref.obj - 0001:00014237 ___freetlocinfo 10015237 f LIBCMT:localref.obj - 0001:00014382 __updatetlocinfoEx_nolock 10015382 f LIBCMT:localref.obj - 0001:000143cf ___updatetlocinfo 100153cf f LIBCMT:localref.obj - 0001:00014448 __get_printf_count_output 10015448 f LIBCMT:printf.obj - 0001:0001445e __wctomb_s_l 1001545e f LIBCMT:wctomb.obj - 0001:000145b3 _wctomb_s 100155b3 f LIBCMT:wctomb.obj - 0001:000145d0 __isleadbyte_l 100155d0 f i LIBCMT:_wctype.obj - 0001:00014608 _isleadbyte 10015608 f i LIBCMT:_wctype.obj - 0001:00014620 __aulldvrm 10015620 f LIBCMT:ulldvrm.obj - 0001:000146b5 __crt_debugger_hook 100156b5 f LIBCMT:dbghook.obj - 0001:00014849 ?_RTC_GetSrcLine@@YAHPAEPA_WKPAH1K@Z 10015849 f LIBCMT:_pdblkup_.obj - 0001:00014ad0 _strcmp 10015ad0 f LIBCMT:strcmp.obj - 0001:00014b58 __getenv_helper_nolock 10015b58 f LIBCMT:getenv.obj - 0001:00014bdf ____lc_codepage_func 10015bdf f LIBCMT:initctyp.obj - 0001:00014c05 __putwch_nolock 10015c05 f LIBCMT:putwch.obj - 0001:00014c47 __mbtowc_l 10015c47 f LIBCMT:mbtowc.obj - 0001:00014d5d _mbtowc 10015d5d f LIBCMT:mbtowc.obj - 0001:00014d80 __chkstk 10015d80 f LIBCMT:chkstk.obj - 0001:00014d80 __alloca_probe 10015d80 LIBCMT:chkstk.obj - 0001:00014db0 __local_unwind4 10015db0 f LIBCMT:exsup4.obj - 0001:00014e86 __seh_longjmp_unwind4@4 10015e86 f LIBCMT:exsup4.obj - 0001:00014ea2 @_EH4_CallFilterFunc@8 10015ea2 f LIBCMT:exsup4.obj - 0001:00014eb9 @_EH4_TransferToHandler@8 10015eb9 f LIBCMT:exsup4.obj - 0001:00014ed2 @_EH4_GlobalUnwind2@8 10015ed2 f LIBCMT:exsup4.obj - 0001:00014eeb @_EH4_LocalUnwind@16 10015eeb f LIBCMT:exsup4.obj - 0001:00014f02 __isdigit_l 10015f02 f i LIBCMT:_ctype.obj - 0001:00014f53 _isdigit 10015f53 f i LIBCMT:_ctype.obj - 0001:00014f81 __tolower_l 10015f81 f LIBCMT:tolower.obj - 0001:00015096 _tolower 10016096 f LIBCMT:tolower.obj - 0001:000150c2 __atodbl_l 100160c2 f LIBCMT:atodbl.obj - 0001:0001516a __atoflt_l 1001616a f LIBCMT:atodbl.obj - 0001:00015220 _memmove 10016220 f LIBCMT:memmove.obj - 0001:00015581 __fptostr 10016581 f LIBCMT:_fptostr.obj - 0001:00015634 ___dtold 10016634 f LIBCMT:_cfout_.obj - 0001:000156e7 __fltout2 100166e7 f LIBCMT:_cfout_.obj - 0001:00015780 __alldvrm 10016780 f LIBCMT:lldvrm.obj - 0001:00015860 __aullshr 10016860 f LIBCMT:ullshr.obj - 0001:0001587f __fptrap 1001687f f LIBCMT:crt0fp.obj - 0001:00015888 __controlfp_s 10016888 f LIBCMT:_contrlfp_.obj - 0001:000158e7 __recalloc 100168e7 f LIBCMT:recalloc.obj - 0001:00015955 _abort 10016955 f LIBCMT:abort.obj - 0001:00015988 __freea 10016988 f i LIBCMT:a_loc.obj - 0001:000159a8 __msize 100169a8 f LIBCMT:msize.obj - 0001:000159db ___crtMessageBoxW 100169db f LIBCMT:crtmboxw.obj - 0001:00015b47 _wcscat_s 10016b47 f LIBCMT:wcscat_s.obj - 0001:00015bbc _wcsncpy_s 10016bbc f LIBCMT:wcsncpy_s.obj - 0001:00015c89 _wcslen 10016c89 f LIBCMT:wcslen.obj - 0001:00015ca4 _wcscpy_s 10016ca4 f LIBCMT:wcscpy_s.obj - 0001:00015d07 __set_error_mode 10016d07 f LIBCMT:errmode.obj - 0001:00015d46 __isctype_l 10016d46 f LIBCMT:isctype.obj - 0001:00015e00 __allmul 10016e00 f LIBCMT:llmul.obj - 0001:00015e87 __ismbblead 10016e87 f LIBCMT:ismbbyte.obj - 0001:00016086 ___crtLCMapStringA 10017086 f LIBCMT:a_map.obj - 0001:000161b3 ___crtGetStringTypeA 100171b3 f LIBCMT:a_str.obj - 0001:000161f3 ___free_lc_time 100171f3 f LIBCMT:inittime.obj - 0001:0001656a ___free_lconv_num 1001756a f LIBCMT:initnum.obj - 0001:000165d3 ___free_lconv_mon 100175d3 f LIBCMT:initmon.obj - 0001:000166d1 __mbsnbicoll_l 100176d1 f LIBCMT:mbsnbico.obj - 0001:000167af __mbsnbicoll 100177af f LIBCMT:mbsnbico.obj - 0001:000167c9 ___wtomb_environ 100177c9 f LIBCMT:wtombenv.obj - 0001:00016860 ___initconout 10017860 f LIBCMT:initcon.obj - 0001:0001687f ___termconout 1001787f f LIBCMT:initcon.obj - 0001:000168a0 __global_unwind2 100178a0 f LIBCMT:exsup.obj - 0001:00016905 __local_unwind2 10017905 f LIBCMT:exsup.obj - 0001:00016989 __abnormal_termination 10017989 f LIBCMT:exsup.obj - 0001:000169ac __NLG_Notify1 100179ac f LIBCMT:exsup.obj - 0001:000169b5 __NLG_Notify 100179b5 f LIBCMT:exsup.obj - 0001:000169cc __NLG_Dispatch 100179cc LIBCMT:exsup.obj - 0001:000169cc __NLG_Dispatch2 100179cc LIBCMT:exsup.obj - 0001:000169d4 __NLG_Call 100179d4 f LIBCMT:exsup.obj - 0001:000169d6 __NLG_Return2 100179d6 LIBCMT:exsup.obj - 0001:000169d7 __ld12tod 100179d7 f LIBCMT:_intrncvt_.obj - 0001:00016f28 __ld12tof 10017f28 f LIBCMT:_intrncvt_.obj - 0001:00017479 ___strgtold12_l 10018479 f LIBCMT:_strgtold_.obj - 0001:00017b55 _$I10_OUTPUT 10018b55 f LIBCMT:_x10fout_.obj - 0001:0001857b __control87 1001957b f i LIBCMT:_ieee87_.obj - 0001:00018890 __alloca_probe_16 10019890 f LIBCMT:alloca16.obj - 0001:000188a6 __alloca_probe_8 100198a6 LIBCMT:alloca16.obj - 0001:000188c0 _strcspn 100198c0 f LIBCMT:strcspn.obj - 0001:00018910 _strpbrk 10019910 f LIBCMT:strpbrk.obj - 0001:00018bbe ___crtCompareStringA 10019bbe f LIBCMT:a_cmp.obj - 0001:00018c00 __strnicoll_l 10019c00 f LIBCMT:strnicol.obj - 0001:00018d9c ___crtsetenv 10019d9c f LIBCMT:setenv.obj - 0001:00018fde ___mtold12 10019fde f LIBCMT:_mantold_.obj - 0001:000191c2 ___set_fpsr_sse2 1001a1c2 f LIBCMT:_fpctrl_.obj - 0001:00019234 __strnicmp_l 1001a234 f LIBCMT:strnicmp.obj - 0001:00019316 __strdup 1001a316 f LIBCMT:strdup.obj - 0001:00019368 __mbschr_l 1001a368 f LIBCMT:mbschr.obj - 0001:00019418 __mbschr 1001a418 f LIBCMT:mbschr.obj - 0001:00019430 ___ascii_strnicmp 1001a430 f LIBCMT:_strnicm.obj - 0001:000194b0 _strchr 1001a4b0 f LIBCMT:strchr.obj - 0001:000194b6 ___from_strstr_to_strchr 1001a4b6 LIBCMT:strchr.obj - 0001:0001956e _RtlUnwind@16 1001a56e f kernel32:KERNEL32.dll - 0001:00019574 __fdopen 1001a574 f LIBCMT:fdopen.obj - 0001:00019574 _fdopen 1001a574 f LIBCMT:fdopen.obj - 0001:00019835 _dup 1001a835 f LIBCMT:dup.obj - 0001:00019835 __dup 1001a835 f LIBCMT:dup.obj - 0001:00019905 __getstream 1001a905 f LIBCMT:stream.obj - 0002:00000000 __imp__RegSetValueExA@24 1001b000 Advapi32:ADVAPI32.dll - 0002:00000004 __imp__RegCreateKeyA@12 1001b004 Advapi32:ADVAPI32.dll - 0002:00000008 __imp__RegDeleteKeyA@8 1001b008 Advapi32:ADVAPI32.dll - 0002:0000000c __imp__RegCloseKey@4 1001b00c Advapi32:ADVAPI32.dll - 0002:00000010 \177ADVAPI32_NULL_THUNK_DATA 1001b010 Advapi32:ADVAPI32.dll - 0002:00000014 __imp__SetEnvironmentVariableA@8 1001b014 kernel32:KERNEL32.dll - 0002:00000018 __imp__CompareStringW@24 1001b018 kernel32:KERNEL32.dll - 0002:0000001c __imp__lstrcpyA@8 1001b01c kernel32:KERNEL32.dll - 0002:00000020 __imp__GetModuleFileNameA@12 1001b020 kernel32:KERNEL32.dll - 0002:00000024 __imp__lstrlenA@4 1001b024 kernel32:KERNEL32.dll - 0002:00000028 __imp__GetOverlappedResult@16 1001b028 kernel32:KERNEL32.dll - 0002:0000002c __imp__GetLastError@0 1001b02c kernel32:KERNEL32.dll - 0002:00000030 __imp__WriteFile@20 1001b030 kernel32:KERNEL32.dll - 0002:00000034 __imp__ReadFile@20 1001b034 kernel32:KERNEL32.dll - 0002:00000038 __imp__SetEvent@4 1001b038 kernel32:KERNEL32.dll - 0002:0000003c __imp__WaitForSingleObject@8 1001b03c kernel32:KERNEL32.dll - 0002:00000040 __imp__TerminateThread@8 1001b040 kernel32:KERNEL32.dll - 0002:00000044 __imp__CloseHandle@4 1001b044 kernel32:KERNEL32.dll - 0002:00000048 __imp__Sleep@4 1001b048 kernel32:KERNEL32.dll - 0002:0000004c __imp__CreateThread@24 1001b04c kernel32:KERNEL32.dll - 0002:00000050 __imp__CreateEventA@16 1001b050 kernel32:KERNEL32.dll - 0002:00000054 __imp__SetCommMask@8 1001b054 kernel32:KERNEL32.dll - 0002:00000058 __imp__SetCommTimeouts@8 1001b058 kernel32:KERNEL32.dll - 0002:0000005c __imp__SetCommState@8 1001b05c kernel32:KERNEL32.dll - 0002:00000060 __imp__GetCommState@8 1001b060 kernel32:KERNEL32.dll - 0002:00000064 __imp__CreateFileA@28 1001b064 kernel32:KERNEL32.dll - 0002:00000068 __imp__WaitCommEvent@12 1001b068 kernel32:KERNEL32.dll - 0002:0000006c __imp__ClearCommError@12 1001b06c kernel32:KERNEL32.dll - 0002:00000070 __imp__HeapFree@12 1001b070 kernel32:KERNEL32.dll - 0002:00000074 __imp__GetTimeZoneInformation@4 1001b074 kernel32:KERNEL32.dll - 0002:00000078 __imp__GetSystemTimeAsFileTime@4 1001b078 kernel32:KERNEL32.dll - 0002:0000007c __imp__GetFileType@4 1001b07c kernel32:KERNEL32.dll - 0002:00000080 __imp__EnterCriticalSection@4 1001b080 kernel32:KERNEL32.dll - 0002:00000084 __imp__LeaveCriticalSection@4 1001b084 kernel32:KERNEL32.dll - 0002:00000088 __imp__GetProcAddress@8 1001b088 kernel32:KERNEL32.dll - 0002:0000008c __imp__GetModuleHandleW@4 1001b08c kernel32:KERNEL32.dll - 0002:00000090 __imp__ExitProcess@4 1001b090 kernel32:KERNEL32.dll - 0002:00000094 __imp__DecodePointer@4 1001b094 kernel32:KERNEL32.dll - 0002:00000098 __imp__HeapAlloc@12 1001b098 kernel32:KERNEL32.dll - 0002:0000009c __imp__HeapReAlloc@16 1001b09c kernel32:KERNEL32.dll - 0002:000000a0 __imp__GetCurrentThreadId@0 1001b0a0 kernel32:KERNEL32.dll - 0002:000000a4 __imp__GetCommandLineA@0 1001b0a4 kernel32:KERNEL32.dll - 0002:000000a8 __imp__UnhandledExceptionFilter@4 1001b0a8 kernel32:KERNEL32.dll - 0002:000000ac __imp__SetUnhandledExceptionFilter@4 1001b0ac kernel32:KERNEL32.dll - 0002:000000b0 __imp__IsDebuggerPresent@0 1001b0b0 kernel32:KERNEL32.dll - 0002:000000b4 __imp__EncodePointer@4 1001b0b4 kernel32:KERNEL32.dll - 0002:000000b8 __imp__TerminateProcess@8 1001b0b8 kernel32:KERNEL32.dll - 0002:000000bc __imp__GetCurrentProcess@0 1001b0bc kernel32:KERNEL32.dll - 0002:000000c0 __imp__RaiseException@16 1001b0c0 kernel32:KERNEL32.dll - 0002:000000c4 __imp__WideCharToMultiByte@32 1001b0c4 kernel32:KERNEL32.dll - 0002:000000c8 __imp__MultiByteToWideChar@24 1001b0c8 kernel32:KERNEL32.dll - 0002:000000cc __imp__LoadLibraryW@4 1001b0cc kernel32:KERNEL32.dll - 0002:000000d0 __imp__HeapCreate@12 1001b0d0 kernel32:KERNEL32.dll - 0002:000000d4 __imp__HeapDestroy@4 1001b0d4 kernel32:KERNEL32.dll - 0002:000000d8 __imp__TlsAlloc@0 1001b0d8 kernel32:KERNEL32.dll - 0002:000000dc __imp__TlsGetValue@4 1001b0dc kernel32:KERNEL32.dll - 0002:000000e0 __imp__TlsSetValue@8 1001b0e0 kernel32:KERNEL32.dll - 0002:000000e4 __imp__TlsFree@4 1001b0e4 kernel32:KERNEL32.dll - 0002:000000e8 __imp__InterlockedIncrement@4 1001b0e8 kernel32:KERNEL32.dll - 0002:000000ec __imp__SetLastError@4 1001b0ec kernel32:KERNEL32.dll - 0002:000000f0 __imp__InterlockedDecrement@4 1001b0f0 kernel32:KERNEL32.dll - 0002:000000f4 __imp__SetStdHandle@8 1001b0f4 kernel32:KERNEL32.dll - 0002:000000f8 __imp__InitializeCriticalSectionAndSpinCount@8 1001b0f8 kernel32:KERNEL32.dll - 0002:000000fc __imp__GetConsoleCP@0 1001b0fc kernel32:KERNEL32.dll - 0002:00000100 __imp__GetConsoleMode@8 1001b100 kernel32:KERNEL32.dll - 0002:00000104 __imp__SetFilePointer@16 1001b104 kernel32:KERNEL32.dll - 0002:00000108 __imp__SetEndOfFile@4 1001b108 kernel32:KERNEL32.dll - 0002:0000010c __imp__GetProcessHeap@0 1001b10c kernel32:KERNEL32.dll - 0002:00000110 __imp__SetHandleCount@4 1001b110 kernel32:KERNEL32.dll - 0002:00000114 __imp__GetStdHandle@4 1001b114 kernel32:KERNEL32.dll - 0002:00000118 __imp__GetStartupInfoW@4 1001b118 kernel32:KERNEL32.dll - 0002:0000011c __imp__DeleteCriticalSection@4 1001b11c kernel32:KERNEL32.dll - 0002:00000120 __imp__FlushFileBuffers@4 1001b120 kernel32:KERNEL32.dll - 0002:00000124 __imp__FreeLibrary@4 1001b124 kernel32:KERNEL32.dll - 0002:00000128 __imp__GetModuleFileNameW@12 1001b128 kernel32:KERNEL32.dll - 0002:0000012c __imp__IsProcessorFeaturePresent@4 1001b12c kernel32:KERNEL32.dll - 0002:00000130 __imp__FreeEnvironmentStringsW@4 1001b130 kernel32:KERNEL32.dll - 0002:00000134 __imp__GetEnvironmentStringsW@0 1001b134 kernel32:KERNEL32.dll - 0002:00000138 __imp__QueryPerformanceCounter@4 1001b138 kernel32:KERNEL32.dll - 0002:0000013c __imp__GetTickCount@0 1001b13c kernel32:KERNEL32.dll - 0002:00000140 __imp__GetCurrentProcessId@0 1001b140 kernel32:KERNEL32.dll - 0002:00000144 __imp__GetCPInfo@8 1001b144 kernel32:KERNEL32.dll - 0002:00000148 __imp__GetACP@0 1001b148 kernel32:KERNEL32.dll - 0002:0000014c __imp__GetOEMCP@0 1001b14c kernel32:KERNEL32.dll - 0002:00000150 __imp__IsValidCodePage@4 1001b150 kernel32:KERNEL32.dll - 0002:00000154 __imp__VirtualQuery@12 1001b154 kernel32:KERNEL32.dll - 0002:00000158 __imp__WriteConsoleW@20 1001b158 kernel32:KERNEL32.dll - 0002:0000015c __imp__RtlUnwind@16 1001b15c kernel32:KERNEL32.dll - 0002:00000160 __imp__HeapSize@12 1001b160 kernel32:KERNEL32.dll - 0002:00000164 __imp__LCMapStringW@24 1001b164 kernel32:KERNEL32.dll - 0002:00000168 __imp__GetStringTypeW@16 1001b168 kernel32:KERNEL32.dll - 0002:0000016c __imp__CreateFileW@28 1001b16c kernel32:KERNEL32.dll - 0002:00000170 __imp__DuplicateHandle@28 1001b170 kernel32:KERNEL32.dll - 0002:00000174 \177KERNEL32_NULL_THUNK_DATA 1001b174 kernel32:KERNEL32.dll - 0002:00000178 __imp__wsprintfA 1001b178 User32:USER32.dll - 0002:0000017c __imp__MessageBoxA@16 1001b17c User32:USER32.dll - 0002:00000180 __imp__SendMessageA@16 1001b180 User32:USER32.dll - 0002:00000184 \177USER32_NULL_THUNK_DATA 1001b184 User32:USER32.dll - 0002:00000188 ___xc_a 1001b188 LIBCMT:crt0init.obj - 0002:0000018c ___xc_z 1001b18c LIBCMT:crt0init.obj - 0002:00000190 ___xi_a 1001b190 LIBCMT:crt0init.obj - 0002:000001a4 ___xi_z 1001b1a4 LIBCMT:crt0init.obj - 0002:000001a8 ___xp_a 1001b1a8 LIBCMT:crt0init.obj - 0002:000001b4 ___xp_z 1001b1b4 LIBCMT:crt0init.obj - 0002:000001b8 ___xt_a 1001b1b8 LIBCMT:crt0init.obj - 0002:000001bc ___xt_z 1001b1bc LIBCMT:crt0init.obj - 0002:000001c0 __real@408ff80000000000 1001b1c0 api.obj - 0002:000001c8 __real@3f6a6d01a6d01a6d 1001b1c8 api.obj - 0002:000001d0 __FPinit 1001b1d0 LIBCMT:_fpinit_.obj - 0002:000001d4 ??_C@_01EEMJAFIK@?6?$AA@ 1001b1d4 LIBCMT:perror.obj - 0002:000001d8 ??_C@_02LMMGGCAJ@?3?5?$AA@ 1001b1d8 LIBCMT:perror.obj - 0002:000001e0 ??_C@_0EA@FCLIIPNN@Visual?5C?$CL?$CL?5CRT?3?5Not?5enough?5memor@ 1001b1e0 LIBCMT:strerror.obj - 0002:00000220 ??_C@_0P@MIGLKIOC@CorExitProcess?$AA@ 1001b220 LIBCMT:crt0dat.obj - 0002:00000230 ??_C@_1BI@BGOHAHKC@?$AAm?$AAs?$AAc?$AAo?$AAr?$AAe?$AAe?$AA?4?$AAd?$AAl?$AAl?$AA?$AA@ 1001b230 LIBCMT:crt0dat.obj - 0002:00000248 __pRawDllMain 1001b248 LIBCMT:dllcrt0.obj - 0002:00000248 __pDefaultRawDllMain 1001b248 LIBCMT:dllcrt0.obj - 0002:0000024c ??_C@_1O@CEDCILHN@?$AA?$CI?$AAn?$AAu?$AAl?$AAl?$AA?$CJ?$AA?$AA@ 1001b24c LIBCMT:output.obj - 0002:0000025c ??_C@_06OJHGLDPL@?$CInull?$CJ?$AA@ 1001b25c LIBCMT:output.obj - 0002:00000268 ___lookuptable 1001b268 LIBCMT:output.obj - 0002:000002cc ??_C@_0BO@GNIAFIKK@Unknown?5Runtime?5Check?5Error?6?$AN?$AA@ 1001b2cc LIBCMT:_error_.obj - 0002:000002ec ??_C@_0CM@NGINOKPC@Stack?5memory?5around?5_alloca?5was?5@ 1001b2ec LIBCMT:_error_.obj - 0002:00000318 ??_C@_0DG@HKJMLLLP@A?5local?5variable?5was?5used?5before@ 1001b318 LIBCMT:_error_.obj - 0002:00000350 ??_C@_0BN@FFOINMNJ@Stack?5memory?5was?5corrupted?6?$AN?$AA@ 1001b350 LIBCMT:_error_.obj - 0002:00000370 ??_C@_0BBN@GPMLNJCF@A?5cast?5to?5a?5smaller?5data?5type?5ha@ 1001b370 LIBCMT:_error_.obj - 0002:00000490 ??_C@_0NN@NGPKDKPD@The?5value?5of?5ESP?5was?5not?5properl@ 1001b490 LIBCMT:_error_.obj - 0002:0000060c ??_C@_0CA@IODNCDPG@Run?9Time?5Check?5Failure?5?$CD?$CFd?5?9?5?$CFs?$AA@ 1001b60c LIBCMT:_error_.obj - 0002:0000062c ??_C@_0BE@GNBOBNCK@Unknown?5Module?5Name?$AA@ 1001b62c LIBCMT:_error_.obj - 0002:00000640 ??_C@_0BB@PFFGGCJP@Unknown?5Filename?$AA@ 1001b640 LIBCMT:_error_.obj - 0002:00000658 ??_C@_1EA@NFKNIFJP@?$AAR?$AAu?$AAn?$AA?9?$AAT?$AAi?$AAm?$AAe?$AA?5?$AAC?$AAh?$AAe?$AAc?$AAk?$AA?5?$AAF?$AAa?$AAi?$AAl?$AAu?$AAr?$AAe?$AA?5?$AA?$CD?$AA?$CF?$AAd?$AA?5?$AA?9?$AA?5?$AA?$CF?$AAs?$AA?$AA@ 1001b658 LIBCMT:_error_.obj - 0002:00000698 ??_C@_1GM@OLMCBDMB@?$AAR?$AAu?$AAn?$AAt?$AAi?$AAm?$AAe?$AA?5?$AAC?$AAh?$AAe?$AAc?$AAk?$AA?5?$AAE?$AAr?$AAr?$AAo?$AAr?$AA?4?$AA?6?$AA?$AN?$AA?5?$AAU?$AAn?$AAa?$AAb?$AAl?$AAe?$AA?5?$AAt?$AAo@ 1001b698 LIBCMT:_error_.obj - 0002:00000704 ??_C@_0CG@IAFNJNEE@Stack?5corrupted?5near?5unknown?5var@ 1001b704 LIBCMT:_error_.obj - 0002:0000072c ??_C@_0BP@OGBCLIBO@Stack?5around?5_alloca?5corrupted?$AA@ 1001b72c LIBCMT:_userapi_.obj - 0002:0000074c ??_C@_0CK@CNLNOEPB@Local?5variable?5used?5before?5initi@ 1001b74c LIBCMT:_userapi_.obj - 0002:00000778 ??_C@_0BI@CIGMDCBH@Stack?5memory?5corruption?$AA@ 1001b778 LIBCMT:_userapi_.obj - 0002:00000790 ??_C@_0CK@FEGOIOPB@Cast?5to?5smaller?5type?5causing?5los@ 1001b790 LIBCMT:_userapi_.obj - 0002:000007bc ??_C@_0BJ@HEGAHDFO@Stack?5pointer?5corruption?$AA@ 1001b7bc LIBCMT:_userapi_.obj - 0002:000007ec ___dnames 1001b7ec LIBCMT:timeset.obj - 0002:00000804 ___mnames 1001b804 LIBCMT:timeset.obj - 0002:0000082c ??_C@_02CLFPBFFP@TZ?$AA@ 1001b82c LIBCMT:tzset.obj - 0002:00000830 ??_C@_1BK@DBDEIDLH@?$AAK?$AAE?$AAR?$AAN?$AAE?$AAL?$AA3?$AA2?$AA?4?$AAD?$AAL?$AAL?$AA?$AA@ 1001b830 LIBCMT:tidtable.obj - 0002:0000084c ??_C@_07PEJMOBNF@FlsFree?$AA@ 1001b84c LIBCMT:tidtable.obj - 0002:00000854 ??_C@_0M@JCPCPOEF@FlsSetValue?$AA@ 1001b854 LIBCMT:tidtable.obj - 0002:00000860 ??_C@_0M@GDNOONDI@FlsGetValue?$AA@ 1001b860 LIBCMT:tidtable.obj - 0002:0000086c ??_C@_08KNHFBNJ@FlsAlloc?$AA@ 1001b86c LIBCMT:tidtable.obj - 0002:00000878 ??_C@_05KLBDPFGC@e?$CL000?$AA@ 1001b878 LIBCMT:cvt.obj - 0002:00000880 ??_C@_0BG@KLEAJEFJ@Illegal?5byte?5sequence?$AA@ 1001b880 LIBCMT:syserr.obj - 0002:00000898 ??_C@_0BE@ICMCHPHH@Directory?5not?5empty?$AA@ 1001b898 LIBCMT:syserr.obj - 0002:000008ac ??_C@_0BJ@IHEHINLI@Function?5not?5implemented?$AA@ 1001b8ac LIBCMT:syserr.obj - 0002:000008c8 ??_C@_0BD@CLHBCGPB@No?5locks?5available?$AA@ 1001b8c8 LIBCMT:syserr.obj - 0002:000008dc ??_C@_0BC@BEDIHIDK@Filename?5too?5long?$AA@ 1001b8dc LIBCMT:syserr.obj - 0002:000008f0 ??_C@_0BK@JAEBMJJM@Resource?5deadlock?5avoided?$AA@ 1001b8f0 LIBCMT:syserr.obj - 0002:0000090c ??_C@_0BB@FCBJFCAJ@Result?5too?5large?$AA@ 1001b90c LIBCMT:syserr.obj - 0002:00000920 ??_C@_0N@MMJPGLJK@Domain?5error?$AA@ 1001b920 LIBCMT:syserr.obj - 0002:00000930 ??_C@_0M@LHEPIIOM@Broken?5pipe?$AA@ 1001b930 LIBCMT:syserr.obj - 0002:0000093c ??_C@_0P@PKCJJLLM@Too?5many?5links?$AA@ 1001b93c LIBCMT:syserr.obj - 0002:0000094c ??_C@_0BG@DDBFNKBH@Read?9only?5file?5system?$AA@ 1001b94c LIBCMT:syserr.obj - 0002:00000964 ??_C@_0N@FEHLOILP@Invalid?5seek?$AA@ 1001b964 LIBCMT:syserr.obj - 0002:00000974 ??_C@_0BI@FEALHKLD@No?5space?5left?5on?5device?$AA@ 1001b974 LIBCMT:syserr.obj - 0002:0000098c ??_C@_0P@LFMMIPAE@File?5too?5large?$AA@ 1001b98c LIBCMT:syserr.obj - 0002:0000099c ??_C@_0CE@ONOKNLPF@Inappropriate?5I?1O?5control?5operat@ 1001b99c LIBCMT:syserr.obj - 0002:000009c0 ??_C@_0BE@INBJMKGG@Too?5many?5open?5files?$AA@ 1001b9c0 LIBCMT:syserr.obj - 0002:000009d4 ??_C@_0BO@IIFBODJE@Too?5many?5open?5files?5in?5system?$AA@ 1001b9d4 LIBCMT:syserr.obj - 0002:000009f4 ??_C@_0BB@HMGGCEBG@Invalid?5argument?$AA@ 1001b9f4 LIBCMT:syserr.obj - 0002:00000a08 ??_C@_0P@NDHGCGKE@Is?5a?5directory?$AA@ 1001ba08 LIBCMT:syserr.obj - 0002:00000a18 ??_C@_0BA@CJBACOOL@Not?5a?5directory?$AA@ 1001ba18 LIBCMT:syserr.obj - 0002:00000a28 ??_C@_0P@NLEIANHE@No?5such?5device?$AA@ 1001ba28 LIBCMT:syserr.obj - 0002:00000a38 ??_C@_0O@OAMDNOCP@Improper?5link?$AA@ 1001ba38 LIBCMT:syserr.obj - 0002:00000a48 ??_C@_0M@NAAJNNGH@File?5exists?$AA@ 1001ba48 LIBCMT:syserr.obj - 0002:00000a54 ??_C@_0BA@BIBLIOEK@Resource?5device?$AA@ 1001ba54 LIBCMT:syserr.obj - 0002:00000a64 ??_C@_0O@NIPGCINC@Unknown?5error?$AA@ 1001ba64 LIBCMT:syserr.obj - 0002:00000a74 ??_C@_0M@LOEHLCJD@Bad?5address?$AA@ 1001ba74 LIBCMT:syserr.obj - 0002:00000a80 ??_C@_0BC@HFNFNKAI@Permission?5denied?$AA@ 1001ba80 LIBCMT:syserr.obj - 0002:00000a94 ??_C@_0BB@IMDKMPFB@Not?5enough?5space?$AA@ 1001ba94 LIBCMT:syserr.obj - 0002:00000aa8 ??_C@_0CB@EPFKGNAK@Resource?5temporarily?5unavailable@ 1001baa8 LIBCMT:syserr.obj - 0002:00000acc ??_C@_0BD@LOHELEP@No?5child?5processes?$AA@ 1001bacc LIBCMT:syserr.obj - 0002:00000ae0 ??_C@_0BE@NFGDDCEF@Bad?5file?5descriptor?$AA@ 1001bae0 LIBCMT:syserr.obj - 0002:00000af4 ??_C@_0BC@HKPNECK@Exec?5format?5error?$AA@ 1001baf4 LIBCMT:syserr.obj - 0002:00000b08 ??_C@_0BC@MFFGCDFL@Arg?5list?5too?5long?$AA@ 1001bb08 LIBCMT:syserr.obj - 0002:00000b1c ??_C@_0BK@DPKMCKJ@No?5such?5device?5or?5address?$AA@ 1001bb1c LIBCMT:syserr.obj - 0002:00000b38 ??_C@_0BD@KKNFOBBD@Input?1output?5error?$AA@ 1001bb38 LIBCMT:syserr.obj - 0002:00000b4c ??_C@_0BK@FJBOAFDK@Interrupted?5function?5call?$AA@ 1001bb4c LIBCMT:syserr.obj - 0002:00000b68 ??_C@_0BA@FKIAIBGA@No?5such?5process?$AA@ 1001bb68 LIBCMT:syserr.obj - 0002:00000b78 ??_C@_0BK@FMDHKPNF@No?5such?5file?5or?5directory?$AA@ 1001bb78 LIBCMT:syserr.obj - 0002:00000b94 ??_C@_0BI@BJFCGOHL@Operation?5not?5permitted?$AA@ 1001bb94 LIBCMT:syserr.obj - 0002:00000bac ??_C@_08INEPGKHH@No?5error?$AA@ 1001bbac LIBCMT:syserr.obj - 0002:00000bb8 ??_C@_1BK@GAEMIDIL@?$AAA?$AAD?$AAV?$AAA?$AAP?$AAI?$AA3?$AA2?$AA?4?$AAD?$AAL?$AAL?$AA?$AA@ 1001bbb8 LIBCMT:rand_s.obj - 0002:00000bd4 ??_C@_1BO@BKOMIGKJ@?$AAr?$AAu?$AAn?$AAt?$AAi?$AAm?$AAe?$AA?5?$AAe?$AAr?$AAr?$AAo?$AAr?$AA?5?$AA?$AA@ 1001bbd4 LIBCMT:crt0msg.obj - 0002:00000bf4 ??_C@_15JNBOKNOG@?$AA?$AN?$AA?6?$AA?$AA@ 1001bbf4 LIBCMT:crt0msg.obj - 0002:00000bfc ??_C@_1BM@JBBEPPHI@?$AAT?$AAL?$AAO?$AAS?$AAS?$AA?5?$AAe?$AAr?$AAr?$AAo?$AAr?$AA?$AN?$AA?6?$AA?$AA@ 1001bbfc LIBCMT:crt0msg.obj - 0002:00000c18 ??_C@_1BK@KMOMNAAI@?$AAS?$AAI?$AAN?$AAG?$AA?5?$AAe?$AAr?$AAr?$AAo?$AAr?$AA?$AN?$AA?6?$AA?$AA@ 1001bc18 LIBCMT:crt0msg.obj - 0002:00000c34 ??_C@_1BO@BFCDCGC@?$AAD?$AAO?$AAM?$AAA?$AAI?$AAN?$AA?5?$AAe?$AAr?$AAr?$AAo?$AAr?$AA?$AN?$AA?6?$AA?$AA@ 1001bc34 LIBCMT:crt0msg.obj - 0002:00000c58 ??_C@_1BOO@KGEDBGAJ@?$AAR?$AA6?$AA0?$AA3?$AA3?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAA?$AAt?$AAt?$AAe?$AAm?$AAp?$AAt?$AA?5?$AAt?$AAo?$AA?5?$AAu?$AAs?$AAe?$AA?5?$AAM?$AAS?$AAI?$AAL?$AA?5?$AAc?$AAo?$AAd@ 1001bc58 LIBCMT:crt0msg.obj - 0002:00000e48 ??_C@_1GG@GOPILAJP@?$AAR?$AA6?$AA0?$AA3?$AA2?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAn?$AAo?$AAt?$AA?5?$AAe?$AAn?$AAo?$AAu?$AAg?$AAh?$AA?5?$AAs?$AAp?$AAa?$AAc?$AAe?$AA?5?$AAf?$AAo?$AAr?$AA?5?$AAl?$AAo@ 1001be48 LIBCMT:crt0msg.obj - 0002:00000eb0 ??_C@_1MG@ENCOOIDF@?$AAR?$AA6?$AA0?$AA3?$AA1?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAA?$AAt?$AAt?$AAe?$AAm?$AAp?$AAt?$AA?5?$AAt?$AAo?$AA?5?$AAi?$AAn?$AAi?$AAt?$AAi?$AAa?$AAl?$AAi?$AAz?$AAe?$AA?5?$AAt@ 1001beb0 LIBCMT:crt0msg.obj - 0002:00000f78 ??_C@_1DO@BMFCDCD@?$AAR?$AA6?$AA0?$AA3?$AA0?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAC?$AAR?$AAT?$AA?5?$AAn?$AAo?$AAt?$AA?5?$AAi?$AAn?$AAi?$AAt?$AAi?$AAa?$AAl?$AAi?$AAz?$AAe?$AAd?$AA?$AN?$AA?6?$AA?$AA@ 1001bf78 LIBCMT:crt0msg.obj - 0002:00000fb8 ??_C@_1EK@HHFLMAOL@?$AAR?$AA6?$AA0?$AA2?$AA8?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAu?$AAn?$AAa?$AAb?$AAl?$AAe?$AA?5?$AAt?$AAo?$AA?5?$AAi?$AAn?$AAi?$AAt?$AAi?$AAa?$AAl?$AAi?$AAz?$AAe?$AA?5?$AAh?$AAe@ 1001bfb8 LIBCMT:crt0msg.obj - 0002:00001008 ??_C@_1GK@MFGOKLAG@?$AAR?$AA6?$AA0?$AA2?$AA7?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAn?$AAo?$AAt?$AA?5?$AAe?$AAn?$AAo?$AAu?$AAg?$AAh?$AA?5?$AAs?$AAp?$AAa?$AAc?$AAe?$AA?5?$AAf?$AAo?$AAr?$AA?5?$AAl?$AAo@ 1001c008 LIBCMT:crt0msg.obj - 0002:00001078 ??_C@_1GK@MCAAGJMO@?$AAR?$AA6?$AA0?$AA2?$AA6?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAn?$AAo?$AAt?$AA?5?$AAe?$AAn?$AAo?$AAu?$AAg?$AAh?$AA?5?$AAs?$AAp?$AAa?$AAc?$AAe?$AA?5?$AAf?$AAo?$AAr?$AA?5?$AAs?$AAt@ 1001c078 LIBCMT:crt0msg.obj - 0002:000010e8 ??_C@_1EM@MAADIHMB@?$AAR?$AA6?$AA0?$AA2?$AA5?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAp?$AAu?$AAr?$AAe?$AA?5?$AAv?$AAi?$AAr?$AAt?$AAu?$AAa?$AAl?$AA?5?$AAf?$AAu?$AAn?$AAc?$AAt?$AAi?$AAo?$AAn?$AA?5?$AAc@ 1001c0e8 LIBCMT:crt0msg.obj - 0002:00001138 ??_C@_1GK@FHCKBEFA@?$AAR?$AA6?$AA0?$AA2?$AA4?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAn?$AAo?$AAt?$AA?5?$AAe?$AAn?$AAo?$AAu?$AAg?$AAh?$AA?5?$AAs?$AAp?$AAa?$AAc?$AAe?$AA?5?$AAf?$AAo?$AAr?$AA?5?$AA_?$AAo@ 1001c138 LIBCMT:crt0msg.obj - 0002:000011a8 ??_C@_1FC@ECHBIFBC@?$AAR?$AA6?$AA0?$AA1?$AA9?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAu?$AAn?$AAa?$AAb?$AAl?$AAe?$AA?5?$AAt?$AAo?$AA?5?$AAo?$AAp?$AAe?$AAn?$AA?5?$AAc?$AAo?$AAn?$AAs?$AAo?$AAl?$AAe?$AA?5@ 1001c1a8 LIBCMT:crt0msg.obj - 0002:00001200 ??_C@_1EC@JIBHAOPH@?$AAR?$AA6?$AA0?$AA1?$AA8?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAu?$AAn?$AAe?$AAx?$AAp?$AAe?$AAc?$AAt?$AAe?$AAd?$AA?5?$AAh?$AAe?$AAa?$AAp?$AA?5?$AAe?$AAr?$AAr?$AAo?$AAr?$AA?$AN?$AA?6@ 1001c200 LIBCMT:crt0msg.obj - 0002:00001248 ??_C@_1FK@BEOGODMC@?$AAR?$AA6?$AA0?$AA1?$AA7?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAu?$AAn?$AAe?$AAx?$AAp?$AAe?$AAc?$AAt?$AAe?$AAd?$AA?5?$AAm?$AAu?$AAl?$AAt?$AAi?$AAt?$AAh?$AAr?$AAe?$AAa?$AAd?$AA?5@ 1001c248 LIBCMT:crt0msg.obj - 0002:000012a8 ??_C@_1FI@LOGNIKDM@?$AAR?$AA6?$AA0?$AA1?$AA6?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAn?$AAo?$AAt?$AA?5?$AAe?$AAn?$AAo?$AAu?$AAg?$AAh?$AA?5?$AAs?$AAp?$AAa?$AAc?$AAe?$AA?5?$AAf?$AAo?$AAr?$AA?5?$AAt?$AAh@ 1001c2a8 LIBCMT:crt0msg.obj - 0002:00001300 ??_C@_1EG@BEHAGFJD@?$AAR?$AA6?$AA0?$AA1?$AA0?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAa?$AAb?$AAo?$AAr?$AAt?$AA?$CI?$AA?$CJ?$AA?5?$AAh?$AAa?$AAs?$AA?5?$AAb?$AAe?$AAe?$AAn?$AA?5?$AAc?$AAa?$AAl?$AAl?$AAe?$AAd@ 1001c300 LIBCMT:crt0msg.obj - 0002:00001348 ??_C@_1FI@HONFMGBI@?$AAR?$AA6?$AA0?$AA0?$AA9?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAn?$AAo?$AAt?$AA?5?$AAe?$AAn?$AAo?$AAu?$AAg?$AAh?$AA?5?$AAs?$AAp?$AAa?$AAc?$AAe?$AA?5?$AAf?$AAo?$AAr?$AA?5?$AAe?$AAn@ 1001c348 LIBCMT:crt0msg.obj - 0002:000013a0 ??_C@_1FE@LLNEDJMD@?$AAR?$AA6?$AA0?$AA0?$AA8?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAn?$AAo?$AAt?$AA?5?$AAe?$AAn?$AAo?$AAu?$AAg?$AAh?$AA?5?$AAs?$AAp?$AAa?$AAc?$AAe?$AA?5?$AAf?$AAo?$AAr?$AA?5?$AAa?$AAr@ 1001c3a0 LIBCMT:crt0msg.obj - 0002:000013f8 ??_C@_1FK@PGACCAFB@?$AAR?$AA6?$AA0?$AA0?$AA2?$AA?$AN?$AA?6?$AA?9?$AA?5?$AAf?$AAl?$AAo?$AAa?$AAt?$AAi?$AAn?$AAg?$AA?5?$AAp?$AAo?$AAi?$AAn?$AAt?$AA?5?$AAs?$AAu?$AAp?$AAp?$AAo?$AAr?$AAt?$AA?5@ 1001c3f8 LIBCMT:crt0msg.obj - 0002:00001508 ??_C@_1EK@MBDPDCGA@?$AAM?$AAi?$AAc?$AAr?$AAo?$AAs?$AAo?$AAf?$AAt?$AA?5?$AAV?$AAi?$AAs?$AAu?$AAa?$AAl?$AA?5?$AAC?$AA?$CL?$AA?$CL?$AA?5?$AAR?$AAu?$AAn?$AAt?$AAi?$AAm?$AAe?$AA?5?$AAL?$AAi?$AAb@ 1001c508 LIBCMT:crt0msg.obj - 0002:00001554 ??_C@_15IABLJNFO@?$AA?6?$AA?6?$AA?$AA@ 1001c554 LIBCMT:crt0msg.obj - 0002:0000155c ??_C@_17LGKOMLJ@?$AA?4?$AA?4?$AA?4?$AA?$AA@ 1001c55c LIBCMT:crt0msg.obj - 0002:00001564 ??_C@_1CO@EAEJAADC@?$AA?$DM?$AAp?$AAr?$AAo?$AAg?$AAr?$AAa?$AAm?$AA?5?$AAn?$AAa?$AAm?$AAe?$AA?5?$AAu?$AAn?$AAk?$AAn?$AAo?$AAw?$AAn?$AA?$DO?$AA?$AA@ 1001c564 LIBCMT:crt0msg.obj - 0002:00001594 ??_C@_1DE@JNGNBFGO@?$AAR?$AAu?$AAn?$AAt?$AAi?$AAm?$AAe?$AA?5?$AAE?$AAr?$AAr?$AAo?$AAr?$AA?$CB?$AA?6?$AA?6?$AAP?$AAr?$AAo?$AAg?$AAr?$AAa?$AAm?$AA?3?$AA?5?$AA?$AA@ 1001c594 LIBCMT:crt0msg.obj - 0002:000015c8 __XcptActTab 1001c5c8 LIBCMT:winxfltr.obj - 0002:00001658 __First_FPE_Indx 1001c658 LIBCMT:winxfltr.obj - 0002:0000165c __Num_FPE 1001c65c LIBCMT:winxfltr.obj - 0002:00001660 __XcptActTabSize 1001c660 LIBCMT:winxfltr.obj - 0002:00001664 __XcptActTabCount 1001c664 LIBCMT:winxfltr.obj - 0002:00001668 ??_C@_1BC@GDGBMEMK@?$AAH?$AAH?$AA?3?$AAm?$AAm?$AA?3?$AAs?$AAs?$AA?$AA@ 1001c668 LIBCMT:nlsdata2.obj - 0002:0000167c ??_C@_1CI@KNAKOEBC@?$AAd?$AAd?$AAd?$AAd?$AA?0?$AA?5?$AAM?$AAM?$AAM?$AAM?$AA?5?$AAd?$AAd?$AA?0?$AA?5?$AAy?$AAy?$AAy?$AAy?$AA?$AA@ 1001c67c LIBCMT:nlsdata2.obj - 0002:000016a4 ??_C@_1BC@IEBCMHCM@?$AAM?$AAM?$AA?1?$AAd?$AAd?$AA?1?$AAy?$AAy?$AA?$AA@ 1001c6a4 LIBCMT:nlsdata2.obj - 0002:000016b8 ??_C@_15CLMNNGEL@?$AAP?$AAM?$AA?$AA@ 1001c6b8 LIBCMT:nlsdata2.obj - 0002:000016c0 ??_C@_15ODEHAHHF@?$AAA?$AAM?$AA?$AA@ 1001c6c0 LIBCMT:nlsdata2.obj - 0002:000016c8 ??_C@_1BC@FEMKIFH@?$AAD?$AAe?$AAc?$AAe?$AAm?$AAb?$AAe?$AAr?$AA?$AA@ 1001c6c8 LIBCMT:nlsdata2.obj - 0002:000016dc ??_C@_1BC@BGLIFPF@?$AAN?$AAo?$AAv?$AAe?$AAm?$AAb?$AAe?$AAr?$AA?$AA@ 1001c6dc LIBCMT:nlsdata2.obj - 0002:000016f0 ??_C@_1BA@EPANDLNG@?$AAO?$AAc?$AAt?$AAo?$AAb?$AAe?$AAr?$AA?$AA@ 1001c6f0 LIBCMT:nlsdata2.obj - 0002:00001700 ??_C@_1BE@DKAAMBJL@?$AAS?$AAe?$AAp?$AAt?$AAe?$AAm?$AAb?$AAe?$AAr?$AA?$AA@ 1001c700 LIBCMT:nlsdata2.obj - 0002:00001714 ??_C@_1O@PAHLKOAC@?$AAA?$AAu?$AAg?$AAu?$AAs?$AAt?$AA?$AA@ 1001c714 LIBCMT:nlsdata2.obj - 0002:00001724 ??_C@_19BIFMLPCD@?$AAJ?$AAu?$AAl?$AAy?$AA?$AA@ 1001c724 LIBCMT:nlsdata2.obj - 0002:00001730 ??_C@_19EPFLPGAP@?$AAJ?$AAu?$AAn?$AAe?$AA?$AA@ 1001c730 LIBCMT:nlsdata2.obj - 0002:0000173c ??_C@_1M@GJNLMHFD@?$AAA?$AAp?$AAr?$AAi?$AAl?$AA?$AA@ 1001c73c LIBCMT:nlsdata2.obj - 0002:00001748 ??_C@_1M@IKEENEDF@?$AAM?$AAa?$AAr?$AAc?$AAh?$AA?$AA@ 1001c748 LIBCMT:nlsdata2.obj - 0002:00001754 ??_C@_1BC@JGDDFFAM@?$AAF?$AAe?$AAb?$AAr?$AAu?$AAa?$AAr?$AAy?$AA?$AA@ 1001c754 LIBCMT:nlsdata2.obj - 0002:00001768 ??_C@_1BA@EFMEIEBA@?$AAJ?$AAa?$AAn?$AAu?$AAa?$AAr?$AAy?$AA?$AA@ 1001c768 LIBCMT:nlsdata2.obj - 0002:00001778 ??_C@_17EGKACKIF@?$AAD?$AAe?$AAc?$AA?$AA@ 1001c778 LIBCMT:nlsdata2.obj - 0002:00001780 ??_C@_17BBDMLCIG@?$AAN?$AAo?$AAv?$AA?$AA@ 1001c780 LIBCMT:nlsdata2.obj - 0002:00001788 ??_C@_17FNLKOI@?$AAO?$AAc?$AAt?$AA?$AA@ 1001c788 LIBCMT:nlsdata2.obj - 0002:00001790 ??_C@_17HCHCOKMG@?$AAS?$AAe?$AAp?$AA?$AA@ 1001c790 LIBCMT:nlsdata2.obj - 0002:00001798 ??_C@_17ICPELBCN@?$AAA?$AAu?$AAg?$AA?$AA@ 1001c798 LIBCMT:nlsdata2.obj - 0002:000017a0 ??_C@_17IJPCKHK@?$AAJ?$AAu?$AAl?$AA?$AA@ 1001c7a0 LIBCMT:nlsdata2.obj - 0002:000017a8 ??_C@_17KCJGOCPB@?$AAJ?$AAu?$AAn?$AA?$AA@ 1001c7a8 LIBCMT:nlsdata2.obj - 0002:000017b0 ??_C@_17PNNKMEED@?$AAM?$AAa?$AAy?$AA?$AA@ 1001c7b0 LIBCMT:nlsdata2.obj - 0002:000017b8 ??_C@_17LFPOIHDD@?$AAA?$AAp?$AAr?$AA?$AA@ 1001c7b8 LIBCMT:nlsdata2.obj - 0002:000017c0 ??_C@_17CKNLEDEC@?$AAM?$AAa?$AAr?$AA?$AA@ 1001c7c0 LIBCMT:nlsdata2.obj - 0002:000017c8 ??_C@_17LMDJEKJN@?$AAF?$AAe?$AAb?$AA?$AA@ 1001c7c8 LIBCMT:nlsdata2.obj - 0002:000017d0 ??_C@_17DKNBKCHM@?$AAJ?$AAa?$AAn?$AA?$AA@ 1001c7d0 LIBCMT:nlsdata2.obj - 0002:000017d8 ??_C@_1BC@ENMNNPAJ@?$AAS?$AAa?$AAt?$AAu?$AAr?$AAd?$AAa?$AAy?$AA?$AA@ 1001c7d8 LIBCMT:nlsdata2.obj - 0002:000017ec ??_C@_1O@PDICJHAG@?$AAF?$AAr?$AAi?$AAd?$AAa?$AAy?$AA?$AA@ 1001c7ec LIBCMT:nlsdata2.obj - 0002:000017fc ??_C@_1BC@HHMNLIHE@?$AAT?$AAh?$AAu?$AAr?$AAs?$AAd?$AAa?$AAy?$AA?$AA@ 1001c7fc LIBCMT:nlsdata2.obj - 0002:00001810 ??_C@_1BE@EBOGMDOH@?$AAW?$AAe?$AAd?$AAn?$AAe?$AAs?$AAd?$AAa?$AAy?$AA?$AA@ 1001c810 LIBCMT:nlsdata2.obj - 0002:00001824 ??_C@_1BA@ENFBFFEK@?$AAT?$AAu?$AAe?$AAs?$AAd?$AAa?$AAy?$AA?$AA@ 1001c824 LIBCMT:nlsdata2.obj - 0002:00001834 ??_C@_1O@MMNBFLIA@?$AAM?$AAo?$AAn?$AAd?$AAa?$AAy?$AA?$AA@ 1001c834 LIBCMT:nlsdata2.obj - 0002:00001844 ??_C@_1O@IHNHDHPB@?$AAS?$AAu?$AAn?$AAd?$AAa?$AAy?$AA?$AA@ 1001c844 LIBCMT:nlsdata2.obj - 0002:00001854 ??_C@_17GGIBDPIH@?$AAS?$AAa?$AAt?$AA?$AA@ 1001c854 LIBCMT:nlsdata2.obj - 0002:0000185c ??_C@_17HFOLPPLP@?$AAF?$AAr?$AAi?$AA?$AA@ 1001c85c LIBCMT:nlsdata2.obj - 0002:00001864 ??_C@_17PDPHAADD@?$AAT?$AAh?$AAu?$AA?$AA@ 1001c864 LIBCMT:nlsdata2.obj - 0002:0000186c ??_C@_17CJEDCEPE@?$AAW?$AAe?$AAd?$AA?$AA@ 1001c86c LIBCMT:nlsdata2.obj - 0002:00001874 ??_C@_17BMKGEGOJ@?$AAT?$AAu?$AAe?$AA?$AA@ 1001c874 LIBCMT:nlsdata2.obj - 0002:0000187c ??_C@_17KBOMKBF@?$AAM?$AAo?$AAn?$AA?$AA@ 1001c87c LIBCMT:nlsdata2.obj - 0002:00001884 ??_C@_17MBGCMIPB@?$AAS?$AAu?$AAn?$AA?$AA@ 1001c884 LIBCMT:nlsdata2.obj - 0002:0000188c ??_C@_08JCCMCCIL@HH?3mm?3ss?$AA@ 1001c88c LIBCMT:nlsdata2.obj - 0002:00001898 ??_C@_0BE@CKGJFCPC@dddd?0?5MMMM?5dd?0?5yyyy?$AA@ 1001c898 LIBCMT:nlsdata2.obj - 0002:000018ac ??_C@_08BPBNCDIB@MM?1dd?1yy?$AA@ 1001c8ac LIBCMT:nlsdata2.obj - 0002:000018b8 ??_C@_02CJNFDJBF@PM?$AA@ 1001c8b8 LIBCMT:nlsdata2.obj - 0002:000018bc ??_C@_02DEDBPAFC@AM?$AA@ 1001c8bc LIBCMT:nlsdata2.obj - 0002:000018c0 ??_C@_08EDHMEBNP@December?$AA@ 1001c8c0 LIBCMT:nlsdata2.obj - 0002:000018cc ??_C@_08HCHEGEOA@November?$AA@ 1001c8cc LIBCMT:nlsdata2.obj - 0002:000018d8 ??_C@_07JJNFCEND@October?$AA@ 1001c8d8 LIBCMT:nlsdata2.obj - 0002:000018e0 ??_C@_09BHHEALKD@September?$AA@ 1001c8e0 LIBCMT:nlsdata2.obj - 0002:000018ec ??_C@_06LBBHFDDG@August?$AA@ 1001c8ec LIBCMT:nlsdata2.obj - 0002:000018f4 ??_C@_04MIEPOIFP@July?$AA@ 1001c8f4 LIBCMT:nlsdata2.obj - 0002:000018fc ??_C@_04CNLMGBGM@June?$AA@ 1001c8fc LIBCMT:nlsdata2.obj - 0002:00001904 ??_C@_05DMJDNLEJ@April?$AA@ 1001c904 LIBCMT:nlsdata2.obj - 0002:0000190c ??_C@_05HPCKOFNC@March?$AA@ 1001c90c LIBCMT:nlsdata2.obj - 0002:00001914 ??_C@_08GNJGEPFN@February?$AA@ 1001c914 LIBCMT:nlsdata2.obj - 0002:00001920 ??_C@_07CGJPFGJA@January?$AA@ 1001c920 LIBCMT:nlsdata2.obj - 0002:00001928 ??_C@_03MKABNOCG@Dec?$AA@ 1001c928 LIBCMT:nlsdata2.obj - 0002:0000192c ??_C@_03JPJOFNIA@Nov?$AA@ 1001c92c LIBCMT:nlsdata2.obj - 0002:00001930 ??_C@_03BMAOKBAD@Oct?$AA@ 1001c930 LIBCMT:nlsdata2.obj - 0002:00001934 ??_C@_03GGCAPAJC@Sep?$AA@ 1001c934 LIBCMT:nlsdata2.obj - 0002:00001938 ??_C@_03IFJFEIGA@Aug?$AA@ 1001c938 LIBCMT:nlsdata2.obj - 0002:0000193c ??_C@_03LBGABGKK@Jul?$AA@ 1001c93c LIBCMT:nlsdata2.obj - 0002:00001940 ??_C@_03IDFGHECI@Jun?$AA@ 1001c940 LIBCMT:nlsdata2.obj - 0002:00001944 ??_C@_03CNMDKL@May?$AA@ 1001c944 LIBCMT:nlsdata2.obj - 0002:00001948 ??_C@_03LEOLGMJP@Apr?$AA@ 1001c948 LIBCMT:nlsdata2.obj - 0002:0000194c ??_C@_03ODNJBKGA@Mar?$AA@ 1001c94c LIBCMT:nlsdata2.obj - 0002:00001950 ??_C@_03HJBDCHOM@Feb?$AA@ 1001c950 LIBCMT:nlsdata2.obj - 0002:00001954 ??_C@_03JIHJHPIE@Jan?$AA@ 1001c954 LIBCMT:nlsdata2.obj - 0002:00001958 ??_C@_08INBOOONO@Saturday?$AA@ 1001c958 LIBCMT:nlsdata2.obj - 0002:00001964 ??_C@_06JECMNKMI@Friday?$AA@ 1001c964 LIBCMT:nlsdata2.obj - 0002:0000196c ??_C@_08HACCIKIA@Thursday?$AA@ 1001c96c LIBCMT:nlsdata2.obj - 0002:00001978 ??_C@_09DLIGFAKA@Wednesday?$AA@ 1001c978 LIBCMT:nlsdata2.obj - 0002:00001984 ??_C@_07BAAGCFCM@Tuesday?$AA@ 1001c984 LIBCMT:nlsdata2.obj - 0002:0000198c ??_C@_06JLEDEDGH@Monday?$AA@ 1001c98c LIBCMT:nlsdata2.obj - 0002:00001994 ??_C@_06OOPIFAJ@Sunday?$AA@ 1001c994 LIBCMT:nlsdata2.obj - 0002:0000199c ??_C@_03FEFJNEK@Sat?$AA@ 1001c99c LIBCMT:nlsdata2.obj - 0002:000019a0 ??_C@_03IDIOELNC@Fri?$AA@ 1001c9a0 LIBCMT:nlsdata2.obj - 0002:000019a4 ??_C@_03IOFIKPDN@Thu?$AA@ 1001c9a4 LIBCMT:nlsdata2.obj - 0002:000019a8 ??_C@_03MHOMLAJA@Wed?$AA@ 1001c9a8 LIBCMT:nlsdata2.obj - 0002:000019ac ??_C@_03NAGEINEP@Tue?$AA@ 1001c9ac LIBCMT:nlsdata2.obj - 0002:000019b0 ??_C@_03PDAGKDH@Mon?$AA@ 1001c9b0 LIBCMT:nlsdata2.obj - 0002:000019b4 ??_C@_03KOEHGMDN@Sun?$AA@ 1001c9b4 LIBCMT:nlsdata2.obj - 0002:000019b8 ___lookuptable_s 1001c9b8 LIBCMT:outputs.obj - 0002:00001a30 ??_C@_1CK@HHHCOJPD@?$AAE?$AAn?$AAv?$AAi?$AAr?$AAo?$AAn?$AAm?$AAe?$AAn?$AAt?$AAD?$AAi?$AAr?$AAe?$AAc?$AAt?$AAo?$AAr?$AAy?$AA?$AA@ 1001ca30 LIBCMT:_pdblkup_.obj - 0002:00001a60 ??_C@_1FM@DNCABAP@?$AAS?$AAO?$AAF?$AAT?$AAW?$AAA?$AAR?$AAE?$AA?2?$AAM?$AAi?$AAc?$AAr?$AAo?$AAs?$AAo?$AAf?$AAt?$AA?2?$AAV?$AAi?$AAs?$AAu?$AAa?$AAl?$AAS?$AAt?$AAu?$AAd?$AAi?$AAo?$AA?2@ 1001ca60 LIBCMT:_pdblkup_.obj - 0002:00001abc ??_C@_0M@HLOHPNFA@RegCloseKey?$AA@ 1001cabc LIBCMT:_pdblkup_.obj - 0002:00001ac8 ??_C@_0BB@GLNAEDBD@RegQueryValueExW?$AA@ 1001cac8 LIBCMT:_pdblkup_.obj - 0002:00001adc ??_C@_0O@COHOBMLB@RegOpenKeyExW?$AA@ 1001cadc LIBCMT:_pdblkup_.obj - 0002:00001aec ??_C@_01KDCPPGHE@r?$AA@ 1001caec LIBCMT:_pdblkup_.obj - 0002:00001af0 ??_C@_0BB@KCIACLNC@PDBOpenValidate5?$AA@ 1001caf0 LIBCMT:_pdblkup_.obj - 0002:00001b04 ??_C@_0BI@DFKBFLJE@GetProcessWindowStation?$AA@ 1001cb04 LIBCMT:crtmboxw.obj - 0002:00001b1c ??_C@_0BK@DEKFELLI@GetUserObjectInformationW?$AA@ 1001cb1c LIBCMT:crtmboxw.obj - 0002:00001b38 ??_C@_0BD@HHGDFDBJ@GetLastActivePopup?$AA@ 1001cb38 LIBCMT:crtmboxw.obj - 0002:00001b4c ??_C@_0BA@HNOPNCHB@GetActiveWindow?$AA@ 1001cb4c LIBCMT:crtmboxw.obj - 0002:00001b5c ??_C@_0M@DLDCCGNP@MessageBoxW?$AA@ 1001cb5c LIBCMT:crtmboxw.obj - 0002:00001b68 ??_C@_1BG@GOEBHBDC@?$AAU?$AAS?$AAE?$AAR?$AA3?$AA2?$AA?4?$AAD?$AAL?$AAL?$AA?$AA@ 1001cb68 LIBCMT:crtmboxw.obj - 0002:00001c00 ___newctype 1001cc00 LIBCMT:ctype.obj - 0002:00001f00 __wctype 1001cf00 LIBCMT:ctype.obj - 0002:00002108 ___newclmap 1001d108 LIBCMT:ctype.obj - 0002:00002288 ___newcumap 1001d288 LIBCMT:ctype.obj - 0002:00002408 ??_C@_1BA@BALFACEM@?$AAC?$AAO?$AAN?$AAO?$AAU?$AAT?$AA$?$AA?$AA@ 1001d408 LIBCMT:initcon.obj - 0002:00002418 ??_C@_06IMKFLFPG@1?$CDQNAN?$AA@ 1001d418 LIBCMT:_x10fout_.obj - 0002:00002420 ??_C@_05DNEBIAHO@1?$CDINF?$AA@ 1001d420 LIBCMT:_x10fout_.obj - 0002:00002428 ??_C@_05PHHOCPM@1?$CDIND?$AA@ 1001d428 LIBCMT:_x10fout_.obj - 0002:00002430 ??_C@_06PGGFOGJG@1?$CDSNAN?$AA@ 1001d430 LIBCMT:_x10fout_.obj - 0002:00002438 __load_config_used 1001d438 LIBCMT:loadcfg.obj - 0002:00002480 ___safe_se_handler_table 1001d480 - 0002:0000248c ___rtc_iaa 1001d48c LIBCMT:_initsect_.obj - 0002:00002490 ___rtc_izz 1001d490 LIBCMT:_initsect_.obj - 0002:00002494 ___rtc_taa 1001d494 LIBCMT:_initsect_.obj - 0002:00002498 ___rtc_tzz 1001d498 LIBCMT:_initsect_.obj - 0002:0000293c __IMPORT_DESCRIPTOR_ADVAPI32 1001d93c Advapi32:ADVAPI32.dll - 0002:00002950 __IMPORT_DESCRIPTOR_USER32 1001d950 User32:USER32.dll - 0002:00002964 __IMPORT_DESCRIPTOR_KERNEL32 1001d964 kernel32:KERNEL32.dll - 0002:00002978 __NULL_IMPORT_DESCRIPTOR 1001d978 Advapi32:ADVAPI32.dll - 0003:00000038 _SVN_REV 1001f038 api.obj - 0003:00003f20 ___security_cookie 10022f20 LIBCMT:gs_cookie.obj - 0003:00003f24 ___security_cookie_complement 10022f24 LIBCMT:gs_cookie.obj - 0003:000040a0 __fltused 100230a0 LIBCMT:_fpinit_.obj - 0003:000040a4 __ldused 100230a4 LIBCMT:_fpinit_.obj - 0003:000040a8 __iob 100230a8 LIBCMT:_file.obj - 0003:00004330 ___nullstring 10023330 LIBCMT:output.obj - 0003:00004334 ___wnullstring 10023334 LIBCMT:output.obj - 0003:00004338 ?_RTC_ErrorLevels@@3PAHA 10023338 LIBCMT:_error_.obj - 0003:00004350 __timezone 10023350 LIBCMT:timeset.obj - 0003:00004354 __daylight 10023354 LIBCMT:timeset.obj - 0003:00004358 __dstbias 10023358 LIBCMT:timeset.obj - 0003:000043e0 __tzname 100233e0 LIBCMT:timeset.obj - 0003:00004400 ___flsindex 10023400 LIBCMT:tidtable.obj - 0003:00004404 ___getvalueindex 10023404 LIBCMT:tidtable.obj - 0003:00004408 __lookuptrailbytes 10023408 LIBCMT:read.obj - 0003:00004508 ___badioinfo 10023508 LIBCMT:ioinit.obj - 0003:00004550 __cfltcvt_tab 10023550 LIBCMT:cmiscdat.obj - 0003:00004698 __sys_errlist 10023698 LIBCMT:syserr.obj - 0003:00004748 __sys_nerr 10023748 LIBCMT:syserr.obj - 0003:00004750 ___initialmbcinfo 10023750 LIBCMT:mbctype.obj - 0003:00004970 __mbctype 10023970 LIBCMT:mbctype.obj - 0003:00004a78 __mbcasemap 10023a78 LIBCMT:mbctype.obj - 0003:00004b78 ___ptmbcinfo 10023b78 LIBCMT:mbctype.obj - 0003:00004c70 ___globallocalestatus 10023c70 LIBCMT:glstatus.obj - 0003:00004c74 ___clocalestr 10023c74 LIBCMT:nlsdata2.obj - 0003:00004c78 ___lc_time_c 10023c78 LIBCMT:nlsdata2.obj - 0003:00004de0 ___initiallocinfo 10023de0 LIBCMT:nlsdata2.obj - 0003:00004eb8 ___ptlocinfo 10023eb8 LIBCMT:nlsdata2.obj - 0003:00004ebc ___initiallocalestructinfo 10023ebc LIBCMT:nlsdata2.obj - 0003:00004ed0 __lpdays 10023ed0 LIBCMT:days.obj - 0003:00004f04 __days 10023f04 LIBCMT:days.obj - 0003:00004f40 ___abort_behavior 10023f40 LIBCMT:abort.obj - 0003:00004f50 ___lconv_static_decimal 10023f50 LIBCMT:lconv.obj - 0003:00004f54 ___lconv_static_W_decimal 10023f54 LIBCMT:lconv.obj - 0003:00004f58 ___lconv_c 10023f58 LIBCMT:lconv.obj - 0003:00004fa8 ___lconv 10023fa8 LIBCMT:lconv.obj - 0003:00004fac __pctype 10023fac LIBCMT:ctype.obj - 0003:00004fb0 __pwctype 10023fb0 LIBCMT:ctype.obj - 0003:00004fb4 __confh 10023fb4 LIBCMT:initcon.obj - 0003:00004fc0 __NLG_Destination 10023fc0 LIBCMT:exsup.obj - 0003:00005000 ___mb_cur_max 10024000 LIBCMT:nlsdata1.obj - 0003:00005004 ___decimal_point 10024004 LIBCMT:nlsdata1.obj - 0003:00005008 ___decimal_point_length 10024008 LIBCMT:nlsdata1.obj - 0003:00005010 __pow10pos 10024010 LIBCMT:_constpow_.obj - 0003:00005170 __pow10neg 10024170 LIBCMT:_constpow_.obj - 0003:00005300 _svn_rev 10024300 api.obj - 0003:00005380 _default_xbee 10024380 api.obj - 0003:00005384 _glob_hModule 10024384 api.obj - 0003:00005388 _win32_hWnd 10024388 api.obj - 0003:0000538c _win32_MessageID 1002438c api.obj - 0003:00005398 ___fastflag 10024398 LIBCMT:_fpinit_.obj - 0003:0000539c __cflush 1002439c LIBCMT:_file.obj - 0003:000053a0 __umaskval 100243a0 LIBCMT:crt0dat.obj - 0003:000053a4 ___argc 100243a4 LIBCMT:crt0dat.obj - 0003:000053a8 ___argv 100243a8 LIBCMT:crt0dat.obj - 0003:000053ac ___wargv 100243ac LIBCMT:crt0dat.obj - 0003:000053b0 __environ 100243b0 LIBCMT:crt0dat.obj - 0003:000053b4 ___initenv 100243b4 LIBCMT:crt0dat.obj - 0003:000053b8 __wenviron 100243b8 LIBCMT:crt0dat.obj - 0003:000053bc ___winitenv 100243bc LIBCMT:crt0dat.obj - 0003:000053c0 __pgmptr 100243c0 LIBCMT:crt0dat.obj - 0003:000053c4 __wpgmptr 100243c4 LIBCMT:crt0dat.obj - 0003:000053c8 __exitflag 100243c8 LIBCMT:crt0dat.obj - 0003:000053cc __C_Termination_Done 100243cc LIBCMT:crt0dat.obj - 0003:000053d0 __C_Exit_Done 100243d0 LIBCMT:crt0dat.obj - 0003:000053d8 __aenvptr 100243d8 LIBCMT:dllcrt0.obj - 0003:000053dc __wenvptr 100243dc LIBCMT:dllcrt0.obj - 0003:000053e0 ___error_mode 100243e0 LIBCMT:dllcrt0.obj - 0003:000053e4 ___app_type 100243e4 LIBCMT:dllcrt0.obj - 0003:000053e8 ___pInvalidArgHandler 100243e8 LIBCMT:invarg.obj - 0003:00005714 ?wsprintffp@@3P6AHPADPBDZZA 10024714 LIBCMT:_error_.obj - 0003:00005720 __crtheap 10024720 LIBCMT:heapinit.obj - 0003:000057e0 _gpFlsAlloc 100247e0 LIBCMT:tidtable.obj - 0003:000057e4 _gpFlsGetValue 100247e4 LIBCMT:tidtable.obj - 0003:000057e8 _gpFlsSetValue 100247e8 LIBCMT:tidtable.obj - 0003:000057ec _gpFlsFree 100247ec LIBCMT:tidtable.obj - 0003:000057f0 __stdbuf 100247f0 LIBCMT:_sftbuf.obj - 0003:00005948 __maxwait 10024948 LIBCMT:crtheap.obj - 0003:0000594c ?__pInconsistency@@3P6AXXZA 1002494c LIBCMT:hooks.obj - 0003:00005968 ___pPurecall 10024968 LIBCMT:inithelp.obj - 0003:0000596c ?_pnhHeap@@3P6AHI@ZA 1002496c LIBCMT:handler.obj - 0003:00005f98 __newmode 10024f98 LIBCMT:_newmode.obj - 0003:000060ac ___mbulinfo 100250ac LIBCMT:mbctype.obj - 0003:000060b8 ___mbcodepage 100250b8 LIBCMT:mbctype.obj - 0003:000060bc ___ismbcodepage 100250bc LIBCMT:mbctype.obj - 0003:000060c0 ___mblcid 100250c0 LIBCMT:mbctype.obj - 0003:000060d0 __fmode 100250d0 LIBCMT:txtmode.obj - 0003:000060d4 __outputformat 100250d4 LIBCMT:outputformat.obj - 0003:000060ec ___locale_changed 100250ec LIBCMT:setlocal.obj - 0003:000060f0 ___lconv_static_null 100250f0 LIBCMT:lconv.obj - 0003:000060f4 ___lconv_static_W_null 100250f4 LIBCMT:lconv.obj - 0003:000060f8 __commode 100250f8 LIBCMT:ncommode.obj - 0003:000060fc _xbee_hnd_mutex 100250fc - 0003:00006100 __debugger_hook_dummy 10025100 - 0003:00006104 ___sse2_available 10025104 - 0003:00006108 __pDestructExceptionObject 10025108 - 0003:0000610c __nhandle 1002510c - 0003:00006120 ___pioinfo 10025120 - 0003:00006220 __acmdln 10025220 - 0003:00006224 ___env_initialized 10025224 - 0003:00006228 ___onexitend 10025228 - 0003:0000622c ___onexitbegin 1002522c - 0003:00006230 ___mbctype_initialized 10025230 - 0003:00006234 ___dyn_tls_init_callback 10025234 - 0003:00006238 ___piob 10025238 - 0003:00006240 __bufin 10025240 - 0003:00007240 __nstream 10026240 - - entry point at 0001:0000da7c - - Static symbols - - 0001:00001190 _xbee_logf 10002190 f api.obj - 0001:00001a00 _Xfree2@4 10002a00 f api.obj - 0001:00002af0 _init_serial@8 10003af0 f api.obj - 0001:00002db0 _Xmalloc2@8 10003db0 f api.obj - 0001:00002e50 _Xcalloc2@8 10003e50 f api.obj - 0001:00002ef0 _xbee_startAPI@4 10003ef0 f api.obj - 0001:00003110 _xbee_sendAT@16 10004110 f api.obj - 0001:00003140 _xbee_sendATdelay@20 10004140 f api.obj - 0001:00003630 _xbee_select@8 10004630 f api.obj - 0001:00005820 _xbee_matchpktcon@12 10006820 f api.obj - 0001:00005b20 _xbee_listen_wrapper@4 10006b20 f api.obj - 0001:00005c30 _xbee_listen@4 10006c30 f api.obj - 0001:00008d10 _Xrealloc2@12 10009d10 f api.obj - 0001:00008d70 _xbee_parse_io@24 10009d70 f api.obj - 0001:00009480 _xbee_callbackWrapper@4 1000a480 f api.obj - 0001:00009970 _xbee_thread_watch@4 1000a970 f api.obj - 0001:00009bb0 _xbee_getbyte@4 1000abb0 f api.obj - 0001:00009c00 _xbee_getrawbyte@4 1000ac00 f api.obj - 0001:00009dc0 __xbee_send_pkt@12 1000adc0 f api.obj - 0001:0000a2e0 _xbee_make_pkt@12 1000b2e0 f api.obj - 0001:0000a7d1 __tsopen_nolock 1000b7d1 f LIBCMT:open.obj - 0001:0000b225 _flsall 1000c225 f LIBCMT:fflush.obj - 0001:0000bae4 _doexit 1000cae4 f LIBCMT:crt0dat.obj - 0001:0000d986 ___DllMainCRTStartup 1000e986 f LIBCMT:dllcrt0.obj - 0001:0000dc8a _write_char 1000ec8a f LIBCMT:output.obj - 0001:0000dcbd _write_string 1000ecbd f LIBCMT:output.obj - 0001:0000eb56 ?DebuggerProbe@@YAHK@Z 1000fb56 f LIBCMT:_error_.obj - 0001:0000eba6 ?DebuggerRuntime@@YAHKHPAXPB_W@Z 1000fba6 f LIBCMT:_error_.obj - 0001:0000ec08 ?failwithmessage@@YAXPAXHHPBD@Z 1000fc08 f LIBCMT:_error_.obj - 0001:0000f019 __tzset_nolock 10010019 f LIBCMT:tzset.obj - 0001:0001167d __shift 1001267d f LIBCMT:cvt.obj - 0001:000116c2 __cftoe2_l 100126c2 f LIBCMT:cvt.obj - 0001:00011c80 __cftof2_l 10012c80 f LIBCMT:cvt.obj - 0001:000127f2 _siglookup 100137f2 f LIBCMT:winsig.obj - 0001:00012a2e __onexit_nolock 10013a2e f LIBCMT:onexit.obj - 0001:00012f9c ?strtoxl@@YAKPAUlocaleinfo_struct@@PBDPAPBDHH@Z 10013f9c f LIBCMT:strtol.obj - 0001:0001349b _parse_cmdline 1001449b f LIBCMT:stdargv.obj - 0001:00013a2b ?CPtoLCID@@YAHH@Z 10014a2b f LIBCMT:mbctype.obj - 0001:00013a5a ?setSBCS@@YAXPAUthreadmbcinfostruct@@@Z 10014a5a f LIBCMT:mbctype.obj - 0001:00013abe ?setSBUpLow@@YAXPAUthreadmbcinfostruct@@@Z 10014abe f LIBCMT:mbctype.obj - 0001:00013cf2 ?getSystemCP@@YAHH@Z 10014cf2 f LIBCMT:mbctype.obj - 0001:000146bd ?GetPdbDll@@YAPAUHINSTANCE__@@XZ 100156bd f LIBCMT:_pdblkup_.obj - 0001:00014e40 __unwind_handler4 10015e40 f LIBCMT:exsup4.obj - 0001:00015e34 ?x_ismbbtype_l@@YAHPAUlocaleinfo_struct@@IHH@Z 10016e34 f LIBCMT:ismbbyte.obj - 0001:00015e9f ?__crtLCMapStringA_stat@@YAHPAUlocaleinfo_struct@@KKPBDHPADHHH@Z 10016e9f f LIBCMT:a_map.obj - 0001:000160cc ?__crtGetStringTypeA_stat@@YAHPAUlocaleinfo_struct@@KPBDHPAGHHH@Z 100170cc f LIBCMT:a_str.obj - 0001:000168c0 __unwind_handler 100178c0 f LIBCMT:exsup.obj - 0001:0001844d __hw_cw 1001944d f LIBCMT:_ieee87_.obj - 0001:000184db ___hw_cw_sse2 100194db f LIBCMT:_ieee87_.obj - 0001:00018950 ?__crtCompareStringA_stat@@YAHPAUlocaleinfo_struct@@KKPBDH1HH@Z 10019950 f LIBCMT:a_cmp.obj - 0001:00018cea _findenv 10019cea f LIBCMT:setenv.obj - 0001:00018d3c _copy_environ 10019d3c f LIBCMT:setenv.obj - 0001:000196ea __dup_nolock 1001a6ea f LIBCMT:dup.obj diff --git a/libs/thirdParty/libxbee/main.c b/libs/thirdParty/libxbee/main.c deleted file mode 100644 index 7dcacafa7e1a02da30b1d9397c34e06509143f9f..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/main.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include - -#include "xbee.h" - -int main(int argc, char *argv[]) { - xbee_con *con, *con2; - xbee_pkt *pkt, *p; - - if (xbee_setuplog("/dev/ttyUSB0",57600,2) == -1) { - perror("xbee_setuplog()"); - exit(1); - } - if (argc >= 2 && !strcmp(argv[1],"sleep")) { - for (;;) { - sleep(86400); /* sleep for a day... forever :) */ - } - } - - /*if ((con = xbee_newcon(NULL,'X',xbee_localAT)) == (void *)-1) { - printf("error creating connection...\n"); - exit(1); - } - - while(1){sleep(10);} - - xbee_senddata(con,"CH%c",0x0C); - sleep(1); - xbee_senddata(con,"ID%c%c",0x33, 0x32); - sleep(1); - xbee_senddata(con,"DH%c%c%c%c",0x00,0x00,0x00,0x00); - sleep(1); - xbee_senddata(con,"DL%c%c%c%c",0x00,0x00,0x00,0x00); - sleep(1); - xbee_senddata(con,"MY%c%c",0x00,0x00); - sleep(1); - // SH - read only - // SL - read only - xbee_senddata(con,"RR%c",0x00); - sleep(1); - xbee_senddata(con,"RN%c",0x00); - sleep(1); - xbee_senddata(con,"MM%c",0x00); - sleep(1); - xbee_senddata(con,"NT%c",0x19); - sleep(1); - xbee_senddata(con,"NO%c",0x00); - sleep(1); - xbee_senddata(con,"CE%c",0x00); - sleep(1); - xbee_senddata(con,"SC%c%c",0x1F,0xFE); - sleep(1); - xbee_senddata(con,"SD%c",0x04); - sleep(1); - xbee_senddata(con,"A1%c",0x00); - sleep(1); - xbee_senddata(con,"A2%c",0x00); - sleep(1); - // AI - read only - xbee_senddata(con,"EE%c",0x00); - sleep(1); - //xbee_senddata(con,"KY%c",0x00); - //sleep(1); - xbee_senddata(con,"NI%s","TIGGER"); - sleep(1); - xbee_senddata(con,"PL%c",0x04); - sleep(1); - xbee_senddata(con,"CA%c",0x2C); - sleep(1); - xbee_senddata(con,"SM%c",0x00); - sleep(1); - xbee_senddata(con,"ST%c%c",0x13,0x88); - sleep(1); - xbee_senddata(con,"SP%c%c",0x00,0x00); - sleep(1); - xbee_senddata(con,"DP%c%c",0x03,0xE8); - sleep(1); - xbee_senddata(con,"SO%c",0x00); - sleep(1); - xbee_senddata(con,"BD%c",0x06); - sleep(1); - xbee_senddata(con,"RO%c",0x03); - sleep(1); - xbee_senddata(con,"AP%c",0x02); - sleep(1); - xbee_senddata(con,"PR%c",0xFF); - sleep(1); - xbee_senddata(con,"D8%c",0x00); - sleep(1); - xbee_senddata(con,"D7%c",0x01); - sleep(1); - xbee_senddata(con,"D6%c",0x00); - sleep(1); - xbee_senddata(con,"D5%c",0x01); - sleep(1); - xbee_senddata(con,"D4%c",0x00); - sleep(1); - xbee_senddata(con,"D3%c",0x00); - sleep(1); - xbee_senddata(con,"D2%c",0x00); - sleep(1); - xbee_senddata(con,"D1%c",0x00); - sleep(1); - xbee_senddata(con,"D0%c",0x00); - sleep(1); - xbee_senddata(con,"IU%c",0x00); - sleep(1); - xbee_senddata(con,"IT%c",0x01); - sleep(1); - xbee_senddata(con,"IC%c",0x00); - sleep(1); - xbee_senddata(con,"IR%c%c",0x00,0x00); - sleep(1); - xbee_senddata(con,"IA%c%c%c%c%c%c%c%c",0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF); - sleep(1); - xbee_senddata(con,"T0%c",0xFF); - sleep(1); - xbee_senddata(con,"T1%c",0xFF); - sleep(1); - xbee_senddata(con,"T2%c",0xFF); - sleep(1); - xbee_senddata(con,"T3%c",0xFF); - sleep(1); - xbee_senddata(con,"T4%c",0xFF); - sleep(1); - xbee_senddata(con,"T5%c",0xFF); - sleep(1); - xbee_senddata(con,"T6%c",0xFF); - sleep(1); - xbee_senddata(con,"T7%c",0xFF); - sleep(1); - xbee_senddata(con,"P0%c",0x01); - sleep(1); - xbee_senddata(con,"P1%c",0x00); - sleep(1); - xbee_senddata(con,"PT%c",0xFF); - sleep(1); - xbee_senddata(con,"RP%c",0x28); - sleep(1); - // VR - read only - // HV - read only - // DB - read only - // EC - read only - // EA - read only - // DD - read only - xbee_senddata(con,"CT%c",0x64); - sleep(1); - xbee_senddata(con,"GT%c%c",0x03,0xE8); - sleep(1); - xbee_senddata(con,"CC%c",0x2B); - sleep(1); - - sleep(10); - */ - - /* test 64bit IO and Data */ - con = xbee_newcon('I',xbee_64bitIO, 0x0013A200, 0x403af247); - con2 = xbee_newcon('I',xbee_64bitData, 0x0013A200, 0x403af247); - - while (1) { - while ((pkt = xbee_getpacket(con)) != NULL) { - int i; - for (i = 0; i < pkt->samples; i++) { - int m; - for (m = 0; m <= 8; m++) { - if (xbee_hasdigital(pkt,i,m)) printf("D%d: %d ",m,xbee_getdigital(pkt,i,m)); - } -#define Vref 3.23 - for (m = 0; m <= 5; m++) { - if (xbee_hasanalog(pkt,i,m)) printf("A%d: %.2fv ",m,xbee_getanalog(pkt,i,m,Vref)); - } - printf("\n"); - } - if (xbee_senddata(con2, "the time is %d\r", time(NULL))) { - printf("Error: xbee_senddata\n"); - return 1; - } - free(pkt); - if (p) { - switch (p->status) { - case 0x01: printf("XBee: txStatus: No ACK\n"); break; - case 0x02: printf("XBee: txStatus: CCA Failure\n"); break; - case 0x03: printf("XBee: txStatus: Purged\n"); break; - } - free(p); - } - } - while ((pkt = xbee_getpacket(con2)) != NULL) { - printf("he said '%s'\n", pkt->data); - if (xbee_senddata(con2, "you said '%s'\r", pkt->data)) { - printf("Error: xbee_senddata\n"); - return 1; - } - free(pkt); - if (p) { - switch (p->status) { - case 0x01: printf("XBee: txStatus: No ACK\n"); break; - case 0x02: printf("XBee: txStatus: CCA Failure\n"); break; - case 0x03: printf("XBee: txStatus: Purged\n"); break; - } - free(p); - } - } - usleep(100); - } - - return 0; -} diff --git a/libs/thirdParty/libxbee/makefile b/libs/thirdParty/libxbee/makefile deleted file mode 100644 index 11b9d3fa62ba0183ffa10ff4db8c1db8db27e962..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/makefile +++ /dev/null @@ -1,226 +0,0 @@ -#-- set this to the man directory you would like to use -MANPATH:=/usr/share/man - -#-- uncomment this to enable debugging -#DEBUG:=-g -DDEBUG - - -###### YOU SHOULD NOT CHANGE BELOW THIS LINE ###### - -VERSION:=1.4.1 -SHELL:=/bin/bash -SRCS:=api.c -MANS:=man3/libxbee.3 \ - man3/xbee_con.3 \ - man3/xbee_end.3 \ - man3/xbee_endcon.3 \ - man3/xbee_flushcon.3 \ - man3/xbee_purgecon.3 \ - man3/xbee_getanalog.3 \ - man3/xbee_getdigital.3 \ - man3/xbee_getpacket.3 \ - man3/xbee_hasanalog.3 \ - man3/xbee_hasdigital.3 \ - man3/xbee_logit.3 \ - man3/xbee_newcon.3 \ - man3/xbee_nsenddata.3 \ - man3/xbee_pkt.3 \ - man3/xbee_senddata.3 \ - man3/xbee_setup.3 \ - man3/xbee_setupAPI.3 \ - man3/xbee_setuplog.3 \ - man3/xbee_setuplogAPI.3 \ - man3/xbee_vsenddata.3 -MANPATHS:=$(foreach dir,$(shell ls man -ln | grep ^d | tr -s ' ' | cut -d ' ' -f 9),${MANPATH}/$(dir)) - -PDFS:=${SRCS} ${SRCS:.c=.h} makefile main.c xbee.h - -CC:=gcc -CFLAGS:=-Wall -Wstrict-prototypes -Wno-variadic-macros -pedantic -c -fPIC ${DEBUG} -CLINKS:=-lpthread -lrt ${DEBUG} -DEFINES:= - -ifeq ($(strip $(wildcard ${MANPATH}/man3/libxbee.3.bz2)),) -FIRSTTIME:=TRUE -else -FIRSTTIME:=FALSE -endif - -ENSCRIPT:=-MA4 --color -f Courier8 -C --margins=15:15:0:20 -ifneq ($(strip $(wildcard /usr/share/enscript/mine-web.hdr)),) - ENSCRIPT+= --fancy-header=mine-web -else - ENSCRIPT+= --fancy-header=a2ps -endif - -SRCS:=${sort ${SRCS}} -PDFS:=${sort ${PDFS}} - -.PHONY: FORCE -.PHONY: all run new clean cleanpdfs main pdfs html -.PHONY: install install_su install_man -.PHONY: uninstall uninstall_su uninstall_man/ - - -# all - do everything (default) # -all: ./lib/libxbee.so.$(VERSION) - @echo "*** Done! ***" - - -# run - remake main and then run # -run: all main - ./bin/main - - -# new - clean and do everything again # -new: clean all - - -# clean - remove any compiled files and PDFs # -clean: - rm -f ./*~ - rm -f ./sample/*~ - rm -f ./obj/*.o - rm -f ./lib/libxbee.so* - rm -f ./bin/main - -cleanpdfs: - rm -f ./pdf/*.pdf - - -# install - installs library # -install: ./lib/libxbee.so.$(VERSION) - @echo - @echo -ifneq ($(shell echo $$USER),root) - @echo "#######################################################################################" - @echo "### To Install this library I need the root password please!" - @echo "#######################################################################################" -endif - su -c "make install_su --no-print-directory" - @echo -ifeq (${FIRSTTIME},TRUE) - @echo "#######################################################################################" - @echo - @pr -h "" -o 3 -w 86 -tT ./README - @echo - @echo "#######################################################################################" -endif - -install_su: /usr/lib/libxbee.so.$(VERSION) /usr/include/xbee.h install_man - -/usr/lib/libxbee.so.$(VERSION): ./lib/libxbee.so.$(VERSION) - cp ./lib/libxbee.so.$(VERSION) /usr/lib/libxbee.so.$(VERSION) -f - @chmod 755 /usr/lib/libxbee.so.$(VERSION) - @chown root:root /usr/lib/libxbee.so.$(VERSION) - ln ./libxbee.so.$(VERSION) /usr/lib/libxbee.so.1 -sf - @chown root:root /usr/lib/libxbee.so.1 - ln ./libxbee.so.$(VERSION) /usr/lib/libxbee.so -sf - @chown root:root /usr/lib/libxbee.so - -/usr/include/xbee.h: ./xbee.h - cp ./xbee.h /usr/include/xbee.h -f - @chmod 644 /usr/include/xbee.h - @chown root:root /usr/include/xbee.h - -install_man: ${MANPATH} ${MANPATHS} ${addsuffix .bz2,${addprefix ${MANPATH}/,${MANS}}} - -${MANPATH} ${MANPATHS}: - @echo "#######################################################################################" - @echo "### $@ does not exist... cannot install man files here!" - @echo "### Please check the directory and the MANPATH variable in the makefile" - @echo "#######################################################################################" - @false - -${MANPATH}/%.bz2: ./man/% - @echo "cat $< | bzip2 -z > $@" - @cat $< | bzip2 -z > $@ || ( \ - echo "#######################################################################################"; \ - echo "### Installing man page '$*' to '$@' failed..."; \ - echo "#######################################################################################"; ) - @chmod 644 $@ - @chown root:root $@ - -./doc/: - mkdir ./doc/ - -html: ./doc/ ./man/ - cd ./doc/; mkdir -p `find ../man/ -type d -not -path *.svn* | cut -b 2-`; - find ./man/ -type f -not -path *.svn* | cut -d / -f 3- | sort > .html_todo - for item in `cat .html_todo`; do \ - man2html -r ./man/$$item | tail -n +3 > ./doc/man/$$item.html; \ - done 2> /dev/null - rm .html_todo - -uninstall: - @echo - @echo -ifneq ($(shell echo $$USER),root) - @echo "#######################################################################################" - @echo "### To Uninstall this library I need the root password please!" - @echo "#######################################################################################" -endif - su -c "make uninstall_su --no-print-directory" - @echo - @echo - -uninstall_su: ${addprefix uninstall_man/,${MANS}} - rm /usr/lib/libxbee.so.$(VERSION) -f - rm /usr/lib/libxbee.so.1 -f - rm /usr/lib/libxbee.so -f - rm /usr/include/xbee.h -f - -uninstall_man/%: - rm ${MANPATH}/$*.bz2 -f - -# main - compile & link objects # -main: ./bin/main - -./bin/main: ./obj/api.o ./bin/ ./main.c - ${CC} ${CLINKS} ./main.c ./obj/api.o -o ./bin/main ${DEBUG} - -./bin/: - mkdir ./bin/ - -./lib/libxbee.so.$(VERSION): ./lib/ ${addprefix ./obj/,${SRCS:.c=.o}} ./xbee.h - gcc -shared -Wl,-soname,libxbee.so.1 $(CLINKS) -o ./lib/libxbee.so.$(VERSION) ./obj/*.o - ln ./libxbee.so.$(VERSION) ./lib/libxbee.so.1 -sf - ln ./libxbee.so.$(VERSION) ./lib/libxbee.so -sf - -./lib/: - mkdir ./lib/ - -./obj/: - mkdir ./obj/ - -./obj/%.o: ./obj/ %.c %.h xbee.h - ${CC} ${CFLAGS} ${DEFINES} ${DEBUG} $*.c -o $@ - -./obj/%.o: ./obj/ %.c xbee.h - ${CC} ${CFLAGS} ${DEFINES} ${DEBUG} $*.c -o $@ - - -# pdfs - generate PDFs for each source file # -ifneq ($(strip $(wildcard /usr/bin/ps2pdf)),) -ifneq ($(strip $(wildcard /usr/bin/enscript)),) -pdfs: ./pdf/ ${addprefix ./pdf/,${addsuffix .pdf,${PDFS}}} - -./pdf/: - mkdir ./pdf/ - -./pdf/makefile.pdf: ./makefile - enscript ${ENSCRIPT} -Emakefile $< -p - | ps2pdf - $@ - -./pdf/%.pdf: % - enscript ${ENSCRIPT} -Ec $< -p - | ps2pdf - $@ - -./pdf/%.pdf: - @echo "*** Cannot make $@ - '$*' does not exist ***" -else -pdfs: - @echo "WARNING: enscript is not installed - cannot generate PDF files" -endif -else -pdfs: - @echo "WARNING: ps2pdf is not installed - cannot generate PDF files" -endif diff --git a/libs/thirdParty/libxbee/man/man3/libxbee.3 b/libs/thirdParty/libxbee/man/man3/libxbee.3 deleted file mode 100644 index 6bcb978f6f26255ee8bd5260d244e63a8730620a..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/libxbee.3 +++ /dev/null @@ -1,91 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH LIBXBEE 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -libxbee -.SH DESCRIPTION -libxbee is a C library to aid the use of Series 1 Digi XBee radios running in API mode (AP=2). -.sp -I have tried to keep flexibility to a maximum. -By allowing connections to individual nodes to be created - you don't have to address each packet, -or filter through incomming packets to get at the one you are after. This is all taken care of -for you by -.BR libxbee -! -.sp -libxbee is still in development, so if you find any bugs or have any enhancement requests, please -feel free to submit an issue on the project page: -.in +4n -.nf -http://code.google.com/p/libxbee/ -.fi -.in -or contact me (Attie) directly: -.in +4n -.nf -attie@attie.co.uk -.fi -.in -.SH "MAN PAGES" -Documentation is avaliable via the following man pages, or by example in the 'sample' folder in the SVN repository -.in +4n -.sp -.BR xbee_pkt "(3) - libxbee's packet structure" -.sp 0 -.BR xbee_con "(3) - libxbee's connection structure" -.sp -.BR xbee_setup "(3) - function to setup libxbee (and its variants)" -.sp 0 -.BR xbee_end "(3) - function to end the libxbee session and close any open handles" -.sp -.BR xbee_logit "(3) - function that allows the user to add to the xbee log output" -.sp -.BR xbee_newcon "(3) - function to create a new connection" -.sp 0 -.BR xbee_purgecon "(3) - function to purge packets from a connection" -.sp 0 -.BR xbee_endcon "(3) - function to end a connection" -.sp -.BR xbee_senddata "(3) - function to send data to a remote XBee (and its variants)" -.sp 0 -.BR xbee_getpacket "(3) - function to get a packet from a connection (and its variants)" -.sp -.BR xbee_hasdigital "(3) - function to check if digital sample is in the packet" -.sp 0 -.BR xbee_getdigital "(3) - function to get digital sample from the packet" -.sp -.BR xbee_hasanalog "(3) - function to check if analog sample is in the packet" -.sp 0 -.BR xbee_getanalog "(3) - function to get the analog sample from the packet" -.fi -.in -.SH "SEE ALSO" -.BR xbee_pkt (3), -.BR xbee_con (3), -.BR xbee_setup (3), -.BR xbee_end (3), -.BR xbee_logit (3), -.BR xbee_newcon (3), -.BR xbee_flushcon (3), -.BR xbee_endcon (3), -.BR xbee_senddata (3), -.BR xbee_getpacket (3), -.BR xbee_hasdigital (3), -.BR xbee_getdigital (3), -.BR xbee_hasanalog (3), -.BR xbee_getanalog (3) diff --git a/libs/thirdParty/libxbee/man/man3/xbee_con.3 b/libs/thirdParty/libxbee/man/man3/xbee_con.3 deleted file mode 100644 index 37e77050449f6d9365525e0d7df8cb8686e1f26a..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_con.3 +++ /dev/null @@ -1,22 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH LIBXBEE 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -libxbee -.sp -This page has not been written yet... diff --git a/libs/thirdParty/libxbee/man/man3/xbee_end.3 b/libs/thirdParty/libxbee/man/man3/xbee_end.3 deleted file mode 100644 index 5fd1de51279f51a2b0ec8b137b9731463e0d9732..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_end.3 +++ /dev/null @@ -1,23 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH LIBXBEE 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -libxbee -.sp -This page has not been written yet... - diff --git a/libs/thirdParty/libxbee/man/man3/xbee_endcon.3 b/libs/thirdParty/libxbee/man/man3/xbee_endcon.3 deleted file mode 100644 index e64ccedb26c6eed86c4ec13a5d8cbb107cdd6efe..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_endcon.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_newcon.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_flushcon.3 b/libs/thirdParty/libxbee/man/man3/xbee_flushcon.3 deleted file mode 100644 index e64ccedb26c6eed86c4ec13a5d8cbb107cdd6efe..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_flushcon.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_newcon.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_getanalog.3 b/libs/thirdParty/libxbee/man/man3/xbee_getanalog.3 deleted file mode 100644 index f7bc1d0c726036a64c6ace07b4247ccea91e1fcc..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_getanalog.3 +++ /dev/null @@ -1,96 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH XBEE_GETPACKET 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -xbee_hasanalog, xbee_getanalog -.SH SYNOPSIS -.B #include -.sp -.BI "int xbee_hasanalog(xbee_pkt *" pkt ", int " sample ", int " input ");" -.sp -.BI "double xbee_getanalog(xbee_pkt *" pkt ", int " sample ", int " input ", double " Vref ");" -.ad b -.SH DESCRIPTION -The -.BR xbee_hasanalog () -function will check the packet for the presence of an analog sample on the specified input. -.sp -The -.BR xbee_getanalog () -function will read the packet and return the sample value for the specified analog input. -.sp -They both take 3 arguments, with the same purposes. -.sp -The argument -.I pkt -points to a packet that was previously retrieved with -.BR xbee_getpacket () -.sp -The argument -.I sample -selects the sample within the packet to use. -.sp -The argument -.I input -specifies which input you are interested in testing. -.sp -.BR xbee_getanalog () -also takes a fourth argument that allows you to provide a -.I Vref -value. This allows the function to convert the raw ADC value into a voltage for you. -.SH "RETURN VALUE" -The -.BR xbee_hasanalog () -function will return -.B 1 -if the provided packet has sample data for the specified input, otherwise -.BR 0 . -.sp -The -.BR xbee_getanalog () -function will return the raw ADC value (0 - 1023) if the provided packet has sample data for the specified input and Vref was given as zero. -If Vref was non-zero, then the return value will be the voltage read. -A -.B -1 -will be returned if the packet does not contain sample data. -.sp -.SH EXAMPLE -To read sample data from previously made connection: -.in +4n -.nf -#include -xbee_pkt *pkt; -double Vref = 3.3; -if ((pkt = xbee_getpacket(con)) != NULL) { - if (xbee_hasanalog(pkt,0,0)) { - printf("A0 read %fv\\n",xbee_getanalog(pkt,0,0,Vref)); - } else { - printf("No A0 data\\n"); - } - free(pkt); -} -.fi -.in -.SH AUTHOR -Attie Grande -.SH "SEE ALSO" -.BR libxbee (3), -.BR xbee_pkt (3), -.BR xbee_getpacket (3), -.BR xbee_hasdigital (3), -.BR xbee_getdigital (3) diff --git a/libs/thirdParty/libxbee/man/man3/xbee_getdigital.3 b/libs/thirdParty/libxbee/man/man3/xbee_getdigital.3 deleted file mode 100644 index 4a0af65b50b11759c10080b4f5872995951d2489..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_getdigital.3 +++ /dev/null @@ -1,91 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH XBEE_GETPACKET 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -xbee_hasdigital, xbee_getdigital -.SH SYNOPSIS -.B #include -.sp -.BI "int xbee_hasdigital(xbee_pkt *" pkt ", int " sample ", int " input ");" -.sp -.BI "int xbee_getdigital(xbee_pkt *" pkt ", int " sample ", int " input ");" -.ad b -.SH DESCRIPTION -The -.BR xbee_hasdigital () -function will check the packet for the presence of a given sample on the specified input. -.sp -The -.BR xbee_getdigital () -function will read the packet and return the sample value for the specified input. -.sp -They both take 3 arguments, with the same purposes. -.sp -The argument -.I pkt -points to a packet that was previously retrieved with -.BR xbee_getpacket () -.sp -The argument -.I sample -selects the sample within the packet to use. -.sp -The argument -.I input -specifies which input you are interested in testing. -.SH "RETURN VALUE" -The -.BR xbee_hasdigital () -function will return -.B 1 -if the provided packet has sample data for the specified input, otherwise -.BR 0 . -.sp -The -.BR xbee_getdigital () -function will return -.B 1 -if the provided packet has sample data for the specified input and the sample was HIGH. -A -.B 0 -will be returned if the sample was LOW, or the packet does not contain sample data. -.sp -.SH EXAMPLE -To read sample data from previously made connection: -.in +4n -.nf -#include -xbee_pkt *pkt; -if ((pkt = xbee_getpacket(con)) != NULL) { - if (xbee_hasdigital(pkt,0,0)) { - printf("D0 read %d\n",xbee_getdigital(pkt,0)); - } else { - printf("No D0 data\n"); - } - free(pkt); -} -.fi -.in -.SH AUTHOR -Attie Grande -.SH "SEE ALSO" -.BR libxbee (3), -.BR xbee_pkt (3), -.BR xbee_getpacket (3), -.BR xbee_hasanalog (3), -.BR xbee_getanalog (3) diff --git a/libs/thirdParty/libxbee/man/man3/xbee_getpacket.3 b/libs/thirdParty/libxbee/man/man3/xbee_getpacket.3 deleted file mode 100644 index a458e49602017c25295ee13bf3766e9b77ca424b..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_getpacket.3 +++ /dev/null @@ -1,88 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH XBEE_GETPACKET 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -xbee_getpacket, xbee_getpacketwait -.SH SYNOPSIS -.B #include -.sp -.BI "xbee_pkt *xbee_getpacket(xbee_con *" con ");" -.sp -.BI "xbee_pkt *xbee_getpacketwait(xbee_con *" con ");" -.ad b -.SH DESCRIPTION -The -.BR xbee_getpacket () -function will return the next avaliable packet for the provided connection. -It takes 1 argument. -.sp -The argument -.I con -points to a connection made previously with -.BR xbee_newcon (). -.sp -The -.BR xbee_getpacketwait () -function behaves the same, but will wait for an internally specified time for a packet to arrive (currently around 1 second). -.SH "RETURN VALUE" -Upon successful return, this function returns the packet, having unlinked it from the internal list. -You must keep hold of the packet until you are finished with it, and then you must -.BR free () -it to prevent memory leaks. -.sp -If a packet was not avaliable for the provided connection, a -.B NULL -is returned. -.sp -If an error occured a -.B NULL -is also returned (though unlikely). -.sp -For more information on the structure of the packet, please see -.BR xbee_pkt (3) -.sp -For information on using callback functions with connections instead, please see -.BR xbee_con (3) -or -.B callback.c -in the SVN sample directory. -.SH EXAMPLE -To recieve a packet from a previously made connection: -.in +4n -.nf -#include -xbee_pkt *pkt; -if ((pkt = xbee_getpacket(con)) != NULL) { - /* process packet... */ - free(pkt); -} -.fi -.in -.SH AUTHOR -Attie Grande -.SH "SEE ALSO" -.BR libxbee (3), -.BR xbee_setup (3), -.BR xbee_newcon (3), -.BR xbee_senddata (3), -.BR xbee_pkt (3), -.BR xbee_con (3), -.BR xbee_hasDigital (3), -.BR xbee_getDigital (3), -.BR xbee_hasAnalog (3), -.BR xbee_getAnalog (3) diff --git a/libs/thirdParty/libxbee/man/man3/xbee_hasanalog.3 b/libs/thirdParty/libxbee/man/man3/xbee_hasanalog.3 deleted file mode 100644 index 402a3f266f409988c87e9e6f2509cf9e4caeaccf..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_hasanalog.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_getanalog.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_hasdigital.3 b/libs/thirdParty/libxbee/man/man3/xbee_hasdigital.3 deleted file mode 100644 index 5557111123b0eb4622ba68b2a88c41426dfa685e..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_hasdigital.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_getdigital.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_logit.3 b/libs/thirdParty/libxbee/man/man3/xbee_logit.3 deleted file mode 100644 index 5fd1de51279f51a2b0ec8b137b9731463e0d9732..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_logit.3 +++ /dev/null @@ -1,23 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH LIBXBEE 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -libxbee -.sp -This page has not been written yet... - diff --git a/libs/thirdParty/libxbee/man/man3/xbee_newcon.3 b/libs/thirdParty/libxbee/man/man3/xbee_newcon.3 deleted file mode 100644 index 2ec511278d45f27a7d0267bdf4deb2665d2ec6a0..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_newcon.3 +++ /dev/null @@ -1,152 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH XBEE_NEWCON 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -xbee_newcon, xbee_purgecon, xbee_endcon -.SH SYNOPSIS -.B #include -.sp -.BI "xbee_con *xbee_newcon(unsigned char " frameID ", xbee_types " type ", ...);" -.sp -.BI "void xbee_purgecon(xbee_con *" con ");" -.sp -.BI "void xbee_endcon(xbee_con *" con ");" -.ad b -.SH DESCRIPTION -The -.BR xbee_newcon () -function will setup a new connection with the specified settings. -It takes at least 2 arguments, and potentially up to 4 depending on the -.I type. -.sp -.B NOTE: -Packets will only be collected when they match an active connection. -You must setup a connection in order to recieve packets. -.sp -The argument -.I frameID -allows similar functionality to that of TCP/IP port numbers. This is 1 -.I unsigned char -(or 8-bit integer) that identifies where the data is coming from or going to. -.s -The -.I type -specifies the type of connection you would like. The following types are avaliable: -.TP -.B xbee_localAT -communicates AT commands with the local XBee -.TP -.B xbee_txStatus -recieves transmit status information from the local XBee -.TP -.B xbee_modemStatus -recieves modem status information from the local XBee -.TP -.B xbee_16bitRemoteAT -communicates AT commands with a remote node (using 16-bit addressing) -.TP -.B xbee_64bitRemoteAT -communicates AT commands with a remote node (using 64-bit addressing) -.TP -.B xbee_16bitData -sends/recieves data through a remote node (using 16-bit addressing) -.TP -.B xbee_64bitData -sends/recieves data through a remote node (using 64-bit addressing) -.TP -.B xbee_16bitIO -sends/recieves I/O data through a remote node (using 16-bit addressing) -.TP -.B xbee_64bitIO -sends/recieves I/O data through a remote node (using 64-bit addressing) -.TP -.B xbee2_data -sends/recieves data using a Series 2 XBee (uses 64-bit addressing) -.TP -.B xbee2_txStatus -recieves transmit status information from the local Series 2 XBee -.PP -If you are using -.BR xbee_localAT ", " xbee_txStatus ", " xbee2_txStatus " or " xbee_modemStatus -then only the -.I frameID -and -.I type -arguments are required. -.sp -If you are using any 16-bit connection, you must also specify 1 right aligned integer, -containing the 16-bit address (e.g. 0x1234). -.sp -If you are using any 64-bit connection, you must also specify 2 integers containing the -64-bit address, first the high 32-bits, then the low 32-bits. -.sp -The -.BR xbee_purgecon () -function is very basic. It removes any packets that have been collected in the buffer for the specified connection. -.sp -The -.BR xbee_endcon () -function is used to end a connection. This will stop collecting packets for the given connection, and remove any packets from the buffer. -.SH "RETURN VALUE" -A pointer to the connection is returned. A connection can only be made once, using the same -.I type -, -.I frameID -and address (if needed). The second call using the same parameters will return the same -connection. -.sp -For information on using callback functions for packet handling please see -.BR xbee_con (3) -or -.B callback.c -in the SVN sample directory. -.SH EXAMPLE -To create a local AT connection: -.in +4n -.nf -#include -xbee_con *con; -con = xbee_newcon('A', xbee_localAT); -.fi -.in -.sp -To create a 16-bit Data connection: -.in +4n -.nf -#include -xbee_con *con; -con = xbee_newcon('A', xbee_16bitData, 0x1234); -.fi -.in -.sp -To create a 64-bit Data connection: -.in +4n -.nf -#include -xbee_con *con; -con = xbee_newcon('A', xbee_64bitData, 0x0013A200, 0x40081826); -.fi -.in -.SH AUTHOR -Attie Grande -.SH "SEE ALSO" -.BR libxbee (3), -.BR xbee_setup (3), -.BR xbee_getpacket (3), -.BR xbee_con (3), -.BR xbee_senddata (3) diff --git a/libs/thirdParty/libxbee/man/man3/xbee_nsenddata.3 b/libs/thirdParty/libxbee/man/man3/xbee_nsenddata.3 deleted file mode 100644 index b36885d8542376a90c89c5864563bd12398a3cd0..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_nsenddata.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_senddata.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_pkt.3 b/libs/thirdParty/libxbee/man/man3/xbee_pkt.3 deleted file mode 100644 index d5e269c13c7b6a702c91d9d341a732d2184b8a60..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_pkt.3 +++ /dev/null @@ -1,79 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH XBEE_PKT 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -xbee_pkt -.SH SYNOPSIS -.B #include -.ad b -.SH DESCRIPTION -This is the packet structure. If you want to get more advanced information from connections (such as RSSI) then this is where it lives. -.sp -.in +4n -.nf -struct xbee_pkt { - unsigned char frameID; /* AT Status */ - unsigned char atCmd[2]; /* AT */ - unsigned char status; /* AT Data Status */ /* status / options */ - unsigned char Addr64[8]; /* AT Data */ - unsigned char Addr16[2]; /* AT Data */ - unsigned char data[128]; /* AT Data */ - unsigned char RSSI; /* Data */ - unsigned int datalen; - - /* X A5 A4 A3 A2 A1 A0 D8 D7 D6 D5 D4 D3 D2 D1 D0 */ - unsigned short IOmask; /* IO */ - - /* X X X X X X X D8 D7 D6 D5 D4 D3 D2 D1 D0 */ - unsigned short IOdata; /* IO */ - - /* X X X X X D D D D D D D D D D D */ - unsigned short IOanalog[6]; /* IO */ -}; -typedef struct xbee_pkt xbee_pkt; -.fi -.in -.sp -Most of these fields are fairly self explanatory, however some need attention brought to them -and others need explaining. I will touch on the most important here: -.TP -.B atCmd -This is the 2 character identifier for the AT command response you just recieved. -Of course if you didnt setup an AT connection, you should never see, or try to see data here. -.TP -.BR Addr64 " and " Addr16 -These contain the address of the XBee that you recieved the packet from. You should really know this -because you setup the connection. However remote AT packets will contain both 16 and 64 bit -addresses. -.TP -.B data -This is the data you just recieved. Either the AT reponse, or the data from the remote XBee node. -.TP -.B datalen -Would you be suprised if I told you this is how much data there is?... Dont try and -.BR printf () -the -.B data -as it isn't null terminated. Use this for processing instead. -.fi -.in -.SH AUTHOR -Attie Grande -.SH "SEE ALSO" -.BR libxbee (3), -.BR xbee_getpacket (3) diff --git a/libs/thirdParty/libxbee/man/man3/xbee_purgecon.3 b/libs/thirdParty/libxbee/man/man3/xbee_purgecon.3 deleted file mode 100644 index e64ccedb26c6eed86c4ec13a5d8cbb107cdd6efe..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_purgecon.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_newcon.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_senddata.3 b/libs/thirdParty/libxbee/man/man3/xbee_senddata.3 deleted file mode 100644 index 10296bb8c12be3e6ad2c7e4420123a9f9a869ac4..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_senddata.3 +++ /dev/null @@ -1,86 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH XBEE_SENDDATA 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -xbee_senddata, xbee_nsenddata, xbee_vsenddata -.SH SYNOPSIS -.B #include -.sp -.BI "int xbee_senddata(xbee_con *" con ", char *" format ", ...);" -.sp -.BI "int xbee_nsenddata(xbee_con *" con ", char *" data ", int " length ");" -.sp -.B #include -.sp -.BI "int xbee_vsenddata(xbee_con *" con ", char *" format ", va_list " ap "); -.ad b -.SH DESCRIPTION -The -.BR xbee_senddata () -function will send data via a provided connection. -It takes at least 2 arguments, and possibly more depending on the format string. -.sp -The argument -.I con -points to a connection made previously with -.BR xbee_newcon (). -.sp -The -.I format -string and any following parameters are passed to -.BR snprintf () -within these functions. -Please see the -.BR printf (3) -man page for more information. -.sp -If you are using -.BR xbee_nsenddata () -you must provide a character array of the data, and the data's length. -.sp -If you are using -.BR xbee_vsenddata () -you must provide a va_list. See -.BR stdarg (3). -.SH "RETURN VALUE" -Upon successful completion, these functions return 0. -.sp -If an invalid packet or connection was provided, -1 is returned. -.sp -If an unknown error occured, -2 is returned. -.sp -If -.I con -has -.I waitforACK -enabled, then these functions return 1 when an ACK was not recieved within 1 second. -.SH EXAMPLE -To send the string "Hello World!" through a previously made connection: -.in +4n -.nf -#include -xbee_senddata(con,"Hello World!"); -.fi -.in -.SH AUTHOR -Attie Grande -.SH "SEE ALSO" -.BR libxbee (3), -.BR xbee_setup (3), -.BR xbee_newcon (3), -.BR xbee_getpacket (3) diff --git a/libs/thirdParty/libxbee/man/man3/xbee_setup.3 b/libs/thirdParty/libxbee/man/man3/xbee_setup.3 deleted file mode 100644 index 2628c46f71f4cd59789dfa5636d35293bd83e6d2..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_setup.3 +++ /dev/null @@ -1,108 +0,0 @@ -.\" libxbee - a C library to aid the use of Digi's Series 1 XBee modules -.\" running in API mode (AP=2). -.\" -.\" Copyright (C) 2009 Attie Grande (attie@attie.co.uk) -.\" -.\" This program is free software: you can redistribute it and/or modify -.\" it under the terms of the GNU General Public License as published by -.\" the Free Software Foundation, either version 3 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program. If not, see . -.TH XBEE_SETUP 3 2009-11-01 "GNU" "Linux Programmer's Manual" -.SH NAME -xbee_setup, xbee_setuplog, xbee_setupAPI, xbee_setuplogAPI -.SH SYNOPSIS -.B #include -.sp -.BI "int xbee_setup(char *" path ", int " baudrate ");" -.sp -.BI "int xbee_setuplog(char *" path ", int " baudrate ", int " logfd ");" -.sp -.BI "int xbee_setupAPI(char *" path ", int " baudrate ", char " cmdSeq ", int " cmdTime ");" -.sp -.BI "int xbee_setuplogAPI(char *" path ", int " baudrate ", int " logfd ", char " cmdSeq ", int " cmdTime ");" -.ad b -.SH DESCRIPTION -.sp -.B A VERSION OF THIS FUNCTION MUST BE CALLED BEFORE ANY OTHER libxbee FUNCTION! -The -.BR xbee_setup () -function will setup libxbee so that it can handle an XBee. -It takes 2 arguments. -.sp -The argument -.I path -is the path to the serial port that the XBee is connected to (e.g. /dev/ttyUSB0). -.sp -The -.I baudrate -is the baud rate that the local XBee is configured to run at. The following are avaliable: -.in +2n -.nf -.B 1200 -.B 2400 -.B 4800 -.B 9600 -.B 19200 -.B 38400 -.B 57600 -.BR 115200 " - this is potentially unstable (read the XBee manual to find out why...)" -.fi -.in -.sp -Using -.BR xbee_setuplog () -is exactly the same, but instead you give an open file descriptor. All log messages will be written to this file (you can use stderr or stdout if you want!). NOTE: The file descriptor is -.BR dup ()'ed -before use, so you may close it immediately. Providing a value of -.B 0 -will disable the log output. -.sp -Using -.BR xbee_setupAPI () -is exactly the same, but instead you provide the 'Command Sequence' character and the 'Guard Time' that your local XBee has been configured with. -libxbee will then place your XBee in API mode 2, and when you call -.BR xbee_end () -it will return your XBee to its previous API mode. -.sp -Using -.BR xbee_setuplogAPI () -is simply a combination of -.BR xbee_setuplog () -and -.BR xbee_setupAPI () -.SH "RETURN VALUE" -If any error occures, -.B -1 -is returned. Otherwise -.B 0 -is returned. -.SH EXAMPLE -To setup libxbee to use /dev/ttyUSB0 at 57600 baud: -.in +4n -.nf -#include -if (xbee_setup("/dev/ttyUSB0",57600) == -1) { - printf("Oh no...\n"); - exit(1); -} -.fi -.in -.SH NOTE -If libxbee is compiled with -.B DEBUG -defined, then the log output will ALWAYS be enabled. If no file descriptor is provided, then stderr will be used. -.SH AUTHOR -Attie Grande -.SH "SEE ALSO" -.BR libxbee (3), -.BR xbee_newcon (3), -.BR xbee_getpacket (3), -.BR xbee_senddata (3) diff --git a/libs/thirdParty/libxbee/man/man3/xbee_setupAPI.3 b/libs/thirdParty/libxbee/man/man3/xbee_setupAPI.3 deleted file mode 100644 index 56a5fcac56acdd751ad631991f2ba13495fc9fea..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_setupAPI.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_setup.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_setuplog.3 b/libs/thirdParty/libxbee/man/man3/xbee_setuplog.3 deleted file mode 100644 index 56a5fcac56acdd751ad631991f2ba13495fc9fea..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_setuplog.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_setup.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_setuplogAPI.3 b/libs/thirdParty/libxbee/man/man3/xbee_setuplogAPI.3 deleted file mode 100644 index 56a5fcac56acdd751ad631991f2ba13495fc9fea..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_setuplogAPI.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_setup.3 diff --git a/libs/thirdParty/libxbee/man/man3/xbee_vsenddata.3 b/libs/thirdParty/libxbee/man/man3/xbee_vsenddata.3 deleted file mode 100644 index b36885d8542376a90c89c5864563bd12398a3cd0..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/man/man3/xbee_vsenddata.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/xbee_senddata.3 diff --git a/libs/thirdParty/libxbee/notes/Notepad++ Style.xml b/libs/thirdParty/libxbee/notes/Notepad++ Style.xml deleted file mode 100644 index 5e56ab9ce39d3f848af6ea05bc753c76fa08db27..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/notes/Notepad++ Style.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - 000000 - - - - - _xbee_nsenddata(): xbee_send_pkt(): - xbee_listen(): - _xbee_logit(): - _xbee_getpacket(): - - - - - - - - - - - - - - - - - - - diff --git a/libs/thirdParty/libxbee/notes/v1-v2.txt b/libs/thirdParty/libxbee/notes/v1-v2.txt deleted file mode 100644 index cb2e1c923dd418a905c61879eecd69ca14118613..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/notes/v1-v2.txt +++ /dev/null @@ -1,29 +0,0 @@ -XBee -0x8A* Modem Status -0x08* AT Command -0x09* AT Command (Queue) -0x88* AT Command Response -0x17* Remote AT Command Request -0x97* Remote AT Command Response -0x00* Tx Request (64-bit) -0x01* Tx Request (16-bit) -0x89* Tx Status -0x80* Rx Data (64-bit) -0x81* Rx Data (16-bit) - -XBee 2.5 -0x8A* Modem Status -0x08* AT Command -0x09* AT Command (Queue) -0x88* AT Command Response -0x17* Remote AT Command Request -0x97* Remote AT Command Response -0x10* ZigBee Transmit Request -0x11 Explicit Addressing ZigBee Command Frame -0x8B* ZigBee Transmit Status -0x90* ZigBee Recieve Packet -0x91 ZigBee Explicit Rx -0x92 ZigBee IO Data Sample Rx -0x94 Xbee Sensor Read -0x95 Node Identification - diff --git a/libs/thirdParty/libxbee/pdf/api.c.pdf b/libs/thirdParty/libxbee/pdf/api.c.pdf deleted file mode 100644 index dc8c75af3cb7130fa8716de8a733fd3a3fe13ba3..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/pdf/api.c.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/pdf/api.h.pdf b/libs/thirdParty/libxbee/pdf/api.h.pdf deleted file mode 100644 index 43d99a493e1864ab981612be1960ae6e71117f56..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/pdf/api.h.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/pdf/main.c.pdf b/libs/thirdParty/libxbee/pdf/main.c.pdf deleted file mode 100644 index 4410e6b8e4d9f3a95779694316ce6943da6202e7..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/pdf/main.c.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/pdf/xbee.h.pdf b/libs/thirdParty/libxbee/pdf/xbee.h.pdf deleted file mode 100644 index a4ee0d754dea35167f2c622db520a173d2fcd0e6..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/pdf/xbee.h.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/sample/README b/libs/thirdParty/libxbee/sample/README deleted file mode 100644 index 3610d034694527c4111e1e8a08652f882ff26b74..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/README +++ /dev/null @@ -1,12 +0,0 @@ -To use these samples, you must first install libxbee. -To install, simply type `make install` and provide the root password. - -If you cannot install the library for any reason, follow these instructions: - http://code.google.com/p/libxbee/wiki/install_libxbee#But_I_can't_install_it! - -The compile line can be found at the top of the source files, surrounded by #ifdef -and #endif. These allow us to run the source file as a shell script. Simply type -`sh simple.c` to compile the simple sample. -If you do not have the library installed, you must edit the compile line, or type -it by hand. - gcc .c ../obj/api.o -o -lpthread -lrt diff --git a/libs/thirdParty/libxbee/sample/analog.c b/libs/thirdParty/libxbee/sample/analog.c deleted file mode 100644 index 84069e39a25e3be537c8c94c45b5e55e947147b8..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/analog.c +++ /dev/null @@ -1,71 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will output the voltage read from analog 0 */ - -#include -#include -#include - -/* set this to the voltage measured between GND and Vref - 3.3 is a good place to start */ -#define Vref 3.3 - -int main(int argc, char *argv[]) { - xbee_con *con; - xbee_pkt *pkt; - int i; - - /* setup libxbee */ - if (xbee_setup("/dev/ttyUSB0",57600) == -1) { - return 1; - } - - /* get a connection to the remote XBee */ - con = xbee_newcon('I',xbee_64bitIO, 0x13A200, 0x403CB26A); - /* do this forever! */ - while (1) { - /* get as many packets as we can */ - while ((pkt = xbee_getpacket(con)) != NULL) { - for (i = 0; i < pkt->samples; i++) { - /* did we get a value for A0? */ - if (!xbee_hasanalog(pkt,i,0)) { - /* there was no data for A0 in the packet */ - printf("A0: -- No Data --\n"); - continue; - } - /* print out the reading in raw, and adjusted */ - printf("A0: %.0f (~%.2fv)\n", - xbee_getanalog(pkt,i,0,0), - xbee_getanalog(pkt,i,0,Vref)); - fflush(stdout); - } - /* release the packet */ - free(pkt); - } - usleep(100); - } - - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/api.c b/libs/thirdParty/libxbee/sample/api.c deleted file mode 100644 index cff70bf1ae9e643b220520753e7cf8493440ac81..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/api.c +++ /dev/null @@ -1,42 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -g -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will show you how to seup the xbee and ensure that it is in API mode */ - -#include -#include -#include - -int main(int argc, char *argv[]) { - /* the extra arguments are the CC ('+' by default) and GT (1000) by default AT values */ - xbee_setuplogAPI("/dev/ttyUSB0",57600,2,'+',1000); - - /* now we can do our stuff! */ - sleep(10); - - /* calling xbee_end() will return the xbee to its previous API mode */ - xbee_end(); - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/atis.c b/libs/thirdParty/libxbee/sample/atis.c deleted file mode 100644 index 66946f184820cf3216089c8d8ffe2a6445523d4d..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/atis.c +++ /dev/null @@ -1,81 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will output the voltage read from analog 0 */ - -#include -#include -#include - -/* set this to the voltage measured between GND and Vref - 3.3 is a good place to start */ -#define Vref 3.3 - -int main(int argc, char *argv[]) { - xbee_con *con; - xbee_pkt *pkt; - - /* setup libxbee */ - if (xbee_setup("/dev/ttyUSB0",57600) == -1) { - printf("xbee_setup failed...\n"); - return 1; - } - - /* create an AT connection */ - con = xbee_newcon('I',xbee_64bitRemoteAT,0x13A200,0x403CB26A); - - /* do this forever! */ - for (;;) { - /* request samples now! */ - xbee_senddata(con,"IS"); - /* get as many packets as we can */ - while ((pkt = xbee_getpacketwait(con)) != NULL) { - if (pkt) { - if (pkt->status != 0x00) { - /* if the return status was not 0x00 (OK) then the request failed... */ - printf("Sample A0: -- Request Failed --\n"); - } else { - if (!xbee_hasanalog(pkt,0,0)) { - /* there was no data for A0 in the packet */ - printf("Sample A0: -- No Data --\n"); - } else { - /* it appears that there is sample data for A0! */ - printf("Sample A0: %.0f (~%.2fv)\n", - xbee_getanalog(pkt,0,0,0), - xbee_getanalog(pkt,0,0,Vref)); - } - } - /* dont forget to free the packet! */ - free(pkt); - } else { - /* couldnt get a packet */ - printf("Sample A0: -- No Packet Returned --\n"); - } - } - /* wait a second for the next sample */ - sleep(1); - } - - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/atsetup.c b/libs/thirdParty/libxbee/sample/atsetup.c deleted file mode 100644 index 13afbe4169882f94c6de568370c0de3e6a7f3741..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/atsetup.c +++ /dev/null @@ -1,157 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will setup certain AT parameters of the local XBee unit */ - -#include -#include -#include -#include - -/* con = connection to use - cmd = 2 character command string, eg NI - parameter = NULL - no parameter - !NULL - command parameter, either NULL terminated string, or block of memory - length = 0 - use parameter as NULL terminated string - !0 - use 'length' bytes from parameter - ret = NULL - don't return anything - !NULL - pointer to pointer. doAT will allocate memory, you must free it! - str = return data pointer - - returns the length of the data in ret, or -ve for error */ -int doAT(xbee_con *con, char *cmd, char *parameter, int length, unsigned char **ret) { - xbee_pkt *pkt; - if (con->type != xbee_localAT && con->type != xbee_16bitRemoteAT && con->type != xbee_64bitRemoteAT) { - printf("Thats not an AT connection!...\n"); - return -1; - } - if (strlen(cmd) != 2) { - printf("Invalid command: \"%s\"\n",cmd); - return -2; - } - if (parameter == NULL) { - xbee_senddata(con,"%s",cmd); - } else if (length != 0) { - char *tmp; - if ((tmp = malloc(1024)) == NULL) { - printf("Failed to get memory!\n"); - return -3; - } - snprintf(tmp,1024,"%s",cmd); - memcpy(&(tmp[2]),parameter,(length>1022)?1022:length); - xbee_nsenddata(con,tmp,length+2); - free(tmp); - } else { - xbee_senddata(con,"%s%s",cmd,parameter); - } - pkt = xbee_getpacketwait(con); - if (pkt == NULL) { - printf("Failed to set %s!\n",cmd); - return -4; - } - if (pkt->status != 0) { - printf("An error occured while setting %s!\n",cmd); - return -5; - } - if (ret && pkt->datalen > 0) { - *ret = realloc(*ret,sizeof(char) * (pkt->datalen + 1)); - memcpy(*ret,pkt->data,pkt->datalen); - (*ret)[pkt->datalen] = '\0'; - free(pkt); - return pkt->datalen; - } - free(pkt); - return 0; -} - -int main(int argc, char *argv[]) { - xbee_con *con; - int ret,i; - unsigned char *str = NULL; - - if (argc != 2) { - printf("Usage: %s \n",argv[0]); - return 1; - } - - /* setup libxbee */ - if (xbee_setup("/dev/ttyUSB0",57600) == -1) { - printf("xbee_setup failed...\n"); - return 1; - } - - /* create an AT connection */ - con = xbee_newcon('I',xbee_localAT); - /*con = xbee_newcon('I',xbee_64bitRemoteAT,0x13A200,0x403CB26A);*/ - - - /* get the node's address! */ - if ((ret = doAT(con,"SH",NULL,0,&str)) < 0) return 1; - if (ret == 4) { - printf("SH: 0x%02X%02X%02X%02X\n", str[0], str[1], str[2], str[3]); - } - if ((ret = doAT(con,"SL",NULL,0,&str)) < 0) return 1; - if (ret == 4) { - printf("SL: 0x%02X%02X%02X%02X\n", str[0], str[1], str[2], str[3]); - } - - /* set the power level - 2 methods, i prefer the first but it generates compile warnings :( */ - /*if ((ret = doAT(con,"PL",&((unsigned char[]){4}),1,&str)) < 0) return 1;*/ - /*{ - char t[] = {0}; - if ((ret = doAT(con,"PL",t,1,&str)) < 0) return 1; - }*/ - - /* get the power level */ - if ((ret = doAT(con,"PL",NULL,0,&str)) < 0) return 1; - if (ret == 1) { - printf("PL: 0x%02X\n", str[0]); - } - - /* get NI */ - if ((ret = doAT(con,"NI",NULL,0,&str)) < 0) return 1; - if (ret > 0) { - printf("NI: "); - for (i = 0; i < ret; i++) { - printf("%c",(str[i]>=32 && str[i]<=126)?str[i]:'.'); - } - printf("\n"); - } - - printf("Setting NI to '%s': ",(argc!=2)?"MyNode":argv[1]); - if ((ret = doAT(con,"NI",(argc!=2)?"MyNode":argv[1],0,NULL)) < 0) return 1; - printf("OK\n"); - - if ((ret = doAT(con,"NI",NULL,0,&str)) < 0) return 1; - if (ret > 0) { - printf("NI: "); - for (i = 0; i < ret; i++) { - printf("%c",(str[i]>=32 && str[i]<=126)?str[i]:'.'); - } - printf("\n"); - } - - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/callback.c b/libs/thirdParty/libxbee/sample/callback.c deleted file mode 100644 index 9e48276b0fcba221e7f294ae07d53822314bd768..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/callback.c +++ /dev/null @@ -1,88 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will return any recieved data, using a callback function */ - -#include -#include -#include -#include - -void sighandler(int sig) { - xbee_pkt *pkt; - if (sig == SIGINT) { - xbee_end(); - exit(0); - } -} - -void callback(xbee_con *con, xbee_pkt *pkt) { - int ret; - /* print the recieved data */ - printf("Rx: %s\n",pkt->data); - /* say thank you */ - if ((ret = xbee_senddata(con,"%s",pkt->data)) != 0) { - printf("xbee_senddata: Error %d... Retrying!\n",ret); - if ((ret = xbee_senddata(con,"%s",pkt->data)) != 0) { - printf("xbee_senddata: Error %d... Data lost!\n",ret); - } else { - printf("xbee_senddata: Success after retry!\n",ret); - } - } -free(pkt); -} - -int main(int argc, char *argv[]) { - xbee_con *con; - xbee_pkt *pkt, *rpkt; - - /* setup the xbee */ - //if (xbee_setupAPI("/dev/ttyUSB0",57600,'+',250) == -1) { - //if (xbee_setuplogAPI("/dev/ttyUSB0",57600,2,'+',250) == -1) { - if (xbee_setuplog("/dev/ttyUSB0",57600,2) == -1) { - /* oh no... it failed */ - printf("xbee_setup() failed...\n"); - exit(1); - } - - /* handle ^C */ - signal(SIGINT, sighandler); - - /* setup a connection */ - con = xbee_newcon('I',xbee_64bitData, 0x0013A200, 0x40081826); - con->waitforACK = 1; - con->callback = callback; - - printf("Waiting...\n"); - - /* do nothing forever! */ - for (;;) { - sleep(86400); /* 24hrs */ - } - - /* shouldn't ever get here but... */ - return 0; -} - diff --git a/libs/thirdParty/libxbee/sample/digital.c b/libs/thirdParty/libxbee/sample/digital.c deleted file mode 100644 index 4b0c9f63310654ae56cdd006b8d443c359b2e505..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/digital.c +++ /dev/null @@ -1,146 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -g -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will control digital output pins of a chosen node */ - -#include -#include -#include -#include - -int mode; -char bitmask; -char outputs; - -void sighandler(int sig) { - if (sig == SIGINT) { - xbee_end(); - exit(0); - } -} - -void doneCB(xbee_con *con, xbee_pkt *pkt) { - /* this packet should be confirmation... */ - xbee_end(); - exit(0); -} -void doCB(xbee_con *con, xbee_pkt *pkt) { - int i,m; - outputs = pkt->IOdata[0].IOdigital; - printf("\n 7 6 5 4 3 2 1 0\n"); - printf("Current output state: "); - for (i = 0; i < 8; i++) { - if (xbee_hasdigital(pkt,0,7-i)) { - if (xbee_getdigital(pkt,0,7-i)) { - printf(" 1"); - } else { - printf(" 0"); - } - } else { - printf(" x"); - } - } - printf("\n"); - switch (mode) { - case 0: outputs |= bitmask; break; - case 1: outputs &= ~bitmask; break; - case 2: default: - xbee_end(); - exit(0); - } - m = outputs; - printf("New output state: "); - for (i = 0; i < 8; i++) { - if (xbee_hasdigital(pkt,0,7-i)) { - if (m & 0x80) { - printf(" 1"); - } else { - printf(" 0"); - } - } else { - printf(" x"); - } - m <<= 1; - } - printf("\n\n"); - con->callback = doneCB; - xbee_senddata(con,"IO%c",outputs); -} - -void usage(char *argv0) { - printf("Usage: %s \n",argv0); - printf("Usage: %s [port[0-7]]...\n",argv0); - exit(1); -} -int main(int argc, char *argv[]) { - xbee_con *con; - - if (argc < 2) usage(argv[0]); - - if (!strcasecmp(argv[1],"on")) { - mode = 0; - } else if (!strcasecmp(argv[1],"off")) { - mode = 1; - } else if (!strcasecmp(argv[1],"query")) { - mode = 2; - } else usage(argv[0]); - - if (mode != 2) { - int i; - char *c; - bitmask = 0; - c = argv[2]; - while (*c != '\0') { - *c -= '0'; - if ((*c >= 0) && (*c <= 7)) { - bitmask |= 0x01 << *c; - } else { - usage(argv[0]); - } - c++; - } - } - - /* setup libxbee */ - if (xbee_setupAPI("/dev/ttyUSB0",57600,'+',250) == -1) { - return 1; - } - - /* handle ^C */ - signal(SIGINT, sighandler); - - /* get a connection to the remote XBee */ - con = xbee_newcon('I',xbee_64bitRemoteAT, 0x0013A200, 0x403CB26B); - con->waitforACK = 1; - con->callback = doCB; - - xbee_senddata(con,"IS"); - - /* timeout after 1 second... */ - sleep(1); - - xbee_end(); - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/digitalout.c b/libs/thirdParty/libxbee/sample/digitalout.c deleted file mode 100644 index 46db084f1381fba9c34d0ebaadfdbc6905748d19..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/digitalout.c +++ /dev/null @@ -1,128 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will control the digital 0 output from the keyboard. Type: - 0, - off - 1, - on - q, - quit */ - -#include -#include -#include - -#include - -int main(int argc,char *argv[]) { - xbee_con *con; - xbee_pkt *pkt; - - printf("Hello\n"); - - if (xbee_setup("/dev/ttyUSB0",57600) == -1) { - printf("failed to setup xbee\n"); - return 1; - } - - con = xbee_newcon('R',xbee_64bitRemoteAT,0x0013a200,0x403af247); - if (!con) { - printf("no connection returned\n"); - return 1; - } - - for (;;) { - - xbee_senddata(con,"D0"); - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("no packet returned from state probe\n"); - return 1; - } - - if (pkt->status != 0) { - printf("state probe failed (ret=0x%02X - ",pkt->status); - switch (pkt->status) { - case 0x1: printf("Error"); break; - case 0x2: printf("Invalid Command"); break; - case 0x3: printf("Invalid Parameter"); break; - case 0x4: printf("No Response"); break; - default: printf("Unknown"); break; - } - printf(")\n"); - return 1; - } - - if (pkt->datalen != 1) { - printf("unexpected datalen from state probe\n"); - return 1; - } - - if (pkt->data[0] == 0x05) { - printf("this port is currently ON\n"); - } else if (pkt->data[0] == 0x04) { - printf("this port is currently OFF\n"); - } else { - printf("this port is currently in an unknown state\n"); - return 1; - } - free(pkt); - pkt = NULL; - - recharprompt: - printf("--> "); - rechar: - switch(getchar()) { - case 'q': case 'Q': - printf("byebye\n"); - return 0; - case '0': - printf("turning off...\n"); - xbee_senddata(con,"D0%c",0x04); - break; - case '1': - printf("turning on...\n"); - xbee_senddata(con,"D0%c",0x05); - break; - case '\n': goto rechar; - default: goto recharprompt; - } - - if ((pkt = xbee_getpacketwait(con)) != NULL) { - if (pkt->status != 0) { - printf("state set failed (ret=0x%02X - ",pkt->status); - switch (pkt->status) { - case 0x1: printf("Error"); break; - case 0x2: printf("Invalid Command"); break; - case 0x3: printf("Invalid Parameter"); break; - case 0x4: printf("No Response"); break; - default: printf("Unknown"); break; - } - printf(")\n"); - return 1; - } - } - - } - - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/multi.c b/libs/thirdParty/libxbee/sample/multi.c deleted file mode 100644 index 107f88f6e9b7a570e293e50edf47e63016afc4be..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/multi.c +++ /dev/null @@ -1,100 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -g -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will make use of multiple instances of libxbee and send messages between the attached XBees */ - -#include -#include -#include -#include - -int mode; -char bitmask; -char outputs; - -xbee_hnd xbee1; -xbee_hnd xbee2; - -void sighandler(int sig) { - if (sig == SIGINT) { - _xbee_end(xbee1); - _xbee_end(xbee2); - exit(0); - } -} - -void xbee1CB(xbee_con *con, xbee_pkt *pkt) { - char data[128]; - snprintf(data,pkt->datalen+1,"%s",pkt->data); - printf("XBee1: Rx[%3d]: %s\n",pkt->datalen,data); -} - -void xbee2CB(xbee_con *con, xbee_pkt *pkt) { - char data[128]; - snprintf(data,pkt->datalen+1,"%s",pkt->data); - printf("XBee2: Rx[%3d]: %s\n",pkt->datalen,data); -} - -int main(int argc, char *argv[]) { - xbee_con *con1; - xbee_con *con2; - - if (!(xbee1 = _xbee_setuplogAPI("/dev/ttyUSB0",57600,3,'+',250))) { - //if (!(xbee1 = _xbee_setupAPI("/dev/ttyUSB0",57600,'+',250))) { - printf("xbee1: setup error...\n"); - return 1; - } - if (!(xbee2 = _xbee_setuplogAPI("/dev/ttyUSB1",57600,4,'+',250))) { - //if (!(xbee2 = _xbee_setupAPI("/dev/ttyUSB1",57600,'+',250))) { - printf("xbee2: setup error...\n"); - return 1; - } - - /* handle ^C */ - signal(SIGINT, sighandler); - - con1 = _xbee_newcon(xbee1,'1',xbee_64bitData, 0x0013A200, 0x40081826); - con1->waitforACK = 1; - con1->callback = xbee1CB; - - con2 = _xbee_newcon(xbee2,'2',xbee_64bitData, 0x0013A200, 0x404B75DE); - con2->waitforACK = 1; - con2->callback = xbee2CB; - - while (1) { - printf("xbee1: Tx\n"); - _xbee_logit(xbee1,"xbee1: Tx"); - _xbee_logit(xbee2,"xbee1: Tx"); - _xbee_senddata(xbee1,con1,"Hello"); - usleep(1000000); - printf("xbee2: Tx\n"); - _xbee_logit(xbee1,"xbee2: Tx"); - _xbee_logit(xbee2,"xbee2: Tx"); - _xbee_senddata(xbee2,con2,"Hi There!"); - usleep(1000000); - } - - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/scan.c b/libs/thirdParty/libxbee/sample/scan.c deleted file mode 100644 index 4546887f9e541782a5b512213ffe72860185f359..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/scan.c +++ /dev/null @@ -1,144 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will scan the currently configured channel for all nodes, - returning the values of a few useful settings */ - -#include -#include -#include -#include -#include -#include - -#define MAXNODES 100 - -int main(int argc, char *argv[]) { - int i; - int saidfull = 0; - int ATNT = 0x19; /* node discover timeout */ - int ATNTc; /* counter */ - - int nodes = 0; - char addrs[MAXNODES][8]; - - xbee_con *con; - xbee_pkt *pkt, *rpkt; - - time_t ttime; - char stime[32]; - - /* setup libxbee */ - if (xbee_setup("/dev/ttyUSB0",57600) == -1) { - return 1; - } - - /* grab a local AT connection */ - con = xbee_newcon('I',xbee_localAT); - - /* get the ND timeout */ - xbee_senddata(con,"NT"); - if ((rpkt = xbee_getpacketwait(con)) == NULL) { - printf("XBee didnt return a result for NT\n"); - return 1; - } - ATNT = rpkt->data[0]; - free(rpkt); - - while (1) { - /* send a ND - Node Discover request */ - xbee_senddata(con,"ND"); - /* only wait for a bit longer than the ND timeout */ - ATNTc = ATNT + 10; - /* loop until the end packet has been received or timeout reached */ - while (ATNTc--) { - /* get a packet */ - pkt = xbee_getpacketwait(con); - /* check a packet was returned, and that its one we are after... */ - if (pkt && !memcmp(pkt->atCmd,"ND",2)) { - /* is this the end packet? you can tell from the 0 datalen */ - if (pkt->datalen == 0) { - /* free the packet */ - free(pkt); - break; - } else { - /* check if we know this node already */ - for (i = 0; i < nodes; i++) { - /* the 64bit address will match one in the list */ - if (!memcmp(&(pkt->data[2]),&(addrs[i]),8)) break; - } - ttime = time(NULL); - strftime(stime,32,"%I:%M:%S %p",gmtime(&ttime)); - /* is there space for another? */ - if ((i == nodes) && - (nodes == MAXNODES) && - (!saidfull)) { - printf("MAXNODES reached... Can't add more...\r"); - /* flush so the change is seen! */ - fflush(stdout); - saidfull = 1; - } else { - /* is this a rewrite? */ - if (i != nodes) { - /* find the line to edit */ - printf("%c[%dA",27,nodes-i); - /* clear the line */ - printf("%c[2K",27); - } - /* write out the info */ - memcpy(&(addrs[nodes]),&(pkt->data[2]),8); - printf("MY: 0x%02X%02X ",pkt->data[0],pkt->data[1]); - printf("SH: 0x%02X%02X%02X%02X ",pkt->data[2],pkt->data[3],pkt->data[4],pkt->data[5]); - printf("SL: 0x%02X%02X%02X%02X ",pkt->data[6],pkt->data[7],pkt->data[8],pkt->data[9]); - printf("dB: -%2d ",pkt->data[10]); - printf("NI: %-20s ",&(pkt->data[11])); - printf("@: %s",stime); - /* is this a rewrite? */ - if (i != nodes) { - /* go back the the bottom */ - printf("%c[%dB\r",27,nodes-i); - } else { - /* new line is only wanted for new nodes */ - printf("\n"); - /* if not, then add 1 to the number of nodes! */ - nodes++; - } - } - /* flush so the change is seen! */ - fflush(stdout); - } - /* free the packet */ - free(pkt); - } - /* sleep for 100ms (same as NT steps) */ - usleep(100000); - } - /* try again! */ - usleep(100000); - } - - return 0; -} - diff --git a/libs/thirdParty/libxbee/sample/scan_adv.c b/libs/thirdParty/libxbee/sample/scan_adv.c deleted file mode 100644 index d3360222cc690f23d6032b6919072ec7377a1664..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/scan_adv.c +++ /dev/null @@ -1,589 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will scan all possible channels for remote nodes and return - the value of a few useful settings */ - -#include -#include -#include -#include -#include -#include -#include - -#define MAXNODES 100 - -int ATCH = 0x0C; /* origional channel number */ -int ATNT = 0x19; /* node discover timeout */ -int ATNTc; /* node discover timeout counter */ -int BREAK = 0; -xbee_con *con; - -void sighandler(int sig) { - xbee_pkt *pkt; - if (sig == SIGINT) { - BREAK = 1; - /* wait for the rest of the timeout... */ - printf("\r%c[2KWaiting for node discover command to timeout...",27); - fflush(stdout); - for (; ATNTc; ATNTc--) { - usleep(100000); - } - /* Restore the XBee's channel setting */ - printf("\r%c[2KRestoring channel to 0x%02X...",27,ATCH); - fflush(stdout); - if (xbee_senddata(con,"CH%c",ATCH)) { - printf("xbee_senddata: Error\n"); - exit(1); - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\r%c[2K*** XBee didnt return a result for CH... ***\nPlease manually reset your channel to 0x%02X\n",27,ATCH); - } - if (pkt->status) { - printf("\r%c[2K*** An error occured while restoring the channel setting... ***\nPlease manually reset your channel to 0x%02X\n",27,ATCH); - } else { - printf("\nDone!\n"); - } - free(pkt); - /* Restore the terminal */ - printf("%c[?25h%c[0m",27,27); - fflush(stdout); - exit(0); - } -} - -int main(int argc, char *argv[]) { - int i; - int saidfull = 0; - int ATCHc; /* current channel number */ - int XBeePro = 0; /* XBee pro? */ - - int nodes = 0; - unsigned char addrs[MAXNODES][19]; /* 0-7 : 64 bit address - 8 : channel - 9-10 : id - 11 : baud - 12 : API - 13-14: HV - 15-16: VR - 17 : CC - 18 : mask - not address */ - - xbee_pkt *pkt, *rpkt; - - time_t ttime; - char stime[32]; - - /* handle ^C */ - signal(SIGINT, sighandler); - - /* setup libxbee */ - if (xbee_setupAPI("/dev/ttyUSB0",57600,'+',250) == -1) { - return 1; - } - - /* grab a local AT connection */ - con = xbee_newcon('I',xbee_localAT); - - /* get the current channel */ - if (xbee_senddata(con,"CH")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("XBee didnt return a result for CH\n"); - return 1; - } - ATCH = pkt->data[0]; - free(pkt); - - /* XBee - 0x0B - 0x1A - XBee Pro - 0x0C - 0x17 */ - if (xbee_senddata(con,"CH%c",0x0B)) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("XBee didnt return a result for CH\n"); - return 1; - } - /* did that fail? */ - if (pkt->status == 0) { - /* nope.. its not a pro */ - printf("Using XBee (not Pro) channels (0x0B - 0x1A)...\n"); - XBeePro = 0; - ATCHc = 0x0B; - } else { - /* yup... its a pro */ - printf("Using XBee Pro channels (0x0C - 0x17)...\n"); - XBeePro = 1; - ATCHc = 0x0C; - } - free(pkt); - - /* find and print data for the local node */ - printf("\n%c[31mCH:%c[32m 0x%02X ",27,27,ATCH); - if (xbee_senddata(con,"ID")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for ID\n"); - return 1; - } - printf("%c[31mID:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]); - free(pkt); - /* ### */ - if (xbee_senddata(con,"MY")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for MY\n"); - return 1; - } - printf("%c[31mMY:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]); - free(pkt); - /* ### */ - if (xbee_senddata(con,"SH")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for SH\n"); - return 1; - } - printf("%c[31mSH:%c[32m 0x%02X%02X%02X%02X ",27,27,pkt->data[0],pkt->data[1],pkt->data[2],pkt->data[3]); - free(pkt); - /* ### */ - if (xbee_senddata(con,"SL")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for SL\n"); - return 1; - } - printf("%c[31mSL:%c[32m 0x%02X%02X%02X%02X ",27,27,pkt->data[0],pkt->data[1],pkt->data[2],pkt->data[3]); - free(pkt); - /* ### */ - if (xbee_senddata(con,"BD")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for BD\n"); - return 1; - } - printf("%c[31mBD:%c[32m ",27,27); - /* print the baud rate */ - switch (pkt->data[3]) { - case 0: printf(" 1200"); break; - case 1: printf(" 2400"); break; - case 2: printf(" 4800"); break; - case 3: printf(" 9600"); break; - case 4: printf(" 19200"); break; - case 5: printf(" 38400"); break; - case 6: printf(" 57600"); break; - case 7: printf("115200"); break; - default: printf(" other"); break; - } - printf(" "); - free(pkt); - /* ### */ - if (xbee_senddata(con,"AP")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for AP\n"); - return 1; - } - printf("%c[31mAP:%c[32m 0x%02X ",27,27,pkt->data[0]); - free(pkt); - /* ### */ - if (xbee_senddata(con,"HV")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for HV\n"); - return 1; - } - printf("%c[31mHV:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]); - free(pkt); - /* ### */ - if (xbee_senddata(con,"VR")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for VR\n"); - return 1; - } - printf("%c[31mVR:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]); - free(pkt); - /* ### */ - if (xbee_senddata(con,"CC")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for CC\n"); - return 1; - } - printf("%c[31mCC:%c[32m '%c' (0x%02X) ",27,27,pkt->data[0],pkt->data[0]); - free(pkt); - /* ### */ - if (xbee_senddata(con,"NI")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("\nXBee didnt return a result for NI\n"); - return 1; - } - printf("%c[31mNI:%c[32m %-20s ",27,27,pkt->data); - free(pkt); - /* ### */ - printf("%c[95m* This is the lobal XBee *",27); - - printf("%c[34m\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------%c[0m\n\n",27,27); - - /* get the ND timeout */ - if (xbee_senddata(con,"NT")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if ((pkt = xbee_getpacketwait(con)) == NULL) { - printf("XBee didnt return a result for NT\n"); - return 1; - } - ATNT = pkt->data[0]; - free(pkt); - - printf("%c[?25l",27); - fflush(stdout); - - usleep(100000); - - while (!BREAK) { - /* set the channel to scan */ - if (xbee_senddata(con,"CH%c",ATCHc)) { - printf("xbee_senddata: Error\n"); - return 1; - } - pkt = xbee_getpacketwait(con); - if (!pkt || pkt->status) { - printf("\nXBee didnt return a result for CH\n"); - return 1; - } - free(pkt); - printf("%c[2KScanning channel 0x%02X...\r",27,ATCHc); - fflush(stdout); - /* send a ND - Node Discover request */ - if (!xbee_senddata(con,"ND")) { - /* only wait for a bit longer than the ND timeout */ - ATNTc = ATNT + 10; - /* loop until the end packet has been received or timeout reached */ - while (!BREAK && ATNTc--) { - /* get a packet */ - pkt = xbee_getpacket(con); - /* check a packet was returned, and that its one we are after... */ - if (pkt && !memcmp(pkt->atCmd,"ND",2)) { - /* is this the end packet? you can tell from the 0 datalen */ - if (pkt->datalen == 0) { - /* free the packet */ - free(pkt); - break; - } else { - /* check if we know this node already */ - for (i = 0; i < nodes; i++) { - /* the 64bit address will match one in the list */ - if (!memcmp(&(pkt->data[2]),&(addrs[i][0]),8)) break; - } - ttime = time(NULL); - strftime(stime,32,"%I:%M:%S %p",gmtime(&ttime)); - /* is there space for another? */ - if ((i == nodes) && - (nodes == MAXNODES) && - (!saidfull)) { - printf("%c[2KMAXNODES reached... Can't add more...\r",27); - /* flush so the change is seen! */ - fflush(stdout); - saidfull = 1; - } else { - /* is this a rewrite? */ - if (i != nodes) { - /* find the line to edit */ - printf("%c[%dA",27,nodes-i+1); - /* clear the line */ - printf("%c[2K",27); - } else { - /* fill the blank line */ - printf("%c[%dA",27,1); - } - /* save the channel */ - addrs[i][8] = ATCHc; - /* write out the info */ - printf("%c[31mCH:%c[32m 0x%02X ",27,27,ATCHc); - printf("%c[31mID:%c[32m 0x",27,27); - if (i == nodes || !(addrs[i][18] & 0x80)) { - printf("...."); - } else { - printf("%02X%02X",addrs[i][9],addrs[i][10]); - } - printf(" "); - printf("%c[31mMY:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]); - printf("%c[31mSH:%c[32m 0x%02X%02X%02X%02X ",27,27,pkt->data[2],pkt->data[3],pkt->data[4],pkt->data[5]); - printf("%c[31mSL:%c[32m 0x%02X%02X%02X%02X ",27,27,pkt->data[6],pkt->data[7],pkt->data[8],pkt->data[9]); - printf("%c[31mBD:%c[32m ",27,27); - if (i == nodes || !(addrs[i][18] & 0x40)) { - printf("......"); - } else { - switch (addrs[i][11]) { - case 0: printf(" 1200"); break; - case 1: printf(" 2400"); break; - case 2: printf(" 4800"); break; - case 3: printf(" 9600"); break; - case 4: printf(" 19200"); break; - case 5: printf(" 38400"); break; - case 6: printf(" 57600"); break; - case 7: printf("115200"); break; - default: printf(" other"); break; - } - } - printf(" "); - printf("%c[31mAP:%c[32m 0x",27,27); - if (i == nodes || !(addrs[i][18] & 0x20)) { - printf(".."); - } else { - printf("%02X",addrs[i][12]); - } - printf(" "); - printf("%c[31mHV:%c[32m 0x",27,27); - if (i == nodes || !(addrs[i][18] & 0x10)) { - printf("...."); - } else { - printf("%02X%02X",addrs[i][13],addrs[i][14]); - } - printf(" "); - printf("%c[31mVR:%c[32m 0x",27,27); - if (i == nodes || !(addrs[i][18] & 0x08)) { - printf("...."); - } else { - printf("%02X%02X",addrs[i][15],addrs[i][16]); - } - printf(" "); - printf("%c[31mCC:%c[32m ",27,27); - if (i == nodes || !(addrs[i][18] & 0x04)) { - printf(" . (0x..)"); - } else { - printf("'%c' (0x%02X)",addrs[i][17],addrs[i][17]); - } - printf(" "); - printf("%c[31mNI:%c[32m %-20s ",27,27,&(pkt->data[11])); - printf("%c[31mdB:%c[32m -%2d ",27,27,pkt->data[10]); - printf("%c[31m@:%c[32m %s",27,27,stime); - /* is this a rewrite? */ - if (i != nodes) { - /* go back the the bottom */ - printf("%c[%dB\r",27,nodes-i+1); - } else { - /* if its new... save the address */ - memcpy(&(addrs[nodes][0]),&(pkt->data[2]),8); - /* turn off all the flags */ - addrs[nodes][18] = 0; - /* new line is only wanted for new nodes */ - printf("\n%c[2K\n%c[0m",27,27); - /* if not, then add 1 to the number of nodes! */ - nodes++; - } - printf("%c[0m%c[2KScanning channel 0x%02X...\r",27,27,ATCHc); - fflush(stdout); - } - /* flush so the change is seen! */ - fflush(stdout); - } - /* free the packet */ - free(pkt); - } - /* sleep for 100ms (same as NT steps */ - usleep(100000); - } - } - fflush(stdout); - /* check for all nodes on this channel, and get thier pan id */ - for (i = 0; i < nodes; i++) { - int first = 1; - if (addrs[i][8] == ATCHc) { - xbee_con *tcon; - unsigned int dh,dl; - if (first) { - printf("%c[2KGathering settings for nodes on channel 0x%02X...\r",27,ATCHc); - first = 0; - } - /* get the address, and turn it the right way up! */ - memcpy(&dh,&(addrs[i][0]),4); - dh = ((dh & 0xFF) << 24) | ((dh & 0xFF00) << 8) | ((dh & 0xFF0000) >> 8) | ((dh & 0xFF000000) >> 24); - memcpy(&dl,&(addrs[i][4]),4); - dl = ((dl & 0xFF) << 24) | ((dl & 0xFF00) << 8) | ((dl & 0xFF0000) >> 8) | ((dl & 0xFF000000) >> 24); - /* setup a connection the the remote node */ - if ((tcon = xbee_newcon('I',xbee_64bitRemoteAT,dh,dl)) != NULL) { - /* find the line to edit */ - printf("\r%c[%dA",27,nodes-i+1); - - /* in this case we dont care if we dont get a response packet... */ - if (xbee_senddata(tcon,"ID")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) { - /* move over the ID column */ - printf("\r%c[18C",27); - /* print the ID */ - printf("%c[32m%02X%02X%c[0m",27,rpkt->data[0],rpkt->data[1],27); - addrs[i][9] = rpkt->data[0]; - addrs[i][10] = rpkt->data[1]; - /* turn on the flag */ - addrs[i][18] |= 0x80; - free(rpkt); - } - - /* in this case we dont care if we dont get a response packet... */ - if (xbee_senddata(tcon,"BD")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) { - /* move over the BD column */ - printf("\r%c[80C",27); - if ((rpkt->data[0] != 0x00) || (rpkt->data[1] != 0x00) || (rpkt->data[2] != 0x00) || ((rpkt->data[3] & 0xF8) != 0x00)) { - addrs[i][11] = 8; - } else { - addrs[i][11] = rpkt->data[3]; - } - /* turn on the flag */ - addrs[i][18] |= 0x40; - /* print the baud rate */ - printf("%c[32m",27); - switch (addrs[i][11]) { - case 0: printf(" 1200"); break; - case 1: printf(" 2400"); break; - case 2: printf(" 4800"); break; - case 3: printf(" 9600"); break; - case 4: printf(" 19200"); break; - case 5: printf(" 38400"); break; - case 6: printf(" 57600"); break; - case 7: printf("115200"); break; - default: printf(" other"); break; - } - printf("%c[0m",27); - free(rpkt); - } - /* in this case we dont care if we dont get a response packet... */ - if (xbee_senddata(tcon,"AP")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) { - /* move over the AP column */ - printf("\r%c[96C",27); - /* print the ID */ - printf("%c[32m%02X%c[0m",27,rpkt->data[0],27); - addrs[i][12] = rpkt->data[0]; - /* turn on the flag */ - addrs[i][18] |= 0x20; - free(rpkt); - } - /* in this case we dont care if we dont get a response packet... */ - if (xbee_senddata(tcon,"HV")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) { - /* move over the HV column */ - printf("\r%c[108C",27); - /* print the ID */ - printf("%c[32m%02X%02X%c[0m",27,rpkt->data[0],rpkt->data[1],27); - addrs[i][13] = rpkt->data[0]; - addrs[i][14] = rpkt->data[1]; - /* turn on the flag */ - addrs[i][18] |= 0x10; - free(rpkt); - } - /* in this case we dont care if we dont get a response packet... */ - if (xbee_senddata(tcon,"VR")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) { - /* move over the VR column */ - printf("\r%c[122C",27); - /* print the ID */ - printf("%c[32m%02X%02X%c[0m",27,rpkt->data[0],rpkt->data[1],27); - addrs[i][15] = rpkt->data[0]; - addrs[i][16] = rpkt->data[1]; - /* turn on the flag */ - addrs[i][18] |= 0x08; - free(rpkt); - } - /* in this case we dont care if we dont get a response packet... */ - if (xbee_senddata(tcon,"CC")) { - printf("xbee_senddata: Error\n"); - return 1; - } - if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) { - /* move over the CC column */ - printf("\r%c[134C",27); - /* print the ID */ - printf("%c[32m'%c' (0x%02X)%c[0m",27,rpkt->data[0],rpkt->data[0],27); - addrs[i][17] = rpkt->data[0]; - /* turn on the flag */ - addrs[i][18] |= 0x04; - free(rpkt); - } - /* go back the the bottom */ - printf("%c[%dB\r",27,nodes-i+1); - fflush(stdout); - } - } - } - /* fall back to the first channel if that was the last */ - if (XBeePro && ATCHc == 0x17) { - ATCHc = 0x0C; - } else if (!XBeePro && ATCHc == 0x1A) { - ATCHc = 0x0B; - } else { - /* else move onto next channel */ - ATCHc++; - } - usleep(100000); - } - - return 0; -} - diff --git a/libs/thirdParty/libxbee/sample/simple.c b/libs/thirdParty/libxbee/sample/simple.c deleted file mode 100644 index 8ab776f127556968cf90f2a26b3daf30b02c4ea1..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/simple.c +++ /dev/null @@ -1,68 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will politely return any recieved data */ - -#include -#include -#include - -int main(int argc, char *argv[]) { - xbee_con *con; - xbee_pkt *pkt, *rpkt; - - /* setup the xbee */ - if (xbee_setup("/dev/ttyUSB0",57600) == -1) { - /* oh no... it failed */ - printf("xbee_setup() failed...\n"); - exit(1); - } - - /* setup a connection */ - con = xbee_newcon('I',xbee_64bitData, 0x0013A200, 0x40081826); - - printf("Waiting...\n"); - - /* just wait for data, and echo it back! */ - while (1) { - /* while there are packets avaliable... */ - while ((pkt = xbee_getpacket(con)) != NULL) { - /* print the recieved data */ - printf("Rx: %s\n",pkt->data); - /* say thank you */ - if (xbee_senddata(con,"thank you for saying '%s'\r\n",pkt->data)) { - printf("xbee_senddata: Error\n"); - return 1; - } - /* free the packet */ - free(pkt); - } - usleep(100000); - } - - /* shouldn't ever get here but... */ - return 0; -} - diff --git a/libs/thirdParty/libxbee/sample/talk_to_me.c b/libs/thirdParty/libxbee/sample/talk_to_me.c deleted file mode 100644 index 26750988abade8d0c1db9820391e660bc6cd7764..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/talk_to_me.c +++ /dev/null @@ -1,82 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -g -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample will make the remote XBee talk to us! */ - -#include -#include -#include -#include - -int main(int argc, char *argv[]) { - union { - unsigned char as8[8]; - unsigned int as32[2]; - } addr; - xbee_con *atCon, *rCon; - xbee_pkt *pkt; - - /* the extra arguments are the CC ('+' by default) and GT (1000) by default AT values */ - xbee_setuplogAPI("/dev/ttyUSB0",57600,2,'+',1000); - - atCon = xbee_newcon('@', xbee_localAT); - - xbee_senddata(atCon, "SH"); - pkt = xbee_getpacketwait(atCon); - if (!pkt || pkt->status || pkt->atCmd[0] != 'S' || pkt->atCmd[1] != 'H') { - printf("Missing SH Packet!\n"); - return 1; - } - addr.as8[3] = pkt->data[0]; - addr.as8[2] = pkt->data[1]; - addr.as8[1] = pkt->data[2]; - addr.as8[0] = pkt->data[3]; - free(pkt); - - xbee_senddata(atCon, "SL"); - pkt = xbee_getpacketwait(atCon); - if (!pkt || pkt->status || pkt->atCmd[0] != 'S' || pkt->atCmd[1] != 'L') { - printf("Missing SL Packet!\n"); - return 1; - } - addr.as8[7] = pkt->data[0]; - addr.as8[6] = pkt->data[1]; - addr.as8[5] = pkt->data[2]; - addr.as8[4] = pkt->data[3]; - free(pkt); - - printf("Local XBee address is: 0x%08X %08X\n", addr.as32[0], addr.as32[1]); - - rCon = xbee_newcon('#', xbee_64bitRemoteAT, 0x13A200, 0x403CB26A); - - xbee_senddata(rCon, "DH%c%c%c%c", addr.as8[3], addr.as8[2], addr.as8[1], addr.as8[0]); - usleep(250000); - xbee_senddata(rCon, "DL%c%c%c%c", addr.as8[7], addr.as8[6], addr.as8[5], addr.as8[4]); - usleep(250000); - - /* calling xbee_end() will return the xbee to its previous API mode */ - xbee_end(); - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/vb6/README.txt b/libs/thirdParty/libxbee/sample/vb6/README.txt deleted file mode 100644 index fe13a7dfcb43ee491a575dd2458781a8511ae2a0..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/vb6/README.txt +++ /dev/null @@ -1,8 +0,0 @@ -These sample projects provide a quick demo of how to use various functions - -Running these assume that you have first compiled libxbee.dll successfully -You will also need to either copy libxbee.dll into this folder or into a - directory in your PATH - -If you want to use libxbee in your own projects, you must include libxbee.bas - which will provide you with access to the functions and type declarations diff --git a/libs/thirdParty/libxbee/sample/vb6/demo/Form1.frm b/libs/thirdParty/libxbee/sample/vb6/demo/Form1.frm deleted file mode 100644 index 4c7c6655bce1337956327e4676c5a025526583f2..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/vb6/demo/Form1.frm +++ /dev/null @@ -1,64 +0,0 @@ -VERSION 5.00 -Begin VB.Form Form1 - Caption = "Form1" - ClientHeight = 2250 - ClientLeft = 120 - ClientTop = 450 - ClientWidth = 3855 - LinkTopic = "Form1" - ScaleHeight = 2250 - ScaleWidth = 3855 - StartUpPosition = 3 'Windows Default - Begin VB.TextBox tb - Height = 1995 - Left = 120 - MultiLine = -1 'True - TabIndex = 0 - Top = 120 - Width = 3615 - End -End -Attribute VB_Name = "Form1" -Attribute VB_GlobalNameSpace = False -Attribute VB_Creatable = False -Attribute VB_PredeclaredId = True -Attribute VB_Exposed = False -Option Explicit - -Dim myCon As Long -Dim myDataCon As Long - -Private Sub Form_Load() - Dim i As Long - Dim x As Byte - Dim ctype, addrH, addrL As Long - Me.Show - DoEvents - - ' Connect to the XBee on COM1 with a baud rate of 57600 - ' The XBee should be in API mode 2 (ATAP2) - If xbee_setupDebug("COM8", 57600, "xbee.log") <> 0 Then - MsgBox "Error while setting up the local XBee module", vbCritical, "xbee_setup()" - End - End If - xbee_logit "Hello!" - - ' Enable callbacks, this only needs to be done ONCE - ' The window handle provided must remain in memory (dont unload the form - callbacks will automatically be disabled) - xbee_enableCallbacks Me.hWnd - - ' Create a Remote AT connection to a node using 64-bit addressing - myCon = xbee_newcon_64bit(&H30, xbee_64bitRemoteAT, &H13A200, &H404B75DE) - xbee_enableACKwait myCon - - myDataCon = xbee_newcon_64bit(&H31, xbee_64bitData, &H13A200, &H404B75DE) - - ' Setup callbacks - xbee_attachCallback myCon, AddressOf Module1.callback1 - xbee_attachCallback myDataCon, AddressOf Module1.callback2 - - ' Send the AT command NI (Node Identifier) - tb.text = "Sending 'ATNI'..." - xbee_sendstring myCon, "NI" -End Sub - diff --git a/libs/thirdParty/libxbee/sample/vb6/demo/demo.bas b/libs/thirdParty/libxbee/sample/vb6/demo/demo.bas deleted file mode 100644 index b1e51fd90780c9bc8ae03e29760788520990b97b..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/vb6/demo/demo.bas +++ /dev/null @@ -1,19 +0,0 @@ -Attribute VB_Name = "Module1" -Public Function callback1(ByVal con As Long, ByRef pkt As xbee_pkt) As Long - ' Check the returned status, if it isnt 0 then an error occured - If pkt.status <> 0 Then - Form1.tb.Text = Form1.tb.Text & vbNewLine & "An error occured (" & pkt.status & ")" - Exit Function - End If - - ' Display the Node Identifier - Form1.tb.Text = Form1.tb.Text & vbNewLine & "Node Identifier:" & StrConv(pkt.data, vbUnicode) - Form1.tb.SelStart = Len(Form1.tb.Text) -End Function - -Public Function callback2(ByVal con As Long, ByRef pkt As xbee_pkt) As Long - ' Display the data - Form1.tb.Text = Form1.tb.Text & vbNewLine & "Rx:" & StrConv(pkt.data, vbUnicode) - Form1.tb.SelStart = Len(Form1.tb.Text) -End Function - diff --git a/libs/thirdParty/libxbee/sample/vb6/demo/demo.vbp b/libs/thirdParty/libxbee/sample/vb6/demo/demo.vbp deleted file mode 100644 index 815e949e70ca2644e8bb8a92a830e0aee07670ac..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/vb6/demo/demo.vbp +++ /dev/null @@ -1,33 +0,0 @@ -Type=Exe -Form=Form1.frm -Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\Windows\SysWOW64\stdole2.tlb#OLE Automation -Module=Module1; demo.bas -Module=libxbee; ..\libxbee.bas -IconForm="Form1" -Startup="Form1" -ExeName32="demo.exe" -Command32="" -Name="Project1" -HelpContextID="0" -CompatibleMode="0" -MajorVer=1 -MinorVer=0 -RevisionVer=0 -AutoIncrementVer=0 -ServerSupportFiles=0 -VersionCompanyName="Microsoft" -CompilationType=0 -OptimizationType=0 -FavorPentiumPro(tm)=0 -CodeViewDebugInfo=0 -NoAliasing=0 -BoundsCheck=0 -OverflowCheck=0 -FlPointCheck=0 -FDIVCheck=0 -UnroundedFP=0 -StartMode=0 -Unattended=0 -Retained=0 -ThreadPerObject=0 -MaxNumberOfThreads=1 diff --git a/libs/thirdParty/libxbee/sample/vb6/libxbee.bas b/libs/thirdParty/libxbee/sample/vb6/libxbee.bas deleted file mode 100644 index 0875907f91b157d595fe58d4906c4c42e53bddcb..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/vb6/libxbee.bas +++ /dev/null @@ -1,285 +0,0 @@ -Attribute VB_Name = "libxbee" -Option Explicit - -Enum xbee_types - xbee_unknown - - xbee_localAT - xbee_remoteAT - xbee_modemStatus - xbee_txStatus - - ' XBee Series 1 stuff - xbee_16bitRemoteAT - xbee_64bitRemoteAT - - xbee_16bitData - xbee_64bitData - - xbee_16bitIO - xbee_64bitIO - - ' XBee Series 2 stuff - xbee2_data - xbee2_txStatus -End Enum - -Type xbee_sample - '# X A5 A4 A3 A2 A1 A0 D8 D7 D6 D5 D4 D3 D2 D1 D0 - IOmask As Integer - '# X X X X X X X D8 D7 D6 D5 D4 D3 D2 D1 D0 - IOdigital As Integer - '# X X X X X D D D D D D D D D D D - IOanalog(0 To 5) As Integer -End Type - -Type xbee_pkt - flags As Long '# bit 0 - is64 - '# bit 1 - dataPkt - '# bit 2 - txStatusPkt - '# bit 3 - modemStatusPkt - '# bit 4 - remoteATPkt - '# bit 5 - IOPkt - frameID As Byte - atCmd(0 To 1) As Byte - - status As Byte - samples As Byte - RSSI As Byte - - Addr16(0 To 1) As Byte - - Addr64(0 To 7) As Byte - - data(0 To 127) As Byte - - datalen As Long - - type As Long ' enum xbee_types - - SPARE As Long ' IGNORE THIS (is the pointer to the next packet in C... this will ALWAYS be 0 in VB) - - IOdata As xbee_sample -End Type - -Private OldhWndHandler As Long -Private ActivehWnd As Long -Private callbackMessageID As Long -Private Callbacks As New Collection - -Public Declare Sub xbee_free Lib "libxbee.dll" (ByVal ptr As Long) - -Public Declare Function xbee_setup Lib "libxbee.dll" (ByVal port As String, ByVal baudRate As Long) As Long -Public Declare Function xbee_setupDebug Lib "libxbee.dll" (ByVal port As String, ByVal baudRate As Long, ByVal logfile As String) As Long -Private Declare Function xbee_setupDebugAPIRaw Lib "libxbee.dll" Alias "xbee_setupDebugAPI" (ByVal port As String, ByVal baudRate As Long, ByVal logfile As String, ByVal cmdSeq As Byte, ByVal cmdTime As Long) As Long -Private Declare Function xbee_setupAPIRaw Lib "libxbee.dll" Alias "xbee_setupAPI" (ByVal port As String, ByVal baudRate As Long, ByVal cmdSeq As Byte, ByVal cmdTime As Long) As Long - -Public Declare Function xbee_end Lib "libxbee.dll" () As Long - -Public Declare Function xbee_newcon_simple Lib "libxbee.dll" (ByVal frameID As Byte, ByVal conType As Long) As Long 'xbee_con * -Public Declare Function xbee_newcon_16bit Lib "libxbee.dll" (ByVal frameID As Byte, ByVal conType As Long, ByVal addr16bit As Long) As Long 'xbee_con * -Public Declare Function xbee_newcon_64bit Lib "libxbee.dll" (ByVal frameID As Byte, ByVal conType As Long, ByVal addr64bitLow As Long, ByVal addr64bitHigh As Long) As Long 'xbee_con * -Public Declare Sub xbee_enableACKwait Lib "libxbee.dll" (ByVal con As Long) -Public Declare Sub xbee_disableACKwait Lib "libxbee.dll" (ByVal con As Long) -Public Declare Sub xbee_enableDestroySelf Lib "libxbee.dll" (ByVal con As Long) - -Private Declare Sub xbee_enableCallbacksRaw Lib "libxbee.dll" Alias "xbee_enableCallbacks" (ByVal hWnd As Long, ByVal uMsg As Long) -Private Declare Sub xbee_attachCallbackRaw Lib "libxbee.dll" Alias "xbee_attachCallback" (ByVal con As Long) -Private Declare Sub xbee_detachCallbackRaw Lib "libxbee.dll" Alias "xbee_detachCallback" (ByVal con As Long) -Private Declare Function xbee_runCallback Lib "libxbee.dll" (ByVal func As Long, ByVal con As Long, ByVal pkt As Long) As Long - -Public Declare Sub xbee_endcon2 Lib "libxbee.dll" (ByVal con As Long) -Public Declare Sub xbee_flushcon Lib "libxbee.dll" (ByVal con As Long) - -Public Declare Function xbee_senddata Lib "libxbee.dll" Alias "xbee_nsenddata" (ByVal con As Long, ByRef data As Byte, ByVal Length As Long) As Long -Private Declare Function xbee_senddata_str Lib "libxbee.dll" Alias "xbee_nsenddata" (ByVal con As Long, ByVal data As String, ByVal Length As Long) As Long - -Public Declare Function xbee_getpacketRaw Lib "libxbee.dll" Alias "xbee_getpacket" (ByVal con As Long) As Long 'xbee_pkt * - -Public Declare Function xbee_hasanalog Lib "libxbee.dll" (ByRef pkt As xbee_pkt, ByVal sample As Long, ByVal inputPin As Long) As Long -Public Declare Function xbee_getanalog Lib "libxbee.dll" (ByRef pkt As xbee_pkt, ByVal sample As Long, ByVal inputPin As Long, ByVal Vref As Double) As Double - -Public Declare Function xbee_hasdigital Lib "libxbee.dll" (ByRef pkt As xbee_pkt, ByVal sample As Long, ByVal inputPin As Long) As Long -Public Declare Function xbee_getdigital Lib "libxbee.dll" (ByRef pkt As xbee_pkt, ByVal sample As Long, ByVal inputPin As Long) As Long - -Private Declare Function xbee_svn_versionRaw Lib "libxbee.dll" Alias "xbee_svn_version" () As Long -Public Declare Sub xbee_logit Lib "libxbee.dll" (ByVal text As String) - -'########################################################################################################################################################################### - -Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) -Private Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long -Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long -Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long -Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long -Private Const WM_DESTROY = &H2 -Private Const GWL_WNDPROC = -4 - -Public Function PointerToString(lngPtr As Long) As String - Dim strTemp As String - Dim lngLen As Long - If lngPtr Then - lngLen = lstrlenW(lngPtr) * 2 - If lngLen Then - strTemp = Space(lngLen) - CopyMemory ByVal strTemp, ByVal lngPtr, lngLen - PointerToString = Replace(strTemp, Chr(0), "") - End If - End If -End Function - -Public Function ArrayToString(data() As Byte, Optional lb As Integer = -1, Optional ub As Integer = -1) As String - Dim tmp As String - Dim i - If lb = -1 Then lb = LBound(data) - If ub = -1 Then ub = UBound(data) - tmp = "" - For i = lb To ub - If (data(i) = 0) Then Exit For - tmp = tmp & Chr(data(i)) - Next - ArrayToString = tmp -End Function - -Public Function xbee_pointerToPacket(lngPtr As Long) As xbee_pkt - Dim p As xbee_pkt - CopyMemory p, ByVal lngPtr, Len(p) - xbee_pointerToPacket = p -End Function - -Public Sub libxbee_load() - ' this function is simply to get VB6 to call a libxbee function - ' if you are using any C DLLs that make use of libxbee, then you should call this function first so that VB6 will load libxbee - xbee_svn_versionRaw -End Sub - -Public Function xbee_svn_version() As String - xbee_svn_version = PointerToString(xbee_svn_versionRaw()) -End Function - -Public Function xbee_setupAPI(ByVal port As String, ByVal baudRate As Long, ByVal cmdSeq As String, ByVal cmdTime As Long) - xbee_setupAPI = xbee_setupAPIRaw(port, baudRate, Asc(cmdSeq), cmdTime) -End Function - -Public Function xbee_setupDebugAPI(ByVal port As String, ByVal baudRate As Long, ByVal logfile As String, ByVal cmdSeq As String, ByVal cmdTime As Long) - xbee_setupDebugAPI = xbee_setupDebugAPIRaw(port, baudRate, logfile, Asc(cmdSeq), cmdTime) -End Function - -Private Sub xbee_ensureMessageID() - If callbackMessageID = 0 Then - callbackMessageID = RegisterWindowMessage("libxbee") - End If - xbee_enableCallbacksRaw ActivehWnd, callbackMessageID -End Sub - -Public Sub xbee_attachCallback(ByVal con As Long, ByVal func As Long) - Dim t(0 To 1) As Long - Dim c As String - If ActivehWnd = 0 Then - Debug.Print "Callbacks not enabled!" - Exit Sub - End If - xbee_ensureMessageID - c = CStr(con) - t(0) = con - t(1) = func - On Error Resume Next - Callbacks.Remove c - Callbacks.Add t, c - On Error GoTo 0 - xbee_attachCallbackRaw con -End Sub - -Public Sub xbee_detachCallback(ByVal con As Long) - If ActivehWnd = 0 Then - Debug.Print "Callbacks not enabled!" - Exit Sub - End If - On Error Resume Next - xbee_detachCallbackRaw con - Callbacks.Remove CStr(con) -End Sub - -Public Sub xbee_enableCallbacks(ByVal hWnd As Long) - If ActivehWnd <> 0 Then - Debug.Print "Callbacks already enabled!" - Exit Sub - End If - ActivehWnd = hWnd - OldhWndHandler = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf libxbee.xbee_messageHandler) - xbee_ensureMessageID -End Sub - -Public Sub xbee_disableCallbacks() - Dim id As Variant - If ActivehWnd = 0 Then - Debug.Print "Callbacks not enabled!" - Exit Sub - End If - For Each id In Callbacks - xbee_detachCallback id(0) - Next - SetWindowLong ActivehWnd, GWL_WNDPROC, OldhWndHandler - ActivehWnd = 0 - OldhWndHandler = 0 -End Sub - -Private Function xbee_messageHandler(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long - If uMsg = callbackMessageID Then - Dim t As Long - On Error Resume Next - Err.Clear - t = Callbacks.Item(CStr(wParam))(1) - If Err.Number = 0 Then - On Error GoTo 0 - xbee_messageHandler = xbee_runCallback(t, wParam, lParam) - Exit Function - End If - On Error GoTo 0 - xbee_logit "Unable to match Connection with active callback!" - End If - xbee_messageHandler = CallWindowProc(OldhWndHandler, hWnd, uMsg, wParam, lParam) - If uMsg = WM_DESTROY And ActivehWnd <> 0 Then - ' Disable the MessageHandler if the form "unload" event is detected - xbee_disableCallbacks - End If -End Function - -Public Sub xbee_endcon(ByRef con As Long) - xbee_endcon2 con - con = 0 -End Sub - -Public Function xbee_sendstring(ByVal con As Long, ByVal str As String) - xbee_sendstring = xbee_senddata_str(con, str, Len(str)) -End Function - -Public Function xbee_getpacketPtr(ByVal con As Long, ByRef pkt As Long) As Integer - Dim ptr As Long - - ptr = xbee_getpacketRaw(con) - If ptr = 0 Then - pkt = 0 - xbee_getpacketPtr = 0 - Exit Function - End If - - pkt = ptr - xbee_getpacketPtr = 1 -End Function - -Public Function xbee_getpacket(ByVal con As Long, ByRef pkt As xbee_pkt) As Integer - Dim ptr As Long - - ptr = xbee_getpacketRaw(con) - If ptr = 0 Then - xbee_getpacket = 0 - Exit Function - End If - - pkt = xbee_pointerToPacket(ptr) - xbee_free ptr - - xbee_getpacket = 1 -End Function - diff --git a/libs/thirdParty/libxbee/sample/vb6/talk_to_me/Form1.frm b/libs/thirdParty/libxbee/sample/vb6/talk_to_me/Form1.frm deleted file mode 100644 index 426a9df9395c731c789ccc64ec25a3f70fc8f160..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/vb6/talk_to_me/Form1.frm +++ /dev/null @@ -1,1197 +0,0 @@ -VERSION 5.00 -Begin VB.Form Form1 - BorderStyle = 1 'Fixed Single - Caption = "Talk to Me" - ClientHeight = 7875 - ClientLeft = 45 - ClientTop = 375 - ClientWidth = 7515 - LinkTopic = "Form1" - MaxButton = 0 'False - ScaleHeight = 7875 - ScaleWidth = 7515 - StartUpPosition = 1 'CenterOwner - Begin VB.Timer tmr_timeout - Enabled = 0 'False - Interval = 5000 - Left = 3720 - Top = 1380 - End - Begin VB.Frame Frame2 - Caption = " Actions " - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 1335 - Left = 180 - TabIndex = 1 - Top = 6420 - Width = 7215 - Begin VB.CommandButton write_settings - Caption = "Write Settings" - Enabled = 0 'False - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 375 - Left = 1920 - TabIndex = 50 - Top = 780 - Width = 1935 - End - Begin VB.CommandButton set_default - Caption = "Set Default" - Enabled = 0 'False - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 375 - Left = 180 - TabIndex = 49 - Top = 780 - Width = 1575 - End - Begin VB.CommandButton reset_node - Caption = "Reset Node" - Enabled = 0 'False - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 375 - Left = 4020 - TabIndex = 47 - Top = 780 - Width = 1575 - End - Begin VB.CommandButton set_dest - Caption = "Set destination" - Enabled = 0 'False - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 375 - Left = 1920 - TabIndex = 46 - Top = 300 - Width = 1935 - End - Begin VB.CommandButton talk_to_me - Caption = "Talk to Me" - Enabled = 0 'False - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 375 - Left = 180 - TabIndex = 45 - Top = 300 - Width = 1575 - End - Begin VB.CommandButton set_ni - Caption = "Set Node Identifier" - Enabled = 0 'False - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 375 - Left = 4020 - TabIndex = 51 - Top = 300 - Width = 2355 - End - End - Begin VB.Frame Frame1 - Caption = " Settings " - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 3315 - Left = 180 - TabIndex = 0 - Top = 3000 - Width = 7215 - Begin VB.Label ni - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 24 - Top = 300 - Width = 3915 - End - Begin VB.Label sl - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 22 - Top = 1020 - Width = 3915 - End - Begin VB.Label sh - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 20 - Top = 780 - Width = 3915 - End - Begin VB.Label my - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 18 - Top = 540 - Width = 3915 - End - Begin VB.Label ap - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 17 - Top = 1260 - Width = 3915 - End - Begin VB.Label bd - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 16 - Top = 1500 - Width = 3915 - End - Begin VB.Label ch - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 15 - Top = 1740 - Width = 3915 - End - Begin VB.Label dh - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 14 - Top = 1980 - Width = 3915 - End - Begin VB.Label dl - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 13 - Top = 2220 - Width = 3915 - End - Begin VB.Label ia - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 11 - Top = 2460 - Width = 3915 - End - Begin VB.Label vr - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 10 - Top = 2940 - Width = 3915 - End - Begin VB.Label hv - BackStyle = 0 'Transparent - Caption = "-" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Left = 3180 - TabIndex = 12 - Top = 2700 - Width = 3915 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "NI - Node Identifier" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 17 - Left = 180 - TabIndex = 25 - Top = 300 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "MY - 16-bit Address" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 13 - Left = 180 - TabIndex = 19 - Top = 540 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "VR - Firmware Version" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 14 - Left = 180 - TabIndex = 9 - Top = 2940 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "IA - I/O Address" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 12 - Left = 180 - TabIndex = 8 - Top = 2460 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "DL - Destination Low" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 10 - Left = 180 - TabIndex = 6 - Top = 2220 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "DH - Destination High" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 9 - Left = 180 - TabIndex = 5 - Top = 1980 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "CH - Channel" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 8 - Left = 180 - TabIndex = 4 - Top = 1740 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "BD - Interface Rate" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 7 - Left = 180 - TabIndex = 3 - Top = 1500 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "AP - API Enable" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 6 - Left = 180 - TabIndex = 2 - Top = 1260 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "HV - Hardware Version" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 11 - Left = 180 - TabIndex = 7 - Top = 2700 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " .....:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 29 - Left = 180 - TabIndex = 44 - Top = 2700 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " ...........:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 28 - Left = 180 - TabIndex = 43 - Top = 1260 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " .......:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 27 - Left = 180 - TabIndex = 42 - Top = 1500 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " ..............:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 26 - Left = 180 - TabIndex = 41 - Top = 1740 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " .....:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 25 - Left = 180 - TabIndex = 40 - Top = 1980 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " ......:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 24 - Left = 180 - TabIndex = 39 - Top = 2220 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " ..........:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 23 - Left = 180 - TabIndex = 38 - Top = 2460 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " .....:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 22 - Left = 180 - TabIndex = 37 - Top = 2940 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " .......:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 21 - Left = 180 - TabIndex = 36 - Top = 540 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " ......:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 18 - Left = 180 - TabIndex = 33 - Top = 300 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "SL - 64-bit Address (Lo)" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 16 - Left = 180 - TabIndex = 23 - Top = 1020 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "SH - 64-bit Address (Hi)" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 255 - Index = 15 - Left = 180 - TabIndex = 21 - Top = 780 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " ..:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 20 - Left = 180 - TabIndex = 35 - Top = 780 - Width = 2955 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = " ..:" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 255 - Index = 19 - Left = 180 - TabIndex = 34 - Top = 1020 - Width = 2955 - End - End - Begin VB.Timer tmr_refresh - Enabled = 0 'False - Interval = 500 - Left = 3240 - Top = 1380 - End - Begin VB.Frame Frame3 - Caption = " Node List " - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 2775 - Left = 180 - TabIndex = 26 - Top = 120 - Width = 7215 - Begin VB.ListBox nodelist - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 2085 - Left = 180 - TabIndex = 27 - Top = 540 - Width = 6855 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "16-bit" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 195 - Index = 0 - Left = 240 - TabIndex = 32 - Top = 300 - Width = 675 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "RSSI" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 195 - Index = 3 - Left = 3660 - TabIndex = 30 - Top = 300 - Width = 435 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "@" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 195 - Index = 4 - Left = 4440 - TabIndex = 29 - Top = 300 - Width = 135 - End - Begin VB.Label Label - BackStyle = 0 'Transparent - Caption = "Node Name" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 195 - Index = 5 - Left = 4740 - TabIndex = 28 - Top = 300 - Width = 915 - End - Begin VB.Label Label - Alignment = 2 'Center - BackStyle = 0 'Transparent - Caption = "- -" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - ForeColor = &H00C0C0C0& - Height = 195 - Index = 2 - Left = 1020 - TabIndex = 48 - Top = 300 - Width = 2355 - End - Begin VB.Label Label - Alignment = 2 'Center - BackStyle = 0 'Transparent - Caption = "(Hi) 64-bit (Lo)" - BeginProperty Font - Name = "Courier New" - Size = 9 - Charset = 0 - Weight = 400 - Underline = 0 'False - Italic = 0 'False - Strikethrough = 0 'False - EndProperty - Height = 195 - Index = 1 - Left = 1020 - TabIndex = 31 - Top = 300 - Width = 2355 - End - End -End -Attribute VB_Name = "Form1" -Attribute VB_GlobalNameSpace = False -Attribute VB_Creatable = False -Attribute VB_PredeclaredId = True -Attribute VB_Exposed = False -Dim dieNow As Boolean - -Private Sub Form_Load() - Me.Show - DoEvents - dieNow = False - - ' setup libxbee - If (xbee_setupDebugAPI("COM8", 57600, "xbee.log", "+", 250) = -1) Then - MsgBox "libxbee setup failed...", vbCritical - Unload Me - End - End If - - ' enable callback functions - xbee_enableCallbacks Me.hWnd - - ' setup a local at connection - atcon = xbee_newcon_simple(Asc("A"), xbee_localAT) - xbee_enableACKwait atcon - xbee_attachCallback atcon, AddressOf localCB - - ' set off the chain reaction! - xbeesend atcon, "MY" -End Sub - -Private Sub Form_Unload(Cancel As Integer) - Static c As Integer - dieNow = 1 - Cancel = 1 - Me.Caption = "Waiting for command to complete..." - c = c + 1 - If (c >= 2) Then - Cancel = 0 - End If -End Sub - -Private Sub nodelist_Click() - Dim tmp() As String - If nodelist.ListCount = 0 Or nodelist.ListIndex = -1 Then Exit Sub - If set_dest.Tag = "yes" Then - nodelist.Enabled = False - Else - If nodelist.ListIndex = 0 Then - remoteCon = atcon - Else - str2 = Split(nodelist.text, " ") - remoteCon = xbee_newcon_64bit(Asc("2"), xbee_64bitRemoteAT, CLng("&H" & Right(str2(1), 8)), CLng("&H" & Right(str2(2), 8))) - End If - setButtons False - nodelist.Enabled = False - tmp = Split(nodelist.List(nodelist.ListIndex), " ") - ni = tmp(5) - my = tmp(0) - sh = tmp(1) - sl = tmp(2) - ap = "-" - bd = "-" - ch = "-" - dh = "-" - dl = "-" - ia = "-" - hv = "-" - vr = "-" - End If -End Sub - -Private Sub reset_node_Click() - If nodelist.ListCount = 0 Or nodelist.ListIndex = -1 Then Exit Sub - nodelist.Enabled = False - setButtons False - reset_node.Tag = "yes" -End Sub - -Private Sub set_default_Click() - If nodelist.ListCount = 0 Or nodelist.ListIndex = -1 Then Exit Sub - nodelist.Enabled = False - setButtons False - set_default.Tag = "yes" -End Sub - -Private Sub set_dest_Click() - If nodelist.ListCount = 0 Or nodelist.ListIndex = -1 Then Exit Sub - nodelist.Tag = nodelist.ListIndex - setButtons False - set_dest.Tag = "yes" -End Sub - -Private Sub set_ni_Click() - Dim newni As String - Dim oldni As String - oldni = Split(nodelist.text, " ")(5) - newni = InputBox("New node identifier:", "Set Node Identifier", oldni) - If newni = oldni Then Exit Sub - nodelist.Enabled = False - setButtons False - set_ni.Tag = newni -End Sub - -Private Sub talk_to_me_Click() - If nodelist.ListCount = 0 Or nodelist.ListIndex = -1 Then Exit Sub - nodelist.Enabled = False - setButtons False - talk_to_me.Tag = "yes" -End Sub - -Private Sub tmr_refresh_Timer() - Dim str As String - Dim str2() As String - tmr_refresh.Enabled = False - If atcon = 0 Then Exit Sub - - If (dieNow) Then - xbee_end - DoEvents - xbee_disableCallbacks - Unload Me - End - End If - - If nodelist.Enabled = False Then - xbee_attachCallback remoteCon, AddressOf remoteCB - If talk_to_me.Tag = "yes" Then - str2 = Split(Form1.nodelist.text, " ") - xbee_attachCallback remoteCon, AddressOf setupCB_TTM - str2 = Split(nodelist.List(0), " ") - str = Chr(CInt("&H" & Mid(str2(1), 9, 2))) - str = Chr(CInt("&H" & Mid(str2(1), 7, 2))) & str - str = Chr(CInt("&H" & Mid(str2(1), 5, 2))) & str - str = Chr(CInt("&H" & Mid(str2(1), 3, 2))) & str - str = "DH" & str - xbeesend remoteCon, str - ElseIf set_dest.Tag = "yes" Then - str2 = Split(Form1.nodelist.text, " ") - xbee_attachCallback remoteCon, AddressOf setupCB_SDEST - str2 = Split(nodelist.text, " ") - str = Chr(CInt("&H" & Mid(str2(1), 9, 2))) - str = Chr(CInt("&H" & Mid(str2(1), 7, 2))) & str - str = Chr(CInt("&H" & Mid(str2(1), 5, 2))) & str - str = Chr(CInt("&H" & Mid(str2(1), 3, 2))) & str - str = "DH" & str - xbeesend remoteCon, str - ElseIf reset_node.Tag = "yes" Then - xbee_sendstring remoteCon, "FR" - setButtons True - reset_node.Tag = "" - tmr_refresh.Enabled = True - ElseIf write_settings.Tag = "yes" Then - xbee_sendstring remoteCon, "WR" - setButtons True - write_settings.Tag = "" - tmr_refresh.Enabled = True - ElseIf set_default.Tag = "yes" Then - setupCB_Default_Start - ElseIf set_ni.Tag <> "" Then - xbeesend remoteCon, "NI" & set_ni.Tag - set_ni.Tag = "" - Else - xbeesend remoteCon, "AP" - End If - Exit Sub - End If - ' initiate network scan - xbee_attachCallback atcon, AddressOf localCB - xbeesend atcon, "MY" -End Sub - -Private Sub tmr_timeout_Timer() - Dim con As Long - Dim str As String - Dim str2() As String - tmr_timeout.Enabled = False - str2 = Split(tmr_timeout.Tag, Chr(1), 2) - con = CStr(str2(0)) - str = str2(1) - If MsgBox("Request timed out... Retry?", vbYesNo + vbQuestion, "Retry?") = vbNo Then - setButtons True - nodelist.Enabled = True - tmr_refresh.Enabled = True - Exit Sub - End If - xbeesend con, str -End Sub - -Private Sub write_settings_Click() - If nodelist.ListCount = 0 Or nodelist.ListIndex = -1 Then Exit Sub - nodelist.Enabled = False - setButtons False - write_settings.Tag = "yes" -End Sub diff --git a/libs/thirdParty/libxbee/sample/vb6/talk_to_me/talk_to_me.bas b/libs/thirdParty/libxbee/sample/vb6/talk_to_me/talk_to_me.bas deleted file mode 100644 index dc9f5f76d16bf1e09c4be2fc43ad579c411b04c2..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/vb6/talk_to_me/talk_to_me.bas +++ /dev/null @@ -1,431 +0,0 @@ -Attribute VB_Name = "Module1" -Public atcon As Long -Public remoteCon As Long - -Public Sub setButtons(ByVal state As Boolean) - Form1.talk_to_me.Tag = "" - Form1.talk_to_me.Enabled = state - Form1.set_dest.Tag = "" - Form1.set_dest.Enabled = state - Form1.reset_node.Tag = "" - Form1.reset_node.Enabled = state - Form1.set_default.Tag = "" - Form1.set_default.Enabled = state - Form1.write_settings.Tag = "" - Form1.write_settings.Enabled = state - Form1.set_ni.Tag = "" - Form1.set_ni.Enabled = state -End Sub - -Public Function xbeesend(ByVal con As Long, ByVal str As String) As Long - Form1.tmr_timeout.Enabled = False - Form1.tmr_timeout.Tag = CStr(con) & Chr(1) & str - Form1.tmr_timeout.Enabled = True - xbee_sendstring con, str -End Function - -Public Sub setupCB_Default_Start() - xbee_attachCallback remoteCon, AddressOf setupCB_Default - xbee_attachCallback atcon, AddressOf setupCB_Default - xbeesend remoteCon, "CH" & Chr(16) -End Sub -Public Function setupCB_Default(ByVal con As Long, ByRef pkt As xbee_pkt) As Long - Dim str As String - Dim str2() As String - ' default values (in order of setting): - ' CH = 10 - ' local CH = 10 - ' MY = FF - ' T3 = 1 - ' BD = 6 - ' AP = 0 - ' RO = 1 - ' D0 = 5 (turn on rest of system) - ' D1 = 2 (battery reading) - ' D2 = 0 - ' D3 = 5 (reset) - ' D4 = 4 (battery reading power) - ' D5 = 0 - ' D6 = 0 - ' D7 = 0 - ' D8 = 0 - ' IA = 0xFFFF (accept inputs from anyone) - ' IU = 0 - Debug.Print ArrayToString(pkt.atCmd) - If con = atcon Then - xbee_attachCallback con, AddressOf localCB - xbeesend remoteCon, "MY" & Chr(255) & Chr(255) - Exit Function - End If - Select Case ArrayToString(pkt.atCmd) - Case "CH" - xbeesend atcon, "CH" & Chr(16) - Case "MY" - xbeesend con, "T3" & Chr(1) - Case "T3" - xbeesend con, "BD" & Chr(0) & Chr(0) & Chr(0) & Chr(6) - Case "BD" - xbeesend con, "AP" & Chr(0) - Case "AP" - xbeesend con, "RO" & Chr(1) - Case "RO" - xbeesend con, "D0" & Chr(5) - Case "D0" - xbeesend con, "D1" & Chr(2) - Case "D1" - xbeesend con, "D2" & Chr(0) - Case "D2" - xbeesend con, "D3" & Chr(4) - Case "D3" - xbeesend con, "D4" & Chr(4) - Case "D4" - xbeesend con, "D5" & Chr(0) - Case "D5" - xbeesend con, "D6" & Chr(0) - Case "D6" - xbeesend con, "D7" & Chr(0) - Case "D7" - xbeesend con, "D8" & Chr(0) - Case "D8" - xbeesend con, "IA" & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(0) & Chr(255) & Chr(255) - Case "IA" - xbeesend con, "IU" & Chr(0) - Case "IU" - Form1.set_default.Tag = "" - Form1.tmr_refresh.Enabled = True - Form1.tmr_timeout.Enabled = False - End Select -End Function - -Public Function setupCB_TTM(ByVal con As Long, ByRef pkt As xbee_pkt) As Long - Dim str As String - Dim str2() As String - Select Case ArrayToString(pkt.atCmd) - Case "DH" - str2 = Split(Form1.nodelist.List(0), " ") - str = Chr(CInt("&H" & Mid(str2(2), 9, 2))) - str = Chr(CInt("&H" & Mid(str2(2), 7, 2))) & str - str = Chr(CInt("&H" & Mid(str2(2), 5, 2))) & str - str = Chr(CInt("&H" & Mid(str2(2), 3, 2))) & str - str = "DL" & str - xbeesend con, str - Case "DL" - Form1.talk_to_me.Tag = "" - Form1.tmr_refresh.Enabled = True - End Select -End Function - -Public Function setupCB_SDEST(ByVal con As Long, ByRef pkt As xbee_pkt) As Long - Dim str As String - Dim str2() As String - Select Case ArrayToString(pkt.atCmd) - Case "DH" - str2 = Split(Form1.nodelist.text, " ") - str = Chr(CInt("&H" & Mid(str2(2), 9, 2))) - str = Chr(CInt("&H" & Mid(str2(2), 7, 2))) & str - str = Chr(CInt("&H" & Mid(str2(2), 5, 2))) & str - str = Chr(CInt("&H" & Mid(str2(2), 3, 2))) & str - str = "DL" & str - xbeesend con, str - Case "DL" - Form1.set_dest.Tag = "" - Form1.nodelist.ListIndex = Form1.nodelist.Tag - Form1.tmr_refresh.Enabled = True - End Select -End Function - -Public Function remoteCB(ByVal con As Long, ByRef pkt As xbee_pkt) As Long - Dim t As String - Dim i As Long - Debug.Print "<+>", ArrayToString(pkt.atCmd) - Form1.tmr_timeout.Enabled = False - Select Case ArrayToString(pkt.atCmd) - Case "AP" - Select Case pkt.data(0) - Case 0 - Form1.ap.Caption = "0 - API Disabled" - Case 1 - Form1.ap.Caption = "1 - API Enabled (no escapes)" - Case 2 - Form1.ap.Caption = "2 - API Enabled (with escapes)" - Case Default - Form1.ap.Caption = "0x" & Hex(pkt.data(0)) & " - Unknown..." - End Select - xbeesend con, "BD" - Case "BD" - t = Hex(pkt.data(3)) - If (Len(t) < 2) Then t = "0" & t - t = Hex(pkt.data(2)) & t - If (Len(t) < 4) Then t = "0" & t - t = Hex(pkt.data(1)) & t - If (Len(t) < 6) Then t = "0" & t - t = Hex(pkt.data(0)) & t - If (Len(t) < 8) Then t = "0" & t - i = CStr("&H" & t) - Select Case i - Case 0 - Form1.bd.Caption = "0 - 1200 bps" - Case 1 - Form1.bd.Caption = "1 - 2400 bps" - Case 2 - Form1.bd.Caption = "2 - 4800 bps" - Case 3 - Form1.bd.Caption = "3 - 9600 bps" - Case 4 - Form1.bd.Caption = "4 - 19200 bps" - Case 5 - Form1.bd.Caption = "5 - 38400 bps" - Case 6 - Form1.bd.Caption = "6 - 57600 bps" - Case 7 - Form1.bd.Caption = "7 - 115200 bps" - Case Default - Form1.bd.Caption = "0x" & Hex(i) & " - Unknwon..." - End Select - xbeesend con, "CH" - Case "CH" - t = Hex(pkt.data(0)) - If (Len(t) < 2) Then t = "0" & t - Form1.ch.Caption = "0x" & t - xbeesend con, "DH" - Case "DH" - t = Hex(pkt.data(3)) - If (Len(t) < 2) Then t = "0" & t - t = Hex(pkt.data(2)) & t - If (Len(t) < 4) Then t = "0" & t - t = Hex(pkt.data(1)) & t - If (Len(t) < 6) Then t = "0" & t - t = Hex(pkt.data(0)) & t - If (Len(t) < 8) Then t = "0" & t - Form1.dh.Caption = "0x" & t - xbeesend con, "DL" - Case "DL" - t = Hex(pkt.data(3)) - If (Len(t) < 2) Then t = "0" & t - t = Hex(pkt.data(2)) & t - If (Len(t) < 4) Then t = "0" & t - t = Hex(pkt.data(1)) & t - If (Len(t) < 6) Then t = "0" & t - t = Hex(pkt.data(0)) & t - If (Len(t) < 8) Then t = "0" & t - Form1.dl.Caption = "0x" & t - xbeesend con, "IA" - Case "IA" - t = Hex(pkt.data(7)) & t - If (Len(t) < 2) Then t = "0" & t - t = Hex(pkt.data(6)) & t - If (Len(t) < 4) Then t = "0" & t - t = Hex(pkt.data(5)) & t - If (Len(t) < 6) Then t = "0" & t - t = Hex(pkt.data(4)) & t - If (Len(t) < 8) Then t = "0" & t - t = Hex(pkt.data(3)) & t - If (Len(t) < 10) Then t = "0" & t - t = Hex(pkt.data(2)) & t - If (Len(t) < 12) Then t = "0" & t - t = Hex(pkt.data(1)) & t - If (Len(t) < 14) Then t = "0" & t - t = Hex(pkt.data(0)) & t - If (Len(t) < 16) Then t = "0" & t - Form1.ia.Caption = "0x" & t - xbeesend con, "HV" - Case "HV" - t = Hex(pkt.data(1)) - If (Len(t) < 2) Then t = "0" & t - t = Hex(pkt.data(0)) & t - If (Len(t) < 4) Then t = "0" & t - Form1.hv.Caption = "0x" & t - xbeesend con, "VR" - Case "VR" - t = Hex(pkt.data(1)) - If (Len(t) < 2) Then t = "0" & t - t = Hex(pkt.data(0)) & t - If (Len(t) < 4) Then t = "0" & t - Form1.vr.Caption = "0x" & t - If con = atcon Then - xbee_attachCallback con, AddressOf localCB - End If - setButtons True - Form1.nodelist.Enabled = True - Form1.tmr_refresh.Enabled = True - Form1.tmr_timeout.Enabled = False - Case Else - If con = atcon Then - xbee_attachCallback con, AddressOf localCB - End If - setButtons True - Form1.nodelist.Enabled = True - Form1.tmr_refresh.Enabled = True - Form1.tmr_timeout.Enabled = False - End Select -End Function - -Public Function localCB(ByVal con As Long, ByRef pkt As xbee_pkt) As Long - Dim nodeinfo As String - Dim nodename As String - Dim tmp As String - Dim tmp2() As String - Dim sh, sl As String - Dim i, m As Integer - Dim AT As String - Form1.tmr_timeout.Enabled = False - AT = ArrayToString(pkt.atCmd) - ' handle initial stuff - Select Case AT - Case "MY" - nodeinfo = "0x" - tmp = Hex(pkt.data(0)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - tmp = Hex(pkt.data(1)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - If Form1.nodelist.ListCount > 0 Then - Form1.nodelist.List(0) = nodeinfo - Else - Form1.nodelist.AddItem nodeinfo - End If - ' issue next command - xbeesend con, "SH" - Case "SH" - nodeinfo = Form1.nodelist.List(0) & " 0x" - tmp = Hex(pkt.data(0)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - tmp = Hex(pkt.data(1)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - tmp = Hex(pkt.data(2)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - tmp = Hex(pkt.data(3)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - Form1.nodelist.List(0) = nodeinfo - ' issue next command - xbeesend con, "SL" - Case "SL" - nodeinfo = Form1.nodelist.List(0) & " 0x" - tmp = Hex(pkt.data(0)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - tmp = Hex(pkt.data(1)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - tmp = Hex(pkt.data(2)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - tmp = Hex(pkt.data(3)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - nodeinfo = nodeinfo & tmp - Form1.nodelist.List(0) = nodeinfo - ' issue next command - xbeesend con, "NI" - Case "NI" - nodeinfo = Form1.nodelist.List(0) & " -***dB * " - tmp = ArrayToString(pkt.data) - nodeinfo = nodeinfo & tmp - Form1.nodelist.List(0) = nodeinfo - ' issue next command - xbeesend con, "ND" - End Select - - If (AT <> "ND") Then Exit Function - If (pkt.status <> 0) Then - MsgBox "An error occured when attempting to scan!", vbCritical - Exit Function - End If - - If (pkt.datalen = 0) Then - ' increment the counter for each node - For i = 0 To Form1.nodelist.ListCount - 1 - tmp2 = Split(Form1.nodelist.List(i), " ") - If tmp2(4) <> "+" And tmp2(4) <> "*" Then - tmp2(4) = CInt(tmp2(4)) + 1 - If (CInt(tmp2(4)) > 9) Then tmp2(4) = "+" - End If - tmp = "" - For m = LBound(tmp2) To UBound(tmp2) - If m > 0 Then tmp = tmp & " " - tmp = tmp & tmp2(m) - Next - Form1.nodelist.List(i) = tmp - Next - - ' restart the refresh timer - Form1.tmr_refresh.Enabled = True - Exit Function - End If - - ' extract the 16-bit address - nodeinfo = "" - tmp = Hex(pkt.data(1)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - tmp = Hex(pkt.data(0)) & tmp - If (Len(tmp) < 4) Then tmp = "0" & tmp - tmp = "0x" & tmp - nodeinfo = nodeinfo & tmp - - nodeinfo = nodeinfo & " " - - ' extract the high portion of the 64-bit address - nodeinfo = nodeinfo - tmp = Hex(pkt.data(5)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - tmp = Hex(pkt.data(4)) & tmp - If (Len(tmp) < 4) Then tmp = "0" & tmp - tmp = Hex(pkt.data(3)) & tmp - If (Len(tmp) < 6) Then tmp = "0" & tmp - tmp = Hex(pkt.data(2)) & tmp - If (Len(tmp) < 8) Then tmp = "0" & tmp - tmp = "0x" & tmp - nodeinfo = nodeinfo & tmp - sh = tmp - - nodeinfo = nodeinfo & " " - - ' extract the low portion of the 64-bit address - nodeinfo = nodeinfo - tmp = Hex(pkt.data(9)) - If (Len(tmp) < 2) Then tmp = "0" & tmp - tmp = Hex(pkt.data(8)) & tmp - If (Len(tmp) < 4) Then tmp = "0" & tmp - tmp = Hex(pkt.data(7)) & tmp - If (Len(tmp) < 6) Then tmp = "0" & tmp - tmp = Hex(pkt.data(6)) & tmp - If (Len(tmp) < 8) Then tmp = "0" & tmp - tmp = "0x" & tmp - nodeinfo = nodeinfo & tmp - sl = tmp - - nodeinfo = nodeinfo & " " - - ' extract the rssi (signal strength) - tmp = "-" & CStr(pkt.data(10)) - If Len(tmp) < 3 Then tmp = " " & tmp - If Len(tmp) < 4 Then tmp = " " & tmp - tmp = tmp & "dB" - nodeinfo = nodeinfo & tmp - - nodeinfo = nodeinfo & " " - ' add a number of scans - nodeinfo = nodeinfo & 0 - - nodeinfo = nodeinfo & " " - - ' extract the node name - nodename = ArrayToString(pkt.data, 11) - nodeinfo = nodeinfo & nodename - - ' see if we have already got this node - For i = 0 To Form1.nodelist.ListCount - 1 - tmp2 = Split(Form1.nodelist.List(i), " ") - If tmp2(1) = sh And tmp2(2) = sl Then - Form1.nodelist.List(i) = nodeinfo - Exit Function - End If - Next - - ' otherwise add the info to the list - Form1.nodelist.AddItem nodeinfo -End Function diff --git a/libs/thirdParty/libxbee/sample/vb6/talk_to_me/talk_to_me.vbp b/libs/thirdParty/libxbee/sample/vb6/talk_to_me/talk_to_me.vbp deleted file mode 100644 index a80cc9bf25076b17986bd5d820465024fc8da7b5..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/vb6/talk_to_me/talk_to_me.vbp +++ /dev/null @@ -1,33 +0,0 @@ -Type=Exe -Form=Form1.frm -Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\..\Windows\SysWOW64\stdole2.tlb#OLE Automation -Module=libxbee; ..\libxbee.bas -Module=Module1; talk_to_me.bas -IconForm="Form1" -Startup="Form1" -ExeName32="talk_to_me.exe" -Command32="" -Name="Project1" -HelpContextID="0" -CompatibleMode="0" -MajorVer=1 -MinorVer=0 -RevisionVer=0 -AutoIncrementVer=0 -ServerSupportFiles=0 -VersionCompanyName="Microsoft" -CompilationType=0 -OptimizationType=0 -FavorPentiumPro(tm)=0 -CodeViewDebugInfo=0 -NoAliasing=0 -BoundsCheck=0 -OverflowCheck=0 -FlPointCheck=0 -FDIVCheck=0 -UnroundedFP=0 -StartMode=0 -Unattended=0 -Retained=0 -ThreadPerObject=0 -MaxNumberOfThreads=1 diff --git a/libs/thirdParty/libxbee/sample/xbee2_rx.c b/libs/thirdParty/libxbee/sample/xbee2_rx.c deleted file mode 100644 index 223ddcf63777e04cb991872a9e62facafa09cdf5..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/xbee2_rx.c +++ /dev/null @@ -1,60 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -g -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample demonstrates how to communicate using series 2 radios */ - -#include -#include -#include -#include - -void callback(xbee_con *con, xbee_pkt *pkt) { - int ret; - /* print the recieved data */ - printf("Rx: %s\n",pkt->data); -} - -int main(int argc, char *argv[]) { - union { - unsigned char as8[8]; - unsigned int as32[2]; - } addr; - xbee_con *rCon; - xbee_pkt *pkt; - - xbee_setuplog("/dev/ttyUSB1",57600, 2); - - rCon = xbee_newcon('#', xbee2_data, 0x13A200, 0x403302B1); - rCon->waitforACK = 1; - rCon->callback = callback; - - for (;;) { - sleep(60); - } - - /* calling xbee_end() will return the xbee to its previous API mode */ - xbee_end(); - return 0; -} diff --git a/libs/thirdParty/libxbee/sample/xbee2_tx.c b/libs/thirdParty/libxbee/sample/xbee2_tx.c deleted file mode 100644 index db49fe6fa618226cdcfba3c99b8cf79e4a57765a..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/sample/xbee2_tx.c +++ /dev/null @@ -1,54 +0,0 @@ -#ifdef shell -gcc -o ${0//.c/} $0 -lxbee -g -exit -} -#endif -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this sample demonstrates how to communicate using series 2 radios */ - -#include -#include -#include -#include - -int main(int argc, char *argv[]) { - union { - unsigned char as8[8]; - unsigned int as32[2]; - } addr; - xbee_con *rCon; - xbee_pkt *pkt; - - xbee_setuplog("/dev/ttyUSB0",57600, 2); - - rCon = xbee_newcon('#', xbee2_data, 0x13A200, 0x403302BF); - - for (;;) { - xbee_senddata(rCon, "Hello!"); - printf("Sent!\n"); - sleep(1); - } - - /* calling xbee_end() will return the xbee to its previous API mode */ - xbee_end(); - return 0; -} diff --git a/libs/thirdParty/libxbee/umakefile b/libs/thirdParty/libxbee/umakefile deleted file mode 100644 index 597a32377f01ad4e74fc4f3029c817512035da6f..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/umakefile +++ /dev/null @@ -1,91 +0,0 @@ -#-- uncomment this to enable debugging -#DEBUG:=-g -DDEBUG - -#-- what compiler are you using? -CC:=gcc - - -###### YOU SHOULD NOT CHANGE BELOW THIS LINE ###### - -VERSION:=1.4.0 -SRCS:=api.c - -CFLAGS:=-Wall -Wstrict-prototypes -Wno-variadic-macros -pedantic -c -fPIC ${DEBUG} -CLINKS:=-lpthread -lrt ${DEBUG} -DEFINES:=-D__UMAKEFILE - -SRCS:=${sort ${SRCS}} - -.PHONY: all run new clean main - - -# all - do everything (default) # -all: ./lib/libxbee.so.$(VERSION) main - @echo "*** Done! ***" - - -# run - remake main and then run # -run: main - ./bin/main - - -# new - clean and do everything again # -new: clean all - - -# clean - remove any compiled files and PDFs # -clean: - rm -f ./*~ - rm -f ./sample/*~ - rm -f ./obj/*.o - rm -f ./lib/libxbee.so* - rm -f ./bin/main - -# install - installs library # -install: /usr/lib/libxbee.so.$(VERSION) /usr/include/xbee.h - -/usr/lib/libxbee.so.$(VERSION): ./lib/libxbee.so.$(VERSION) - cp ./lib/libxbee.so.$(VERSION) /usr/lib/libxbee.so.$(VERSION) -f - @chmod 755 /usr/lib/libxbee.so.$(VERSION) - @chown root:root /usr/lib/libxbee.so.$(VERSION) - ln ./libxbee.so.$(VERSION) /usr/lib/libxbee.so.1 -sf - @chown root:root /usr/lib/libxbee.so.1 - ln ./libxbee.so.$(VERSION) /usr/lib/libxbee.so -sf - @chown root:root /usr/lib/libxbee.so - -/usr/include/xbee.h: ./xbee.h - cp ./xbee.h /usr/include/xbee.h -f - @chmod 644 /usr/include/xbee.h - @chown root:root /usr/include/xbee.h - -uninstall: - rm /usr/lib/libxbee.so.$(VERSION) -f - rm /usr/lib/libxbee.so.1 -f - rm /usr/lib/libxbee.so -f - rm /usr/include/xbee.h -f - -# main - compile & link objects # -main: ./bin/main - -./bin/main: ./obj/api.o ./bin/ ./main.c - ${CC} ${CLINKS} ./main.c ./obj/api.o -o ./bin/main ${DEBUG} - -./bin/: - mkdir ./bin/ - -./lib/libxbee.so.$(VERSION): ./lib/ ${addprefix ./obj/,${SRCS:.c=.o}} ./xbee.h - gcc -shared -Wl,-soname,libxbee.so.1 -o ./lib/libxbee.so.$(VERSION) ./obj/*.o -lrt - ln ./libxbee.so.$(VERSION) ./lib/libxbee.so.1 -sf - ln ./libxbee.so.$(VERSION) ./lib/libxbee.so -sf - -./lib/: - mkdir ./lib/ - -./obj/: - mkdir ./obj/ - -./obj/%.o: ./obj/ %.c %.h xbee.h - ${CC} ${CFLAGS} ${DEFINES} ${DEBUG} $*.c -o $@ - -./obj/%.o: ./obj/ %.c xbee.h - ${CC} ${CFLAGS} ${DEFINES} ${DEBUG} $*.c -o $@ diff --git a/libs/thirdParty/libxbee/win32.README.txt b/libs/thirdParty/libxbee/win32.README.txt deleted file mode 100644 index f16dc0d94eda4b5ad239c31e806ee2a90f970d92..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/win32.README.txt +++ /dev/null @@ -1,31 +0,0 @@ -Welcome to libxbee! - -I have proveded sample code in the ./sample directory. Hopefully this will help -get you up and running with libxbee. If you would like samples showing a different -aspect of libxbee, then please do not hesitate to file an 'issue' on the project -site, and I will get to it ASAP: - http://code.google.com/p/libxbee/issues/list - - -Documentation is avaliable as HTML in the 'doc' folder. - - -Please note that this project is still in development, so should not be used for -any purpose other than learning/playing/testing etc... Basically don't use it to -make money, and then hold me responsible if it breaks! - -Feel free to contact me directly with any queries: - attie@attie.co.uk - - -=== Compiling & Using === - -To compile you must: - 1) Have Visual C++ 2008 (v9.0) installed (Express or otherwise) - 2) Have make installed - see GnuWin - 3) Modify win32.makefile so that the paths at the top are correct - -Compile using `make -f win32.makefile` from the command prompt - -For C/C++ (and probrably others) just include xbee.h and link with libxbee.dll -For VB6 see ./sample/vb6/ for more info & examples diff --git a/libs/thirdParty/libxbee/win32.makefile b/libs/thirdParty/libxbee/win32.makefile deleted file mode 100644 index d90965681799c87a2e9f7b4b0da82d67f4d418bc..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/win32.makefile +++ /dev/null @@ -1,48 +0,0 @@ -#-- uncomment this to enable debugging -#DEBUG:=/Zi /DDEBUG /MTd -#LDBUG:=/DEBUG - -#-- you may need to edit these lines if your installation is different -VCPath:=C:\Program Files\Microsoft Visual Studio 10.0\VC -SDKPath:=C:\Program Files\Microsoft SDKs\Windows\v7.1 - -#!! if using visual studio 2010, you may need to run the following in a shell, -# and then within the same shell run `make -f win32.makefile` -# C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat - -###### YOU SHOULD NOT CHANGE BELOW THIS LINE ###### -SHELL:=cmd -DEBUG?=/MT - -SRCS:=api.c - -CC:="${VCPath}\bin\cl.exe" -LINK:="${VCPath}\bin\link.exe" -RC:="${SDKPath}\bin\rc.exe" - -.PHONY: all new clean - -all: .\lib\libxbee.dll - -new: clean all - -clean: - -rmdir /Q /S lib - -rmdir /Q /S obj - -.\obj: - mkdir obj - -.\lib: - mkdir lib - -.\lib\libxbee.dll: .\lib .\obj\api.obj .\obj\win32.res - ${LINK} ${LDBUG} /nologo /DLL /MAP:lib\libxbee.map /DEF:xsys\win32.def \ - "/LIBPATH:${SDKPath}\Lib" "/LIBPATH:${VCPath}\lib" \ - /OUT:.\lib\libxbee.dll .\obj\api.obj .\obj\win32.res - -.\obj\api.obj: .\obj api.c api.h xbee.h - ${CC} ${DEBUG} /nologo "/I${SDKPath}\Include" "/I${VCPath}\include" /RTCs /Gz /c /Fd.\lib\libxbee.pdb /Fo.\obj\api.obj ${SRCS} - -.\obj\win32.res: .\xsys\win32.rc - ${RC} "/I${SDKPath}\Include" "/I${VCPath}\include" /n /fo.\obj\win32.res .\xsys\win32.rc diff --git a/libs/thirdParty/libxbee/xbee.h b/libs/thirdParty/libxbee/xbee.h deleted file mode 100644 index 61331d84434f4170501acda1e794a6a8d669ad3c..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xbee.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#ifndef XBEE_H -#define XBEE_H - -#if !defined(__GNUC__) && !defined(_WIN32) -#error "This library is only currently compatible with Linux and Win32" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __LIBXBEE_API_H -typedef void* xbee_hnd; -#endif - -#include - -#ifdef __GNUC__ /* ---- */ -#include -typedef pthread_mutex_t xbee_mutex_t; -typedef pthread_cond_t xbee_cond_t; -typedef pthread_t xbee_thread_t; -typedef sem_t xbee_sem_t; -typedef FILE* xbee_file_t; -#elif (defined(WIN32) || defined(_WIN32)) /* -------------- */ -#include -#define CALLTYPE __stdcall -#define CALLTYPEVA __cdecl -typedef HANDLE xbee_mutex_t; -typedef CONDITION_VARIABLE xbee_cond_t; -typedef HANDLE xbee_thread_t; -typedef HANDLE xbee_sem_t; -typedef HANDLE xbee_file_t; -#else -#error "Unknown operating system or compiler" -#endif /* ------------- */ - -#ifndef CALLTYPE -#define CALLTYPE -#endif - -#ifndef CALLTYPEVA -#define CALLTYPEVA -#endif - -enum xbee_types { - xbee_unknown, - - xbee_localAT, /* frame ID */ - xbee_remoteAT, - xbee_modemStatus, - xbee_txStatus, - - /* XBee Series 1 stuff */ - xbee_16bitRemoteAT, /* frame ID */ - xbee_64bitRemoteAT, /* frame ID */ - - xbee_16bitData, /* frame ID for ACKs */ - xbee_64bitData, /* frame ID for ACKs */ - - xbee_16bitIO, - xbee_64bitIO, - - /* XBee Series 2 stuff */ - xbee2_data, - xbee2_txStatus -}; -typedef enum xbee_types xbee_types; - -typedef struct xbee_sample xbee_sample; -struct xbee_sample { - /* X A5 A4 A3 A2 A1 A0 D8 D7 D6 D5 D4 D3 D2 D1 D0 */ - unsigned short IOmask; /* IO */ - /* X X X X X X X D8 D7 D6 D5 D4 D3 D2 D1 D0 */ - unsigned short IOdigital; /* IO */ - /* X X X X X D D D D D D D D D D D */ - unsigned short IOanalog[6]; /* IO */ -}; - -typedef struct xbee_pkt xbee_pkt; -struct xbee_pkt { - unsigned int sAddr64 : 1; /* yes / no */ - unsigned int dataPkt : 1; /* if no - AT packet */ - unsigned int txStatusPkt : 1; - unsigned int modemStatusPkt : 1; - unsigned int remoteATPkt : 1; - unsigned int IOPkt : 1; - unsigned int isBroadcastADR : 1; - unsigned int isBroadcastPAN : 1; - - unsigned char frameID; /* AT Status */ - unsigned char atCmd[2]; /* AT */ - - unsigned char status; /* AT Data Status */ /* status / options */ - unsigned char samples; - unsigned char RSSI; /* Data */ - - unsigned char Addr16[2]; /* AT Data */ - - unsigned char Addr64[8]; /* AT Data */ - - unsigned char data[128]; /* AT Data */ - - unsigned int datalen; - xbee_types type; - - xbee_pkt *next; - - xbee_sample IOdata[1]; /* this array can be extended by using a this trick: - p = calloc(sizeof(xbee_pkt) + (sizeof(xbee_sample) * (samples - 1))) */ -}; - -typedef struct xbee_con xbee_con; -struct xbee_con { - unsigned int tAddr64 : 1; - unsigned int atQueue : 1; /* queues AT commands until AC is sent */ - unsigned int txDisableACK : 1; - unsigned int txBroadcastPAN: 1; /* broadcasts to PAN */ - unsigned int destroySelf : 1; /* if set, the callback thread will destroy the connection - after all of the packets have been processed */ - unsigned int waitforACK : 1; /* waits for the ACK or NAK after transmission */ - unsigned int noFreeAfterCB : 1; /* prevents libxbee from free'ing the packet after the callback has completed */ - unsigned int __spare__ : 1; - xbee_types type; - unsigned char frameID; - unsigned char tAddr[8]; /* 64-bit 0-7 16-bit 0-1 */ - void *customData; /* can be used to store data related to this connection */ - void (CALLTYPE *callback)(xbee_con*,xbee_pkt*); /* call back function */ - void *callbackList; - xbee_mutex_t callbackmutex; - xbee_mutex_t callbackListmutex; - xbee_mutex_t Txmutex; - xbee_sem_t waitforACKsem; - volatile unsigned char ACKstatus; /* 255 = waiting, 0 = success, 1 = no ack, 2 = cca fail, 3 = purged */ - xbee_con *next; -}; - -int CALLTYPE xbee_setup(char *path, int baudrate); -int CALLTYPE xbee_setuplog(char *path, int baudrate, int logfd); -int CALLTYPE xbee_setupAPI(char *path, int baudrate, char cmdSeq, int cmdTime); -int CALLTYPE xbee_setuplogAPI(char *path, int baudrate, int logfd, char cmdSeq, int cmdTime); -xbee_hnd CALLTYPE _xbee_setup(char *path, int baudrate); -xbee_hnd CALLTYPE _xbee_setuplog(char *path, int baudrate, int logfd); -xbee_hnd CALLTYPE _xbee_setupAPI(char *path, int baudrate, char cmdSeq, int cmdTime); -xbee_hnd CALLTYPE _xbee_setuplogAPI(char *path, int baudrate, int logfd, char cmdSeq, int cmdTime); - -int CALLTYPE xbee_end(void); -int CALLTYPE _xbee_end(xbee_hnd xbee); - -void CALLTYPE xbee_logitf(char *format, ...); -void CALLTYPE _xbee_logitf(xbee_hnd xbee, char *format, ...); -void CALLTYPE xbee_logit(char *str); -void CALLTYPE _xbee_logit(xbee_hnd xbee, char *str); - -xbee_con * CALLTYPEVA xbee_newcon(unsigned char frameID, xbee_types type, ...); -xbee_con * CALLTYPEVA _xbee_newcon(xbee_hnd xbee, unsigned char frameID, xbee_types type, ...); -xbee_con * CALLTYPE _xbee_vnewcon(xbee_hnd xbee, unsigned char frameID, xbee_types type, va_list ap); - -void CALLTYPE xbee_purgecon(xbee_con *con); -void CALLTYPE _xbee_purgecon(xbee_hnd xbee, xbee_con *con); - -void CALLTYPE xbee_endcon2(xbee_con **con, int alreadyUnlinked); -void CALLTYPE _xbee_endcon2(xbee_hnd xbee, xbee_con **con, int alreadyUnlinked); -#define xbee_endcon(x) xbee_endcon2(&(x),0) -#define _xbee_endcon(xbee,x) _xbee_endcon2((xbee),&(x),0) - -int CALLTYPE xbee_nsenddata(xbee_con *con, char *data, int length); -int CALLTYPE _xbee_nsenddata(xbee_hnd xbee, xbee_con *con, char *data, int length); -int CALLTYPEVA xbee_senddata(xbee_con *con, char *format, ...); -int CALLTYPEVA _xbee_senddata(xbee_hnd xbee, xbee_con *con, char *format, ...); -int CALLTYPE xbee_vsenddata(xbee_con *con, char *format, va_list ap); -int CALLTYPE _xbee_vsenddata(xbee_hnd xbee, xbee_con *con, char *format, va_list ap); - -#if defined(WIN32) -/* oh and just 'cos windows has rubbish memory management rules... this too */ -void CALLTYPE xbee_free(void *ptr); -#endif /* ------------- */ - -xbee_pkt * CALLTYPE xbee_getpacket(xbee_con *con); -xbee_pkt * CALLTYPE _xbee_getpacket(xbee_hnd xbee, xbee_con *con); -xbee_pkt * CALLTYPE xbee_getpacketwait(xbee_con *con); -xbee_pkt * CALLTYPE _xbee_getpacketwait(xbee_hnd xbee, xbee_con *con); - -int CALLTYPE xbee_hasdigital(xbee_pkt *pkt, int sample, int input); -int CALLTYPE xbee_getdigital(xbee_pkt *pkt, int sample, int input); - -int CALLTYPE xbee_hasanalog(xbee_pkt *pkt, int sample, int input); -double CALLTYPE xbee_getanalog(xbee_pkt *pkt, int sample, int input, double Vref); - -const char * CALLTYPE xbee_svn_version(void); -const char * CALLTYPE xbee_build_info(void); - -void CALLTYPE xbee_listen_stop(xbee_hnd xbee); - -#ifdef __cplusplus -} /* cplusplus */ -#endif - -#endif diff --git a/libs/thirdParty/libxbee/xsys/README b/libs/thirdParty/libxbee/xsys/README deleted file mode 100644 index 48d3928505730bab3f66fd31195b427700648bd3..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xsys/README +++ /dev/null @@ -1 +0,0 @@ -This directory contains cross-system support files. \ No newline at end of file diff --git a/libs/thirdParty/libxbee/xsys/linux.c b/libs/thirdParty/libxbee/xsys/linux.c deleted file mode 100644 index 768d5b3d4ecb9edf05cc53bbc2c088df398810d6..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xsys/linux.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* ################################################################# */ -/* ### Linux Code ################################################## */ -/* ################################################################# */ - -/* this file contains code that is used by Linux ONLY */ -#ifndef __GNUC__ -#error "This file should only be used on a Linux system" -#endif - -#include "linux.h" - -int init_serial(xbee_hnd xbee, int baudrate) { - struct flock fl; - struct termios tc; - speed_t chosenbaud; - - /* select the baud rate */ - switch (baudrate) { - case 1200: chosenbaud = B1200; break; - case 2400: chosenbaud = B2400; break; - case 4800: chosenbaud = B4800; break; - case 9600: chosenbaud = B9600; break; - case 19200: chosenbaud = B19200; break; - case 38400: chosenbaud = B38400; break; - case 57600: chosenbaud = B57600; break; - case 115200:chosenbaud = B115200; break; - default: - fprintf(stderr,"%s(): Unknown or incompatiable baud rate specified... (%d)\n",__FUNCTION__,baudrate); - return -1; - }; - - /* open the serial port as a file descriptor */ - if ((xbee->ttyfd = open(xbee->path,O_RDWR | O_NOCTTY | O_NONBLOCK)) == -1) { - xbee_perror("xbee_setup():open()"); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee->path); - return -1; - } - - /* lock the file */ - fl.l_type = F_WRLCK | F_RDLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_pid = getpid(); - if (fcntl(xbee->ttyfd, F_SETLK, &fl) == -1) { - xbee_perror("xbee_setup():fcntl()"); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee->path); - close(xbee->ttyfd); - return -1; - } - - /* open the serial port as a FILE* */ - if ((xbee->tty = fdopen(xbee->ttyfd,"r+")) == NULL) { - xbee_perror("xbee_setup():fdopen()"); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee->path); - close(xbee->ttyfd); - return -1; - } - - /* flush the serial port */ - fflush(xbee->tty); - - /* disable buffering */ - setvbuf(xbee->tty,NULL,_IONBF,BUFSIZ); - - /* setup the baud rate and other io attributes */ - tcgetattr(xbee->ttyfd, &tc); - /* input flags */ - tc.c_iflag &= ~ IGNBRK; /* enable ignoring break */ - tc.c_iflag &= ~(IGNPAR | PARMRK); /* disable parity checks */ - tc.c_iflag &= ~ INPCK; /* disable parity checking */ - tc.c_iflag &= ~ ISTRIP; /* disable stripping 8th bit */ - tc.c_iflag &= ~(INLCR | ICRNL); /* disable translating NL <-> CR */ - tc.c_iflag &= ~ IGNCR; /* disable ignoring CR */ - tc.c_iflag &= ~(IXON | IXOFF); /* disable XON/XOFF flow control */ - /* output flags */ - tc.c_oflag &= ~ OPOST; /* disable output processing */ - tc.c_oflag &= ~(ONLCR | OCRNL); /* disable translating NL <-> CR */ - tc.c_oflag &= ~ OFILL; /* disable fill characters */ - /* control flags */ - tc.c_cflag |= CREAD; /* enable reciever */ - tc.c_cflag &= ~ PARENB; /* disable parity */ - tc.c_cflag &= ~ CSTOPB; /* disable 2 stop bits */ - tc.c_cflag &= ~ CSIZE; /* remove size flag... */ - tc.c_cflag |= CS8; /* ...enable 8 bit characters */ - tc.c_cflag |= HUPCL; /* enable lower control lines on close - hang up */ - /* local flags */ - tc.c_lflag &= ~ ISIG; /* disable generating signals */ - tc.c_lflag &= ~ ICANON; /* disable canonical mode - line by line */ - tc.c_lflag &= ~ ECHO; /* disable echoing characters */ - tc.c_lflag &= ~ ECHONL; /* ??? */ - tc.c_lflag &= ~ NOFLSH; /* disable flushing on SIGINT */ - tc.c_lflag &= ~ IEXTEN; /* disable input processing */ - /* control characters */ - memset(tc.c_cc,0,sizeof(tc.c_cc)); - /* i/o rates */ - cfsetspeed(&tc, chosenbaud); /* set i/o baud rate */ - tcsetattr(xbee->ttyfd, TCSANOW, &tc); - tcflow(xbee->ttyfd, TCOON|TCION); /* enable input & output transmission */ - - return 0; -} - -static int xbee_select(xbee_hnd xbee, struct timeval *timeout) { - fd_set fds; - - FD_ZERO(&fds); - FD_SET(xbee->ttyfd, &fds); - - return select(xbee->ttyfd+1, &fds, NULL, NULL, timeout); -} - -#define xbee_sem_wait1sec(a) xbee_sem_wait1sec2(&(a)) -static inline int xbee_sem_wait1sec2(xbee_sem_t *sem) { - struct timespec to; - clock_gettime(CLOCK_REALTIME,&to); - to.tv_sec++; - return sem_timedwait(sem,&to); -} diff --git a/libs/thirdParty/libxbee/xsys/linux.h b/libs/thirdParty/libxbee/xsys/linux.h deleted file mode 100644 index 886bbf5bf1c33ed4a59fa6d7396dc198ff3d9342..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xsys/linux.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this file contains code that is used by Linux ONLY */ -#ifndef __GNUC__ -#error "This file should only be used on a Linux system" -#endif - -/* ################################################################# */ -/* ### Linux Code ################################################## */ -/* ################################################################# */ - -#define xbee_thread_create(a,b,c) pthread_create(&(a),NULL,(void *(*)(void *))(b),(void *)(c)) -#define xbee_thread_cancel(a,b) pthread_cancel((a)) -#define xbee_thread_join(a) pthread_join((a),NULL) -#define xbee_thread_tryjoin(a) pthread_tryjoin_np((a),NULL) - -#define xbee_mutex_init(a) pthread_mutex_init(&(a),NULL) -#define xbee_mutex_destroy(a) pthread_mutex_destroy(&(a)) -#define xbee_mutex_lock(a) pthread_mutex_lock(&(a)) -#define xbee_mutex_trylock(a) pthread_mutex_trylock(&(a)) -#define xbee_mutex_unlock(a) pthread_mutex_unlock(&(a)) - -#define xbee_sem_init(a) sem_init(&(a),0,0) -#define xbee_sem_destroy(a) sem_destroy(&(a)) -#define xbee_sem_wait(a) sem_wait(&(a)) -#define xbee_sem_post(a) sem_post(&(a)) - -#define xbee_cond_init(a) pthread_cond_init(&(a),NULL) -#define xbee_cond_destroy(a) pthread_cond_destroy(&(a)) -#define xbee_cond_wait(a,b) pthread_cond_wait(&(a),&(b)) -#define xbee_cond_signal(a) pthread_cond_signal(&(a)) -#define xbee_cond_broadcast(a) pthread_cond_broadcast(&(a)) - -#define xbee_write(xbee,a,b) fwrite((a),1,(b),(xbee)->tty) -#define xbee_read(xbee,a,b) fread((a),1,(b),(xbee)->tty) -#define xbee_ferror(xbee) ferror((xbee)->tty) -#define xbee_feof(xbee) feof((xbee)->tty) -#define xbee_close(a) fclose((a)) - diff --git a/libs/thirdParty/libxbee/xsys/pdf/linux.c.pdf b/libs/thirdParty/libxbee/xsys/pdf/linux.c.pdf deleted file mode 100644 index 75a9a38b29af858ad4bb773704982d44fa400b32..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/xsys/pdf/linux.c.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/xsys/pdf/linux.h.pdf b/libs/thirdParty/libxbee/xsys/pdf/linux.h.pdf deleted file mode 100644 index a4c65ae408966bc912ed72e08fc49c4edee516ff..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/xsys/pdf/linux.h.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/xsys/pdf/win32.c.pdf b/libs/thirdParty/libxbee/xsys/pdf/win32.c.pdf deleted file mode 100644 index ec776c30b824ae659ab2cb2f31907df2f608dff8..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/xsys/pdf/win32.c.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/xsys/pdf/win32.def.pdf b/libs/thirdParty/libxbee/xsys/pdf/win32.def.pdf deleted file mode 100644 index 99b0548e4d2703b57cf69ec0fde18166639f570e..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/xsys/pdf/win32.def.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/xsys/pdf/win32.dll.c.pdf b/libs/thirdParty/libxbee/xsys/pdf/win32.dll.c.pdf deleted file mode 100644 index 97d7acb34cfe49904b5c08b6c227512fc8bc6048..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/xsys/pdf/win32.dll.c.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/xsys/pdf/win32.h.pdf b/libs/thirdParty/libxbee/xsys/pdf/win32.h.pdf deleted file mode 100644 index b844726f1a19607952831452b160be3896a412b1..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/xsys/pdf/win32.h.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/xsys/pdf/win32.rc.pdf b/libs/thirdParty/libxbee/xsys/pdf/win32.rc.pdf deleted file mode 100644 index 8ff8a7956bff9e4e4ff4b5cb33683835c635a36c..0000000000000000000000000000000000000000 Binary files a/libs/thirdParty/libxbee/xsys/pdf/win32.rc.pdf and /dev/null differ diff --git a/libs/thirdParty/libxbee/xsys/win32.c b/libs/thirdParty/libxbee/xsys/win32.c deleted file mode 100644 index a05950a94b6a44e84db33f067f85c07ae9c90342..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xsys/win32.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* ################################################################# */ -/* ### Win32 Code ################################################## */ -/* ################################################################# */ - -/* this file contains code that is used by Win32 ONLY */ -#ifndef _WIN32 -#error "This file should only be used on a Win32 system" -#endif - -#include "win32.h" -#include "win32.dll.c" - -static int init_serial(xbee_hnd xbee, int baudrate) { - int chosenbaud; - DCB tc; - int evtMask; - COMMTIMEOUTS timeouts; - - /* open the serial port */ - xbee->tty = CreateFile(TEXT(xbee->path), - GENERIC_READ | GENERIC_WRITE, - 0, /* exclusive access */ - NULL, /* default security attributes */ - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - if (xbee->tty == INVALID_HANDLE_VALUE) { - xbee_logS("Invalid file handle..."); - xbee_logE("Is the XBee plugged in and avaliable on the correct port?"); - xbee_mutex_destroy(xbee->conmutex); - xbee_mutex_destroy(xbee->pktmutex); - xbee_mutex_destroy(xbee->sendmutex); - Xfree(xbee->path); - return -1; - } - - GetCommState(xbee->tty, &tc); - tc.BaudRate = baudrate; - tc.fBinary = TRUE; - tc.fParity = FALSE; - tc.fOutxCtsFlow = FALSE; - tc.fOutxDsrFlow = FALSE; - tc.fDtrControl = DTR_CONTROL_DISABLE; - tc.fDsrSensitivity = FALSE; - tc.fTXContinueOnXoff = FALSE; - tc.fOutX = FALSE; - tc.fInX = FALSE; - tc.fErrorChar = FALSE; - tc.fNull = FALSE; - tc.fRtsControl = RTS_CONTROL_DISABLE; - tc.fAbortOnError = FALSE; - tc.ByteSize = 8; - tc.Parity = NOPARITY; - tc.StopBits = ONESTOPBIT; - SetCommState(xbee->tty, &tc); - - timeouts.ReadIntervalTimeout = MAXDWORD; - timeouts.ReadTotalTimeoutMultiplier = 0; - timeouts.ReadTotalTimeoutConstant = 0; - timeouts.WriteTotalTimeoutMultiplier = 0; - timeouts.WriteTotalTimeoutConstant = 0; - SetCommTimeouts(xbee->tty, &timeouts); - - SetCommMask(xbee->tty, EV_RXCHAR); - - return 0; -} - -/* a replacement for the linux select() function... for a serial port */ -static int xbee_select(xbee_hnd xbee, struct timeval *timeout) { - int evtMask = 0; - COMSTAT status; - int ret; - - for (;;) { - /* find out how many bytes are in the Rx buffer... */ - if (ClearCommError(xbee->tty,NULL,&status) && (status.cbInQue > 0)) { - /* if there is data... return! */ - return 1; /*status.cbInQue;*/ - } else if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { - /* if the timeout was 0 (return immediately) then return! */ - return 0; - } - - /* otherwise wait for an Rx event... */ - memset(&(xbee->ttyovrs),0,sizeof(OVERLAPPED)); - xbee->ttyovrs.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - if (!WaitCommEvent(xbee->tty,&evtMask,&(xbee->ttyovrs))) { - if (GetLastError() == ERROR_IO_PENDING) { - DWORD timeoutval; - if (!timeout) { - /* behave like the linux function... if the timeout pointer was NULL - then wait indefinately */ - timeoutval = INFINITE; - } else { - /* Win32 doesn't give the luxury of microseconds and seconds... just miliseconds! */ - timeoutval = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); - } - ret = WaitForSingleObject(xbee->ttyovrs.hEvent,timeoutval); - if (ret == WAIT_TIMEOUT) { - /* cause the WaitCommEvent() call to stop */ - SetCommMask(xbee->tty, EV_RXCHAR); - /* if a timeout occured, then return 0 */ - CloseHandle(xbee->ttyovrs.hEvent); - return 0; - } - } else { - return -1; - } - } - CloseHandle(xbee->ttyovrs.hEvent); - } - - /* always return -1 (error) for now... */ - return -1; -} - -/* this offers the same behavior as non-blocking I/O under linux */ -int xbee_write(xbee_hnd xbee, const void *ptr, size_t size) { - xbee->ttyeof = FALSE; - if (!WriteFile(xbee->tty, ptr, size, NULL, &(xbee->ttyovrw)) && - (GetLastError() != ERROR_IO_PENDING)) return 0; - if (!GetOverlappedResult(xbee->tty, &(xbee->ttyovrw), &(xbee->ttyw), TRUE)) { - if (GetLastError() == ERROR_HANDLE_EOF) xbee->ttyeof = TRUE; - return 0; - } - return xbee->ttyw; -} - -/* this offers the same behavior as non-blocking I/O under linux */ -int xbee_read(xbee_hnd xbee, void *ptr, size_t size) { - xbee->ttyeof = FALSE; - if (!ReadFile(xbee->tty, ptr, size, NULL, &(xbee->ttyovrr)) && - (GetLastError() != ERROR_IO_PENDING)) return 0; - if (!GetOverlappedResult(xbee->tty, &(xbee->ttyovrr), &(xbee->ttyr), TRUE)) { - if (GetLastError() == ERROR_HANDLE_EOF) xbee->ttyeof = TRUE; - return 0; - } - return xbee->ttyr; -} - -/* this is because Win32 has some weird memory management rules... - - the thread that allocated the memory, MUST free it... */ -void xbee_free(void *ptr) { - if (!ptr) return; - free(ptr); -} - -/* win32 equivalent of unix gettimeofday() */ -int gettimeofday(struct timeval *tv, struct timezone *tz) { - if (tv) { - struct _timeb timeb; - _ftime(&timeb); - tv->tv_sec = timeb.time; - tv->tv_usec = timeb.millitm * 1000; - } - /* ignore tz for now */ - return 0; -} - -/* ################################################################# */ -/* ### Helper Functions (Mainly for VB6 use) ####################### */ -/* ################################################################# */ - -/* enable the debug output to a custom file or fallback to stderr */ -int xbee_setupDebugAPI(char *path, int baudrate, char *logfile, char cmdSeq, int cmdTime) { - xbee_hnd xbee = NULL; - int fd, ret; - if ((fd = _open(logfile,_O_WRONLY | _O_CREAT | _O_TRUNC)) == -1) { - fd = 2; - } - ret = xbee_setuplogAPI(path,baudrate,fd,cmdSeq,cmdTime); - if (fd > 2) { /* close fd, as libxbee dup'ed it */ - //_close(fd); - } - if (!ret) { /* libxbee started correctly */ - xbee = default_xbee; - if (fd == -1) { - xbee_log("Error opening logfile '%s' (errno=%d)... using stderr instead!",logfile,errno); - } - } - return ret; -} -int xbee_setupDebug(char *path, int baudrate, char *logfile) { - return xbee_setupDebugAPI(path,baudrate,logfile,0,0); -} - -/* These silly little functions are required for VB6 - - it freaks out when you call a function that uses va_args... */ -xbee_con *xbee_newcon_simple(unsigned char frameID, xbee_types type) { - return xbee_newcon(frameID, type); -} -xbee_con *xbee_newcon_16bit(unsigned char frameID, xbee_types type, int addr) { - return xbee_newcon(frameID, type, addr); -} -xbee_con *xbee_newcon_64bit(unsigned char frameID, xbee_types type, int addrL, int addrH) { - return xbee_newcon(frameID, type, addrL, addrH); -} - -void xbee_enableACKwait(xbee_con *con) { - con->waitforACK = 1; -} -void xbee_disableACKwait(xbee_con *con) { - con->waitforACK = 0; -} - -void xbee_enableDestroySelf(xbee_con *con) { - con->destroySelf = 1; -} - -/* for vb6... it will send a message to the given hWnd which can in turn check for a packet */ -void xbee_callback(xbee_con *con, xbee_pkt *pkt) { - xbee_hnd xbee = default_xbee; - - if (!win32_hWnd) { - xbee_log("*** Cannot do callback! No hWnd set... ***"); - return; - } - if (!win32_MessageID) { - xbee_log("*** Cannot do callback! No MessageID set... ***"); - return; - } - - xbee_log("Callback message sent!"); - SendMessage(win32_hWnd, win32_MessageID, (int)con, (int)pkt); -} - -/* very simple C function to provide more functionality to VB6 */ -int xbee_runCallback(int(*func)(xbee_con*,xbee_pkt*), xbee_con *con, xbee_pkt *pkt) { - return func(con,pkt); -} - -void xbee_enableCallbacks(HWND hWnd, UINT uMsg) { - xbee_hnd xbee = default_xbee; - if (!win32_MessageID || win32_MessageID != uMsg) { - xbee_log("Configuring libxbee to use MessageID = 0x%08X", uMsg); - win32_MessageID = uMsg; - } - if (!win32_hWnd || win32_hWnd != hWnd) { - xbee_log("Configuring libxbee to use hWnd = 0x%08X", hWnd); - win32_hWnd = hWnd; - } -} - -void xbee_attachCallback(xbee_con *con) { - xbee_hnd xbee = default_xbee; - - /* setup the callback function */ - xbee_log("Setting callback for connection @ 0x%08X",con); - con->callback = xbee_callback; -} - -void xbee_detachCallback(xbee_con *con) { - xbee_hnd xbee = default_xbee; - - /* un-setup the callback function */ - xbee_log("Unsetting callback for connection @ 0x%08X",con); - con->callback = NULL; -} diff --git a/libs/thirdParty/libxbee/xsys/win32.def b/libs/thirdParty/libxbee/xsys/win32.def deleted file mode 100644 index 888040ee38085c483632a80f083ba61390c36eb5..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xsys/win32.def +++ /dev/null @@ -1,71 +0,0 @@ -LIBRARY libxbee - -EXPORTS - ver - DllMain - DllCanUnloadNow PRIVATE - DllRegisterServer PRIVATE - DllUnregisterServer PRIVATE - - xbee_free - - xbee_setup - _xbee_setup - xbee_setuplog - _xbee_setuplog - xbee_setupAPI - _xbee_setupAPI - xbee_setuplogAPI - _xbee_setuplogAPI - xbee_setupDebug - xbee_setupDebugAPI - - xbee_end - _xbee_end - xbee_listen_stop - - xbee_newcon - _xbee_newcon - xbee_newcon_simple - xbee_newcon_16bit - xbee_newcon_64bit - - xbee_enableACKwait - xbee_disableACKwait - xbee_enableDestroySelf - - xbee_enableCallbacks - xbee_attachCallback - xbee_detachCallback - xbee_runCallback - - xbee_endcon2 - _xbee_endcon2 - xbee_purgecon - _xbee_purgecon - - xbee_senddata - _xbee_senddata - xbee_nsenddata - _xbee_nsenddata - xbee_vsenddata - _xbee_vsenddata - - xbee_getpacket - _xbee_getpacket - xbee_getpacketwait - _xbee_getpacketwait - - xbee_hasanalog - xbee_getanalog - - xbee_hasdigital - xbee_getdigital - - xbee_svn_version - xbee_build_info - - xbee_logit - _xbee_logit - xbee_logitf - _xbee_logitf diff --git a/libs/thirdParty/libxbee/xsys/win32.dll.c b/libs/thirdParty/libxbee/xsys/win32.dll.c deleted file mode 100644 index 1a9ebcaa8573d6b77f9af6cdc70d12eeaa6b308b..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xsys/win32.dll.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* ################################################################# */ -/* ### Win32 DLL Code ############################################## */ -/* ################################################################# */ - -/* this file contains code that is used by Win32 ONLY */ -#ifndef _WIN32 -#error "This file should only be used on a Win32 system" -#endif - -int ver(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - char t[256]; - sprintf(t,"libxbee.dll\n%s\n%s",xbee_svn_version(),xbee_build_info()); - MessageBox(NULL, t, "libxbee Win32 DLL", MB_OK); - return 0; -} - -void xbee_UNLOADALL(void) { - while (default_xbee) { - _xbee_end(default_xbee); - } -} - -/* this gets called when the dll is loaded and unloaded... */ -BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { - if (dwReason == DLL_PROCESS_DETACH) { - /* ensure that libxbee has been shut down nicely */ - xbee_UNLOADALL(); - } else if (dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH) { - if (!glob_hModule) { - /* keep a handle on the module */ - glob_hModule = (HMODULE)hModule; - } - } - return TRUE; -} - -HRESULT DllCanUnloadNow(void) { - if (default_xbee) return 0; - return 1; -} - -/* ################################################################# */ -/* ### Win32 DLL COM Code ########################################## */ -/* ################################################################# */ - -/* this function is from this tutorial: - http://www.codeguru.com/Cpp/COM-Tech/activex/tutorials/article.php/c5567 */ -BOOL RegWriteKey(HKEY roothk, const char *lpSubKey, LPCTSTR val_name, - DWORD dwType, void *lpvData, DWORD dwDataSize) { - /* roothk: HKEY_CLASSES_ROOT, HKEY_LOCAL_MACHINE, etc - lpSubKey: the key relative to 'roothk' - val_name: the key value name where the data will be written - dwType: REG_SZ,REG_BINARY, etc. - lpvData: a pointer to the data buffer - dwDataSize: the size of the data pointed to by lpvData */ - HKEY hk; - if (ERROR_SUCCESS != RegCreateKey(roothk,lpSubKey,&hk) ) return FALSE; - if (ERROR_SUCCESS != RegSetValueEx(hk,val_name,0,dwType,(CONST BYTE *)lpvData,dwDataSize)) return FALSE; - if (ERROR_SUCCESS != RegCloseKey(hk)) return FALSE; - return TRUE; -} - -/* this is used by the regsrv32 application */ -STDAPI DllRegisterServer(void) { - char key[MAX_PATH]; - char value[MAX_PATH]; - - wsprintf(key,"CLSID\\%s",dllGUID); - wsprintf(value,"%s",dlldesc); - RegWriteKey(HKEY_CLASSES_ROOT, key, NULL, REG_SZ, (void *)value, lstrlen(value)); - - wsprintf(key,"CLSID\\%s\\InprocServer32",dllGUID); - GetModuleFileName(glob_hModule,value,MAX_PATH); - RegWriteKey(HKEY_CLASSES_ROOT, key, NULL, REG_SZ, (void *)value, lstrlen(value)); - - wsprintf(key,"CLSID\\%s\\ProgId",dllGUID); - lstrcpy(value,dllid); - RegWriteKey(HKEY_CLASSES_ROOT, key, NULL, REG_SZ, (void *)value, lstrlen(value)); - - lstrcpy(key,dllid); - lstrcpy(value,dlldesc); - RegWriteKey(HKEY_CLASSES_ROOT, key, NULL, REG_SZ, (void *)value, lstrlen(value)); - - wsprintf(key,"%s\\CLSID",dllid); - RegWriteKey(HKEY_CLASSES_ROOT, key, NULL, REG_SZ, (void *)dllGUID, lstrlen(dllGUID)); - - return S_OK; -} - -/* this is used by the regsrv32 application */ -STDAPI DllUnregisterServer(void) { - char key[MAX_PATH]; - char value[MAX_PATH]; - - wsprintf(key,"%s\\CLSID",dllid); - RegDeleteKey(HKEY_CLASSES_ROOT,key); - - wsprintf(key,"%s",dllid); - RegDeleteKey(HKEY_CLASSES_ROOT,key); - - wsprintf(key,"CLSID\\%s\\InprocServer32",dllGUID); - RegDeleteKey(HKEY_CLASSES_ROOT,key); - - wsprintf(key,"CLSID\\%s\\ProgId",dllGUID); - RegDeleteKey(HKEY_CLASSES_ROOT,key); - - wsprintf(key,"CLSID\\%s",dllGUID); - RegDeleteKey(HKEY_CLASSES_ROOT,key); - - return S_OK; -} diff --git a/libs/thirdParty/libxbee/xsys/win32.h b/libs/thirdParty/libxbee/xsys/win32.h deleted file mode 100644 index 65f19f805cb978899aa3e9a19cf3e9fd115185e4..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xsys/win32.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - libxbee - a C library to aid the use of Digi's Series 1 XBee modules - running in API mode (AP=2). - - Copyright (C) 2009 Attie Grande (attie@attie.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* this file contains code that is used by Win32 ONLY */ -#ifndef _WIN32 -#error "This file should only be used on a Win32 system" -#endif - -/* ################################################################# */ -/* ### Win32 Code ################################################## */ -/* ################################################################# */ - -#pragma comment(lib, "Advapi32.lib") -#pragma comment(lib, "User32.lib") - -#define dllid "attie-co-uk.libxbee" -#define dlldesc "libxbee - XBee API Library" -/* libxbee's GUID is {7A6E25AA-ECB5-4370-87B5-A1D31840FE23} */ -#define dllGUID "{7A6E25AA-ECB5-4370-87B5-A1D31840FE23}" - -#define Win32Message() MessageBox(0,"Run xbee_setup() first!...","libxbee",MB_OK); - -HMODULE glob_hModule = NULL; - -/* this uses miliseconds not microseconds... */ -#define usleep(a) Sleep((a)/1000) - -#define xbee_thread_create(a,b,c) (((a) = CreateThread(NULL,0,(void *)(b),(void *)(c),0,NULL)) == NULL) -#define xbee_thread_cancel(a,b) TerminateThread((a),(b)) -#define xbee_thread_join(a) WaitForSingleObject((a),INFINITE) -#define xbee_thread_tryjoin(a) WaitForSingleObject((a),0) - -#define xbee_mutex_init(a) (((a) = CreateEvent(NULL,FALSE,TRUE,NULL)) == NULL) -#define xbee_mutex_destroy(a) CloseHandle((a)) -#define xbee_mutex_lock(a) WaitForSingleObject((a),INFINITE) -#define xbee_mutex_trylock(a) WaitForSingleObject((a),0) -#define xbee_mutex_unlock(a) SetEvent((a)) - -#define xbee_sem_init(a) (((a) = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL) -#define xbee_sem_destroy(a) CloseHandle((a)) -#define xbee_sem_wait(a) WaitForSingleObject((a),INFINITE) -#define xbee_sem_wait1sec(a) WaitForSingleObject((a),1000) -#define xbee_sem_post(a) SetEvent((a)) - -#define xbee_cond_init(a) InitializeConditionVariable(&(a)) -#define xbee_cond_destroy(a) -#define xbee_cond_wait(a,b) SleepConditionVariableCS(&(a),&(b),INFINITE) -#define xbee_cond_signal(a) WakeConditionVariable(&(a)) -#define xbee_cond_broadcast(a) WakeAllConditionVariable(&(a)) - -#define xbee_feof(a) (xbee->ttyeof) -#define xbee_ferror(a) (0) -#define xbee_close(a) (((a)==xbee->log)?fclose((a)):CloseHandle((a))) - -HWND win32_hWnd = 0; -UINT win32_MessageID = 0; diff --git a/libs/thirdParty/libxbee/xsys/win32.rc b/libs/thirdParty/libxbee/xsys/win32.rc deleted file mode 100644 index 80f7d33bc4d151193b3f12e5a59baf6c5b545405..0000000000000000000000000000000000000000 --- a/libs/thirdParty/libxbee/xsys/win32.rc +++ /dev/null @@ -1,47 +0,0 @@ -/* more info: http://msdn.microsoft.com/en-us/library/aa381058(v=vs.85).aspx */ - -#define APSTUDIO_READONLY_SYMBOLS -#include "winresrc.h" -#undef APSTUDIO_READONLY_SYMBOLS - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) - -#ifdef _WIN32 -/* Englush (UK) */ -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK -#pragma code_page(1252) -#endif //_WIN32 - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,1,0 - FILEFLAGSMASK 0x00L - FILEFLAGS 0x00L - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "Provides a simple interface for XBee radios" - VALUE "CompanyName", "attie.co.uk" - VALUE "FileDescription", "Provides a simple interface for XBee radios" - VALUE "InternalName", "libxbee" - VALUE "LegalCopyright", "Copyright (C) 2009 onwards Attie Grande" - VALUE "LegalTrademarks", "" - VALUE "OriginalFilename", "libxbee.dll" - VALUE "PrivateBuild", "" - VALUE "ProductName", "libxbee - http://code.google.com/p/libxbee/" - VALUE "ProductVersion", "v1.4.1" - VALUE "SpecialBuild", "" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1200 - END -END - - -#endif diff --git a/qgcresources.qrc b/qgcresources.qrc index 703a8361fde52bcb8e6d5e2d0b243a78ecb6c64f..ae67a275deadee15131f5a8449e588f4b3268f2c 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -46,6 +46,7 @@ src/AutoPilotPlugins/Common/Images/HelicopterCoaxial.svg src/AutoPilotPlugins/Common/Images/wifi.svg src/QmlControls/arrow-down.png + src/QmlControls/check.png src/VehicleSetup/FirmwareUpgradeIcon.png src/AutoPilotPlugins/PX4/Images/FlightModesComponentIcon.png src/AutoPilotPlugins/PX4/Images/CameraTrigger.svg @@ -54,11 +55,17 @@ src/AutoPilotPlugins/PX4/Images/DatalinkLossLight.svg src/AutoPilotPlugins/PX4/Images/GeoFence.svg src/AutoPilotPlugins/PX4/Images/GeoFenceLight.svg - src/AnalyzeView/GeoTagIcon.png + src/AnalyzeView/GeoTagIcon.svg src/AutoPilotPlugins/PX4/Images/LandMode.svg src/AutoPilotPlugins/PX4/Images/LandModeCopter.svg src/AutoPilotPlugins/APM/Images/LightsComponentIcon.png - src/AnalyzeView/LogDownloadIcon.png + src/AutoPilotPlugins/APM/Images/SubFrameComponentIcon.png + src/AutoPilotPlugins/APM/Images/bluerov-frame.png + src/AutoPilotPlugins/APM/Images/vectored-frame.png + src/AutoPilotPlugins/APM/Images/vectored6dof-frame.png + src/AutoPilotPlugins/APM/Images/simple3-frame.png + src/AutoPilotPlugins/APM/Images/simple4-frame.png + src/AnalyzeView/LogDownloadIcon.svg src/AutoPilotPlugins/PX4/Images/LowBattery.svg src/AutoPilotPlugins/PX4/Images/LowBatteryLight.svg src/AutoPilotPlugins/Common/Images/MotorComponentIcon.svg @@ -94,9 +101,7 @@ src/FlightMap/Images/attitudeDial.svg src/FlightMap/Images/attitudeInstrument.svg src/FlightMap/Images/attitudePointer.svg - src/FlightMap/Images/buttonHome.svg - src/FlightMap/Images/buttonMore.svg - src/FlightMap/Images/compassInstrumentAirplane.svg + src/FlightMap/Images/compassInstrumentArrow.svg src/FlightMap/Images/compassInstrumentDial.svg src/FlightMap/Images/crossHair.svg src/FlightMap/Images/PiP.svg @@ -106,11 +111,10 @@ src/FlightMap/Images/scale_end.png src/FlightMap/Images/scaleLight.png src/FlightMap/Images/scale_endLight.png - src/FlightMap/Images/airplaneOutline.svg - src/FlightMap/Images/airplaneOpaque.svg + src/FlightMap/Images/vehicleArrowOutline.svg + src/FlightMap/Images/vehicleArrowOpaque.svg src/FlightMap/Images/ZoomPlus.svg src/FlightMap/Images/ZoomMinus.svg - src/FlightMap/Images/ArrowHead.svg src/FlightMap/Images/Help.svg src/FlightMap/Images/HelpBlack.svg src/FlightMap/Images/MapAddMission.svg @@ -147,6 +151,7 @@ src/ui/toolbar/Images/Signal100.svg src/ui/toolbar/Images/TelemRSSI.svg src/ui/toolbar/Images/Yield.svg + src/ui/toolbar/Images/CameraIcon.svg src/MissionManager/CogWheel.svg src/AutoPilotPlugins/Common/Images/StationMode.svg src/AutoPilotPlugins/Common/Images/APMode.svg @@ -181,6 +186,7 @@ resources/TrashDelete.svg resources/XDelete.svg resources/XDeleteBlack.svg + resources/waves.svg resources/icons/qgroundcontrol.ico @@ -243,17 +249,6 @@ resources/calibration/mode2/radioThrottleDown.png resources/calibration/mode2/radioSwitchMinMax.png - - resources/calibration/joystick/joystickCenter.png - resources/calibration/joystick/joystickRollLeft.png - resources/calibration/joystick/joystickRollRight.png - resources/calibration/joystick/joystickPitchUp.png - resources/calibration/joystick/joystickPitchDown.png - resources/calibration/joystick/joystickYawLeft.png - resources/calibration/joystick/joystickYawRight.png - resources/calibration/joystick/joystickThrottleUp.png - resources/calibration/joystick/joystickThrottleDown.png - resources/SDL_GameControllerDB/gamecontrollerdb.txt @@ -264,33 +259,51 @@ resources/audio/alert.wav - - src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml - - - src/AutoPilotPlugins/APM/APMAirframeFactMetaData.xml + + resources/opengl/buglist.json - - src/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.3.xml - src/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.5.xml - src/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.3.xml - src/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.4.xml - src/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.0.xml - src/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.4.xml - src/FirmwarePlugin/APM/CopterGeoFenceEditor.qml - src/FirmwarePlugin/APM/PlaneGeoFenceEditor.qml - src/FirmwarePlugin/APM/Copter3.4.OfflineEditing.params - src/FirmwarePlugin/APM/Plane3.7.OfflineEditing.params + + resources/calibration/joystick/mode1/joystickCenter.png + resources/calibration/joystick/mode1/joystickPitchDown.png + resources/calibration/joystick/mode1/joystickPitchUp.png + resources/calibration/joystick/mode1/joystickRollLeft.png + resources/calibration/joystick/mode1/joystickRollRight.png + resources/calibration/joystick/mode1/joystickThrottleDown.png + resources/calibration/joystick/mode1/joystickThrottleUp.png + resources/calibration/joystick/mode1/joystickYawLeft.png + resources/calibration/joystick/mode1/joystickYawRight.png - - src/FirmwarePlugin/GeoFenceEditor.qml + + resources/calibration/joystick/mode2/joystickCenter.png + resources/calibration/joystick/mode2/joystickPitchDown.png + resources/calibration/joystick/mode2/joystickPitchUp.png + resources/calibration/joystick/mode2/joystickRollLeft.png + resources/calibration/joystick/mode2/joystickRollRight.png + resources/calibration/joystick/mode2/joystickThrottleDown.png + resources/calibration/joystick/mode2/joystickThrottleUp.png + resources/calibration/joystick/mode2/joystickYawLeft.png + resources/calibration/joystick/mode2/joystickYawRight.png - - src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml - src/FirmwarePlugin/PX4/PX4GeoFenceEditor.qml - src/FirmwarePlugin/PX4/V1.4.OfflineEditing.params + + resources/calibration/joystick/mode3/joystickCenter.png + resources/calibration/joystick/mode3/joystickPitchDown.png + resources/calibration/joystick/mode3/joystickPitchUp.png + resources/calibration/joystick/mode3/joystickRollLeft.png + resources/calibration/joystick/mode3/joystickRollRight.png + resources/calibration/joystick/mode3/joystickThrottleDown.png + resources/calibration/joystick/mode3/joystickThrottleUp.png + resources/calibration/joystick/mode3/joystickYawLeft.png + resources/calibration/joystick/mode3/joystickYawRight.png - - resources/opengl/buglist.json + + resources/calibration/joystick/mode4/joystickCenter.png + resources/calibration/joystick/mode4/joystickPitchDown.png + resources/calibration/joystick/mode4/joystickPitchUp.png + resources/calibration/joystick/mode4/joystickRollLeft.png + resources/calibration/joystick/mode4/joystickRollRight.png + resources/calibration/joystick/mode4/joystickThrottleDown.png + resources/calibration/joystick/mode4/joystickThrottleUp.png + resources/calibration/joystick/mode4/joystickYawLeft.png + resources/calibration/joystick/mode4/joystickYawRight.png diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 9dfad863f037d1c97aaa31f5a6a1e1ce778c5e52..51e7f314616a4ebb7a0a040d7412478e96d0e234 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -21,6 +21,7 @@ include(QGCCommon.pri) TARGET = QGroundControl TEMPLATE = app +QGCROOT = $$PWD DebugBuild { DESTDIR = $${OUT_PWD}/debug @@ -34,6 +35,69 @@ exists(user_config.pri):infile(user_config.pri, CONFIG) { message($$sprintf("Using user-supplied additional config: '%1' specified in user_config.pri", $$fromfile(user_config.pri, CONFIG))) } +# +# Custom Build +# +# QGC will create a "CUSTOMCLASS" object (exposed by your custom build +# and derived from QGCCorePlugin). +# This is the start of allowing custom Plugins, which will eventually use a +# more defined runtime plugin architecture and not require a QGC project +# file you would have to keep in sync with the upstream repo. +# + +# This allows you to ignore the custom build even if the custom build +# is present. It's useful to run "regular" builds to make sure you didn't +# break anything. + +contains (CONFIG, QGC_DISABLE_CUSTOM_BUILD) { + message("Disable custom build override") +} else { + exists($$PWD/custom/custom.pri) { + message("Found custom build") + CONFIG += CustomBuild + DEFINES += QGC_CUSTOM_BUILD + # custom.pri must define: + # CUSTOMCLASS = YourIQGCCorePluginDerivation + # CUSTOMHEADER = \"\\\"YourIQGCCorePluginDerivation.h\\\"\" + include($$PWD/custom/custom.pri) + } +} + +# +# Plugin configuration +# +# This allows you to build custom versions of QGC which only includes your +# specific vehicle plugin. To remove support for a firmware type completely, +# disable both the Plugin and PluginFactory entries. To include custom support +# for an existing plugin type disable PluginFactory only. Then provide you own +# implementation of FirmwarePluginFactory and use the FirmwarePlugin and +# AutoPilotPlugin classes as the base clase for your derived plugin +# implementation. + +contains (CONFIG, QGC_DISABLE_APM_PLUGIN) { + message("Disable APM Plugin") +} else { + CONFIG += APMFirmwarePlugin +} + +contains (CONFIG, QGC_DISABLE_APM_PLUGIN_FACTORY) { + message("Disable APM Plugin Factory") +} else { + CONFIG += APMFirmwarePluginFactory +} + +contains (CONFIG, QGC_DISABLE_PX4_PLUGIN) { + message("Disable PX4 Plugin") +} else { + CONFIG += PX4FirmwarePlugin +} + +contains (CONFIG, QGC_DISABLE_PX4_PLUGIN_FACTORY) { + message("Disable PX4 Plugin Factory") +} else { + CONFIG += PX4FirmwarePluginFactory +} + # Bluetooth contains (DEFINES, QGC_DISABLE_BLUETOOTH) { message("Skipping support for Bluetooth (manual override from command line)") @@ -212,21 +276,28 @@ INCLUDEPATH += . INCLUDEPATH += \ include/ui \ src \ + src/api \ src/AnalyzeView \ - src/audio \ src/AutoPilotPlugins \ - src/comm \ src/FlightDisplay \ src/FlightMap \ src/FlightMap/Widgets \ - src/input \ - src/Joystick \ src/FollowMe \ src/GPS \ - src/lib/qmapcontrol \ + src/Joystick \ src/MissionEditor \ src/MissionManager \ + src/PositionManager \ src/QmlControls \ + src/QtLocationPlugin \ + src/QtLocationPlugin/QMLControl \ + src/Settings \ + src/VehicleSetup \ + src/ViewWidgets \ + src/audio \ + src/comm \ + src/input \ + src/lib/qmapcontrol \ src/uas \ src/ui \ src/ui/linechart \ @@ -236,11 +307,6 @@ INCLUDEPATH += \ src/ui/px4_configuration \ src/ui/toolbar \ src/ui/uas \ - src/VehicleSetup \ - src/ViewWidgets \ - src/QtLocationPlugin \ - src/QtLocationPlugin/QMLControl \ - src/PositionManager \ FORMS += \ src/ui/MainWindow.ui \ @@ -248,50 +314,124 @@ FORMS += \ !MobileBuild { FORMS += \ - src/ui/uas/QGCUnconnectedInfoWidget.ui \ - src/ui/uas/UASMessageView.ui \ src/ui/Linechart.ui \ src/ui/MultiVehicleDockWidget.ui \ - src/ui/QGCDataPlot2D.ui \ src/ui/QGCHilConfiguration.ui \ src/ui/QGCHilFlightGearConfiguration.ui \ src/ui/QGCHilJSBSimConfiguration.ui \ src/ui/QGCHilXPlaneConfiguration.ui \ - src/ui/QGCMapRCToParamDialog.ui \ src/ui/QGCMAVLinkInspector.ui \ src/ui/QGCMAVLinkLogPlayer.ui \ + src/ui/QGCMapRCToParamDialog.ui \ src/ui/QGCTabbedInfoView.ui \ src/ui/QGCUASFileView.ui \ src/ui/QGCUASFileViewMulti.ui \ + src/ui/uas/QGCUnconnectedInfoWidget.ui \ + src/ui/uas/UASMessageView.ui \ src/ui/uas/UASQuickView.ui \ src/ui/uas/UASQuickViewItemSelect.ui \ } +# +# Plugin API +# + HEADERS += \ - src/audio/QGCAudioWorker.h \ + src/api/QGCCorePlugin.h \ + src/api/QGCOptions.h \ + src/api/QGCSettings.h \ + +SOURCES += \ + src/api/QGCCorePlugin.cc \ + src/api/QGCOptions.cc \ + src/api/QGCSettings.cc \ + +# +# Unit Test specific configuration goes here (requires full debug build with all plugins) +# + +DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin { APMFirmwarePluginFactory { !MobileBuild { + DEFINES += UNITTEST_BUILD + + INCLUDEPATH += \ + src/qgcunittest + + HEADERS += \ + src/AnalyzeView/LogDownloadTest.h \ + src/FactSystem/FactSystemTestBase.h \ + src/FactSystem/FactSystemTestGeneric.h \ + src/FactSystem/FactSystemTestPX4.h \ + src/FactSystem/ParameterManagerTest.h \ + src/MissionManager/ComplexMissionItemTest.h \ + src/MissionManager/MissionCommandTreeTest.h \ + src/MissionManager/MissionControllerManagerTest.h \ + src/MissionManager/MissionControllerTest.h \ + src/MissionManager/MissionItemTest.h \ + src/MissionManager/MissionManagerTest.h \ + src/MissionManager/SimpleMissionItemTest.h \ + src/qgcunittest/FileDialogTest.h \ + src/qgcunittest/FileManagerTest.h \ + src/qgcunittest/FlightGearTest.h \ + src/qgcunittest/GeoTest.h \ + src/qgcunittest/LinkManagerTest.h \ + src/qgcunittest/MainWindowTest.h \ + src/qgcunittest/MavlinkLogTest.h \ + src/qgcunittest/MessageBoxTest.h \ + src/qgcunittest/MultiSignalSpy.h \ + src/qgcunittest/RadioConfigTest.h \ + src/qgcunittest/TCPLinkTest.h \ + src/qgcunittest/TCPLoopBackServer.h \ + src/qgcunittest/UnitTest.h \ + src/Vehicle/SendMavCommandTest.h \ + + SOURCES += \ + src/AnalyzeView/LogDownloadTest.cc \ + src/FactSystem/FactSystemTestBase.cc \ + src/FactSystem/FactSystemTestGeneric.cc \ + src/FactSystem/FactSystemTestPX4.cc \ + src/FactSystem/ParameterManagerTest.cc \ + src/MissionManager/ComplexMissionItemTest.cc \ + src/MissionManager/MissionCommandTreeTest.cc \ + src/MissionManager/MissionControllerManagerTest.cc \ + src/MissionManager/MissionControllerTest.cc \ + src/MissionManager/MissionItemTest.cc \ + src/MissionManager/MissionManagerTest.cc \ + src/MissionManager/SimpleMissionItemTest.cc \ + src/qgcunittest/FileDialogTest.cc \ + src/qgcunittest/FileManagerTest.cc \ + src/qgcunittest/FlightGearTest.cc \ + src/qgcunittest/GeoTest.cc \ + src/qgcunittest/LinkManagerTest.cc \ + src/qgcunittest/MainWindowTest.cc \ + src/qgcunittest/MavlinkLogTest.cc \ + src/qgcunittest/MessageBoxTest.cc \ + src/qgcunittest/MultiSignalSpy.cc \ + src/qgcunittest/RadioConfigTest.cc \ + src/qgcunittest/TCPLinkTest.cc \ + src/qgcunittest/TCPLoopBackServer.cc \ + src/qgcunittest/UnitTest.cc \ + src/qgcunittest/UnitTestList.cc \ + src/Vehicle/SendMavCommandTest.cc \ +} } } } } } + +# Main QGC Headers and Source files + +HEADERS += \ + src/AnalyzeView/ExifParser.h \ src/CmdLineOptParser.h \ - src/comm/LinkConfiguration.h \ - src/comm/LinkInterface.h \ - src/comm/LinkManager.h \ - src/comm/MAVLinkProtocol.h \ - src/comm/ProtocolInterface.h \ - src/comm/QGCMAVLink.h \ - src/comm/TCPLink.h \ - src/comm/UDPLink.h \ + src/FirmwarePlugin/PX4/px4_custom_mode.h \ src/FlightDisplay/VideoManager.h \ src/FlightMap/FlightMapSettings.h \ src/FlightMap/Widgets/ValuesWidgetController.h \ + src/FollowMe/FollowMe.h \ src/GAudioOutput.h \ - src/HomePositionManager.h \ src/Joystick/Joystick.h \ src/Joystick/JoystickManager.h \ - src/VehicleSetup/JoystickConfigController.h \ - src/FollowMe/FollowMe.h \ - src/PositionManager/SimulatedPosition.h \ src/JsonHelper.h \ src/LogCompressor.h \ src/MG.h \ src/MissionManager/ComplexMissionItem.h \ + src/MissionManager/FixedWingLandingComplexItem.h \ src/MissionManager/GeoFenceController.h \ src/MissionManager/GeoFenceManager.h \ src/MissionManager/MissionCommandList.h \ @@ -308,6 +448,8 @@ HEADERS += \ src/MissionManager/SimpleMissionItem.h \ src/MissionManager/SurveyMissionItem.h \ src/MissionManager/VisualMissionItem.h \ + src/PositionManager/PositionManager.h \ + src/PositionManager/SimulatedPosition.h \ src/QGC.h \ src/QGCApplication.h \ src/QGCComboBox.h \ @@ -327,23 +469,32 @@ HEADERS += \ src/QmlControls/CoordinateVector.h \ src/QmlControls/MavlinkQmlSingleton.h \ src/QmlControls/ParameterEditorController.h \ - src/QmlControls/RCChannelMonitorController.h \ - src/QmlControls/ScreenToolsController.h \ + src/QmlControls/QGCImageProvider.h \ src/QmlControls/QGroundControlQmlGlobal.h \ src/QmlControls/QmlObjectListModel.h \ + src/QmlControls/RCChannelMonitorController.h \ + src/QmlControls/ScreenToolsController.h \ + src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ + src/Settings/AppSettings.h \ + src/Settings/AutoConnectSettings.h \ + src/Settings/SettingsGroup.h \ + src/Settings/SettingsManager.h \ + src/Settings/UnitsSettings.h \ + src/Settings/VideoSettings.h \ + src/Vehicle/MAVLinkLogManager.h \ + src/VehicleSetup/JoystickConfigController.h \ + src/audio/QGCAudioWorker.h \ + src/comm/LinkConfiguration.h \ + src/comm/LinkInterface.h \ + src/comm/LinkManager.h \ + src/comm/MAVLinkProtocol.h \ + src/comm/ProtocolInterface.h \ + src/comm/QGCMAVLink.h \ + src/comm/TCPLink.h \ + src/comm/UDPLink.h \ src/uas/UAS.h \ src/uas/UASInterface.h \ src/uas/UASMessageHandler.h \ - src/ui/toolbar/MainToolBarController.h \ - src/AutoPilotPlugins/PX4/PX4AirframeLoader.h \ - src/AutoPilotPlugins/APM/APMAirframeLoader.h \ - src/QmlControls/QGCImageProvider.h \ - src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ - src/PositionManager/PositionManager.h - -AndroidBuild { -HEADERS += \ -} DebugBuild { HEADERS += \ @@ -364,7 +515,7 @@ contains(DEFINES, QGC_ENABLE_BLUETOOTH) { src/comm/BluetoothLink.h \ } -!iOSBuild { +!NoSerialBuild { HEADERS += \ src/comm/QGCSerialPortInfo.h \ src/comm/SerialLink.h \ @@ -374,56 +525,56 @@ HEADERS += \ HEADERS += \ src/AnalyzeView/GeoTagController.h \ src/AnalyzeView/LogDownloadController.h \ + src/GPS/Drivers/src/gps_helper.h \ + src/GPS/Drivers/src/ubx.h \ + src/GPS/GPSManager.h \ + src/GPS/GPSPositionMessage.h \ + src/GPS/GPSProvider.h \ + src/GPS/RTCM/RTCMMavlink.h \ + src/GPS/definitions.h \ + src/GPS/satellite_info.h \ + src/GPS/vehicle_gps_position.h \ + src/Joystick/JoystickSDL.h \ + src/QGCFileDialog.h \ + src/QGCMessageBox.h \ + src/RunGuard.h \ + src/ViewWidgets/CustomCommandWidget.h \ + src/ViewWidgets/CustomCommandWidgetController.h \ + src/ViewWidgets/ViewWidgetController.h \ src/comm/LogReplayLink.h \ src/comm/QGCFlightGearLink.h \ src/comm/QGCHilLink.h \ src/comm/QGCJSBSimLink.h \ src/comm/QGCXPlaneLink.h \ - src/Joystick/JoystickSDL.h \ - src/QGCFileDialog.h \ - src/QGCMessageBox.h \ src/uas/FileManager.h \ src/ui/HILDockWidget.h \ - src/ui/linechart/ChartPlot.h \ - src/ui/linechart/IncrementalPlot.h \ - src/ui/linechart/LinechartPlot.h \ - src/ui/linechart/Linecharts.h \ - src/ui/linechart/LinechartWidget.h \ - src/ui/linechart/Scrollbar.h \ - src/ui/linechart/ScrollZoomer.h \ - src/ui/MainWindow.h \ src/ui/MAVLinkDecoder.h \ + src/ui/MainWindow.h \ src/ui/MultiVehicleDockWidget.h \ - src/ui/QGCMAVLinkLogPlayer.h \ - src/ui/QGCMapRCToParamDialog.h \ - src/ui/uas/UASMessageView.h \ - src/ui/uas/QGCUnconnectedInfoWidget.h \ - src/ui/QGCDataPlot2D.h \ src/ui/QGCHilConfiguration.h \ src/ui/QGCHilFlightGearConfiguration.h \ src/ui/QGCHilJSBSimConfiguration.h \ src/ui/QGCHilXPlaneConfiguration.h \ src/ui/QGCMAVLinkInspector.h \ + src/ui/QGCMAVLinkLogPlayer.h \ + src/ui/QGCMapRCToParamDialog.h \ src/ui/QGCTabbedInfoView.h \ src/ui/QGCUASFileView.h \ src/ui/QGCUASFileViewMulti.h \ + src/ui/linechart/ChartPlot.h \ + src/ui/linechart/IncrementalPlot.h \ + src/ui/linechart/LinechartPlot.h \ + src/ui/linechart/LinechartWidget.h \ + src/ui/linechart/Linecharts.h \ + src/ui/linechart/ScrollZoomer.h \ + src/ui/linechart/Scrollbar.h \ + src/ui/uas/QGCUnconnectedInfoWidget.h \ + src/ui/uas/UASMessageView.h \ src/ui/uas/UASQuickView.h \ src/ui/uas/UASQuickViewGaugeItem.h \ src/ui/uas/UASQuickViewItem.h \ src/ui/uas/UASQuickViewItemSelect.h \ src/ui/uas/UASQuickViewTextItem.h \ - src/GPS/Drivers/src/gps_helper.h \ - src/GPS/Drivers/src/ubx.h \ - src/GPS/definitions.h \ - src/GPS/vehicle_gps_position.h \ - src/GPS/satellite_info.h \ - src/GPS/RTCM/RTCMMavlink.h \ - src/GPS/GPSManager.h \ - src/GPS/GPSPositionMessage.h \ - src/GPS/GPSProvider.h \ - src/ViewWidgets/CustomCommandWidget.h \ - src/ViewWidgets/CustomCommandWidgetController.h \ - src/ViewWidgets/ViewWidgetController.h \ } iOSBuild { @@ -436,29 +587,20 @@ AndroidBuild { SOURCES += src/MobileScreenMgr.cc \ } - SOURCES += \ - src/audio/QGCAudioWorker.cpp \ + src/AnalyzeView/ExifParser.cc \ src/CmdLineOptParser.cc \ - src/comm/LinkConfiguration.cc \ - src/comm/LinkManager.cc \ - src/comm/MAVLinkProtocol.cc \ - src/comm/QGCMAVLink.cc \ - src/comm/TCPLink.cc \ - src/comm/UDPLink.cc \ src/FlightDisplay/VideoManager.cc \ src/FlightMap/FlightMapSettings.cc \ src/FlightMap/Widgets/ValuesWidgetController.cc \ + src/FollowMe/FollowMe.cc \ src/GAudioOutput.cc \ - src/HomePositionManager.cc \ src/Joystick/Joystick.cc \ src/Joystick/JoystickManager.cc \ - src/VehicleSetup/JoystickConfigController.cc \ src/JsonHelper.cc \ - src/FollowMe/FollowMe.cc \ src/LogCompressor.cc \ - src/main.cc \ src/MissionManager/ComplexMissionItem.cc \ + src/MissionManager/FixedWingLandingComplexItem.cc \ src/MissionManager/GeoFenceController.cc \ src/MissionManager/GeoFenceManager.cc \ src/MissionManager/MissionCommandList.cc \ @@ -475,36 +617,50 @@ SOURCES += \ src/MissionManager/SimpleMissionItem.cc \ src/MissionManager/SurveyMissionItem.cc \ src/MissionManager/VisualMissionItem.cc \ + src/PositionManager/PositionManager.cpp \ + src/PositionManager/SimulatedPosition.cc \ src/QGC.cc \ src/QGCApplication.cc \ src/QGCComboBox.cc \ src/QGCDockWidget.cc \ src/QGCFileDownload.cc \ + src/QGCGeo.cc \ src/QGCLoggingCategory.cc \ src/QGCMapPalette.cc \ src/QGCMobileFileDialogController.cc \ src/QGCPalette.cc \ - src/QGCQuickWidget.cc \ src/QGCQmlWidgetHolder.cpp \ + src/QGCQuickWidget.cc \ src/QGCTemporaryFile.cc \ src/QGCToolbox.cc \ - src/QGCGeo.cc \ src/QmlControls/AppMessages.cc \ src/QmlControls/CoordinateVector.cc \ src/QmlControls/ParameterEditorController.cc \ - src/QmlControls/RCChannelMonitorController.cc \ - src/QmlControls/ScreenToolsController.cc \ + src/QmlControls/QGCImageProvider.cc \ src/QmlControls/QGroundControlQmlGlobal.cc \ src/QmlControls/QmlObjectListModel.cc \ + src/QmlControls/RCChannelMonitorController.cc \ + src/QmlControls/ScreenToolsController.cc \ + src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \ + src/Settings/AppSettings.cc \ + src/Settings/AutoConnectSettings.cc \ + src/Settings/SettingsGroup.cc \ + src/Settings/SettingsManager.cc \ + src/Settings/UnitsSettings.cc \ + src/Settings/VideoSettings.cc \ + src/Vehicle/MAVLinkLogManager.cc \ + src/VehicleSetup/JoystickConfigController.cc \ + src/audio/QGCAudioWorker.cpp \ + src/comm/LinkConfiguration.cc \ + src/comm/LinkInterface.cc \ + src/comm/LinkManager.cc \ + src/comm/MAVLinkProtocol.cc \ + src/comm/QGCMAVLink.cc \ + src/comm/TCPLink.cc \ + src/comm/UDPLink.cc \ + src/main.cc \ src/uas/UAS.cc \ src/uas/UASMessageHandler.cc \ - src/ui/toolbar/MainToolBarController.cc \ - src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc \ - src/AutoPilotPlugins/APM/APMAirframeLoader.cc \ - src/QmlControls/QGCImageProvider.cc \ - src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \ - src/PositionManager/SimulatedPosition.cc \ - src/PositionManager/PositionManager.cpp DebugBuild { SOURCES += \ @@ -513,7 +669,7 @@ SOURCES += \ src/comm/MockLinkMissionItemHandler.cc \ } -!iOSBuild { +!NoSerialBuild { SOURCES += \ src/comm/QGCSerialPortInfo.cc \ src/comm/SerialLink.cc \ @@ -528,264 +684,236 @@ contains(DEFINES, QGC_ENABLE_BLUETOOTH) { SOURCES += \ src/AnalyzeView/GeoTagController.cc \ src/AnalyzeView/LogDownloadController.cc \ - src/ui/uas/UASMessageView.cc \ - src/uas/FileManager.cc \ - src/ui/uas/QGCUnconnectedInfoWidget.cc \ - src/ui/MAVLinkDecoder.cc \ - src/ui/QGCMapRCToParamDialog.cpp \ - src/comm/LogReplayLink.cc \ + src/GPS/Drivers/src/gps_helper.cpp \ + src/GPS/Drivers/src/ubx.cpp \ + src/GPS/GPSManager.cc \ + src/GPS/GPSProvider.cc \ + src/GPS/RTCM/RTCMMavlink.cc \ + src/Joystick/JoystickSDL.cc \ src/QGCFileDialog.cc \ - src/ui/QGCMAVLinkLogPlayer.cc \ + src/RunGuard.cc \ + src/ViewWidgets/CustomCommandWidget.cc \ + src/ViewWidgets/CustomCommandWidgetController.cc \ + src/ViewWidgets/ViewWidgetController.cc \ + src/comm/LogReplayLink.cc \ src/comm/QGCFlightGearLink.cc \ src/comm/QGCJSBSimLink.cc \ src/comm/QGCXPlaneLink.cc \ - src/Joystick/JoystickSDL.cc \ + src/uas/FileManager.cc \ src/ui/HILDockWidget.cc \ - src/ui/linechart/ChartPlot.cc \ - src/ui/linechart/IncrementalPlot.cc \ - src/ui/linechart/LinechartPlot.cc \ - src/ui/linechart/Linecharts.cc \ - src/ui/linechart/LinechartWidget.cc \ - src/ui/linechart/Scrollbar.cc \ - src/ui/linechart/ScrollZoomer.cc \ + src/ui/MAVLinkDecoder.cc \ src/ui/MainWindow.cc \ src/ui/MultiVehicleDockWidget.cc \ - src/ui/QGCDataPlot2D.cc \ src/ui/QGCHilConfiguration.cc \ src/ui/QGCHilFlightGearConfiguration.cc \ src/ui/QGCHilJSBSimConfiguration.cc \ src/ui/QGCHilXPlaneConfiguration.cc \ src/ui/QGCMAVLinkInspector.cc \ + src/ui/QGCMAVLinkLogPlayer.cc \ + src/ui/QGCMapRCToParamDialog.cpp \ src/ui/QGCTabbedInfoView.cpp \ src/ui/QGCUASFileView.cc \ src/ui/QGCUASFileViewMulti.cc \ + src/ui/linechart/ChartPlot.cc \ + src/ui/linechart/IncrementalPlot.cc \ + src/ui/linechart/LinechartPlot.cc \ + src/ui/linechart/LinechartWidget.cc \ + src/ui/linechart/Linecharts.cc \ + src/ui/linechart/ScrollZoomer.cc \ + src/ui/linechart/Scrollbar.cc \ + src/ui/uas/QGCUnconnectedInfoWidget.cc \ + src/ui/uas/UASMessageView.cc \ src/ui/uas/UASQuickView.cc \ src/ui/uas/UASQuickViewGaugeItem.cc \ src/ui/uas/UASQuickViewItem.cc \ src/ui/uas/UASQuickViewItemSelect.cc \ src/ui/uas/UASQuickViewTextItem.cc \ - src/GPS/Drivers/src/gps_helper.cpp \ - src/GPS/Drivers/src/ubx.cpp \ - src/GPS/RTCM/RTCMMavlink.cc \ - src/GPS/GPSManager.cc \ - src/GPS/GPSProvider.cc \ - src/ViewWidgets/CustomCommandWidget.cc \ - src/ViewWidgets/CustomCommandWidgetController.cc \ - src/ViewWidgets/ViewWidgetController.cc } -# -# Unit Test specific configuration goes here -# - +# Palette test widget in debug builds DebugBuild { - -HEADERS += src/QmlControls/QmlTestWidget.h -SOURCES += src/QmlControls/QmlTestWidget.cc - -!MobileBuild { - -INCLUDEPATH += \ - src/qgcunittest - -HEADERS += \ - src/AnalyzeView/LogDownloadTest.h \ - src/FactSystem/FactSystemTestBase.h \ - src/FactSystem/FactSystemTestGeneric.h \ - src/FactSystem/FactSystemTestPX4.h \ - src/FactSystem/ParameterManagerTest.h \ - src/MissionManager/ComplexMissionItemTest.h \ - src/MissionManager/MissionCommandTreeTest.h \ - src/MissionManager/MissionControllerTest.h \ - src/MissionManager/MissionControllerManagerTest.h \ - src/MissionManager/MissionItemTest.h \ - src/MissionManager/MissionManagerTest.h \ - src/MissionManager/SimpleMissionItemTest.h \ - src/qgcunittest/GeoTest.h \ - src/qgcunittest/FileDialogTest.h \ - src/qgcunittest/FileManagerTest.h \ - src/qgcunittest/FlightGearTest.h \ - src/qgcunittest/LinkManagerTest.h \ - src/qgcunittest/MainWindowTest.h \ - src/qgcunittest/MavlinkLogTest.h \ - src/qgcunittest/MessageBoxTest.h \ - src/qgcunittest/MultiSignalSpy.h \ - src/qgcunittest/RadioConfigTest.h \ - src/qgcunittest/TCPLinkTest.h \ - src/qgcunittest/TCPLoopBackServer.h \ - src/qgcunittest/UnitTest.h \ - -SOURCES += \ - src/AnalyzeView/LogDownloadTest.cc \ - src/FactSystem/FactSystemTestBase.cc \ - src/FactSystem/FactSystemTestGeneric.cc \ - src/FactSystem/FactSystemTestPX4.cc \ - src/FactSystem/ParameterManagerTest.cc \ - src/MissionManager/ComplexMissionItemTest.cc \ - src/MissionManager/MissionCommandTreeTest.cc \ - src/MissionManager/MissionControllerTest.cc \ - src/MissionManager/MissionControllerManagerTest.cc \ - src/MissionManager/MissionItemTest.cc \ - src/MissionManager/MissionManagerTest.cc \ - src/MissionManager/SimpleMissionItemTest.cc \ - src/qgcunittest/GeoTest.cc \ - src/qgcunittest/FileDialogTest.cc \ - src/qgcunittest/FileManagerTest.cc \ - src/qgcunittest/FlightGearTest.cc \ - src/qgcunittest/LinkManagerTest.cc \ - src/qgcunittest/MainWindowTest.cc \ - src/qgcunittest/MavlinkLogTest.cc \ - src/qgcunittest/MessageBoxTest.cc \ - src/qgcunittest/MultiSignalSpy.cc \ - src/qgcunittest/RadioConfigTest.cc \ - src/qgcunittest/TCPLinkTest.cc \ - src/qgcunittest/TCPLoopBackServer.cc \ - src/qgcunittest/UnitTest.cc \ - src/qgcunittest/UnitTestList.cc \ -} # !MobileBuild -} # DebugBuild + HEADERS += src/QmlControls/QmlTestWidget.h + SOURCES += src/QmlControls/QmlTestWidget.cc +} # # Firmware Plugin Support # INCLUDEPATH += \ - src/AutoPilotPlugins/APM \ src/AutoPilotPlugins/Common \ - src/AutoPilotPlugins/PX4 \ src/FirmwarePlugin \ - src/FirmwarePlugin/APM \ - src/FirmwarePlugin/PX4 \ src/Vehicle \ src/VehicleSetup \ HEADERS+= \ src/AutoPilotPlugins/AutoPilotPlugin.h \ - src/AutoPilotPlugins/AutoPilotPluginManager.h \ - src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h \ - src/AutoPilotPlugins/APM/APMAirframeComponent.h \ - src/AutoPilotPlugins/APM/APMAirframeComponentController.h \ - src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h \ - src/AutoPilotPlugins/APM/APMCameraComponent.h \ - src/AutoPilotPlugins/APM/APMLightsComponent.h \ - src/AutoPilotPlugins/APM/APMCompassCal.h \ - src/AutoPilotPlugins/APM/APMFlightModesComponent.h \ - src/AutoPilotPlugins/APM/APMFlightModesComponentController.h \ - src/AutoPilotPlugins/APM/APMPowerComponent.h \ - src/AutoPilotPlugins/APM/APMRadioComponent.h \ - src/AutoPilotPlugins/APM/APMSafetyComponent.h \ - src/AutoPilotPlugins/APM/APMSensorsComponent.h \ - src/AutoPilotPlugins/APM/APMSensorsComponentController.h \ - src/AutoPilotPlugins/APM/APMTuningComponent.h \ + src/AutoPilotPlugins/Common/ESP8266Component.h \ + src/AutoPilotPlugins/Common/ESP8266ComponentController.h \ + src/AutoPilotPlugins/Common/MixersComponent.h \ src/AutoPilotPlugins/Common/MotorComponent.h \ src/AutoPilotPlugins/Common/RadioComponentController.h \ - src/AutoPilotPlugins/Common/ESP8266ComponentController.h \ - src/AutoPilotPlugins/Common/ESP8266Component.h \ src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.h \ - src/AutoPilotPlugins/PX4/AirframeComponent.h \ - src/AutoPilotPlugins/PX4/AirframeComponentAirframes.h \ - src/AutoPilotPlugins/PX4/AirframeComponentController.h \ - src/AutoPilotPlugins/PX4/FlightModesComponent.h \ - src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.h \ - src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.h \ - src/AutoPilotPlugins/PX4/PowerComponent.h \ - src/AutoPilotPlugins/PX4/PowerComponentController.h \ - src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h \ - src/AutoPilotPlugins/PX4/PX4RadioComponent.h \ - src/AutoPilotPlugins/PX4/CameraComponent.h \ - src/AutoPilotPlugins/PX4/SafetyComponent.h \ - src/AutoPilotPlugins/PX4/SensorsComponent.h \ - src/AutoPilotPlugins/PX4/SensorsComponentController.h \ - src/AutoPilotPlugins/PX4/PX4TuningComponent.h \ - src/FirmwarePlugin/FirmwarePluginManager.h \ src/FirmwarePlugin/FirmwarePlugin.h \ - src/FirmwarePlugin/APM/APMFirmwarePlugin.h \ - src/FirmwarePlugin/APM/APMGeoFenceManager.h \ - src/FirmwarePlugin/APM/APMParameterMetaData.h \ - src/FirmwarePlugin/APM/APMRallyPointManager.h \ - src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h \ - src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.h \ - src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.h \ - src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.h \ - src/FirmwarePlugin/PX4/px4_custom_mode.h \ - src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h \ - src/FirmwarePlugin/PX4/PX4GeoFenceManager.h \ - src/FirmwarePlugin/PX4/PX4ParameterMetaData.h \ + src/FirmwarePlugin/FirmwarePluginManager.h \ src/Vehicle/MultiVehicleManager.h \ src/Vehicle/Vehicle.h \ src/VehicleSetup/VehicleComponent.h \ !MobileBuild { -HEADERS += \ - src/VehicleSetup/FirmwareUpgradeController.h \ - src/VehicleSetup/Bootloader.h \ - src/VehicleSetup/PX4FirmwareUpgradeThread.h \ - src/VehicleSetup/FirmwareImage.h \ - + HEADERS += \ + src/VehicleSetup/Bootloader.h \ + src/VehicleSetup/FirmwareImage.h \ + src/VehicleSetup/FirmwareUpgradeController.h \ + src/VehicleSetup/PX4FirmwareUpgradeThread.h \ } SOURCES += \ src/AutoPilotPlugins/AutoPilotPlugin.cc \ - src/AutoPilotPlugins/AutoPilotPluginManager.cc \ - src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc \ - src/AutoPilotPlugins/APM/APMAirframeComponent.cc \ - src/AutoPilotPlugins/APM/APMAirframeComponentController.cc \ - src/AutoPilotPlugins/APM/APMCameraComponent.cc \ - src/AutoPilotPlugins/APM/APMLightsComponent.cc \ - src/AutoPilotPlugins/APM/APMCompassCal.cc \ - src/AutoPilotPlugins/APM/APMFlightModesComponent.cc \ - src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc \ - src/AutoPilotPlugins/APM/APMPowerComponent.cc \ - src/AutoPilotPlugins/APM/APMRadioComponent.cc \ - src/AutoPilotPlugins/APM/APMSafetyComponent.cc \ - src/AutoPilotPlugins/APM/APMSensorsComponent.cc \ - src/AutoPilotPlugins/APM/APMSensorsComponentController.cc \ - src/AutoPilotPlugins/APM/APMTuningComponent.cc \ + src/AutoPilotPlugins/Common/ESP8266Component.cc \ + src/AutoPilotPlugins/Common/ESP8266ComponentController.cc \ + src/AutoPilotPlugins/Common/MixersComponent.cc \ src/AutoPilotPlugins/Common/MotorComponent.cc \ src/AutoPilotPlugins/Common/RadioComponentController.cc \ - src/AutoPilotPlugins/Common/ESP8266ComponentController.cc \ - src/AutoPilotPlugins/Common/ESP8266Component.cc \ - src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc \ src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.cc \ - src/AutoPilotPlugins/PX4/AirframeComponent.cc \ - src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc \ - src/AutoPilotPlugins/PX4/AirframeComponentController.cc \ - src/AutoPilotPlugins/PX4/FlightModesComponent.cc \ - src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.cc \ - src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.cc \ - src/AutoPilotPlugins/PX4/PowerComponent.cc \ - src/AutoPilotPlugins/PX4/PowerComponentController.cc \ - src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc \ - src/AutoPilotPlugins/PX4/PX4RadioComponent.cc \ - src/AutoPilotPlugins/PX4/CameraComponent.cc \ - src/AutoPilotPlugins/PX4/SafetyComponent.cc \ - src/AutoPilotPlugins/PX4/SensorsComponent.cc \ - src/AutoPilotPlugins/PX4/SensorsComponentController.cc \ - src/AutoPilotPlugins/PX4/PX4TuningComponent.cc \ - src/FirmwarePlugin/APM/APMFirmwarePlugin.cc \ - src/FirmwarePlugin/APM/APMGeoFenceManager.cc \ - src/FirmwarePlugin/APM/APMParameterMetaData.cc \ - src/FirmwarePlugin/APM/APMRallyPointManager.cc \ - src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.cc \ - src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.cc \ - src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.cc \ - src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc \ src/FirmwarePlugin/FirmwarePlugin.cc \ src/FirmwarePlugin/FirmwarePluginManager.cc \ - src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc \ - src/FirmwarePlugin/PX4/PX4GeoFenceManager.cc \ - src/FirmwarePlugin/PX4/PX4ParameterMetaData.cc \ src/Vehicle/MultiVehicleManager.cc \ src/Vehicle/Vehicle.cc \ src/VehicleSetup/VehicleComponent.cc \ !MobileBuild { -SOURCES += \ - src/VehicleSetup/FirmwareUpgradeController.cc \ - src/VehicleSetup/Bootloader.cc \ - src/VehicleSetup/PX4FirmwareUpgradeThread.cc \ - src/VehicleSetup/FirmwareImage.cc \ + SOURCES += \ + src/VehicleSetup/Bootloader.cc \ + src/VehicleSetup/FirmwareImage.cc \ + src/VehicleSetup/FirmwareUpgradeController.cc \ + src/VehicleSetup/PX4FirmwareUpgradeThread.cc \ +} + +# ArduPilot FirmwarePlugin + +APMFirmwarePlugin { + RESOURCES *= src/FirmwarePlugin/APM/APMResources.qrc + INCLUDEPATH += \ + src/AutoPilotPlugins/APM \ + src/FirmwarePlugin/APM \ + + HEADERS += \ + src/AutoPilotPlugins/APM/APMAirframeComponent.h \ + src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h \ + src/AutoPilotPlugins/APM/APMAirframeComponentController.h \ + src/AutoPilotPlugins/APM/APMAirframeLoader.h \ + src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h \ + src/AutoPilotPlugins/APM/APMCameraComponent.h \ + src/AutoPilotPlugins/APM/APMCompassCal.h \ + src/AutoPilotPlugins/APM/APMFlightModesComponent.h \ + src/AutoPilotPlugins/APM/APMFlightModesComponentController.h \ + src/AutoPilotPlugins/APM/APMLightsComponent.h \ + src/AutoPilotPlugins/APM/APMSubFrameComponent.h \ + src/AutoPilotPlugins/APM/APMPowerComponent.h \ + src/AutoPilotPlugins/APM/APMRadioComponent.h \ + src/AutoPilotPlugins/APM/APMSafetyComponent.h \ + src/AutoPilotPlugins/APM/APMSensorsComponent.h \ + src/AutoPilotPlugins/APM/APMSensorsComponentController.h \ + src/AutoPilotPlugins/APM/APMTuningComponent.h \ + src/FirmwarePlugin/APM/APMFirmwarePlugin.h \ + src/FirmwarePlugin/APM/APMGeoFenceManager.h \ + src/FirmwarePlugin/APM/APMParameterMetaData.h \ + src/FirmwarePlugin/APM/APMRallyPointManager.h \ + src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h \ + src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.h \ + src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.h \ + src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.h \ + + SOURCES += \ + src/AutoPilotPlugins/APM/APMAirframeComponent.cc \ + src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc \ + src/AutoPilotPlugins/APM/APMAirframeComponentController.cc \ + src/AutoPilotPlugins/APM/APMAirframeLoader.cc \ + src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc \ + src/AutoPilotPlugins/APM/APMCameraComponent.cc \ + src/AutoPilotPlugins/APM/APMCompassCal.cc \ + src/AutoPilotPlugins/APM/APMFlightModesComponent.cc \ + src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc \ + src/AutoPilotPlugins/APM/APMLightsComponent.cc \ + src/AutoPilotPlugins/APM/APMSubFrameComponent.cc \ + src/AutoPilotPlugins/APM/APMPowerComponent.cc \ + src/AutoPilotPlugins/APM/APMRadioComponent.cc \ + src/AutoPilotPlugins/APM/APMSafetyComponent.cc \ + src/AutoPilotPlugins/APM/APMSensorsComponent.cc \ + src/AutoPilotPlugins/APM/APMSensorsComponentController.cc \ + src/AutoPilotPlugins/APM/APMTuningComponent.cc \ + src/FirmwarePlugin/APM/APMFirmwarePlugin.cc \ + src/FirmwarePlugin/APM/APMGeoFenceManager.cc \ + src/FirmwarePlugin/APM/APMParameterMetaData.cc \ + src/FirmwarePlugin/APM/APMRallyPointManager.cc \ + src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.cc \ + src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.cc \ + src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.cc \ + src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc \ +} + +APMFirmwarePluginFactory { + HEADERS += src/FirmwarePlugin/APM/APMFirmwarePluginFactory.h + SOURCES += src/FirmwarePlugin/APM/APMFirmwarePluginFactory.cc +} + +# PX4 FirmwarePlugin + +PX4FirmwarePlugin { + RESOURCES *= src/FirmwarePlugin/PX4/PX4Resources.qrc + + INCLUDEPATH += \ + src/AutoPilotPlugins/PX4 \ + src/FirmwarePlugin/PX4 \ + + HEADERS+= \ + src/AutoPilotPlugins/PX4/AirframeComponent.h \ + src/AutoPilotPlugins/PX4/AirframeComponentAirframes.h \ + src/AutoPilotPlugins/PX4/AirframeComponentController.h \ + src/AutoPilotPlugins/PX4/CameraComponent.h \ + src/AutoPilotPlugins/PX4/FlightModesComponent.h \ + src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.h \ + src/AutoPilotPlugins/PX4/PX4AirframeLoader.h \ + src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h \ + src/AutoPilotPlugins/PX4/PX4RadioComponent.h \ + src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.h \ + src/AutoPilotPlugins/PX4/PX4TuningComponent.h \ + src/AutoPilotPlugins/PX4/PowerComponent.h \ + src/AutoPilotPlugins/PX4/PowerComponentController.h \ + src/AutoPilotPlugins/PX4/SafetyComponent.h \ + src/AutoPilotPlugins/PX4/SensorsComponent.h \ + src/AutoPilotPlugins/PX4/SensorsComponentController.h \ + src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h \ + src/FirmwarePlugin/PX4/PX4GeoFenceManager.h \ + src/FirmwarePlugin/PX4/PX4ParameterMetaData.h \ + + SOURCES += \ + src/AutoPilotPlugins/PX4/AirframeComponent.cc \ + src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc \ + src/AutoPilotPlugins/PX4/AirframeComponentController.cc \ + src/AutoPilotPlugins/PX4/CameraComponent.cc \ + src/AutoPilotPlugins/PX4/FlightModesComponent.cc \ + src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.cc \ + src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc \ + src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc \ + src/AutoPilotPlugins/PX4/PX4RadioComponent.cc \ + src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.cc \ + src/AutoPilotPlugins/PX4/PX4TuningComponent.cc \ + src/AutoPilotPlugins/PX4/PowerComponent.cc \ + src/AutoPilotPlugins/PX4/PowerComponentController.cc \ + src/AutoPilotPlugins/PX4/SafetyComponent.cc \ + src/AutoPilotPlugins/PX4/SensorsComponent.cc \ + src/AutoPilotPlugins/PX4/SensorsComponentController.cc \ + src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc \ + src/FirmwarePlugin/PX4/PX4GeoFenceManager.cc \ + src/FirmwarePlugin/PX4/PX4ParameterMetaData.cc \ +} + +PX4FirmwarePluginFactory { + HEADERS += src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.h + SOURCES += src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.cc } # Fact System code @@ -796,8 +924,8 @@ INCLUDEPATH += \ HEADERS += \ src/FactSystem/Fact.h \ - src/FactSystem/FactGroup.h \ src/FactSystem/FactControls/FactPanelController.h \ + src/FactSystem/FactGroup.h \ src/FactSystem/FactMetaData.h \ src/FactSystem/FactSystem.h \ src/FactSystem/FactValidator.h \ @@ -806,8 +934,8 @@ HEADERS += \ SOURCES += \ src/FactSystem/Fact.cc \ - src/FactSystem/FactGroup.cc \ src/FactSystem/FactControls/FactPanelController.cc \ + src/FactSystem/FactGroup.cc \ src/FactSystem/FactMetaData.cc \ src/FactSystem/FactSystem.cc \ src/FactSystem/FactValidator.cc \ @@ -846,32 +974,11 @@ contains (CONFIG, DISABLE_VIDEOSTREAMING) { # Android AndroidBuild { - include($$PWD/libs/qtandroidserialport/src/qtandroidserialport.pri) - message("Adding Serial Java Classes") - QT += androidextras - ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android - OTHER_FILES += \ - $$PWD/android/AndroidManifest.xml \ - $$PWD/android/res/xml/device_filter.xml \ - $$PWD/android/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java \ - $$PWD/android/src/com/hoho/android/usbserial/driver/CommonUsbSerialDriver.java \ - $$PWD/android/src/com/hoho/android/usbserial/driver/Cp2102SerialDriver.java \ - $$PWD/android/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java \ - $$PWD/android/src/com/hoho/android/usbserial/driver/ProlificSerialDriver.java \ - $$PWD/android/src/com/hoho/android/usbserial/driver/UsbId.java \ - $$PWD/android/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java \ - $$PWD/android/src/com/hoho/android/usbserial/driver/UsbSerialProber.java \ - $$PWD/android/src/com/hoho/android/usbserial/driver/UsbSerialRuntimeException.java \ - $$PWD/android/src/org/qgroundcontrol/qgchelper/UsbDeviceJNI.java \ - $$PWD/android/src/org/qgroundcontrol/qgchelper/UsbIoManager.java - - DISTFILES += \ - android/gradle/wrapper/gradle-wrapper.jar \ - android/gradlew \ - android/res/values/libs.xml \ - android/build.gradle \ - android/gradle/wrapper/gradle-wrapper.properties \ - android/gradlew.bat + contains (CONFIG, DISABLE_BUILTIN_ANDROID) { + message("Skipping builtin support for Android") + } else { + include(android.pri) + } } #------------------------------------------------------------------------------------- diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 69dd1d0bf73292f2b8bf40a543271a75c1f722b3..231e970ce2f8811f42ea392dea4a57fcc6d4efcb 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -1,79 +1,90 @@ - src/comm/PX4MockLink.params - src/comm/APMArduCopterMockLink.params - src/comm/APMArduPlaneMockLink.params - src/comm/APMArduSubMockLink.params src/FactSystem/FactSystemTest.qml + + src/ui/toolbar/BatteryIndicator.qml + src/ui/toolbar/GPSIndicator.qml + src/ui/toolbar/MessageIndicator.qml + src/ui/toolbar/ModeIndicator.qml + src/ui/toolbar/RCRSSIIndicator.qml + src/ui/toolbar/TelemetryRSSIIndicator.qml + src/AutoPilotPlugins/PX4/AirframeComponent.qml src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml - src/AutoPilotPlugins/APM/APMAirframeComponent.qml - src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml + src/AnalyzeView/AnalyzeView.qml + src/ui/AppSettings.qml + src/ui/preferences/BluetoothSettings.qml + src/AutoPilotPlugins/PX4/CameraComponent.qml + src/AutoPilotPlugins/PX4/CameraComponentSummary.qml src/ViewWidgets/CustomCommandWidget.qml + src/ui/preferences/DebugWindow.qml + src/AutoPilotPlugins/Common/ESP8266Component.qml + src/AutoPilotPlugins/Common/ESP8266ComponentSummary.qml src/VehicleSetup/FirmwareUpgrade.qml - src/FlightDisplay/FlightDisplayView.qml - src/FlightDisplay/FlightDisplayViewUVC.qml src/FlightDisplay/FlightDisplayViewDummy.qml - src/AutoPilotPlugins/PX4/PX4FlightModes.qml - src/AutoPilotPlugins/PX4/PX4AdvancedFlightModes.qml - src/AutoPilotPlugins/PX4/PX4SimpleFlightModes.qml + src/FlightDisplay/FlightDisplayViewUVC.qml src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml - src/AutoPilotPlugins/APM/APMFlightModesComponent.qml - src/AutoPilotPlugins/APM/APMFlightModesComponentSummary.qml - src/ui/preferences/BluetoothSettings.qml - src/ui/preferences/DebugWindow.qml src/ui/preferences/GeneralSettings.qml + src/MissionEditor/GeoFenceEditor.qml + src/AnalyzeView/GeoTagPage.qml + src/VehicleSetup/JoystickConfig.qml src/ui/preferences/LinkSettings.qml + src/AnalyzeView/LogDownloadPage.qml src/ui/preferences/LogReplaySettings.qml - src/ui/preferences/MavlinkSettings.qml - src/ui/preferences/MockLink.qml - src/ui/preferences/MockLinkSettings.qml - src/QtLocationPlugin/QMLControl/OfflineMap.qml - src/ui/preferences/SerialSettings.qml - src/ui/preferences/TcpSettings.qml - src/ui/preferences/UdpSettings.qml - src/VehicleSetup/JoystickConfig.qml - src/ui/toolbar/MainToolBar.qml src/ui/MainWindowHybrid.qml src/ui/MainWindowInner.qml src/ui/MainWindowNative.qml - src/ui/AppSettings.qml + src/ui/preferences/MavlinkSettings.qml src/MissionEditor/MissionEditor.qml + src/MissionEditor/MissionSettingsEditor.qml + src/AutoPilotPlugins/Common/MixersComponent.qml + src/ui/preferences/MockLink.qml + src/ui/preferences/MockLinkSettings.qml + src/MultiVehicle/MultiVehicleView.qml src/AutoPilotPlugins/Common/MotorComponent.qml + src/QtLocationPlugin/QMLControl/OfflineMap.qml src/AutoPilotPlugins/PX4/PowerComponent.qml src/AutoPilotPlugins/PX4/PowerComponentSummary.qml src/VehicleSetup/PX4FlowSensor.qml - src/QmlControls/QGroundControl.Controls.qmldir src/AnalyzeView/AnalyzePage.qml + src/QmlControls/AppMessages.qml + src/MissionEditor/ComplexMissionItem.qml src/QmlControls/ClickableColor.qml src/QmlControls/DropButton.qml src/QmlControls/ExclusiveGroupItem.qml src/QmlControls/FactSliderPanel.qml + src/QmlControls/FlightModeDropdown.qml + src/QmlControls/FlightModeMenu.qml + src/MissionEditor/FWLandingPatternMapVisual.qml + src/QmlControls/GuidedBar.qml src/QmlControls/IndicatorButton.qml src/QmlControls/JoystickThumbPad.qml src/ui/toolbar/MainToolBar.qml src/ui/toolbar/MainToolBarIndicators.qml + src/QmlControls/MissionCommandDialog.qml src/MissionEditor/MissionItemEditor.qml src/QmlControls/MissionItemIndexLabel.qml src/MissionEditor/MissionItemStatus.qml - src/QmlControls/MissionCommandDialog.qml - src/QmlControls/MultiRotorMotorDisplay.qml src/QmlControls/ModeSwitchDisplay.qml + src/QmlControls/MultiRotorMotorDisplay.qml + src/QmlControls/OfflineMapButton.qml src/QmlControls/ParameterEditor.qml src/QmlControls/ParameterEditorDialog.qml - src/MissionEditor/RallyPointItemEditor.qml - src/QmlControls/RCChannelMonitor.qml src/QmlControls/QGCButton.qml src/QmlControls/QGCCheckBox.qml src/QmlControls/QGCColoredImage.qml src/QmlControls/QGCComboBox.qml src/QmlControls/QGCFlickable.qml - src/QmlControls/QGCFlickableVerticalIndicator.qml src/QmlControls/QGCFlickableHorizontalIndicator.qml + src/QmlControls/QGCFlickableVerticalIndicator.qml + src/QmlControls/QGCGroupBox.qml src/QmlControls/QGCLabel.qml - src/QmlControls/QGCMobileFileDialog.qml + src/QmlControls/QGCListView.qml + src/QmlControls/QGCMapLabel.qml + src/QmlControls/QGCMobileFileOpenDialog.qml + src/QmlControls/QGCMobileFileSaveDialog.qml src/QmlControls/QGCMovableItem.qml src/QmlControls/QGCPipable.qml src/QmlControls/QGCRadioButton.qml @@ -84,19 +95,21 @@ src/QmlControls/QGCViewDialog.qml src/QmlControls/QGCViewMessage.qml src/QmlControls/QGCViewPanel.qml + src/QmlControls/QGroundControl.Controls.qmldir src/MissionEditor/RallyPointEditorHeader.qml + src/MissionEditor/RallyPointItemEditor.qml + src/QmlControls/RCChannelMonitor.qml src/QmlControls/RoundButton.qml src/AutoPilotPlugins/Common/SetupPage.qml src/ui/toolbar/SignalStrength.qml src/QmlControls/SliderSwitch.qml src/QmlControls/SubMenuButton.qml + src/MissionEditor/SurveyComplexItem.qml src/QmlControls/VehicleRotationCal.qml src/QmlControls/VehicleSummaryRow.qml - src/QmlControls/AppMessages.qml + src/QmlControls/ToolStrip.qml + src/QmlControls/DropPanel.qml src/ViewWidgets/ViewWidget.qml - src/MissionEditor/SimpleItemEditor.qml - src/MissionEditor/SurveyItemEditor.qml - src/MissionEditor/GeoFenceEditor.qml src/FactSystem/FactControls/FactBitmask.qml src/FactSystem/FactControls/FactCheckBox.qml src/FactSystem/FactControls/FactComboBox.qml @@ -106,15 +119,17 @@ src/FactSystem/FactControls/FactTextFieldGrid.qml src/FactSystem/FactControls/FactTextFieldRow.qml src/FactSystem/FactControls/qmldir - src/FlightDisplay/qmldir src/FlightDisplay/FlightDisplayView.qml src/FlightDisplay/FlightDisplayViewMap.qml src/FlightDisplay/FlightDisplayViewVideo.qml src/FlightDisplay/FlightDisplayViewWidgets.qml - src/FlightDisplay/VirtualJoystick.qml - src/FlightMap/qmldir + src/FlightDisplay/MultiVehicleList.qml + src/FlightDisplay/qmldir + src/FlightMap/Widgets/CenterMapDropButton.qml + src/FlightMap/Widgets/CenterMapDropPanel.qml + src/FlightMap/Widgets/MapFitFunctions.qml src/FlightMap/FlightMap.qml - src/MissionEditor/QGCMapPolygonControls.qml + src/FlightMap/Widgets/InstrumentSwipeView.qml src/FlightMap/MapScale.qml src/FlightMap/MapItems/MissionItemIndicator.qml src/FlightMap/MapItems/MissionItemView.qml @@ -123,58 +138,37 @@ src/FlightMap/Widgets/QGCAttitudeHUD.qml src/FlightMap/Widgets/QGCAttitudeWidget.qml src/FlightMap/Widgets/QGCCompassWidget.qml - src/FlightMap/Widgets/QGCInstrumentWidget.qml - src/FlightMap/Widgets/QGCInstrumentWidgetAlternate.qml + src/FlightMap/Widgets/QGCInstrumentWidget.qml + src/FlightMap/Widgets/QGCInstrumentWidgetAlternate.qml + src/MissionEditor/QGCMapPolygonControls.qml src/FlightMap/Widgets/QGCPitchIndicator.qml src/FlightMap/QGCVideoBackground.qml + src/FlightMap/qmldir + src/FlightMap/Widgets/CameraWidget.qml src/FlightMap/Widgets/ValuesWidget.qml - src/FlightMap/Widgets/VibrationWidget.qml + src/FlightMap/Widgets/VehicleHealthWidget.qml src/FlightMap/MapItems/VehicleMapItem.qml - src/FlightMap/Widgets/InstrumentSwipeView.qml + src/FlightMap/Widgets/VibrationWidget.qml src/QmlControls/QGroundControl.ScreenTools.qmldir src/QmlControls/ScreenTools.qml src/QmlControls/QmlTest.qml src/AutoPilotPlugins/Common/RadioComponent.qml - src/AutoPilotPlugins/Common/ESP8266Component.qml - src/AutoPilotPlugins/Common/ESP8266ComponentSummary.qml - src/AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml - src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml - src/AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml - src/AutoPilotPlugins/APM/APMNotSupported.qml - src/AutoPilotPlugins/APM/APMCameraComponent.qml - src/AutoPilotPlugins/APM/APMCameraComponentSummary.qml - src/AutoPilotPlugins/APM/APMLightsComponent.qml - src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml - src/AutoPilotPlugins/APM/APMPowerComponent.qml - src/AutoPilotPlugins/APM/APMPowerComponentSummary.qml - src/AutoPilotPlugins/APM/APMRadioComponentSummary.qml - src/AutoPilotPlugins/APM/APMSafetyComponentCopter.qml - src/AutoPilotPlugins/APM/APMSafetyComponentPlane.qml - src/AutoPilotPlugins/APM/APMSafetyComponentRover.qml - src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml - src/AutoPilotPlugins/APM/APMSafetyComponentSummaryCopter.qml - src/AutoPilotPlugins/APM/APMSafetyComponentSummaryPlane.qml - src/AutoPilotPlugins/APM/APMSafetyComponentSummaryRover.qml - src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml - src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml - src/AutoPilotPlugins/PX4/CameraComponent.qml - src/AutoPilotPlugins/PX4/CameraComponentSummary.qml src/AutoPilotPlugins/PX4/SafetyComponent.qml src/AutoPilotPlugins/PX4/SafetyComponentSummary.qml src/AutoPilotPlugins/PX4/SensorsComponent.qml src/AutoPilotPlugins/PX4/SensorsComponentSummary.qml src/AutoPilotPlugins/PX4/SensorsComponentSummaryFixedWing.qml - src/AutoPilotPlugins/APM/APMSensorsComponent.qml - src/AutoPilotPlugins/APM/APMSensorsComponentSummary.qml + src/ui/preferences/SerialSettings.qml src/VehicleSetup/SetupParameterEditor.qml src/VehicleSetup/SetupView.qml + src/MissionEditor/SimpleItemEditor.qml + src/MissionEditor/SurveyItemEditor.qml + src/MissionEditor/FWLandingPatternEditor.qml + src/ui/preferences/TcpSettings.qml src/test.qml + src/ui/preferences/UdpSettings.qml src/VehicleSetup/VehicleSummary.qml - src/QmlControls/OfflineMapButton.qml - src/AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml - src/AnalyzeView/AnalyzeView.qml - src/AnalyzeView/GeoTagPage.qml - src/AnalyzeView/LogDownloadPage.qml + src/FlightDisplay/VirtualJoystick.qml src/MissionManager/MavCmdInfoCommon.json @@ -183,25 +177,28 @@ src/MissionManager/MavCmdInfoRover.json src/MissionManager/MavCmdInfoSub.json src/MissionManager/MavCmdInfoVTOL.json - src/FirmwarePlugin/APM/MavCmdInfoCommon.json - src/FirmwarePlugin/APM/MavCmdInfoFixedWing.json - src/FirmwarePlugin/APM/MavCmdInfoMultiRotor.json - src/FirmwarePlugin/APM/MavCmdInfoRover.json - src/FirmwarePlugin/APM/MavCmdInfoSub.json - src/FirmwarePlugin/APM/MavCmdInfoVTOL.json - src/FirmwarePlugin/PX4/MavCmdInfoCommon.json - src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json - src/FirmwarePlugin/PX4/MavCmdInfoMultiRotor.json - src/FirmwarePlugin/PX4/MavCmdInfoRover.json - src/FirmwarePlugin/PX4/MavCmdInfoSub.json - src/FirmwarePlugin/PX4/MavCmdInfoVTOL.json src/Vehicle/VehicleFact.json src/Vehicle/BatteryFact.json src/Vehicle/GPSFact.json src/Vehicle/WindFact.json src/Vehicle/VibrationFact.json - src/QmlControls/QGroundControlQmlGlobal.json + src/Settings/App.SettingsGroup.json + src/Settings/AutoConnect.SettingsGroup.json + src/Settings/Units.SettingsGroup.json + src/Settings/Video.SettingsGroup.json src/MissionManager/RallyPoint.FactMetaData.json + src/MissionManager/FWLandingPattern.FactMetaData.json src/MissionManager/Survey.FactMetaData.json + src/comm/USBBoardInfo.json + src/Vehicle/TemperatureFact.json + + + src/comm/APMArduCopterMockLink.params + src/comm/APMArduPlaneMockLink.params + src/comm/APMArduSubMockLink.params + src/comm/PX4MockLink.params + + + src/FirmwarePlugin/NoGeoFenceEditor.qml diff --git a/resources/calibration/joystick/joystickCenter.png b/resources/calibration/joystick/mode1/joystickCenter.png similarity index 100% rename from resources/calibration/joystick/joystickCenter.png rename to resources/calibration/joystick/mode1/joystickCenter.png diff --git a/resources/calibration/joystick/joystickThrottleDown.png b/resources/calibration/joystick/mode1/joystickPitchDown.png similarity index 100% rename from resources/calibration/joystick/joystickThrottleDown.png rename to resources/calibration/joystick/mode1/joystickPitchDown.png diff --git a/resources/calibration/joystick/joystickThrottleUp.png b/resources/calibration/joystick/mode1/joystickPitchUp.png similarity index 100% rename from resources/calibration/joystick/joystickThrottleUp.png rename to resources/calibration/joystick/mode1/joystickPitchUp.png diff --git a/resources/calibration/joystick/joystickRollLeft.png b/resources/calibration/joystick/mode1/joystickRollLeft.png similarity index 100% rename from resources/calibration/joystick/joystickRollLeft.png rename to resources/calibration/joystick/mode1/joystickRollLeft.png diff --git a/resources/calibration/joystick/joystickRollRight.png b/resources/calibration/joystick/mode1/joystickRollRight.png similarity index 100% rename from resources/calibration/joystick/joystickRollRight.png rename to resources/calibration/joystick/mode1/joystickRollRight.png diff --git a/resources/calibration/joystick/joystickPitchDown.png b/resources/calibration/joystick/mode1/joystickThrottleDown.png similarity index 100% rename from resources/calibration/joystick/joystickPitchDown.png rename to resources/calibration/joystick/mode1/joystickThrottleDown.png diff --git a/resources/calibration/joystick/joystickPitchUp.png b/resources/calibration/joystick/mode1/joystickThrottleUp.png similarity index 100% rename from resources/calibration/joystick/joystickPitchUp.png rename to resources/calibration/joystick/mode1/joystickThrottleUp.png diff --git a/resources/calibration/joystick/joystickYawLeft.png b/resources/calibration/joystick/mode1/joystickYawLeft.png similarity index 100% rename from resources/calibration/joystick/joystickYawLeft.png rename to resources/calibration/joystick/mode1/joystickYawLeft.png diff --git a/resources/calibration/joystick/joystickYawRight.png b/resources/calibration/joystick/mode1/joystickYawRight.png similarity index 100% rename from resources/calibration/joystick/joystickYawRight.png rename to resources/calibration/joystick/mode1/joystickYawRight.png diff --git a/resources/calibration/joystick/mode2/joystickCenter.png b/resources/calibration/joystick/mode2/joystickCenter.png new file mode 100644 index 0000000000000000000000000000000000000000..556321ec4b1c3142dc40acaf8068b4fb57e923a5 Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickCenter.png differ diff --git a/resources/calibration/joystick/mode2/joystickPitchDown.png b/resources/calibration/joystick/mode2/joystickPitchDown.png new file mode 100644 index 0000000000000000000000000000000000000000..6e895b1a5a50dac35d977dd496a830cd26b1a5d8 Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickPitchDown.png differ diff --git a/resources/calibration/joystick/mode2/joystickPitchUp.png b/resources/calibration/joystick/mode2/joystickPitchUp.png new file mode 100644 index 0000000000000000000000000000000000000000..ad9d7c03fa5dc49d5889eedf2551f900381c11fc Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickPitchUp.png differ diff --git a/resources/calibration/joystick/mode2/joystickRollLeft.png b/resources/calibration/joystick/mode2/joystickRollLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..fddc7dfb4217051af0ca1b51897f82ef7cd2c810 Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickRollLeft.png differ diff --git a/resources/calibration/joystick/mode2/joystickRollRight.png b/resources/calibration/joystick/mode2/joystickRollRight.png new file mode 100644 index 0000000000000000000000000000000000000000..9556eed1e7e62df8c0ffe5e0206ad03db6c6f943 Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickRollRight.png differ diff --git a/resources/calibration/joystick/mode2/joystickThrottleDown.png b/resources/calibration/joystick/mode2/joystickThrottleDown.png new file mode 100644 index 0000000000000000000000000000000000000000..7436477b0acd29f42758d77df5978cb955785d6a Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickThrottleDown.png differ diff --git a/resources/calibration/joystick/mode2/joystickThrottleUp.png b/resources/calibration/joystick/mode2/joystickThrottleUp.png new file mode 100644 index 0000000000000000000000000000000000000000..223199991fc90272b1fae1ba6f28799b31681ca2 Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickThrottleUp.png differ diff --git a/resources/calibration/joystick/mode2/joystickYawLeft.png b/resources/calibration/joystick/mode2/joystickYawLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..788a09c0b8c504db6f6c1068dd408cf8f39d7554 Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickYawLeft.png differ diff --git a/resources/calibration/joystick/mode2/joystickYawRight.png b/resources/calibration/joystick/mode2/joystickYawRight.png new file mode 100644 index 0000000000000000000000000000000000000000..381108825e10adacbbc729dd9ea1ea22b8665f87 Binary files /dev/null and b/resources/calibration/joystick/mode2/joystickYawRight.png differ diff --git a/resources/calibration/joystick/mode3/joystickCenter.png b/resources/calibration/joystick/mode3/joystickCenter.png new file mode 100644 index 0000000000000000000000000000000000000000..556321ec4b1c3142dc40acaf8068b4fb57e923a5 Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickCenter.png differ diff --git a/resources/calibration/joystick/mode3/joystickPitchDown.png b/resources/calibration/joystick/mode3/joystickPitchDown.png new file mode 100644 index 0000000000000000000000000000000000000000..7436477b0acd29f42758d77df5978cb955785d6a Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickPitchDown.png differ diff --git a/resources/calibration/joystick/mode3/joystickPitchUp.png b/resources/calibration/joystick/mode3/joystickPitchUp.png new file mode 100644 index 0000000000000000000000000000000000000000..223199991fc90272b1fae1ba6f28799b31681ca2 Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickPitchUp.png differ diff --git a/resources/calibration/joystick/mode3/joystickRollLeft.png b/resources/calibration/joystick/mode3/joystickRollLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..788a09c0b8c504db6f6c1068dd408cf8f39d7554 Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickRollLeft.png differ diff --git a/resources/calibration/joystick/mode3/joystickRollRight.png b/resources/calibration/joystick/mode3/joystickRollRight.png new file mode 100644 index 0000000000000000000000000000000000000000..381108825e10adacbbc729dd9ea1ea22b8665f87 Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickRollRight.png differ diff --git a/resources/calibration/joystick/mode3/joystickThrottleDown.png b/resources/calibration/joystick/mode3/joystickThrottleDown.png new file mode 100644 index 0000000000000000000000000000000000000000..6e895b1a5a50dac35d977dd496a830cd26b1a5d8 Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickThrottleDown.png differ diff --git a/resources/calibration/joystick/mode3/joystickThrottleUp.png b/resources/calibration/joystick/mode3/joystickThrottleUp.png new file mode 100644 index 0000000000000000000000000000000000000000..ad9d7c03fa5dc49d5889eedf2551f900381c11fc Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickThrottleUp.png differ diff --git a/resources/calibration/joystick/mode3/joystickYawLeft.png b/resources/calibration/joystick/mode3/joystickYawLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..fddc7dfb4217051af0ca1b51897f82ef7cd2c810 Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickYawLeft.png differ diff --git a/resources/calibration/joystick/mode3/joystickYawRight.png b/resources/calibration/joystick/mode3/joystickYawRight.png new file mode 100644 index 0000000000000000000000000000000000000000..9556eed1e7e62df8c0ffe5e0206ad03db6c6f943 Binary files /dev/null and b/resources/calibration/joystick/mode3/joystickYawRight.png differ diff --git a/resources/calibration/joystick/mode4/joystickCenter.png b/resources/calibration/joystick/mode4/joystickCenter.png new file mode 100644 index 0000000000000000000000000000000000000000..556321ec4b1c3142dc40acaf8068b4fb57e923a5 Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickCenter.png differ diff --git a/resources/calibration/joystick/mode4/joystickPitchDown.png b/resources/calibration/joystick/mode4/joystickPitchDown.png new file mode 100644 index 0000000000000000000000000000000000000000..6e895b1a5a50dac35d977dd496a830cd26b1a5d8 Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickPitchDown.png differ diff --git a/resources/calibration/joystick/mode4/joystickPitchUp.png b/resources/calibration/joystick/mode4/joystickPitchUp.png new file mode 100644 index 0000000000000000000000000000000000000000..ad9d7c03fa5dc49d5889eedf2551f900381c11fc Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickPitchUp.png differ diff --git a/resources/calibration/joystick/mode4/joystickRollLeft.png b/resources/calibration/joystick/mode4/joystickRollLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..788a09c0b8c504db6f6c1068dd408cf8f39d7554 Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickRollLeft.png differ diff --git a/resources/calibration/joystick/mode4/joystickRollRight.png b/resources/calibration/joystick/mode4/joystickRollRight.png new file mode 100644 index 0000000000000000000000000000000000000000..381108825e10adacbbc729dd9ea1ea22b8665f87 Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickRollRight.png differ diff --git a/resources/calibration/joystick/mode4/joystickThrottleDown.png b/resources/calibration/joystick/mode4/joystickThrottleDown.png new file mode 100644 index 0000000000000000000000000000000000000000..7436477b0acd29f42758d77df5978cb955785d6a Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickThrottleDown.png differ diff --git a/resources/calibration/joystick/mode4/joystickThrottleUp.png b/resources/calibration/joystick/mode4/joystickThrottleUp.png new file mode 100644 index 0000000000000000000000000000000000000000..223199991fc90272b1fae1ba6f28799b31681ca2 Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickThrottleUp.png differ diff --git a/resources/calibration/joystick/mode4/joystickYawLeft.png b/resources/calibration/joystick/mode4/joystickYawLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..fddc7dfb4217051af0ca1b51897f82ef7cd2c810 Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickYawLeft.png differ diff --git a/resources/calibration/joystick/mode4/joystickYawRight.png b/resources/calibration/joystick/mode4/joystickYawRight.png new file mode 100644 index 0000000000000000000000000000000000000000..9556eed1e7e62df8c0ffe5e0206ad03db6c6f943 Binary files /dev/null and b/resources/calibration/joystick/mode4/joystickYawRight.png differ diff --git a/resources/waves.svg b/resources/waves.svg new file mode 100644 index 0000000000000000000000000000000000000000..fbca7c7819fd882452ada1c52c56db7ddb0f2afa --- /dev/null +++ b/resources/waves.svg @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/src/AnalyzeView/AnalyzeView.qml b/src/AnalyzeView/AnalyzeView.qml index 33545d0f97c0afb42e10e37e120dd6617b9f1975..cd910754a9c1f1fbf2f890b1e2cece19d6ad94bf 100644 --- a/src/AnalyzeView/AnalyzeView.qml +++ b/src/AnalyzeView/AnalyzeView.qml @@ -58,8 +58,8 @@ Rectangle { // I don't know why this does not work Connections { - target: QGroundControl - onBaseFontPointSizeChanged: buttonColumn.reflowWidths() + target: QGroundControl.settingsManager.appSettings.appFontPointSize + onValueChanged: buttonColumn.reflowWidths() } function reflowWidths() { @@ -86,25 +86,25 @@ Rectangle { model: ListModel { ListElement { - buttonImage: "/qmlimages/LogDownloadIcon" - buttonText: qsTr("Log Download") - pageSource: "LogDownloadPage.qml" + buttonImage: "/qmlimages/LogDownloadIcon" + buttonText: qsTr("Log Download") + pageSource: "LogDownloadPage.qml" } ListElement { - buttonImage: "/qmlimages/GeoTagIcon" - buttonText: qsTr("GeoTag Images") - pageSource: "GeoTagPage.qml" + buttonImage: "/qmlimages/GeoTagIcon" + buttonText: qsTr("GeoTag Images") + pageSource: "GeoTagPage.qml" } } Component.onCompleted: itemAt(0).checked = true SubMenuButton { - imageResource: buttonImage - setupIndicator: false - exclusiveGroup: setupButtonGroup - text: buttonText - onClicked: panelLoader.source = pageSource + imageResource: buttonImage + setupIndicator: false + exclusiveGroup: setupButtonGroup + text: buttonText + onClicked: panelLoader.source = pageSource } } } diff --git a/src/AnalyzeView/ExifParser.cc b/src/AnalyzeView/ExifParser.cc new file mode 100644 index 0000000000000000000000000000000000000000..2b4ccf0639efdc652067f26af996473aea34163f --- /dev/null +++ b/src/AnalyzeView/ExifParser.cc @@ -0,0 +1,224 @@ +#include "ExifParser.h" +#include +#include +#include + +ExifParser::ExifParser() +{ + +} + +ExifParser::~ExifParser() +{ + +} + +double ExifParser::readTime(QByteArray& buf) +{ + QByteArray tiffHeader("\x49\x49\x2A", 3); + QByteArray createDateHeader("\x04\x90\x02", 3); + + // find header position + uint32_t tiffHeaderIndex = buf.indexOf(tiffHeader); + + // find creation date header index + uint32_t createDateHeaderIndex = buf.indexOf(createDateHeader); + + // extract size of date-time string, -1 accounting for null-termination + uint32_t* sizeString = reinterpret_cast(buf.mid(createDateHeaderIndex + 4, 4).data()); + uint32_t createDateStringSize = qFromLittleEndian(*sizeString) - 1; + + // extract location of date-time string + uint32_t* dataIndex = reinterpret_cast(buf.mid(createDateHeaderIndex + 8, 4).data()); + uint32_t createDateStringDataIndex = qFromLittleEndian(*dataIndex) + tiffHeaderIndex; + + // read out data of create date-time field + QString createDate = buf.mid(createDateStringDataIndex, createDateStringSize); + + QStringList createDateList = createDate.split(' '); + if (createDateList.count() < 2) { + qWarning() << "Could not decode creation time and date: " << createDateList; + return -1.0; + } + QStringList dateList = createDateList[0].split(':'); + if (dateList.count() < 3) { + qWarning() << "Could not decode creation date: " << dateList; + return -1.0; + } + QStringList timeList = createDateList[1].split(':'); + if (timeList.count() < 3) { + qWarning() << "Could not decode creation time: " << timeList; + return -1.0; + } + QDate date(dateList[0].toInt(), dateList[1].toInt(), dateList[2].toInt()); + QTime time(timeList[0].toInt(), timeList[1].toInt(), timeList[2].toInt()); + QDateTime tagTime(date, time); + return tagTime.toMSecsSinceEpoch()/1000.0; +} + +bool ExifParser::write(QByteArray &buf, QGeoCoordinate coordinate) +{ + QByteArray app1Header("\xff\xe1", 2); + uint32_t app1HeaderInd = buf.indexOf(app1Header); + uint16_t *conversionPointer = reinterpret_cast(buf.mid(app1HeaderInd + 2, 2).data()); + uint16_t app1Size = *conversionPointer; + uint16_t app1SizeEndian = qFromBigEndian(app1Size) + 0xa5; // change wrong endian + QByteArray tiffHeader("\x49\x49\x2A", 3); + uint32_t tiffHeaderInd = buf.indexOf(tiffHeader); + conversionPointer = reinterpret_cast(buf.mid(tiffHeaderInd + 8, 2).data()); + uint16_t numberOfTiffFields = *conversionPointer; + uint32_t nextIfdOffsetInd = tiffHeaderInd + 10 + 12 * (numberOfTiffFields); + conversionPointer = reinterpret_cast(buf.mid(nextIfdOffsetInd, 2).data()); + uint16_t nextIfdOffset = *conversionPointer; + + // Definition of usefull unions and structs + union char2uint32_u { + char c[4]; + uint32_t i; + }; + union char2uint16_u { + char c[2]; + uint16_t i; + }; + // This struct describes a standart field used in exif files + struct field_s { + uint16_t tagID; // Describes which information is added here, e.g. GPS Lat + uint16_t type; // Describes the data type, e.g. string, uint8_t,... + uint32_t size; // Describes the size + uint32_t content; // Either contains the information, or the offset to the exif header where the information is stored (if 32 bits is not enough) + }; + // This struct contains all the fields that we want to add to the image + struct fields_s { + field_s gpsVersion; + field_s gpsLatRef; + field_s gpsLat; + field_s gpsLonRef; + field_s gpsLon; + field_s gpsAltRef; + field_s gpsAlt; + field_s gpsMapDatum; + uint32_t finishedDataField; + }; + // These are the additional information that can not be put into a single uin32_t + struct extended_s { + uint32_t gpsLat[6]; + uint32_t gpsLon[6]; + uint32_t gpsAlt[2]; + char mapDatum[7];// = {0x57,0x47,0x53,0x2D,0x38,0x34,0x00}; + }; + // This struct contains all the information we want to add to the image + struct readable_s { + fields_s fields; + extended_s extendedData; + }; + + // This union is used because for writing the information we have to use a char array, but we still want the information to be available in a more descriptive way + union { + char c[0xa3]; + readable_s readable; + } gpsData; + + + char2uint32_u gpsIFDInd; + gpsIFDInd.i = nextIfdOffset; + + // this will stay constant + QByteArray gpsInfo("\x25\x88\x04\x00\x01\x00\x00\x00", 8); + gpsInfo.append(gpsIFDInd.c[0]); + gpsInfo.append(gpsIFDInd.c[1]); + gpsInfo.append(gpsIFDInd.c[2]); + gpsInfo.append(gpsIFDInd.c[3]); + + // filling values to gpsData + uint32_t gpsDataExtInd = gpsIFDInd.i + 2 + sizeof(fields_s); + + // Filling up the fields with the corresponding values + gpsData.readable.fields.gpsVersion.tagID = 0; + gpsData.readable.fields.gpsVersion.type = 1; + gpsData.readable.fields.gpsVersion.size = 4; + gpsData.readable.fields.gpsVersion.content = 2; + + gpsData.readable.fields.gpsLatRef.tagID = 1; + gpsData.readable.fields.gpsLatRef.type = 2; + gpsData.readable.fields.gpsLatRef.size = 2; + gpsData.readable.fields.gpsLatRef.content = coordinate.latitude() > 0 ? 'N' : 'S'; + + gpsData.readable.fields.gpsLat.tagID = 2; + gpsData.readable.fields.gpsLat.type = 5; + gpsData.readable.fields.gpsLat.size = 3; + gpsData.readable.fields.gpsLat.content = gpsDataExtInd; + + gpsData.readable.fields.gpsLonRef.tagID = 3; + gpsData.readable.fields.gpsLonRef.type = 2; + gpsData.readable.fields.gpsLonRef.size = 2; + gpsData.readable.fields.gpsLonRef.content = coordinate.longitude() > 0 ? 'E' : 'W'; + + gpsData.readable.fields.gpsLon.tagID = 4; + gpsData.readable.fields.gpsLon.type = 5; + gpsData.readable.fields.gpsLon.size = 3; + gpsData.readable.fields.gpsLon.content = gpsDataExtInd + 6 * 4; + + gpsData.readable.fields.gpsAltRef.tagID = 5; + gpsData.readable.fields.gpsAltRef.type = 2; + gpsData.readable.fields.gpsAltRef.size = 2; + gpsData.readable.fields.gpsAltRef.content = 0x00; + + gpsData.readable.fields.gpsAlt.tagID = 6; + gpsData.readable.fields.gpsAlt.type = 5; + gpsData.readable.fields.gpsAlt.size = 1; + gpsData.readable.fields.gpsAlt.content = gpsDataExtInd + 6 * 4 * 2; + + gpsData.readable.fields.gpsMapDatum.tagID = 18; + gpsData.readable.fields.gpsMapDatum.type = 2; + gpsData.readable.fields.gpsMapDatum.size = 7; + gpsData.readable.fields.gpsMapDatum.content = gpsDataExtInd + 6 * 4 * 2 + 2 * 4; + + gpsData.readable.fields.finishedDataField = 0; + + // Filling up the additional information that does not fit into the fields + gpsData.readable.extendedData.gpsLat[0] = abs(static_cast(coordinate.latitude())); + gpsData.readable.extendedData.gpsLat[1] = 1; + gpsData.readable.extendedData.gpsLat[2] = static_cast((fabs(coordinate.latitude()) - floor(fabs(coordinate.latitude()))) * 60.0); + gpsData.readable.extendedData.gpsLat[3] = 1; + gpsData.readable.extendedData.gpsLat[4] = static_cast((fabs(coordinate.latitude()) * 60.0 - floor(fabs(coordinate.latitude()) * 60.0)) * 60000.0); + gpsData.readable.extendedData.gpsLat[5] = 1000; + + gpsData.readable.extendedData.gpsLon[0] = abs(static_cast(coordinate.longitude())); + gpsData.readable.extendedData.gpsLon[1] = 1; + gpsData.readable.extendedData.gpsLon[2] = static_cast((fabs(coordinate.longitude()) - floor(fabs(coordinate.longitude()))) * 60.0); + gpsData.readable.extendedData.gpsLon[3] = 1; + gpsData.readable.extendedData.gpsLon[4] = static_cast((fabs(coordinate.longitude()) * 60.0 - floor(fabs(coordinate.longitude()) * 60.0)) * 60000.0); + gpsData.readable.extendedData.gpsLon[5] = 1000; + + gpsData.readable.extendedData.gpsAlt[0] = coordinate.altitude() * 100; + gpsData.readable.extendedData.gpsAlt[1] = 100; + gpsData.readable.extendedData.mapDatum[0] = 'W'; + gpsData.readable.extendedData.mapDatum[1] = 'G'; + gpsData.readable.extendedData.mapDatum[2] = 'S'; + gpsData.readable.extendedData.mapDatum[3] = '-'; + gpsData.readable.extendedData.mapDatum[4] = '8'; + gpsData.readable.extendedData.mapDatum[5] = '4'; + gpsData.readable.extendedData.mapDatum[6] = 0x00; + + // remove 12 spaces from image description, as otherwise we need to loop through every field and correct the new address values + buf.remove(nextIfdOffsetInd + 4, 12); + // TODO correct size in image description + // insert Gps Info to image file + buf.insert(nextIfdOffsetInd, gpsInfo, 12); + char numberOfFields[2] = {0x08, 0x00}; + // insert number of gps specific fields that we want to add + buf.insert(gpsIFDInd.i + tiffHeaderInd, numberOfFields, 2); + // insert the gps data + buf.insert(gpsIFDInd.i + 2 + tiffHeaderInd, gpsData.c, 0xa3); + + // update the new file size and exif offsets + char2uint16_u converter; + converter.i = qToBigEndian(app1SizeEndian); + buf.replace(app1HeaderInd + 2, 2, converter.c, 2); + converter.i = nextIfdOffset + 12 + 0xa5; + buf.replace(nextIfdOffsetInd + 12, 2, converter.c, 2); + + converter.i = (numberOfTiffFields) + 1; + buf.replace(tiffHeaderInd + 8, 2, converter.c, 2); + return true; +} diff --git a/src/AnalyzeView/ExifParser.h b/src/AnalyzeView/ExifParser.h new file mode 100644 index 0000000000000000000000000000000000000000..9a29da3806d0132373df90e900c235efcba681a6 --- /dev/null +++ b/src/AnalyzeView/ExifParser.h @@ -0,0 +1,16 @@ +#ifndef EXIFPARSER_H +#define EXIFPARSER_H + +#include +#include + +class ExifParser +{ +public: + ExifParser(); + ~ExifParser(); + double readTime(QByteArray& buf); + bool write(QByteArray& data, QGeoCoordinate coordinate); +}; + +#endif // EXIFPARSER_H diff --git a/src/AnalyzeView/GeoTagController.cc b/src/AnalyzeView/GeoTagController.cc index f9314c31eb352b4e863c9f3645cd355a0cacd69c..9c49c4f596d2b3c14fa3271aea1ed24b0a4cb4f1 100644 --- a/src/AnalyzeView/GeoTagController.cc +++ b/src/AnalyzeView/GeoTagController.cc @@ -8,7 +8,15 @@ ****************************************************************************/ #include "GeoTagController.h" +#include "ExifParser.h" #include "QGCFileDialog.h" +#include "QGCLoggingCategory.h" +#include "MainWindow.h" +#include +#include +#include +#include +#include GeoTagController::GeoTagController(void) : _progress(0) @@ -27,7 +35,7 @@ GeoTagController::~GeoTagController() void GeoTagController::pickLogFile(void) { - QString filename = QGCFileDialog::getOpenFileName(NULL, "Select log file load", QString(), "PX4 log file (*.px4log);;All Files (*.*)"); + QString filename = QGCFileDialog::getOpenFileName(MainWindow::instance(), "Select log file load", QString(), "PX4 log file (*.px4log);;All Files (*.*)"); if (!filename.isEmpty()) { _worker.setLogFile(filename); emit logFileChanged(filename); @@ -36,17 +44,88 @@ void GeoTagController::pickLogFile(void) void GeoTagController::pickImageDirectory(void) { - QString dir = QGCFileDialog::getExistingDirectory(NULL, "Select image directory"); + QString dir = QGCFileDialog::getExistingDirectory(MainWindow::instance(), "Select image directory"); if (!dir.isEmpty()) { _worker.setImageDirectory(dir); emit imageDirectoryChanged(dir); } } +void GeoTagController::pickSaveDirectory(void) +{ + QString dir = QGCFileDialog::getExistingDirectory(MainWindow::instance(), "Select save directory"); + if (!dir.isEmpty()) { + _worker.setSaveDirectory(dir); + emit saveDirectoryChanged(dir); + } +} + void GeoTagController::startTagging(void) { _errorMessage.clear(); emit errorMessageChanged(_errorMessage); + + QDir imageDirectory = QDir(_worker.imageDirectory()); + if(!imageDirectory.exists()) { + _errorMessage = tr("Cannot find the image directory"); + emit errorMessageChanged(_errorMessage); + return; + } + if(_worker.saveDirectory() == "") { + if(!imageDirectory.mkdir(_worker.imageDirectory() + "/TAGGED")) { + QMessageBox msgBox(QMessageBox::Question, + tr("Images have alreay been tagged."), + tr("The images have already been tagged. Do you want to replace the previously tagged images?"), + QMessageBox::Cancel); + msgBox.setWindowModality(Qt::ApplicationModal); + msgBox.addButton(tr("Replace"), QMessageBox::ActionRole); + if (msgBox.exec() == QMessageBox::Cancel) { + _errorMessage = tr("Images have already been tagged"); + emit errorMessageChanged(_errorMessage); + return; + } + QDir oldTaggedFolder = QDir(_worker.imageDirectory() + "/TAGGED"); + oldTaggedFolder.removeRecursively(); + if(!imageDirectory.mkdir(_worker.imageDirectory() + "/TAGGED")) { + _errorMessage = tr("Couldn't replace the previously tagged images"); + emit errorMessageChanged(_errorMessage); + return; + } + } + } else { + QDir saveDirectory = QDir(_worker.saveDirectory()); + if(!saveDirectory.exists()) { + _errorMessage = tr("Cannot find the save directory"); + emit errorMessageChanged(_errorMessage); + return; + } + saveDirectory.setFilter(QDir::Files | QDir::Readable | QDir::NoSymLinks | QDir::Writable); + QStringList nameFilters; + nameFilters << "*.jpg" << "*.JPG"; + saveDirectory.setNameFilters(nameFilters); + QStringList imageList = saveDirectory.entryList(); + if(!imageList.isEmpty()) { + QMessageBox msgBox(QMessageBox::Question, + tr("Save folder not empty."), + tr("The save folder already contains images. Do you want to replace them?"), + QMessageBox::Cancel); + msgBox.setWindowModality(Qt::ApplicationModal); + msgBox.addButton(tr("Replace"), QMessageBox::ActionRole); + if (msgBox.exec() == QMessageBox::Cancel) { + _errorMessage = tr("Save folder not empty"); + emit errorMessageChanged(_errorMessage); + return; + } + foreach(QString dirFile, imageList) + { + if(!saveDirectory.remove(dirFile)) { + _errorMessage = tr("Couldn't replace the existing images"); + emit errorMessageChanged(_errorMessage); + return; + } + } + } + } _worker.start(); } @@ -64,6 +143,9 @@ void GeoTagController::_workerError(QString errorMessage) GeoTagWorker::GeoTagWorker(void) : _cancel(false) + , _logFile("") + , _imageDirectory("") + , _saveDirectory("") { } @@ -71,17 +153,237 @@ GeoTagWorker::GeoTagWorker(void) void GeoTagWorker::run(void) { _cancel = false; - emit progressChanged(0); + emit progressChanged(1); + double nSteps = 5; + + // Load Images + _imageList.clear(); + QDir imageDirectory = QDir(_imageDirectory); + imageDirectory.setFilter(QDir::Files | QDir::Readable | QDir::NoSymLinks | QDir::Writable); + imageDirectory.setSorting(QDir::Name); + QStringList nameFilters; + nameFilters << "*.jpg" << "*.JPG"; + imageDirectory.setNameFilters(nameFilters); + _imageList = imageDirectory.entryInfoList(); + if(_imageList.isEmpty()) { + emit error(tr("The image directory doesn't contain images, make sure your images are of the JPG format")); + return; + } + emit progressChanged((100/nSteps)); + + // Parse EXIF + ExifParser exifParser; + _tagTime.clear(); + for (int i = 0; i < _imageList.size(); ++i) { + QFile file(_imageList.at(i).absoluteFilePath()); + if (!file.open(QIODevice::ReadOnly)) { + emit error(tr("Geotagging failed. Couldn't open an image.")); + return; + } + QByteArray imageBuffer = file.readAll(); + file.close(); + + _tagTime.append(exifParser.readTime(imageBuffer)); + + emit progressChanged((100/nSteps) + ((100/nSteps) / _imageList.size())*i); + + if (_cancel) { + qCDebug(GeotaggingLog) << "Tagging cancelled"; + emit error(tr("Tagging cancelled")); + return; + } + } + + // Load PX4 log + _geoRef.clear(); + _triggerTime.clear(); + if (!parsePX4Log()) { + if (_cancel) { + qCDebug(GeotaggingLog) << "Tagging cancelled"; + emit error(tr("Tagging cancelled")); + return; + } else { + qCDebug(GeotaggingLog) << "Log parsing failed"; + emit error(tr("Log parsing failed - tagging cancelled")); + return; + } + } + emit progressChanged(3*(100/nSteps)); + + qCDebug(GeotaggingLog) << "Found " << _geoRef.count() << " trigger logs."; + + if (_cancel) { + qCDebug(GeotaggingLog) << "Tagging cancelled"; + emit error(tr("Tagging cancelled")); + return; + } + + // Filter Trigger + if (!triggerFiltering()) { + qCDebug(GeotaggingLog) << "Geotagging failed in trigger filtering"; + emit error(tr("Geotagging failed in trigger filtering")); + return; + } + emit progressChanged(4*(100/nSteps)); + + if (_cancel) { + qCDebug(GeotaggingLog) << "Tagging cancelled"; + emit error(tr("Tagging cancelled")); + return; + } + + // Tag images + int maxIndex = std::min(_imageIndices.count(), _triggerIndices.count()); + maxIndex = std::min(maxIndex, _imageList.count()); + for(int i = 0; i < maxIndex; i++) { + QFile fileRead(_imageList.at(_imageIndices[i]).absoluteFilePath()); + if (!fileRead.open(QIODevice::ReadOnly)) { + emit error(tr("Geotagging failed. Couldn't open an image.")); + return; + } + QByteArray imageBuffer = fileRead.readAll(); + fileRead.close(); + + if (!exifParser.write(imageBuffer, _geoRef[_triggerIndices[i]])) { + emit error(tr("Geotagging failed. Couldn't write to image.")); + return; + } else { + QFile fileWrite; + if(_saveDirectory == "") { + fileWrite.setFileName(_imageDirectory + "/TAGGED/" + _imageList.at(_imageIndices[i]).fileName()); + } else { + fileWrite.setFileName(_saveDirectory + "/" + _imageList.at(_imageIndices[i]).fileName()); + } + if (!fileWrite.open(QFile::WriteOnly)) { + emit error(tr("Geotagging failed. Couldn't write to an image.")); + return; + } + fileWrite.write(imageBuffer); + fileWrite.close(); + } + emit progressChanged(4*(100/nSteps) + ((100/nSteps) / maxIndex)*i); - for (int i=0; i<10;i++) { if (_cancel) { + qCDebug(GeotaggingLog) << "Tagging cancelled"; emit error(tr("Tagging cancelled")); return; } - emit progressChanged(i*10); - sleep(1); + } + + if (_cancel) { + qCDebug(GeotaggingLog) << "Tagging cancelled"; + emit error(tr("Tagging cancelled")); + return; } emit progressChanged(100); - emit taggingComplete(); +} + +bool GeoTagWorker::parsePX4Log() +{ + // general message header + char header[] = {(char)0xA3, (char)0x95, (char)0x00}; + // header for GPOS message header + char gposHeaderHeader[] = {(char)0xA3, (char)0x95, (char)0x80, (char)0x10, (char)0x00}; + int gposHeaderOffset; + // header for GPOS message + char gposHeader[] = {(char)0xA3, (char)0x95, (char)0x10, (char)0x00}; + int gposOffsets[3] = {3, 7, 11}; + int gposLengths[3] = {4, 4, 4}; + // header for trigger message header + char triggerHeaderHeader[] = {(char)0xA3, (char)0x95, (char)0x80, (char)0x37, (char)0x00}; + int triggerHeaderOffset; + // header for trigger message + char triggerHeader[] = {(char)0xA3, (char)0x95, (char)0x37, (char)0x00}; + int triggerOffsets[2] = {3, 11}; + int triggerLengths[2] = {8, 4}; + + // load log + QFile file(_logFile); + if (!file.open(QIODevice::ReadOnly)) { + qCDebug(GeotaggingLog) << "Could not open log file " << _logFile; + return false; + } + QByteArray log = file.readAll(); + file.close(); + + // extract header information: message lengths + uint8_t* iptr = reinterpret_cast(log.mid(log.indexOf(gposHeaderHeader) + 4, 1).data()); + gposHeaderOffset = static_cast(qFromLittleEndian(*iptr)); + iptr = reinterpret_cast(log.mid(log.indexOf(triggerHeaderHeader) + 4, 1).data()); + triggerHeaderOffset = static_cast(qFromLittleEndian(*iptr)); + + // extract trigger data + int index = 1; + int sequence = -1; + QGeoCoordinate lastCoordinate; + while(index < log.count() - 1) { + + if (_cancel) { + return false; + } + + // first extract trigger + index = log.indexOf(triggerHeader, index + 1); + // check for whether last entry has been passed + if (index < 0) { + break; + } + + if (log.indexOf(header, index + 1) != index + triggerHeaderOffset) { + continue; + } + uint64_t* time = reinterpret_cast(log.mid(index + triggerOffsets[0], triggerLengths[0]).data()); + double timeDouble = static_cast(qFromLittleEndian(*time)) / 1.0e6; + uint32_t* seq = reinterpret_cast(log.mid(index + triggerOffsets[1], triggerLengths[1]).data()); + int seqInt = static_cast(qFromLittleEndian(*seq)); + if (sequence >= seqInt || sequence + 20 < seqInt) { // assume that logging has not skipped more than 20 triggers. this prevents wrong header detection + continue; + } + _triggerTime.append(timeDouble); + sequence = seqInt; + + // second extract position + bool lookForGpos = true; + while (lookForGpos) { + + if (_cancel) { + return false; + } + + int gposIndex = log.indexOf(gposHeader, index + 1); + if (gposIndex < 0) { + _geoRef.append(lastCoordinate); + break; + } + index = gposIndex; + // verify that at an offset of gposHeaderOffset the next log message starts + if (gposIndex + gposHeaderOffset == log.indexOf(header, gposIndex + 1)) { + int32_t* lat = reinterpret_cast(log.mid(gposIndex + gposOffsets[0], gposLengths[0]).data()); + double latitude = static_cast(qFromLittleEndian(*lat))/1.0e7; + lastCoordinate.setLatitude(latitude); + int32_t* lon = reinterpret_cast(log.mid(gposIndex + gposOffsets[1], gposLengths[1]).data()); + double longitude = static_cast(qFromLittleEndian(*lon))/1.0e7; + longitude = fmod(180.0 + longitude, 360.0) - 180.0; + lastCoordinate.setLongitude(longitude); + float* alt = reinterpret_cast(log.mid(gposIndex + gposOffsets[2], gposLengths[2]).data()); + lastCoordinate.setAltitude(qFromLittleEndian(*alt)); + _geoRef.append(lastCoordinate); + break; + } + } + } + return true; +} + +bool GeoTagWorker::triggerFiltering() +{ + _imageIndices.clear(); + _triggerIndices.clear(); + for(int i = 0; i < _tagTime.count() && i < _triggerTime.count(); i++) { + _imageIndices.append(i); + _triggerIndices.append(i); + } + + return true; } diff --git a/src/AnalyzeView/GeoTagController.h b/src/AnalyzeView/GeoTagController.h index a2820fa35fc697bdc1c2587d0d535c7222bd7a32..a9c67f68cc110cda6c22fd271c1684386d77cd9e 100644 --- a/src/AnalyzeView/GeoTagController.h +++ b/src/AnalyzeView/GeoTagController.h @@ -10,9 +10,16 @@ #ifndef GeoTagController_H #define GeoTagController_H +#include "QmlObjectListModel.h" +#include "Fact.h" +#include "FactMetaData.h" #include #include #include +#include +#include +#include +#include class GeoTagWorker : public QThread { @@ -21,26 +28,38 @@ class GeoTagWorker : public QThread public: GeoTagWorker(void); - QString logFile(void) const { return _logFile; } - QString imageDirectory(void) const { return _imageDirectory; } + void setLogFile (const QString& logFile) { _logFile = logFile; } + void setImageDirectory (const QString& imageDirectory) { _imageDirectory = imageDirectory; } + void setSaveDirectory (const QString& saveDirectory) { _saveDirectory = saveDirectory; } - void setLogFile(const QString& logFile) { _logFile = logFile; } - void setImageDirectory(const QString& imageDirectory) { _imageDirectory = imageDirectory; } + QString logFile (void) const { return _logFile; } + QString imageDirectory (void) const { return _imageDirectory; } + QString saveDirectory (void) const { return _saveDirectory; } - void cancellTagging(void) { _cancel = true; } + void cancelTagging (void) { _cancel = true; } protected: void run(void) final; signals: - void error(QString errorMsg); - void taggingComplete(void); - void progressChanged(double progress); + void error (QString errorMsg); + void taggingComplete (void); + void progressChanged (double progress); private: - bool _cancel; - QString _logFile; - QString _imageDirectory; + bool parsePX4Log(); + bool triggerFiltering(); + + bool _cancel; + QString _logFile; + QString _imageDirectory; + QString _saveDirectory; + QFileInfoList _imageList; + QList _tagTime; + QList _geoRef; + QList _triggerTime; + QList _imageIndices; + QList _triggerIndices; }; /// Controller for GeoTagPage.qml. Supports geotagging images based on logfile camera tags. @@ -54,6 +73,7 @@ public: Q_PROPERTY(QString logFile READ logFile NOTIFY logFileChanged) Q_PROPERTY(QString imageDirectory READ imageDirectory NOTIFY imageDirectoryChanged) + Q_PROPERTY(QString saveDirectory READ saveDirectory NOTIFY saveDirectoryChanged) /// Set to an error message is geotagging fails Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged) @@ -66,32 +86,35 @@ public: Q_INVOKABLE void pickLogFile(void); Q_INVOKABLE void pickImageDirectory(void); + Q_INVOKABLE void pickSaveDirectory(void); Q_INVOKABLE void startTagging(void); - Q_INVOKABLE void cancelTagging(void) { _worker.cancellTagging(); } + Q_INVOKABLE void cancelTagging(void) { _worker.cancelTagging(); } - QString logFile (void) const { return _worker.logFile(); } - QString imageDirectory (void) const { return _worker.imageDirectory(); } - double progress (void) const { return _progress; } - bool inProgress (void) const { return _worker.isRunning(); } - QString errorMessage (void) const { return _errorMessage; } + QString logFile (void) const { return _worker.logFile(); } + QString imageDirectory (void) const { return _worker.imageDirectory(); } + QString saveDirectory (void) const { return _worker.saveDirectory(); } + double progress (void) const { return _progress; } + bool inProgress (void) const { return _worker.isRunning(); } + QString errorMessage (void) const { return _errorMessage; } signals: - void logFileChanged(QString logFile); - void imageDirectoryChanged(QString imageDirectory); - void progressChanged(double progress); - void inProgressChanged(void); - void errorMessageChanged(QString errorMessage); + void logFileChanged (QString logFile); + void imageDirectoryChanged (QString imageDirectory); + void saveDirectoryChanged (QString saveDirectory); + void progressChanged (double progress); + void inProgressChanged (void); + void errorMessageChanged (QString errorMessage); private slots: void _workerProgressChanged(double progress); void _workerError(QString errorMsg); private: - QString _errorMessage; - double _progress; - bool _inProgress; + QString _errorMessage; + double _progress; + bool _inProgress; - GeoTagWorker _worker; + GeoTagWorker _worker; }; #endif diff --git a/src/AnalyzeView/GeoTagIcon.png b/src/AnalyzeView/GeoTagIcon.png deleted file mode 100644 index 6aa8343a341df18048e0c9feeeb9491e2c63aaa8..0000000000000000000000000000000000000000 Binary files a/src/AnalyzeView/GeoTagIcon.png and /dev/null differ diff --git a/src/AnalyzeView/GeoTagIcon.svg b/src/AnalyzeView/GeoTagIcon.svg new file mode 100644 index 0000000000000000000000000000000000000000..ba15cb0ad2c5bc4bc62aa661950ccef7661f5a16 --- /dev/null +++ b/src/AnalyzeView/GeoTagIcon.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/src/AnalyzeView/GeoTagPage.qml b/src/AnalyzeView/GeoTagPage.qml index a7d84071082f4bb91ade83f6e2bafbecc1aaf425..a4881a7f8bbb36433a770ca87ea600a66b16165b 100644 --- a/src/AnalyzeView/GeoTagPage.qml +++ b/src/AnalyzeView/GeoTagPage.qml @@ -11,7 +11,10 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Dialogs 1.2 +import QGroundControl 1.0 import QGroundControl.Palette 1.0 +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 import QGroundControl.Controls 1.0 import QGroundControl.ScreenTools 1.0 import QGroundControl.Controllers 1.0 @@ -19,17 +22,17 @@ import QGroundControl.Controllers 1.0 AnalyzePage { id: geoTagPage pageComponent: pageComponent - pageName: qsTr("GeoTag Images (WIP)") - pageDescription: qsTr("GetTag Images is used to tag a set of images from a survey mission with gps coordinates. You must provide the binary log from the flight as well as the directory which contains the images to tag.") + pageName: qsTr("GeoTag Images") + pageDescription: qsTr("GeoTag Images is used to tag a set of images from a survey mission with gps coordinates. You must provide the binary log from the flight as well as the directory which contains the images to tag.") - property real _margin: ScreenTools.defaultFontPixelWidth + property real _margin: ScreenTools.defaultFontPixelWidth * 2 GeoTagController { id: controller } Component { - id: pageComponent + id: pageComponent Column { id: mainColumn @@ -37,67 +40,104 @@ AnalyzePage { spacing: _margin Row { - spacing: _margin + spacing: ScreenTools.defaultFontPixelWidth * 2 - QGCLabel { - text: "Log file:" + ProgressBar { + id: progressBar + width: qgcView.width -_margin * 5 + maximumValue: 100 + value: controller.progress } - QGCLabel { - text: controller.logFile + BusyIndicator { + running: controller.progress > 0 && controller.progress < 100 && controller.errorMessage === "" + width: progressBar.height + height: progressBar.height } + } + + QGCLabel { + text: controller.errorMessage + font.bold: true + font.pointSize: ScreenTools.largeFontPointSize + color: "red" + } + + // Horizontal spacer line + Rectangle { + height: 1 + width: qgcView.width * 1.0 + color: qgcPal.windowShadeDark + anchors.horizontalCenter: parent.horizontalCenter + } + + Row { + spacing: _margin QGCButton { text: qsTr("Select log file") + width: ScreenTools.defaultFontPixelWidth * 30 onClicked: controller.pickLogFile() + anchors.verticalCenter: parent.verticalCenter + } + + QGCLabel { + text: controller.logFile + anchors.verticalCenter: parent.verticalCenter } } Row { spacing: _margin - QGCLabel { - text: "Image directory:" + QGCButton { + text: qsTr("Select image directory") + width: ScreenTools.defaultFontPixelWidth * 30 + onClicked: controller.pickImageDirectory() + anchors.verticalCenter: parent.verticalCenter } QGCLabel { text: controller.imageDirectory + anchors.verticalCenter: parent.verticalCenter } + } + + Row { + spacing: _margin QGCButton { - text: qsTr("Select image directory") - onClicked: controller.pickImageDirectory() + text: qsTr("(Optionally) Select save directory") + width: ScreenTools.defaultFontPixelWidth * 30 + onClicked: controller.pickSaveDirectory() + anchors.verticalCenter: parent.verticalCenter + } + + QGCLabel { + text: controller.saveDirectory != "" ? controller.saveDirectory : "/TAGGED folder in your image folder" + anchors.verticalCenter: parent.verticalCenter } } - QGCLabel { text: "NYI - Simulated only" } + // Horizontal spacer line + Rectangle { + height: 1 + width: qgcView.width * 1.0 + color: qgcPal.windowShadeDark + anchors.horizontalCenter: parent.horizontalCenter + } QGCButton { text: controller.inProgress ? qsTr("Cancel Tagging") : qsTr("Start Tagging") - + width: ScreenTools.defaultFontPixelWidth * 30 onClicked: { if (controller.inProgress) { controller.cancelTagging() } else { - if (controller.logFile == "" || controller.imageDirectory == "") { - geoTagPage.showMessage(qsTr("Error"), qsTr("You must select a log file and image directory before you can start tagging."), StandardButton.Ok) - return - } controller.startTagging() } } } - - QGCLabel { - text: controller.errorMessage - } - - ProgressBar { - anchors.left: parent.left - anchors.right: parent.right - maximumValue: 100 - value: controller.progress - } } // Column } // Component } // AnalyzePage diff --git a/src/AnalyzeView/LogDownloadController.cc b/src/AnalyzeView/LogDownloadController.cc index 38cf2c4b85a3fde05d20f87349a5d3eab275cc00..a63f3ba8879c5ba83c5f09d50208349889001091 100644 --- a/src/AnalyzeView/LogDownloadController.cc +++ b/src/AnalyzeView/LogDownloadController.cc @@ -16,6 +16,7 @@ #include "QGCApplication.h" #include "QGCToolbox.h" #include "QGCMapEngine.h" +#include "ParameterManager.h" #include "Vehicle.h" #include "MainWindow.h" @@ -583,8 +584,14 @@ LogDownloadController::_prepareLogDownload() } _downloadData = new LogDownloadData(entry); _downloadData->filename = QString("log_") + QString::number(entry->id()) + "_" + ftime; - if(_vehicle->firmwareType() == MAV_AUTOPILOT_PX4) { - _downloadData->filename += ".px4log"; + if (_vehicle->firmwareType() == MAV_AUTOPILOT_PX4) { + + // This is a stopgap and should be removed once log file types are properly supported by the log download protocol + if (_vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, "SYS_LOGGER")->rawValue().toInt() == 0) { + _downloadData->filename += ".px4log"; + } else { + _downloadData->filename += ".ulg"; + } } else { _downloadData->filename += ".bin"; } diff --git a/src/AnalyzeView/LogDownloadIcon.png b/src/AnalyzeView/LogDownloadIcon.png deleted file mode 100644 index 6aa8343a341df18048e0c9feeeb9491e2c63aaa8..0000000000000000000000000000000000000000 Binary files a/src/AnalyzeView/LogDownloadIcon.png and /dev/null differ diff --git a/src/AnalyzeView/LogDownloadIcon.svg b/src/AnalyzeView/LogDownloadIcon.svg new file mode 100644 index 0000000000000000000000000000000000000000..a8d9b0b7a13af86ff4f58a5f0b6a84aec01bb400 --- /dev/null +++ b/src/AnalyzeView/LogDownloadIcon.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.cc b/src/AutoPilotPlugins/APM/APMAirframeComponent.cc index d6aedc86dbb505558b1e98e69a94d0d72912538b..0c60172567052abf977159238145eca656d2e0ce 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.cc +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.cc @@ -11,16 +11,27 @@ #include "ArduCopterFirmwarePlugin.h" #include "ParameterManager.h" +const char* APMAirframeComponent::_oldFrameParam = "FRAME"; +const char* APMAirframeComponent::_newFrameParam = "FRAME_CLASS"; + APMAirframeComponent::APMAirframeComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : VehicleComponent(vehicle, autopilot, parent) , _requiresFrameSetup(false) , _name("Airframe") { if (qobject_cast(_vehicle->firmwarePlugin()) != NULL) { + ParameterManager* paramMgr = _vehicle->parameterManager(); _requiresFrameSetup = true; - MAV_TYPE vehicleType = vehicle->vehicleType(); - if (vehicleType == MAV_TYPE_TRICOPTER || vehicleType == MAV_TYPE_HELICOPTER) { - _requiresFrameSetup = false; + if (paramMgr->parameterExists(FactSystem::defaultComponentId, _oldFrameParam)) { + _useNewFrameParam = false; + _frameParamFact = paramMgr->getParameter(FactSystem::defaultComponentId, _oldFrameParam); + MAV_TYPE vehicleType = vehicle->vehicleType(); + if (vehicleType == MAV_TYPE_TRICOPTER || vehicleType == MAV_TYPE_HELICOPTER) { + _requiresFrameSetup = false; + } + } else { + _useNewFrameParam = true; + _frameParamFact = paramMgr->getParameter(FactSystem::defaultComponentId, _newFrameParam); } } } @@ -49,7 +60,11 @@ bool APMAirframeComponent::requiresSetup(void) const bool APMAirframeComponent::setupComplete(void) const { if (_requiresFrameSetup) { - return _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, QStringLiteral("FRAME"))->rawValue().toInt() >= 0; + if (_useNewFrameParam) { + return _frameParamFact->rawValue().toInt() > 0; + } else { + return _frameParamFact->rawValue().toInt() >= 0; + } } else { return true; } @@ -60,7 +75,7 @@ QStringList APMAirframeComponent::setupCompleteChangedTriggerList(void) const QStringList list; if (_requiresFrameSetup) { - list << QStringLiteral("FRAME"); + list << (_useNewFrameParam ? _newFrameParam : _oldFrameParam); } return list; diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.h b/src/AutoPilotPlugins/APM/APMAirframeComponent.h index 5a707b52d6bf9bae7fe6a4aeb96b18db9cb55f13..0b7c6be183a12e2185171dad52669258767c43c0 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.h +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.h @@ -36,6 +36,11 @@ public: private: bool _requiresFrameSetup; ///< true: FRAME parameter must be set const QString _name; + Fact* _frameParamFact; + bool _useNewFrameParam; + + static const char* _oldFrameParam; + static const char* _newFrameParam; }; #endif diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml index 29ec60771b88b6792b49e2b2013c6aca916d96f7..bcf4cef9085790bf234830d25874c4f9cbfbe6ab 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml @@ -14,6 +14,7 @@ import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.2 import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 import QGroundControl.Palette 1.0 import QGroundControl.Controls 1.0 import QGroundControl.Controllers 1.0 @@ -21,10 +22,80 @@ import QGroundControl.ScreenTools 1.0 SetupPage { id: airframePage - pageComponent: airframePageComponent + pageComponent: _useOldFrameParam ? oldFramePageComponent: newFramePageComponent + + property real _margins: ScreenTools.defaultFontPixelWidth + property bool _useOldFrameParam: controller.parameterExists(-1, "FRAME") + property Fact _oldFrameParam: controller.getParameterFact(-1, "FRAME", false) + property Fact _newFrameParam: controller.getParameterFact(-1, "FRAME_CLASS", false) + property Fact _frameTypeParam: controller.getParameterFact(-1, "FRAME_TYPE", false) + property var _flatParamList: ListModel { + ListElement { + name: "3DR Aero M" + file: "3DR_AERO_M.param" + } + ListElement { + name: "3DR Aero RTF" + file: "3DR_Aero_RTF.param" + } + ListElement { + name: "3DR Rover" + file: "3DR_Rover.param" + } + ListElement { + name: "3DR Tarot" + file: "3DR_Tarot.bgsc" + } + ListElement { + name: "Parrot Bebop" + file: "Parrot_Bebop.param" + } + ListElement { + name: "Storm32" + file: "SToRM32-MAVLink.param" + } + ListElement { + name: "3DR X8-M RTF" + file: "3DR_X8-M_RTF.param" + } + ListElement { + name: "3DR Y6A" + file: "3DR_Y6A_RTF.param" + } + ListElement { + name: "3DR X8+ RTF" + file: "3DR_X8+_RTF.param" + } + ListElement { + name: "3DR QUAD X4 RTF" + file: "3DR_QUAD_X4_RTF.param" + } + ListElement { + name: "3DR X8" + file: "3DR_X8_RTF.param" + } + ListElement { + name: "Iris with GoPro" + file: "Iris with Front Mount Go Pro.param" + } + ListElement { + name: "Iris with Tarot" + file: "Iris with Tarot Gimbal.param" + } + ListElement { + name: "3DR Iris+" + file: "3DR_Iris+.param" + } + ListElement { + name: "Iris" + file: "Iris.param" + } + ListElement { + name: "3DR Y6B" + file: "3DR_Y6B_RTF.param" + } + } - property real _margins: ScreenTools.defaultFontPixelWidth - property Fact _frame: controller.getParameterFact(-1, "FRAME") APMAirframeComponentController { id: controller @@ -88,7 +159,49 @@ SetupPage { } Component { - id: airframePageComponent + id: selectParamFileDialogComponent + + QGCViewDialog { + QGCLabel { + id: applyParamsText + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: _margins + wrapMode: Text.WordWrap + text: qsTr("Select your drone to load the default parameters for it. ") + } + + Flow { + anchors.margins: _margins + anchors.top: applyParamsText.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + spacing : _margins + layoutDirection: Qt.Vertical; + + Repeater { + id: airframePicker + model: _flatParamList + + delegate: QGCButton { + width: parent.width / 2.1 + height: (ScreenTools.defaultFontPixelHeight * 14) / 5 + text: name + + onClicked : { + controller.loadParameters(file) + hideDialog() + } + } + } + } + } + } + + Component { + id: oldFramePageComponent Column { width: availableWidth @@ -129,5 +242,41 @@ SetupPage { } } } // Column - } // Component - pageComponent + } // Component - oldFramePageComponent + + Component { + id: newFramePageComponent + + Grid { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margins + columns: 2 + + QGCLabel { + text: qsTr("Frame Class:") + } + + FactComboBox { + fact: _newFrameParam + indexModel: false + width: ScreenTools.defaultFontPixelWidth * 15 + } + + QGCLabel { + text: qsTr("Frame Type:") + } + + FactComboBox { + fact: _frameTypeParam + indexModel: false + width: ScreenTools.defaultFontPixelWidth * 15 + } + + QGCButton { + text: qsTr("Load common parameters") + onClicked: showDialog(selectParamFileDialogComponent, qsTr("Load common parameters"), qgcView.showDialogDefaultWidth, StandardButton.Close) + } + } + } } // SetupPage diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc b/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc index 3f488f217154cdf1e333c226891139aae50aa718..670005397999eda03d4c4cc74c1302c51fad5937 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc @@ -15,7 +15,6 @@ #include "APMAirframeComponentAirframes.h" #include "QGCMAVLink.h" #include "MultiVehicleManager.h" -#include "AutoPilotPluginManager.h" #include "QGCApplication.h" #include "QGCFileDownload.h" #include "ParameterManager.h" @@ -29,18 +28,25 @@ bool APMAirframeComponentController::_typesRegistered = false; +const char* APMAirframeComponentController::_oldFrameParam = "FRAME"; +const char* APMAirframeComponentController::_newFrameParam = "FRAME_CLASS"; + APMAirframeComponentController::APMAirframeComponentController(void) : _airframeTypesModel(new QmlObjectListModel(this)) { if (!_typesRegistered) { _typesRegistered = true; - qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "APMAiframeType", QStringLiteral("Can only reference APMAirframeType")); - qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "APMAiframe", QStringLiteral("Can only reference APMAirframe")); + qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "APMAirframeType", QStringLiteral("Can only reference APMAirframeType")); } _fillAirFrames(); - Fact *frame = getParameterFact(FactSystem::defaultComponentId, QStringLiteral("FRAME")); - connect(frame, &Fact::vehicleUpdated, this, &APMAirframeComponentController::_factFrameChanged); + Fact* frame; + if (parameterExists(FactSystem::defaultComponentId, _oldFrameParam)) { + frame = getParameterFact(FactSystem::defaultComponentId, _oldFrameParam); + } else { + frame = getParameterFact(FactSystem::defaultComponentId, _newFrameParam); + } + connect(frame, &Fact::rawValueChanged, this, &APMAirframeComponentController::_factFrameChanged); _factFrameChanged(frame->rawValue()); } diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentController.h b/src/AutoPilotPlugins/APM/APMAirframeComponentController.h index 936cd96ee338a3c8a1d5920bd5ecec82eb811b9d..47e383529350de8185461883500d2f45fb8e9c57 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponentController.h +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentController.h @@ -71,9 +71,12 @@ private slots: private: void _loadParametersFromDownloadFile(const QString& downloadedParamFile); - static bool _typesRegistered; APMAirframeType *_currentAirframeType; QmlObjectListModel *_airframeTypesModel; + + static bool _typesRegistered; + static const char* _oldFrameParam; + static const char* _newFrameParam; }; class APMAirframe : public QObject diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml b/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml index 9097ce44f6ff6c93002afa9e6783f6ad219bace7..8ba3da326c658806d04e1d21185ce1a1a56cc649 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml @@ -18,18 +18,31 @@ FactPanel { factPanel: panel } - property Fact sysIdFact: controller.getParameterFact(-1, "FRAME") + property bool _useOldFrameParam: controller.parameterExists(-1, "FRAME") + property Fact _oldFrameParam: controller.getParameterFact(-1, "FRAME", false) + property Fact _newFrameParam: controller.getParameterFact(-1, "FRAME_CLASS", false) + property Fact _frameTypeParam: controller.getParameterFact(-1, "FRAME_TYPE", false) Column { anchors.fill: parent + + VehicleSummaryRow { + labelText: qsTr("Frame Type:") + valueText: controller.currentAirframeTypeName() + " " + _oldFrameParam.enumStringValue + visible: _useOldFrameParam + } + + VehicleSummaryRow { + labelText: qsTr("Frame Class:") + valueText: _newFrameParam.enumStringValue + visible: !_useOldFrameParam + + } + VehicleSummaryRow { - id: nameRow; - labelText: qsTr("Frame Type:") - valueText: controller.currentAirframeTypeName() + " " + (sysIdFact.valueString === "0" ? "Plus" - : sysIdFact.valueString === "1" ? "X" - : sysIdFact.valueString === "2" ? "V" - : sysIdFact.valueString == "3" ? "H" - : /* Fact.value == 10 */ "New Y6"); + labelText: qsTr("Frame Type:") + valueText: _frameTypeParam.enumStringValue + visible: !_useOldFrameParam } diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc index 9b8b70245592a1e20e7b45a42639d6b6a8a9b988..c8bf2d92f89ffe290f881af57acf8e1a0ac6857e 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc @@ -9,7 +9,6 @@ #include "APMAutoPilotPlugin.h" -#include "AutoPilotPluginManager.h" #include "UAS.h" #include "FirmwarePlugin/APM/APMParameterMetaData.h" // FIXME: Hack #include "FirmwarePlugin/APM/APMFirmwarePlugin.h" // FIXME: Hack @@ -17,7 +16,6 @@ #include "VehicleComponent.h" #include "APMAirframeComponent.h" #include "APMAirframeComponentAirframes.h" -#include "APMAirframeComponentController.h" #include "APMAirframeLoader.h" #include "APMFlightModesComponent.h" #include "APMRadioComponent.h" @@ -28,7 +26,9 @@ #include "MotorComponent.h" #include "APMCameraComponent.h" #include "APMLightsComponent.h" +#include "APMSubFrameComponent.h" #include "ESP8266Component.h" +#include "MixersComponent.h" /// This is the AutoPilotPlugin implementatin for the MAV_AUTOPILOT_ARDUPILOT type. APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent) @@ -37,6 +37,7 @@ APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent) , _airframeComponent(NULL) , _cameraComponent(NULL) , _lightsComponent(NULL) + , _subFrameComponent(NULL) , _flightModesComponent(NULL) , _powerComponent(NULL) #if 0 @@ -49,6 +50,7 @@ APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent) , _tuningComponent(NULL) , _airframeFacts(new APMAirframeLoader(this, vehicle->uas(), this)) , _esp8266Component(NULL) + , _mixersComponent(NULL) { APMAirframeLoader::loadAirframeFactMetaData(); } @@ -102,6 +104,10 @@ const QVariantList& APMAutoPilotPlugin::vehicleComponents(void) _tuningComponent->setupTriggerSignals(); _components.append(QVariant::fromValue((VehicleComponent*)_tuningComponent)); + _mixersComponent = new MixersComponent(_vehicle, this); + _mixersComponent->setupTriggerSignals(); + _components.append(QVariant::fromValue((VehicleComponent*)_mixersComponent)); + _cameraComponent = new APMCameraComponent(_vehicle, this); _cameraComponent->setupTriggerSignals(); _components.append(QVariant::fromValue((VehicleComponent*)_cameraComponent)); @@ -110,6 +116,12 @@ const QVariantList& APMAutoPilotPlugin::vehicleComponents(void) _lightsComponent = new APMLightsComponent(_vehicle, this); _lightsComponent->setupTriggerSignals(); _components.append(QVariant::fromValue((VehicleComponent*)_lightsComponent)); + + if(_vehicle->firmwareMajorVersion() > 3 || (_vehicle->firmwareMajorVersion() == 3 && _vehicle->firmwareMinorVersion() >= 5)) { + _subFrameComponent = new APMSubFrameComponent(_vehicle, this); + _subFrameComponent->setupTriggerSignals(); + _components.append(QVariant::fromValue((VehicleComponent*)_subFrameComponent)); + } } //-- Is there an ESP8266 Connected? diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h index 6bd6031526bad7d82075be43285452f538b0e286..838bbe39396fb81b6da0cecf3ce0fc7c9ad87296 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h @@ -25,7 +25,9 @@ class APMPowerComponent; class MotorComponent; class APMCameraComponent; class APMLightsComponent; +class APMSubFrameComponent; class ESP8266Component; +class MixersComponent; /// This is the APM specific implementation of the AutoPilot class. class APMAutoPilotPlugin : public AutoPilotPlugin @@ -42,6 +44,7 @@ public: APMAirframeComponent* airframeComponent (void) const { return _airframeComponent; } APMCameraComponent* cameraComponent (void) const { return _cameraComponent; } APMLightsComponent* lightsComponent (void) const { return _lightsComponent; } + APMSubFrameComponent* subFrameComponent (void) const { return _subFrameComponent; } APMFlightModesComponent* flightModesComponent(void) const { return _flightModesComponent; } APMPowerComponent* powerComponent (void) const { return _powerComponent; } #if 0 @@ -53,6 +56,7 @@ public: APMSensorsComponent* sensorsComponent (void) const { return _sensorsComponent; } APMTuningComponent* tuningComponent (void) const { return _tuningComponent; } ESP8266Component* esp8266Component (void) const { return _esp8266Component; } + MixersComponent* mixersComponent (void) { return _mixersComponent; } private: bool _incorrectParameterVersion; ///< true: parameter version incorrect, setup not allowed @@ -61,6 +65,7 @@ private: APMAirframeComponent* _airframeComponent; APMCameraComponent* _cameraComponent; APMLightsComponent* _lightsComponent; + APMSubFrameComponent* _subFrameComponent; APMFlightModesComponent* _flightModesComponent; APMPowerComponent* _powerComponent; #if 0 @@ -73,6 +78,7 @@ private: APMTuningComponent* _tuningComponent; APMAirframeLoader* _airframeFacts; ESP8266Component* _esp8266Component; + MixersComponent* _mixersComponent; }; #endif diff --git a/src/AutoPilotPlugins/APM/APMCameraComponent.qml b/src/AutoPilotPlugins/APM/APMCameraComponent.qml index 6ff44a5ceb300fdc94ac9b7ef8eca860cb4cbd13..0eafaade9402fde0f18b24d767affde9cdb32c1e 100644 --- a/src/AutoPilotPlugins/APM/APMCameraComponent.qml +++ b/src/AutoPilotPlugins/APM/APMCameraComponent.qml @@ -55,21 +55,23 @@ SetupPage { property Fact _mountAngMinPan: controller.getParameterFact(-1, "MNT_ANGMIN_PAN") property Fact _mountAngMaxPan: controller.getParameterFact(-1, "MNT_ANGMAX_PAN") - property Fact _rc5Function: controller.getParameterFact(-1, "RC5_FUNCTION") - property Fact _rc6Function: controller.getParameterFact(-1, "RC6_FUNCTION") - property Fact _rc7Function: controller.getParameterFact(-1, "RC7_FUNCTION") - property Fact _rc8Function: controller.getParameterFact(-1, "RC8_FUNCTION") - property Fact _rc9Function: controller.getParameterFact(-1, "RC9_FUNCTION") - property Fact _rc10Function: controller.getParameterFact(-1, "RC10_FUNCTION") - property Fact _rc11Function: controller.getParameterFact(-1, "RC11_FUNCTION") - property Fact _rc12Function: controller.getParameterFact(-1, "RC12_FUNCTION") - property Fact _rc13Function: controller.getParameterFact(-1, "RC13_FUNCTION") - property Fact _rc14Function: controller.getParameterFact(-1, "RC14_FUNCTION") + 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") + property Fact _rc8Function: controller.getParameterFact(-1, "r.SERVO8_FUNCTION") + property Fact _rc9Function: controller.getParameterFact(-1, "r.SERVO9_FUNCTION") + property Fact _rc10Function: controller.getParameterFact(-1, "r.SERVO10_FUNCTION") + property Fact _rc11Function: controller.getParameterFact(-1, "r.SERVO11_FUNCTION") + 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 bool _tiltEnabled: false property bool _panEnabled: false property bool _rollEnabled: false + property bool _servoReverseIsBool: controller.parameterExists(-1, "RC5_REVERSED") + // Gimbal Settings not available on older firmware property bool _showGimbaLSettings: controller.parameterExists(-1, "MNT_DEFLT_MODE") @@ -95,10 +97,17 @@ SetupPage { loader.gimbalOutIndex = channel - 4 loader.servoPWMMinFact = controller.getParameterFact(-1, rcPrefix + "MIN") loader.servoPWMMaxFact = controller.getParameterFact(-1, rcPrefix + "MAX") - loader.servoReverseFact = controller.getParameterFact(-1, rcPrefix + "REV") + if (controller.parameterExists(-1, "RC5_REVERSED")) { + // Newer firmware parameter + loader.servoReverseFact = controller.getParameterFact(-1, rcPrefix + "REVERSED") + } else { + // Older firmware parameter + loader.servoReverseFact = controller.getParameterFact(-1, rcPrefix + "REV") + } + } - /// Gimbal output channels are stored in RC#_FUNCTION parameters. We need to loop through those + /// Gimbal output channels are stored in SERVO#_FUNCTION parameters. We need to loop through those /// to find them and setup the ui accordindly. function calcGimbalOutValues() { gimbalDirectionTiltLoader.gimbalOutIndex = 0 @@ -108,7 +117,7 @@ SetupPage { _panEnabled = false _rollEnabled = false for (var channel=_firstGimbalOutChannel; channel<=_lastGimbalOutChannel; channel++) { - var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + var functionFact = controller.getParameterFact(-1, "r.SERVO" + channel + "_FUNCTION") if (functionFact.value == _rcFunctionMountTilt) { _tiltEnabled = true setGimbalSettingsServoInfo(gimbalDirectionTiltLoader, channel) @@ -125,7 +134,7 @@ SetupPage { function setRCFunction(channel, rcFunction) { // First clear any previous settings for this function for (var index=_firstGimbalOutChannel; index<=_lastGimbalOutChannel; index++) { - var functionFact = controller.getParameterFact(-1, "RC" + index + "_FUNCTION") + var functionFact = controller.getParameterFact(-1, "r.SERVO" + index + "_FUNCTION") if (functionFact.value != _rcFunctionDisabled && functionFact.value == rcFunction) { functionFact.value = _rcFunctionDisabled } @@ -133,12 +142,12 @@ SetupPage { // Now set the function into the new channel if (channel != 0) { - var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + var functionFact = controller.getParameterFact(-1, "r.SERVO" + channel + "_FUNCTION") functionFact.value = rcFunction } } - // Whenever any RC#_FUNCTION parameters chagnes we need to go looking for gimbal output channels again + // Whenever any SERVO#_FUNCTION parameters changes we need to go looking for gimbal output channels again Connections { target: _rc5Function; onValueChanged: calcGimbalOutValues() } Connections { target: _rc6Function; onValueChanged: calcGimbalOutValues() } Connections { target: _rc7Function; onValueChanged: calcGimbalOutValues() } @@ -195,6 +204,7 @@ SetupPage { // property Fact servoPWMMinFact // property Fact servoPWMMaxFact // property Fact servoReverseFact + // property bool servoReverseIsBool // property int rcFunction Item { @@ -234,10 +244,12 @@ SetupPage { anchors.top: mountStabCheckBox.bottom anchors.right: parent.right text: qsTr("Servo reverse") - checkedValue: 1 - uncheckedValue: 0 + checkedValue: _servoReverseIsBool ? 1 : -1 + uncheckedValue: _servoReverseIsBool ? 0 : 1 fact: servoReverseFact enabled: directionEnabled + + property bool _servoReverseIsBool: servoReverseIsBool } QGCLabel { @@ -462,6 +474,7 @@ SetupPage { property Fact servoPWMMinFact: Fact { } property Fact servoPWMMaxFact: Fact { } property Fact servoReverseFact: Fact { } + property bool servoReverseIsBool: _servoReverseIsBool property int rcFunction: _rcFunctionMountTilt } @@ -479,6 +492,7 @@ SetupPage { property Fact servoPWMMinFact: Fact { } property Fact servoPWMMaxFact: Fact { } property Fact servoReverseFact: Fact { } + property bool servoReverseIsBool: _servoReverseIsBool property int rcFunction: _rcFunctionMountRoll } @@ -496,6 +510,7 @@ SetupPage { property Fact servoPWMMinFact: Fact { } property Fact servoPWMMaxFact: Fact { } property Fact servoReverseFact: Fact { } + property bool servoReverseIsBool: _servoReverseIsBool property int rcFunction: _rcFunctionMountPan } diff --git a/src/AutoPilotPlugins/APM/APMCompassCal.cc b/src/AutoPilotPlugins/APM/APMCompassCal.cc index 42939faee2efd62c90d5943c9b255637d60a11e7..88dd8a67bebfbf641cbbaf8933449453511a00fb 100644 --- a/src/AutoPilotPlugins/APM/APMCompassCal.cc +++ b/src/AutoPilotPlugins/APM/APMCompassCal.cc @@ -145,7 +145,10 @@ CalWorkerThread::calibrate_return CalWorkerThread::calibrate(void) sensorId = 6.0f; } if (sensorId != 0.0f) { - _vehicle->doCommandLong(_vehicle->defaultComponentId(), MAV_CMD_PREFLIGHT_SET_SENSOR_OFFSETS, sensorId, -sphere_x[cur_mag], -sphere_y[cur_mag], -sphere_z[cur_mag]); + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), + MAV_CMD_PREFLIGHT_SET_SENSOR_OFFSETS, + true, /* showErrors */ + sensorId, -sphere_x[cur_mag], -sphere_y[cur_mag], -sphere_z[cur_mag]); } } } diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc b/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc index 970d9fced458bb49a7f39f6ce16c48dac2248753..58410af7722867003ec677298f5e76feff76be61 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc @@ -10,7 +10,6 @@ #include "APMFlightModesComponentController.h" #include "QGCMAVLink.h" -#include "AutoPilotPluginManager.h" #include #include diff --git a/src/AutoPilotPlugins/APM/APMLightsComponent.cc b/src/AutoPilotPlugins/APM/APMLightsComponent.cc index 6c6d62219ddd192e95dcf762e2a4bc73aa14eeaf..46d7bdbd74c8dc2f3755bf3578e8aa06b640841f 100644 --- a/src/AutoPilotPlugins/APM/APMLightsComponent.cc +++ b/src/AutoPilotPlugins/APM/APMLightsComponent.cc @@ -65,12 +65,5 @@ QUrl APMLightsComponent::summaryQmlSource(void) const QString APMLightsComponent::prerequisiteSetup(void) const { - APMAutoPilotPlugin* plugin = dynamic_cast(_autopilot); - Q_ASSERT(plugin); - - if (!plugin->airframeComponent()->setupComplete()) { - return plugin->airframeComponent()->name(); - } - return QString(); } diff --git a/src/AutoPilotPlugins/APM/APMLightsComponent.qml b/src/AutoPilotPlugins/APM/APMLightsComponent.qml index 42c76d1a24b18e20b533fa56d6e49c234b83765c..b2eac54bb67e2dc320ed73e56c2a91e59881e4cd 100644 --- a/src/AutoPilotPlugins/APM/APMLightsComponent.qml +++ b/src/AutoPilotPlugins/APM/APMLightsComponent.qml @@ -32,16 +32,17 @@ SetupPage { QGCPalette { id: palette; colorGroupEnabled: true } - property Fact _rc5Function: controller.getParameterFact(-1, "RC5_FUNCTION") - property Fact _rc6Function: controller.getParameterFact(-1, "RC6_FUNCTION") - property Fact _rc7Function: controller.getParameterFact(-1, "RC7_FUNCTION") - property Fact _rc8Function: controller.getParameterFact(-1, "RC8_FUNCTION") - property Fact _rc9Function: controller.getParameterFact(-1, "RC9_FUNCTION") - property Fact _rc10Function: controller.getParameterFact(-1, "RC10_FUNCTION") - property Fact _rc11Function: controller.getParameterFact(-1, "RC11_FUNCTION") - property Fact _rc12Function: controller.getParameterFact(-1, "RC12_FUNCTION") - property Fact _rc13Function: controller.getParameterFact(-1, "RC13_FUNCTION") - property Fact _rc14Function: controller.getParameterFact(-1, "RC14_FUNCTION") + 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") + property Fact _rc8Function: controller.getParameterFact(-1, "r.SERVO8_FUNCTION") + property Fact _rc9Function: controller.getParameterFact(-1, "r.SERVO9_FUNCTION") + property Fact _rc10Function: controller.getParameterFact(-1, "r.SERVO10_FUNCTION") + property Fact _rc11Function: controller.getParameterFact(-1, "r.SERVO11_FUNCTION") + 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") readonly property real _margins: ScreenTools.defaultFontPixelHeight readonly property int _rcFunctionDisabled: 0 @@ -52,15 +53,16 @@ SetupPage { Component.onCompleted: { calcLightOutValues() + calcCurrentStep() } - /// Light output channels are stored in RC#_FUNCTION parameters. We need to loop through those + /// Light output channels are stored in SERVO#_FUNCTION parameters. We need to loop through those /// to find them and setup the ui accordindly. function calcLightOutValues() { lightsLoader.lights1OutIndex = 0 lightsLoader.lights2OutIndex = 0 for (var channel=_firstLightsOutChannel; channel<=_lastLightsOutChannel; channel++) { - var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + var functionFact = controller.getParameterFact(-1, "r.SERVO" + channel + "_FUNCTION") if (functionFact.value == _rcFunctionRCIN9) { lightsLoader.lights1OutIndex = channel - 4 } else if (functionFact.value == _rcFunctionRCIN10) { @@ -72,7 +74,7 @@ SetupPage { function setRCFunction(channel, rcFunction) { // First clear any previous settings for this function for (var index=_firstLightsOutChannel; index<=_lastLightsOutChannel; index++) { - var functionFact = controller.getParameterFact(-1, "RC" + index + "_FUNCTION") + var functionFact = controller.getParameterFact(-1, "r.SERVO" + index + "_FUNCTION") if (functionFact.value != _rcFunctionDisabled && functionFact.value == rcFunction) { functionFact.value = _rcFunctionDisabled } @@ -80,12 +82,31 @@ SetupPage { // Now set the function into the new channel if (channel != 0) { - var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + var functionFact = controller.getParameterFact(-1, "r.SERVO" + channel + "_FUNCTION") functionFact.value = rcFunction } } - // Whenever any RC#_FUNCTION parameters chagnes we need to go looking for light output channels again + function calcCurrentStep() { + 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 + } + + function calcStepSize(steps) { + _stepSize.value = (1900-1100)/steps + } + + // Whenever any SERVO#_FUNCTION parameters chagnes we need to go looking for light output channels again Connections { target: _rc5Function; onValueChanged: calcLightOutValues() } Connections { target: _rc6Function; onValueChanged: calcLightOutValues() } Connections { target: _rc7Function; onValueChanged: calcLightOutValues() } @@ -129,14 +150,14 @@ SetupPage { id: rectangle anchors.topMargin: _margins / 2 anchors.top: settingsLabel.bottom - width: lights1Combo.x + lights1Combo.width + _margins - height: lights2Combo.y + lights2Combo.height + _margins + width: lights1Combo.x + lights1Combo.width + lightsStepCombo.width + _margins + height: lights2Combo.y + lights2Combo.height + lightsStepCombo.height + 2*_margins color: palette.windowShade QGCLabel { id: lights1Label anchors.margins: _margins - anchors.left: parent.left + anchors.right: lights1Combo.left anchors.baseline: lights1Combo.baseline text: qsTr("Lights 1:") } @@ -145,7 +166,7 @@ SetupPage { id: lights1Combo anchors.margins: _margins anchors.top: parent.top - anchors.left: lights1Label.right + anchors.left: lightsStepLabel.right width: ScreenTools.defaultFontPixelWidth * 15 model: lightsOutModel currentIndex: lights1OutIndex @@ -156,7 +177,7 @@ SetupPage { QGCLabel { id: lights2Label anchors.margins: _margins - anchors.left: parent.left + anchors.right: lights2Combo.left anchors.baseline: lights2Combo.baseline text: qsTr("Lights 2:") } @@ -165,13 +186,33 @@ SetupPage { id: lights2Combo anchors.margins: _margins anchors.top: lights1Combo.bottom - anchors.left: lights2Label.right + anchors.left: lightsStepLabel.right width: lights1Combo.width model: lightsOutModel currentIndex: lights2OutIndex onActivated: setRCFunction(lightsOutModel.get(index).value, lights2Function) } + + QGCLabel { + id: lightsStepLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: lightsStepCombo.baseline + text: qsTr("Brightness Steps:") + } + + QGCComboBox { + id: lightsStepCombo + anchors.margins: _margins + anchors.top: lights2Combo.bottom + anchors.left: lightsStepLabel.right + width: lights2Combo.width + model: [1,2,3,4,5,6,7,8,9,10] + currentIndex: lightsSteps-1 + + onActivated: calcStepSize(index+1) + } } // Rectangle } // Item } // Component - lightSettings @@ -184,6 +225,7 @@ SetupPage { property int lights2OutIndex: 0 property int lights1Function: _rcFunctionRCIN9 property int lights2Function: _rcFunctionRCIN10 + property int lightsSteps: 1 } } // Column } // Component diff --git a/src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml b/src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml index 3eb129d28a14139ace27fd6c94346a00fa525e46..7712df99c7169cfafd95b0a2fed9107b075cda50 100644 --- a/src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml +++ b/src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml @@ -14,16 +14,16 @@ FactPanel { QGCPalette { id: qgcPal; colorGroupEnabled: enabled } FactPanelController { id: controller; factPanel: panel } - property Fact _rc5Function: controller.getParameterFact(-1, "RC5_FUNCTION") - property Fact _rc6Function: controller.getParameterFact(-1, "RC6_FUNCTION") - property Fact _rc7Function: controller.getParameterFact(-1, "RC7_FUNCTION") - property Fact _rc8Function: controller.getParameterFact(-1, "RC8_FUNCTION") - property Fact _rc9Function: controller.getParameterFact(-1, "RC9_FUNCTION") - property Fact _rc10Function: controller.getParameterFact(-1, "RC10_FUNCTION") - property Fact _rc11Function: controller.getParameterFact(-1, "RC11_FUNCTION") - property Fact _rc12Function: controller.getParameterFact(-1, "RC12_FUNCTION") - property Fact _rc13Function: controller.getParameterFact(-1, "RC13_FUNCTION") - property Fact _rc14Function: controller.getParameterFact(-1, "RC14_FUNCTION") + 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") + property Fact _rc8Function: controller.getParameterFact(-1, "r.SERVO8_FUNCTION") + property Fact _rc9Function: controller.getParameterFact(-1, "r.SERVO9_FUNCTION") + property Fact _rc10Function: controller.getParameterFact(-1, "r.SERVO10_FUNCTION") + property Fact _rc11Function: controller.getParameterFact(-1, "r.SERVO11_FUNCTION") + 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") readonly property int _rcFunctionRCIN9: 59 readonly property int _rcFunctionRCIN10: 60 @@ -34,13 +34,13 @@ FactPanel { calcLightOutValues() } - /// Light output channels are stored in RC#_FUNCTION parameters. We need to loop through those + /// Light output channels are stored in SERVO#_FUNCTION parameters. We need to loop through those /// to find them and setup the ui accordindly. function calcLightOutValues() { lightsLoader.lights1OutIndex = 0 lightsLoader.lights2OutIndex = 0 for (var channel=_firstLightsOutChannel; channel<=_lastLightsOutChannel; channel++) { - var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + var functionFact = controller.getParameterFact(-1, "r.SERVO" + channel + "_FUNCTION") if (functionFact.value == _rcFunctionRCIN9) { lightsLoader.lights1OutIndex = channel - 4 } else if (functionFact.value == _rcFunctionRCIN10) { @@ -49,7 +49,7 @@ FactPanel { } } - // Whenever any RC#_FUNCTION parameters chagnes we need to go looking for light output channels again + // Whenever any SERVO#_FUNCTION parameters chagnes we need to go looking for light output channels again Connections { target: _rc5Function; onValueChanged: calcLightOutValues() } Connections { target: _rc6Function; onValueChanged: calcLightOutValues() } Connections { target: _rc7Function; onValueChanged: calcLightOutValues() } diff --git a/src/AutoPilotPlugins/APM/APMPowerComponent.qml b/src/AutoPilotPlugins/APM/APMPowerComponent.qml index 9a1c6b19e965c190174543d6d75ea50581922574..7cb5437a1d0a5f67c83b9e17f2195dff1055c894 100644 --- a/src/AutoPilotPlugins/APM/APMPowerComponent.qml +++ b/src/AutoPilotPlugins/APM/APMPowerComponent.qml @@ -138,11 +138,11 @@ SetupPage { onClicked: { var measuredVoltageValue = parseFloat(measuredVoltage.text) - if (measuredVoltageValue == 0) { + if (measuredVoltageValue == 0 || isNaN(measuredVoltageValue)) { return } var newVoltageMultiplier = (measuredVoltageValue * battVoltMult.value) / controller.vehicle.battery.voltage.value - if (newVoltageMultiplier != 0) { + if (newVoltageMultiplier > 0) { battVoltMult.value = newVoltageMultiplier } } diff --git a/src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml b/src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml index affae197ece8f2ec909bd67d77e3846887d878cb..12f8103225e4ee7f7ca70071d036b6fce8368ba1 100644 --- a/src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml +++ b/src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml @@ -172,7 +172,7 @@ SetupPage { QGCLabel { id: leakDetectorLabel - text: qsTr("Leak detector") + text: qsTr("Leak Detector") font.family: ScreenTools.demiboldFontFamily } @@ -205,7 +205,7 @@ SetupPage { anchors.margins: _margins anchors.left: parent.left anchors.top: leakPinLabel.bottom - text: qsTr("Logic:") + text: qsTr("Logic (when dry):") } FactComboBox { diff --git a/src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml b/src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml index 7bab272be5f2bddd208df850f985fc34ff7c9161..1ab63b7c4ce3df851f220f342f8c01c5ac40a10d 100644 --- a/src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml +++ b/src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml @@ -25,34 +25,6 @@ FactPanel { property Fact _armingCheck: controller.getParameterFact(-1, "ARMING_CHECK") - property string _failsafeGCSEnableText - - Component.onCompleted: { - setFailsafeGCSEnableText() - } - - Connections { - target: _failsafeGCSEnable - - onValueChanged: setFailsafeGCSEnableText() - } - - function setFailsafeGCSEnableText() { - switch (_failsafeGCSEnable.value) { - case 0: - _failsafeGCSEnableText = qsTr("Disabled") - break - case 1: - _failsafeGCSEnableText = qsTr("Always RTL") - break - case 2: - _failsafeGCSEnableText = qsTr("Continue with Mission in Auto Mode") - break - default: - _failsafeGCSEnableText = qsTr("Unknown") - } - } - Column { anchors.fill: parent @@ -63,17 +35,17 @@ FactPanel { VehicleSummaryRow { labelText: qsTr("GCS failsafe:") - valueText: _failsafeGCSEnableText + valueText: _failsafeGCSEnable.enumOrValueString } VehicleSummaryRow { labelText: qsTr("Leak failsafe:") - valueText: _failsafeLeakEnable.value ? qsTr("Enabled") : qsTr("Disabled") + valueText: _failsafeLeakEnable.enumOrValueString } VehicleSummaryRow { labelText: qsTr("Leak detector:") - valueText: _leakPin.value > 0 ? qsTr("Enabled") : qsTr("Disabled") + valueText: _leakPin.enumOrValueString } VehicleSummaryRow { diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponent.cc b/src/AutoPilotPlugins/APM/APMSensorsComponent.cc index e5933b554142c6040528b8616ef5f3b8df8aea1a..0efdf4e6ac5ad2616693ae39f61b913c93b52502 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponent.cc +++ b/src/AutoPilotPlugins/APM/APMSensorsComponent.cc @@ -62,12 +62,6 @@ QStringList APMSensorsComponent::setupCompleteChangedTriggerList(void) const // Accelerometer triggers triggers << "INS_ACCOFFS_X" << "INS_ACCOFFS_Y" << "INS_ACCOFFS_Z"; - if (_vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, QStringLiteral("INS_USE"))) { - triggers << QStringLiteral("INS_USE") << QStringLiteral("INS_USE2") << QStringLiteral("INS_USE3"); - triggers << QStringLiteral("INS_ACC2OFFS_X") << QStringLiteral("INS_ACC2OFFS_Y") << QStringLiteral("INS_ACC2OFFS_Z"); - triggers << QStringLiteral("INS_ACC3OFFS_X") << QStringLiteral("INS_ACC3OFFS_Y") << QStringLiteral("INS_ACC3OFFS_Z"); - } - return triggers; } @@ -123,39 +117,18 @@ bool APMSensorsComponent::compassSetupNeeded(void) const bool APMSensorsComponent::accelSetupNeeded(void) const { - QStringList rgUse; - QStringList rgOffsets; - QList rgAccels; + QStringList rgOffsets; - // We always at a minimum test the first accel + // The best we can do is test the first accel which will always be there. We don't have enough information to know + // whether any of the other accels are available. rgOffsets << QStringLiteral("INS_ACCOFFS_X") << QStringLiteral("INS_ACCOFFS_Y") << QStringLiteral("INS_ACCOFFS_Z"); - rgAccels << rgOffsets; - rgOffsets.clear(); - - // This parameter is not available in all firmware version. Specifically missing from older Solo firmware. - if (_vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, QStringLiteral("INS_USE"))) { - rgUse << QStringLiteral("INS_USE") << QStringLiteral("INS_USE2") << QStringLiteral("INS_USE3"); - - // We have usage information for the remaining accels, so we can test them sa well - rgOffsets << QStringLiteral("INS_ACC2OFFS_X") << QStringLiteral("INS_ACC2OFFS_Y") << QStringLiteral("INS_ACC2OFFS_Z"); - rgAccels << rgOffsets; - rgOffsets.clear(); - - rgOffsets << QStringLiteral("INS_ACC3OFFS_X") << QStringLiteral("INS_ACC3OFFS_Y") << QStringLiteral("INS_ACC3OFFS_Z"); - rgAccels << rgOffsets; - rgOffsets.clear(); - } - for (int i=0; iparameterManager()->getParameter(FactSystem::defaultComponentId, rgUse[i])->rawValue().toInt() != 0) { - for (int j=0; jparameterManager()->getParameter(FactSystem::defaultComponentId, rgAccels[i][j])->rawValue().toFloat() == 0.0f) { - return true; - } - } + int zeroCount = 0; + for (int i=0; iparameterManager()->getParameter(FactSystem::defaultComponentId, rgOffsets[i])->rawValue().toFloat() == 0.0f) { + zeroCount++; } } - return false; + return zeroCount == rgOffsets.count(); } - diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponent.qml b/src/AutoPilotPlugins/APM/APMSensorsComponent.qml index bb87f6985f408875725ee5f8afd3d805b9d7e526..1f328647edbdc01adb929a6255b9524e244c4351 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponent.qml +++ b/src/AutoPilotPlugins/APM/APMSensorsComponent.qml @@ -14,12 +14,14 @@ import QtQuick.Controls.Styles 1.2 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.2 +import QGroundControl 1.0 import QGroundControl.FactSystem 1.0 import QGroundControl.FactControls 1.0 import QGroundControl.Palette 1.0 import QGroundControl.Controls 1.0 import QGroundControl.ScreenTools 1.0 import QGroundControl.Controllers 1.0 +import QGroundControl.ArduPilot 1.0 SetupPage { id: sensorsPage @@ -29,8 +31,8 @@ SetupPage { id: sensorsPageComponent RowLayout { - width: 1000//availableWidth - height: 1000//availableHeight + width: availableWidth + height: availableHeight spacing: ScreenTools.defaultFontPixelWidth / 2 // Help text which is shown both in the status text area prior to pressing a cal button and in the @@ -62,49 +64,12 @@ SetupPage { readonly property int rotationColumnWidth: 250 - property Fact compass1Id: controller.getParameterFact(-1, "COMPASS_DEV_ID") - property Fact compass2Id: controller.getParameterFact(-1, "COMPASS_DEV_ID2") - property Fact compass3Id: controller.getParameterFact(-1, "COMPASS_DEV_ID3") - property Fact compass1ExternalFact: controller.getParameterFact(-1, "COMPASS_EXTERNAL") - property Fact compass1Rot: controller.getParameterFact(-1, "COMPASS_ORIENT") - - property Fact boardRot: controller.getParameterFact(-1, "AHRS_ORIENTATION") - - property bool accelCalNeeded: controller.accelSetupNeeded - property bool compassCalNeeded: controller.compassSetupNeeded - + property Fact noFact: Fact { } - // The following parameters are not available in olders firmwares + property bool accelCalNeeded: controller.accelSetupNeeded + property bool compassCalNeeded: controller.compassSetupNeeded - property bool compass2ExternalParamAvailable: controller.parameterExists(-1, "COMPASS_EXTERN2") - property bool compass3ExternalParamAvailable: controller.parameterExists(-1, "COMPASS_EXTERN3") - property bool compass2RotParamAvailable: controller.parameterExists(-1, "COMPASS_ORIENT2") - property bool compass3RotParamAvailable: controller.parameterExists(-1, "COMPASS_ORIENT3") - property bool compass1UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE") - property bool compass2UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE2") - property bool compass3UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE3") - - property Fact noFact: Fact { } - property Fact compass2ExternalFact: compass2ExternalParamAvailable ? controller.getParameterFact(-1, "COMPASS_EXTERN2") : noFact - property Fact compass3ExternalFact: compass3ExternalParamAvailable ? controller.getParameterFact(-1, "COMPASS_EXTERN3") : noFact - property Fact compass2Rot: compass2RotParamAvailable ? controller.getParameterFact(-1, "COMPASS_ORIENT2") : noFact - property Fact compass3Rot: compass3RotParamAvailable ? controller.getParameterFact(-1, "COMPASS_ORIENT3") : noFact - property Fact compass1UseFact: compass1UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE") : noFact - property Fact compass2UseFact: compass2UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE2") : noFact - property Fact compass3UseFact: compass3UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE3") : noFact - - // We track these values by binding through a separate property so we can handle missing params - property bool compass1External: compass1ExternalFact.value - property bool compass2External: compass2ExternalParamAvailable ? compass2ExternalFact.value : false // false: Simulate internal so we don't show rotation combos - property bool compass3External: compass3ExternalParamAvailable ? compass3ExternalFact.value : false // false: Simulate internal so we don't show rotation combos - property bool compass1Use: compass1UseParamAvailable ? compass1UseFact.value : true - property bool compass2Use: compass2UseParamAvailable ? compass2UseFact.value : true - property bool compass3Use: compass3UseParamAvailable ? compass3UseFact.value : true - - // Id > = signals compass available, rot < 0 signals internal compass - property bool showCompass1: compass1Id.value > 0 - property bool showCompass2: compass2Id.value > 0 - property bool showCompass3: compass3Id.value > 0 + property Fact boardRot: controller.getParameterFact(-1, "AHRS_ORIENTATION") readonly property int _calTypeCompass: 1 ///< Calibrate compass readonly property int _calTypeAccel: 2 ///< Calibrate accel @@ -114,13 +79,6 @@ SetupPage { property string _orientationDialogHelp: orientationHelpSet property int _orientationDialogCalType - function validCompassOffsets(compassParamPrefix) { - var ofsX = controller.getParameterFact(-1, compassParamPrefix + "X") - var ofsY = controller.getParameterFact(-1, compassParamPrefix + "Y") - var ofsZ = controller.getParameterFact(-1, compassParamPrefix + "Z") - return Math.sqrt(ofsX.value^2 + ofsY.value^2 + ofsZ.value^2) < 600 - } - function showOrientationsDialog(calType) { var dialogTitle var buttons = StandardButton.Ok @@ -149,6 +107,11 @@ SetupPage { showDialog(orientationsDialogComponent, dialogTitle, qgcView.showDialogDefaultWidth, buttons) } + APMSensorParams { + id: sensorParams + factPanelController: controller + } + APMSensorsComponentController { id: controller factPanel: sensorsPage.viewPanel @@ -157,11 +120,15 @@ SetupPage { compassButton: compassButton accelButton: accelButton compassMotButton: motorInterferenceButton + levelButton: levelHorizonButton + calibratePressureButton: calibratePressureButton nextButton: nextButton cancelButton: cancelButton setOrientationsButton: setOrientationsButton orientationCalAreaHelpText: orientationCalAreaHelpText + property var rgCompassCalFitness: [ controller.compass1CalFitness, controller.compass2CalFitness, controller.compass3CalFitness ] + onResetStatusTextArea: statusLog.text = statusTextAreaDefaultText onWaitingForCancelChanged: { @@ -173,43 +140,16 @@ SetupPage { } onCalibrationComplete: { - if (_orientationDialogCalType == _calTypeAccel) { - _postCalibrationDialogText = qsTr("Accelerometer calibration complete.") - _postCalibrationDialogParams = [ "INS_ACCSCAL_X", "INS_ACCSCAL_Y", "INS_ACCSCAL_Z", - "INS_ACC2SCAL_X", "INS_ACC2SCAL_Y", "INS_ACC2SCAL_Z", - "INS_ACC3SCAL_X", "INS_ACC3SCAL_Y", "INS_ACC3SCAL_Z", - "INS_GYROFFS_X", "INS_GYROFFS_Y", "INS_GYROFFS_Z", - "INS_GYR2OFFS_X", "INS_GYR2OFFS_Y", "INS_GYR2OFFS_Z", - "INS_GYR3OFFS_X", "INS_GYR3OFFS_Y", "INS_GYR3OFFS_Z" ] - showDialog(postCalibrationDialogComponent, qsTr("Calibration complete"), qgcView.showDialogDefaultWidth, StandardButton.Ok) - } else if (_orientationDialogCalType == _calTypeCompass) { - _postCalibrationDialogText = qsTr("Compass calibration complete. ") - _postCalibrationDialogParams = []; - if (compass1Id.value > 0) { - if (!validCompassOffsets("COMPASS_OFS_")) { - _postCalibrationDialogText += _badCompassCalText.replace("%1", 1) - } - _postCalibrationDialogParams.push("COMPASS_OFS_X") - _postCalibrationDialogParams.push("COMPASS_OFS_Y") - _postCalibrationDialogParams.push("COMPASS_OFS_Z") - } - if (compass2Id.value > 0) { - if (!validCompassOffsets("COMPASS_OFS_")) { - _postCalibrationDialogText += _badCompassCalText.replace("%1", 2) - } - _postCalibrationDialogParams.push("COMPASS_OFS2_X") - _postCalibrationDialogParams.push("COMPASS_OFS2_Y") - _postCalibrationDialogParams.push("COMPASS_OFS2_Z") - } - if (compass3Id.value > 0) { - if (!validCompassOffsets("COMPASS_OFS_")) { - _postCalibrationDialogText += _badCompassCalText.replace("%1", 3) - } - _postCalibrationDialogParams.push("COMPASS_OFS3_X") - _postCalibrationDialogParams.push("COMPASS_OFS3_Y") - _postCalibrationDialogParams.push("COMPASS_OFS3_Z") - } - showDialog(postCalibrationDialogComponent, qsTr("Calibration complete"), qgcView.showDialogDefaultWidth, StandardButton.Ok) + switch (calType) { + case APMSensorsComponentController.CalTypeAccel: + showMessage(qsTr("Calibration complete"), qsTr("Accelerometer calibration complete."), StandardButton.Ok) + break + case APMSensorsComponentController.CalTypeOffboardCompass: + showMessage(qsTr("Calibration complete"), qsTr("Compass calibration complete."), StandardButton.Ok) + break + case APMSensorsComponentController.CalTypeOnboardCompass: + showDialog(postOnboardCompassCalibrationComponent, qsTr("Calibration complete"), qgcView.showDialogDefaultWidth, StandardButton.Ok) + break } } } @@ -217,51 +157,151 @@ SetupPage { Component.onCompleted: { var usingUDP = controller.usingUDPLink() if (usingUDP) { - console.log("onUsingUDPLink") - showMessage("Sensor Calibration", "Performing sensor calibration over a WiFi connection is known to be unreliable. You should disconnect and perform calibration using a direct USB connection instead.", StandardButton.Ok) + showMessage("Sensor Calibration", "Performing sensor calibration over a WiFi connection can be unreliable. If you run into problems try using a direct USB connection instead.", StandardButton.Ok) } } QGCPalette { id: qgcPal; colorGroupEnabled: true } Component { - id: postCalibrationDialogComponent + id: singleCompassOnboardResultsComponent - QGCViewDialog { - QGCLabel { - id: textLabel + Column { + anchors.left: parent.left + anchors.right: parent.right + spacing: Math.round(ScreenTools.defaultFontPixelHeight / 2) + visible: sensorParams.rgCompassAvailable[index] + + property real greenMaxThreshold: 8 * (sensorParams.rgCompassExternal[index] ? 1 : 2) + property real yellowMaxThreshold: 15 * (sensorParams.rgCompassExternal[index] ? 1 : 2) + property real fitnessRange: 25 * (sensorParams.rgCompassExternal[index] ? 1 : 2) + + Item { anchors.left: parent.left anchors.right: parent.right - wrapMode: Text.WordWrap - text: _postCalibrationDialogText + height: ScreenTools.defaultFontPixelHeight + + Row { + id: fitnessRow + anchors.fill: parent + + Rectangle { + width: parent.width * (greenMaxThreshold / fitnessRange) + height: parent.height + color: "green" + } + Rectangle { + width: parent.width * ((yellowMaxThreshold - greenMaxThreshold) / fitnessRange) + height: parent.height + color: "yellow" + } + Rectangle { + width: parent.width * ((fitnessRange - yellowMaxThreshold) / fitnessRange) + height: parent.height + color: "red" + } + } + + Rectangle { + height: fitnessRow.height * 0.66 + width: height + anchors.verticalCenter: fitnessRow.verticalCenter + x: (fitnessRow.width * (Math.min(Math.max(controller.rgCompassCalFitness[index], 0.0), fitnessRange) / fitnessRange)) - (width / 2) + radius: height / 2 + color: "white" + border.color: "black" + } + } + + Column { + anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2 + anchors.left: parent.left + anchors.right: parent.right + spacing: Math.round(ScreenTools.defaultFontPixelHeight / 4) + + QGCLabel { + text: "Compass " + (index+1) + " " + + (sensorParams.rgCompassPrimary[index] ? "(primary" : "(secondary") + + (sensorParams.rgCompassExternalParamAvailable[index] ? + (sensorParams.rgCompassExternal[index] ? ", external" : ", internal" ) : + "") + + ")" + } + + FactCheckBox { + text: "Use Compass" + fact: sensorParams.rgCompassUseFact[index] + visible: sensorParams.rgCompassUseParamAvailable[index] && !sensorParams.rgCompassPrimary[index] + } } + } + } + + Component { + id: postOnboardCompassCalibrationComponent - QGCCheckBox { - id: showValues - anchors.topMargin: ScreenTools.defaultFontPixelHeight - anchors.top: textLabel.bottom - text: qsTr("Show values") + QGCViewDialog { + Column { + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelHeight + + Repeater { + model: 3 + delegate: singleCompassOnboardResultsComponent + } + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: qsTr("Shown in the indicator bars is the quality of the calibration for each compass.\n\n") + + qsTr("- Green indicates a well functioning compass.\n") + + qsTr("- Yellow indicates a questionable compass or calibration.\n") + + qsTr("- Red indicates a compass which should not be used.\n\n") + + qsTr("YOU MUST REBOOT YOUR VEHICLE AFTER EACH CALIBRATION.") + } } + } + } - QGCFlickable { - anchors.topMargin: ScreenTools.defaultFontPixelHeight - anchors.top: showValues.bottom - anchors.bottom: parent.bottom - contentHeight: valueColumn.height - flickableDirection: Flickable.VerticalFlick - visible: showValues.checked + Component { + id: singleCompassSettingsComponent - Column { - id: valueColumn + Column { + spacing: Math.round(ScreenTools.defaultFontPixelHeight / 2) + visible: sensorParams.rgCompassAvailable[index] - Repeater { - model: _postCalibrationDialogParams + QGCLabel { + text: "Compass " + (index+1) + " " + + (sensorParams.rgCompassPrimary[index] ? "(primary" : "(secondary") + + (sensorParams.rgCompassExternalParamAvailable[index] ? + (sensorParams.rgCompassExternal[index] ? ", external" : ", internal" ) : + "") + + ")" + } - QGCLabel { - text: fact.name +": " + fact.valueString + Column { + anchors.margins: ScreenTools.defaultFontPixelWidth * 2 + anchors.left: parent.left + spacing: Math.round(ScreenTools.defaultFontPixelHeight / 4) - property Fact fact: controller.getParameterFact(-1, modelData) - } + FactCheckBox { + text: "Use Compass" + fact: sensorParams.rgCompassUseFact[index] + visible: sensorParams.rgCompassUseParamAvailable[index] && !sensorParams.rgCompassPrimary[index] + } + + Column { + visible: sensorParams.rgCompassExternal[index] && sensorParams.rgCompassRotParamAvailable[index] + + QGCLabel { text: qsTr("Orientation:") } + + FactComboBox { + width: rotationColumnWidth + indexModel: false + fact: sensorParams.rgCompassRotFact[index] } } } @@ -303,9 +343,7 @@ SetupPage { } Column { - QGCLabel { - text: qsTr("Autopilot Orientation:") - } + QGCLabel { text: qsTr("Autopilot Orientation:") } FactComboBox { width: rotationColumnWidth @@ -314,73 +352,9 @@ SetupPage { } } - Column { - visible: _orientationsDialogShowCompass && showCompass1 - - FactCheckBox { - text: "Use Compass 1" - fact: compass1UseFact - } - - Column { - visible: showCompass1Rot - - QGCLabel { - text: qsTr("Compass 1 Orientation:") - } - - FactComboBox { - width: rotationColumnWidth - indexModel: false - fact: compass1Rot - } - } - } - - Column { - visible: _orientationsDialogShowCompass && showCompass2 - - FactCheckBox { - text: "Use Compass 2" - fact: compass2UseFact - } - - Column { - visible: showCompass1Rot - - QGCLabel { - text: qsTr("Compass 2 Orientation:") - } - - FactComboBox { - width: rotationColumnWidth - indexModel: false - fact: compass2Rot - } - } - } - - Column { - visible: _orientationsDialogShowCompass && showCompass3 - - FactCheckBox { - text: "Use Compass 3" - fact: compass3UseFact - } - - Column { - visible: showCompass3Rot - - QGCLabel { - text: qsTr("Compass 3 Orientation:") - } - - FactComboBox { - width: rotationColumnWidth - indexModel: false - fact: compass3Rot - } - } + Repeater { + model: _orientationsDialogShowCompass ? 3 : 0 + delegate: singleCompassSettingsComponent } } // Column } // QGCFlickable @@ -453,6 +427,47 @@ SetupPage { } // QGCViewDialog } // Component - compassMotDialogComponent + Component { + id: levelHorizonDialogComponent + + QGCViewDialog { + id: levelHorizonDialog + + function accept() { + controller.levelHorizon() + levelHorizonDialog.hideDialog() + } + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: qsTr("To level the horizon you need to place the vehicle in its level flight position and press Ok.") + } + } // QGCViewDialog + } // Component - levelHorizonDialogComponent + + Component { + id: calibratePressureDialogComponent + + QGCViewDialog { + id: calibratePressureDialog + + function accept() { + controller.calibratePressure() + calibratePressureDialog.hideDialog() + } + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: qsTr("Pressure calibration will set the depth to zero at the current pressure reading.") + } + } // QGCViewDialog + } // Component - calibratePressureDialogComponent + + /// Left button column Column { spacing: ScreenTools.defaultFontPixelHeight / 2 Layout.alignment: Qt.AlignLeft | Qt.AlignTop @@ -483,10 +498,44 @@ SetupPage { } } + QGCButton { + id: levelHorizonButton + width: parent.buttonWidth + text: _levelHorizonText + + readonly property string _levelHorizonText: qsTr("Level Horizon") + + onClicked: { + if (controller.accelSetupNeeded) { + showMessage(_levelHorizonText, qsTr("Accelerometer must be calibrated prior to Level Horizon."), StandardButton.Ok) + } else { + showDialog(levelHorizonDialogComponent, _levelHorizonText, qgcView.showDialogDefaultWidth, StandardButton.Cancel | StandardButton.Ok) + } + } + } + + QGCButton { + id: calibratePressureButton + width: parent.buttonWidth + text: _calibratePressureText + visible: _activeVehicle ? _activeVehicle.supportsCalibratePressure : false + + readonly property string _calibratePressureText: qsTr("Calibrate Pressure") + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + + onClicked: { + showDialog(calibratePressureDialogComponent, _calibratePressureText, qgcView.showDialogDefaultWidth, StandardButton.Cancel | StandardButton.Ok) + } + } + QGCButton { id: motorInterferenceButton width: parent.buttonWidth text: qsTr("CompassMot") + visible: _activeVehicle ? _activeVehicle.supportsMotorInterference : false + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + onClicked: showDialog(compassMotDialogComponent, qsTr("CompassMot - Compass Motor Interference Calibration"), qgcView.showDialogFullWidth, StandardButton.Cancel | StandardButton.Ok) } @@ -514,6 +563,7 @@ SetupPage { } } // Column - Buttons + /// Right column - cal area Column { anchors.top: parent.top anchors.bottom: parent.bottom diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponentController.cc b/src/AutoPilotPlugins/APM/APMSensorsComponentController.cc index c887663043e0d0d9d0dbf2c48abe3b350f0be06d..c951904a0fbc1a5a89cbb896dfb987fb63e78684 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponentController.cc +++ b/src/AutoPilotPlugins/APM/APMSensorsComponentController.cc @@ -19,45 +19,49 @@ #include QGC_LOGGING_CATEGORY(APMSensorsComponentControllerLog, "APMSensorsComponentControllerLog") - -APMSensorsComponentController::APMSensorsComponentController(void) : - _statusLog(NULL), - _progressBar(NULL), - _compassButton(NULL), - _accelButton(NULL), - _compassMotButton(NULL), - _nextButton(NULL), - _cancelButton(NULL), - _setOrientationsButton(NULL), - _showOrientationCalArea(false), - _magCalInProgress(false), - _accelCalInProgress(false), - _compassMotCalInProgress(false), - _orientationCalDownSideDone(false), - _orientationCalUpsideDownSideDone(false), - _orientationCalLeftSideDone(false), - _orientationCalRightSideDone(false), - _orientationCalNoseDownSideDone(false), - _orientationCalTailDownSideDone(false), - _orientationCalDownSideVisible(false), - _orientationCalUpsideDownSideVisible(false), - _orientationCalLeftSideVisible(false), - _orientationCalRightSideVisible(false), - _orientationCalNoseDownSideVisible(false), - _orientationCalTailDownSideVisible(false), - _orientationCalDownSideInProgress(false), - _orientationCalUpsideDownSideInProgress(false), - _orientationCalLeftSideInProgress(false), - _orientationCalRightSideInProgress(false), - _orientationCalNoseDownSideInProgress(false), - _orientationCalTailDownSideInProgress(false), - _orientationCalDownSideRotate(false), - _orientationCalUpsideDownSideRotate(false), - _orientationCalLeftSideRotate(false), - _orientationCalRightSideRotate(false), - _orientationCalNoseDownSideRotate(false), - _orientationCalTailDownSideRotate(false), - _waitingForCancel(false) +QGC_LOGGING_CATEGORY(APMSensorsComponentControllerVerboseLog, "APMSensorsComponentControllerVerboseLog") + +const char* APMSensorsComponentController::_compassCalFitnessParam = "COMPASS_CAL_FIT"; + +APMSensorsComponentController::APMSensorsComponentController(void) + : _statusLog(NULL) + , _progressBar(NULL) + , _compassButton(NULL) + , _accelButton(NULL) + , _compassMotButton(NULL) + , _levelButton(NULL) + , _calibratePressureButton(NULL) + , _nextButton(NULL) + , _cancelButton(NULL) + , _setOrientationsButton(NULL) + , _showOrientationCalArea(false) + , _calTypeInProgress(CalTypeNone) + , _orientationCalDownSideDone(false) + , _orientationCalUpsideDownSideDone(false) + , _orientationCalLeftSideDone(false) + , _orientationCalRightSideDone(false) + , _orientationCalNoseDownSideDone(false) + , _orientationCalTailDownSideDone(false) + , _orientationCalDownSideVisible(false) + , _orientationCalUpsideDownSideVisible(false) + , _orientationCalLeftSideVisible(false) + , _orientationCalRightSideVisible(false) + , _orientationCalNoseDownSideVisible(false) + , _orientationCalTailDownSideVisible(false) + , _orientationCalDownSideInProgress(false) + , _orientationCalUpsideDownSideInProgress(false) + , _orientationCalLeftSideInProgress(false) + , _orientationCalRightSideInProgress(false) + , _orientationCalNoseDownSideInProgress(false) + , _orientationCalTailDownSideInProgress(false) + , _orientationCalDownSideRotate(false) + , _orientationCalUpsideDownSideRotate(false) + , _orientationCalLeftSideRotate(false) + , _orientationCalRightSideRotate(false) + , _orientationCalNoseDownSideRotate(false) + , _orientationCalTailDownSideRotate(false) + , _waitingForCancel(false) + , _restoreCompassCalFitness(false) { _compassCal.setVehicle(_vehicle); connect(&_compassCal, &APMCompassCal::vehicleTextMessage, this, &APMSensorsComponentController::_handleUASTextMessage); @@ -66,6 +70,13 @@ APMSensorsComponentController::APMSensorsComponentController(void) : _sensorsComponent = apmPlugin->sensorsComponent(); connect(_sensorsComponent, &VehicleComponent::setupCompleteChanged, this, &APMSensorsComponentController::setupNeededChanged); + + connect(qgcApp()->toolbox()->mavlinkProtocol(), &MAVLinkProtocol::messageReceived, this, &APMSensorsComponentController::_mavlinkMessageReceived); +} + +APMSensorsComponentController::~APMSensorsComponentController() +{ + _restorePreviousCompassCalFitness(); } /// Appends the specified text to the status log area in the ui @@ -90,11 +101,13 @@ void APMSensorsComponentController::_startLogCalibration(void) _compassButton->setEnabled(false); _accelButton->setEnabled(false); _compassMotButton->setEnabled(false); + _levelButton->setEnabled(false); + _calibratePressureButton->setEnabled(false); _setOrientationsButton->setEnabled(false); - if (_accelCalInProgress || _compassMotCalInProgress) { + if (_calTypeInProgress == CalTypeAccel || _calTypeInProgress == CalTypeCompassMot) { _nextButton->setEnabled(true); } - _cancelButton->setEnabled(false); + _cancelButton->setEnabled(_calTypeInProgress == CalTypeOnboardCompass); } void APMSensorsComponentController::_startVisualCalibration(void) @@ -102,6 +115,8 @@ void APMSensorsComponentController::_startVisualCalibration(void) _compassButton->setEnabled(false); _accelButton->setEnabled(false); _compassMotButton->setEnabled(false); + _levelButton->setEnabled(false); + _calibratePressureButton->setEnabled(false); _setOrientationsButton->setEnabled(false); _cancelButton->setEnabled(true); @@ -145,13 +160,22 @@ void APMSensorsComponentController::_stopCalibration(APMSensorsComponentControll _compassButton->setEnabled(true); _accelButton->setEnabled(true); _compassMotButton->setEnabled(true); + _levelButton->setEnabled(true); + _calibratePressureButton->setEnabled(true); _setOrientationsButton->setEnabled(true); _nextButton->setEnabled(false); _cancelButton->setEnabled(false); + if (_calTypeInProgress == CalTypeOnboardCompass) { + _restorePreviousCompassCalFitness(); + } + if (code == StopCalibrationSuccess) { _resetInternalState(); _progressBar->setProperty("value", 1); + if (parameterExists(FactSystem::defaultComponentId, QStringLiteral("COMPASS_LEARN"))) { + getParameterFact(FactSystem::defaultComponentId, QStringLiteral("COMPASS_LEARN"))->setRawValue(0); + } } else { _progressBar->setProperty("value", 0); } @@ -165,7 +189,11 @@ void APMSensorsComponentController::_stopCalibration(APMSensorsComponentControll case StopCalibrationSuccess: _orientationCalAreaHelpText->setProperty("text", "Calibration complete"); emit resetStatusTextArea(); - emit calibrationComplete(); + emit calibrationComplete(_calTypeInProgress); + break; + + case StopCalibrationSuccessShowLog: + emit calibrationComplete(_calTypeInProgress); break; case StopCalibrationCancelled: @@ -180,20 +208,95 @@ void APMSensorsComponentController::_stopCalibration(APMSensorsComponentControll break; } - _magCalInProgress = false; - _accelCalInProgress = false; - _compassMotCalInProgress = false; + _calTypeInProgress = CalTypeNone; +} + +void APMSensorsComponentController::_mavCommandResult(int vehicleId, int component, int command, int result, bool noReponseFromVehicle) +{ + Q_UNUSED(component); + Q_UNUSED(noReponseFromVehicle); + + if (_vehicle->id() != vehicleId) { + return; + } + + if (command == MAV_CMD_DO_CANCEL_MAG_CAL) { + disconnect(_vehicle, &Vehicle::mavCommandResult, this, &APMSensorsComponentController::_mavCommandResult); + if (result == MAV_RESULT_ACCEPTED) { + // Onboard mag cal is supported + _calTypeInProgress = CalTypeOnboardCompass; + _rgCompassCalProgress[0] = 0; + _rgCompassCalProgress[1] = 0; + _rgCompassCalProgress[2] = 0; + _rgCompassCalComplete[0] = false; + _rgCompassCalComplete[1] = false; + _rgCompassCalComplete[2] = false; + + _startLogCalibration(); + uint8_t compassBits = 0; + if (getParameterFact(FactSystem::defaultComponentId, "COMPASS_DEV_ID")->rawValue().toInt() > 0) { + compassBits |= 1 << 0; + qCDebug(APMSensorsComponentControllerLog) << "Performing onboard compass cal for compass 1"; + } else { + _rgCompassCalComplete[0] = true; + _rgCompassCalSucceeded[0] = true; + _rgCompassCalFitness[0] = 0; + } + if (getParameterFact(FactSystem::defaultComponentId, "COMPASS_DEV_ID2")->rawValue().toInt() > 0) { + compassBits |= 1 << 1; + qCDebug(APMSensorsComponentControllerLog) << "Performing onboard compass cal for compass 2"; + } else { + _rgCompassCalComplete[1] = true; + _rgCompassCalSucceeded[1] = true; + _rgCompassCalFitness[1] = 0; + } + if (getParameterFact(FactSystem::defaultComponentId, "COMPASS_DEV_ID3")->rawValue().toInt() > 0) { + compassBits |= 1 << 2; + qCDebug(APMSensorsComponentControllerLog) << "Performing onboard compass cal for compass 3"; + } else { + _rgCompassCalComplete[2] = true; + _rgCompassCalSucceeded[2] = true; + _rgCompassCalFitness[2] = 0; + } + + // We bump up the fitness value so calibration will always succeed + Fact* compassCalFitness = getParameterFact(FactSystem::defaultComponentId, _compassCalFitnessParam); + _restoreCompassCalFitness = true; + _previousCompassCalFitness = compassCalFitness->rawValue().toFloat(); + getParameterFact(FactSystem::defaultComponentId, _compassCalFitnessParam)->setRawValue(100.0); + + _appendStatusLog(tr("Rotate the vehicle randomly around all axes until the progress bar fills all the way to the right .")); + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), + MAV_CMD_DO_START_MAG_CAL, + true, // showError + compassBits, // which compass(es) to calibrate + 0, // no retry on failure + 1, // save values after complete + 0, // no delayed start + 0); // no auto-reboot + + } else { + // Onboard mag cal is not supported + _compassCal.startCalibration(); + } + } else if (command == MAV_CMD_DO_START_MAG_CAL && result != MAV_RESULT_ACCEPTED) { + _restorePreviousCompassCalFitness(); + } } void APMSensorsComponentController::calibrateCompass(void) { - _startLogCalibration(); - _compassCal.startCalibration(); + // First we need to determine if the vehicle support onboard compass cal. There isn't an easy way to + // do this. A hack is to send the mag cancel command and see if it is accepted. + connect(_vehicle, &Vehicle::mavCommandResult, this, &APMSensorsComponentController::_mavCommandResult); + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), MAV_CMD_DO_CANCEL_MAG_CAL, false /* showError */); + + // Now we wait for the result to come back } void APMSensorsComponentController::calibrateAccel(void) { - _accelCalInProgress = true; + _calTypeInProgress = CalTypeAccel; _vehicle->setConnectionLostEnabled(false); _startLogCalibration(); _uas->startCalibration(UASInterface::StartCalibrationAccel); @@ -201,7 +304,7 @@ void APMSensorsComponentController::calibrateAccel(void) void APMSensorsComponentController::calibrateMotorInterference(void) { - _compassMotCalInProgress = true; + _calTypeInProgress = CalTypeCompassMot; _vehicle->setConnectionLostEnabled(false); _startLogCalibration(); _appendStatusLog(tr("Raise the throttle slowly to between 50% ~ 75% (the props will spin!) for 5 ~ 10 seconds.")); @@ -210,6 +313,24 @@ void APMSensorsComponentController::calibrateMotorInterference(void) _uas->startCalibration(UASInterface::StartCalibrationCompassMot); } +void APMSensorsComponentController::levelHorizon(void) +{ + _calTypeInProgress = CalTypeLevelHorizon; + _vehicle->setConnectionLostEnabled(false); + _startLogCalibration(); + _appendStatusLog(tr("Hold the vehicle in its level flight position.")); + _uas->startCalibration(UASInterface::StartCalibrationLevel); +} + +void APMSensorsComponentController::calibratePressure(void) +{ + _calTypeInProgress = CalTypePressure; + _vehicle->setConnectionLostEnabled(false); + _startLogCalibration(); + _appendStatusLog(tr("Requesting pressure calibration...")); + _uas->startCalibration(UASInterface::StartCalibrationPressure); +} + void APMSensorsComponentController::_handleUASTextMessage(int uasId, int compId, int severity, QString text) { Q_UNUSED(compId); @@ -228,8 +349,7 @@ void APMSensorsComponentController::_handleUASTextMessage(int uasId, int compId, QString percent = text.split("<").last().split(">").first(); bool ok; int p = percent.toInt(&ok); - if (ok) { - Q_ASSERT(_progressBar); + if (ok && _progressBar) { _progressBar->setProperty("value", (float)(p / 100.0)); } return; @@ -293,7 +413,7 @@ void APMSensorsComponentController::_handleUASTextMessage(int uasId, int compId, _orientationCalAreaHelpText->setProperty("text", "Place your vehicle into one of the Incomplete orientations shown below and hold it still"); if (text == "accel") { - _accelCalInProgress = true; + _calTypeInProgress = CalTypeAccel; _orientationCalDownSideVisible = true; _orientationCalUpsideDownSideVisible = true; _orientationCalLeftSideVisible = true; @@ -301,7 +421,7 @@ void APMSensorsComponentController::_handleUASTextMessage(int uasId, int compId, _orientationCalTailDownSideVisible = true; _orientationCalNoseDownSideVisible = true; } else if (text == "mag") { - _magCalInProgress = true; + _calTypeInProgress = CalTypeOffboardCompass; _orientationCalDownSideVisible = true; _orientationCalUpsideDownSideVisible = true; _orientationCalLeftSideVisible = true; @@ -325,37 +445,37 @@ void APMSensorsComponentController::_handleUASTextMessage(int uasId, int compId, if (side == QLatin1Literal("down")) { _orientationCalDownSideInProgress = true; - if (_magCalInProgress) { + if (_calTypeInProgress == CalTypeOffboardCompass) { _orientationCalDownSideRotate = true; } } else if (side == QLatin1Literal("up")) { _orientationCalUpsideDownSideInProgress = true; - if (_magCalInProgress) { + if (_calTypeInProgress == CalTypeOffboardCompass) { _orientationCalUpsideDownSideRotate = true; } } else if (side == QLatin1Literal("left")) { _orientationCalLeftSideInProgress = true; - if (_magCalInProgress) { + if (_calTypeInProgress == CalTypeOffboardCompass) { _orientationCalLeftSideRotate = true; } } else if (side == QLatin1Literal("right")) { _orientationCalRightSideInProgress = true; - if (_magCalInProgress) { + if (_calTypeInProgress == CalTypeOffboardCompass) { _orientationCalRightSideRotate = true; } } else if (side == QLatin1Literal("front")) { _orientationCalNoseDownSideInProgress = true; - if (_magCalInProgress) { + if (_calTypeInProgress == CalTypeOffboardCompass) { _orientationCalNoseDownSideRotate = true; } } else if (side == QLatin1Literal("back")) { _orientationCalTailDownSideInProgress = true; - if (_magCalInProgress) { + if (_calTypeInProgress == CalTypeOffboardCompass) { _orientationCalTailDownSideRotate = true; } } - if (_magCalInProgress) { + if (_calTypeInProgress == CalTypeOffboardCompass) { _orientationCalAreaHelpText->setProperty("text", "Rotate the vehicle continuously as shown in the diagram until marked as Completed"); } else { _orientationCalAreaHelpText->setProperty("text", "Hold still in the current orientation"); @@ -448,17 +568,23 @@ void APMSensorsComponentController::_hideAllCalAreas(void) void APMSensorsComponentController::cancelCalibration(void) { - _waitingForCancel = true; - emit waitingForCancelChanged(); _cancelButton->setEnabled(false); - if (_magCalInProgress) { + if (_calTypeInProgress == CalTypeOffboardCompass) { + _waitingForCancel = true; + emit waitingForCancelChanged(); _compassCal.cancelCalibration(); + } else if (_calTypeInProgress == CalTypeOnboardCompass) { + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), MAV_CMD_DO_CANCEL_MAG_CAL, true /* showError */); + _stopCalibration(StopCalibrationCancelled); } else { + _waitingForCancel = true; + emit waitingForCancelChanged(); // The firmware doesn't always allow us to cancel calibration. The best we can do is wait // for it to timeout. _uas->stopCalibration(); } + } void APMSensorsComponentController::nextClicked(void) @@ -476,7 +602,7 @@ void APMSensorsComponentController::nextClicked(void) _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); - if (_compassMotCalInProgress) { + if (_calTypeInProgress == CalTypeCompassMot) { _stopCalibration(StopCalibrationSuccess); } } @@ -495,3 +621,147 @@ bool APMSensorsComponentController::usingUDPLink(void) { return _vehicle->priorityLink()->getLinkConfiguration()->type() == LinkConfiguration::TypeUdp; } + +void APMSensorsComponentController::_handleCommandAck(mavlink_message_t& message) +{ + if (_calTypeInProgress == CalTypeLevelHorizon) { + mavlink_command_ack_t commandAck; + mavlink_msg_command_ack_decode(&message, &commandAck); + + if (commandAck.command == MAV_CMD_PREFLIGHT_CALIBRATION) { + switch (commandAck.result) { + case MAV_RESULT_ACCEPTED: + _appendStatusLog(tr("Level horizon complete")); + _stopCalibration(StopCalibrationSuccessShowLog); + break; + default: + _appendStatusLog(tr("Level horizon failed")); + _stopCalibration(StopCalibrationFailed); + break; + } + } + } + + if (_calTypeInProgress == CalTypePressure) { + mavlink_command_ack_t commandAck; + mavlink_msg_command_ack_decode(&message, &commandAck); + + if (commandAck.command == MAV_CMD_PREFLIGHT_CALIBRATION) { + switch (commandAck.result) { + case MAV_RESULT_ACCEPTED: + _appendStatusLog(tr("Pressure calibration success")); + _stopCalibration(StopCalibrationSuccessShowLog); + break; + default: + _appendStatusLog(tr("Pressure calibration fail")); + _stopCalibration(StopCalibrationFailed); + break; + } + } + } +} + +void APMSensorsComponentController::_handleMagCalProgress(mavlink_message_t& message) +{ + if (_calTypeInProgress == CalTypeOnboardCompass) { + mavlink_mag_cal_progress_t magCalProgress; + mavlink_msg_mag_cal_progress_decode(&message, &magCalProgress); + + qCDebug(APMSensorsComponentControllerVerboseLog) << "_handleMagCalProgress id:mask:pct" + << magCalProgress.compass_id << magCalProgress.cal_mask << magCalProgress.completion_pct; + + // How many compasses are we calibrating? + int compassCalCount = 0; + for (int i=0; i<3; i++) { + if (magCalProgress.cal_mask & (1 << i)) { + compassCalCount++; + } + } + + if (magCalProgress.compass_id < 3) { + // Each compass gets a portion of the overall progress + _rgCompassCalProgress[magCalProgress.compass_id] = magCalProgress.completion_pct / compassCalCount; + } + + if (_progressBar) { + _progressBar->setProperty("value", (float)(_rgCompassCalProgress[0] + _rgCompassCalProgress[1] + _rgCompassCalProgress[2]) / 100.0); + } + } +} + +void APMSensorsComponentController::_handleMagCalReport(mavlink_message_t& message) +{ + if (_calTypeInProgress == CalTypeOnboardCompass) { + mavlink_mag_cal_report_t magCalReport; + mavlink_msg_mag_cal_report_decode(&message, &magCalReport); + + qCDebug(APMSensorsComponentControllerVerboseLog) << "_handleMagCalReport id:mask:status:fitness" + << magCalReport.compass_id << magCalReport.cal_mask << magCalReport.cal_status << magCalReport.fitness; + + bool additionalCompassCompleted = false; + if (magCalReport.compass_id < 3 && !_rgCompassCalComplete[magCalReport.compass_id]) { + if (magCalReport.cal_status == MAG_CAL_SUCCESS) { + _appendStatusLog(tr("Compass %1 calibration complete").arg(magCalReport.compass_id)); + } else { + _appendStatusLog(tr("Compass %1 calibration below quality threshold").arg(magCalReport.compass_id)); + } + _rgCompassCalComplete[magCalReport.compass_id] = true; + _rgCompassCalSucceeded[magCalReport.compass_id] = magCalReport.cal_status == MAG_CAL_SUCCESS; + _rgCompassCalFitness[magCalReport.compass_id] = magCalReport.fitness; + additionalCompassCompleted = true; + } + + if (_rgCompassCalComplete[0] && _rgCompassCalComplete[1] &&_rgCompassCalComplete[2]) { + for (int i=0; i<3; i++) { + qCDebug(APMSensorsComponentControllerLog) << QString("Onboard compass call report #%1: succeed:fitness %2:%3").arg(i).arg(_rgCompassCalSucceeded[i]).arg(_rgCompassCalFitness[i]); + } + emit compass1CalFitnessChanged(_rgCompassCalFitness[0]); + emit compass2CalFitnessChanged(_rgCompassCalFitness[1]); + emit compass3CalFitnessChanged(_rgCompassCalFitness[2]); + emit compass1CalSucceededChanged(_rgCompassCalSucceeded[0]); + emit compass2CalSucceededChanged(_rgCompassCalSucceeded[1]); + emit compass3CalSucceededChanged(_rgCompassCalSucceeded[2]); + if (_rgCompassCalSucceeded[0] && _rgCompassCalSucceeded[1] && _rgCompassCalSucceeded[2]) { + _appendStatusLog(tr("All compasses calibrated successfully")); + _appendStatusLog(tr("YOU MUST REBOOT YOUR VEHICLE NOW FOR NEW SETTINGS TO TAKE AFFECT")); + _stopCalibration(StopCalibrationSuccessShowLog); + } else { + _appendStatusLog(tr("Compass calibration failed")); + _appendStatusLog(tr("YOU MUST REBOOT YOUR VEHICLE NOW AND RETRY COMPASS CALIBRATION PRIOR TO FLIGHT")); + _stopCalibration(StopCalibrationFailed); + } + } else if (additionalCompassCompleted) { + _appendStatusLog(tr("Continue rotating...")); + } + + } +} + +void APMSensorsComponentController::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message) +{ + Q_UNUSED(link); + + if (message.sysid != _vehicle->id()) { + return; + } + + switch (message.msgid) { + case MAVLINK_MSG_ID_COMMAND_ACK: + _handleCommandAck(message); + break; + case MAVLINK_MSG_ID_MAG_CAL_PROGRESS: + _handleMagCalProgress(message); + break; + case MAVLINK_MSG_ID_MAG_CAL_REPORT: + _handleMagCalReport(message); + break; + } +} + +void APMSensorsComponentController::_restorePreviousCompassCalFitness(void) +{ + if (_restoreCompassCalFitness) { + _restoreCompassCalFitness = false; + getParameterFact(FactSystem::defaultComponentId, _compassCalFitnessParam)->setRawValue(_previousCompassCalFitness); + } +} diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponentController.h b/src/AutoPilotPlugins/APM/APMSensorsComponentController.h index efd4d0338218386e00a6f3611e79ae902ce272dd..16e0fd23e48e06b08dc3157e05eec38e35876248 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponentController.h +++ b/src/AutoPilotPlugins/APM/APMSensorsComponentController.h @@ -20,6 +20,7 @@ #include "APMCompassCal.h" Q_DECLARE_LOGGING_CATEGORY(APMSensorsComponentControllerLog) +Q_DECLARE_LOGGING_CATEGORY(APMSensorsComponentControllerVerboseLog) /// Sensors Component MVC Controller for SensorsComponent.qml. class APMSensorsComponentController : public FactPanelController @@ -28,6 +29,7 @@ class APMSensorsComponentController : public FactPanelController public: APMSensorsComponentController(void); + ~APMSensorsComponentController(); Q_PROPERTY(QQuickItem* statusLog MEMBER _statusLog) Q_PROPERTY(QQuickItem* progressBar MEMBER _progressBar) @@ -35,6 +37,8 @@ public: Q_PROPERTY(QQuickItem* compassButton MEMBER _compassButton) Q_PROPERTY(QQuickItem* accelButton MEMBER _accelButton) Q_PROPERTY(QQuickItem* compassMotButton MEMBER _compassMotButton) + Q_PROPERTY(QQuickItem* levelButton MEMBER _levelButton) + Q_PROPERTY(QQuickItem* calibratePressureButton MEMBER _calibratePressureButton) Q_PROPERTY(QQuickItem* nextButton MEMBER _nextButton) Q_PROPERTY(QQuickItem* cancelButton MEMBER _cancelButton) Q_PROPERTY(QQuickItem* setOrientationsButton MEMBER _setOrientationsButton) @@ -74,17 +78,46 @@ public: Q_PROPERTY(bool orientationCalTailDownSideRotate MEMBER _orientationCalTailDownSideRotate NOTIFY orientationCalSidesRotateChanged) Q_PROPERTY(bool waitingForCancel MEMBER _waitingForCancel NOTIFY waitingForCancelChanged) - + + Q_PROPERTY(bool compass1CalSucceeded READ compass1CalSucceeded NOTIFY compass1CalSucceededChanged) + Q_PROPERTY(bool compass2CalSucceeded READ compass2CalSucceeded NOTIFY compass2CalSucceededChanged) + Q_PROPERTY(bool compass3CalSucceeded READ compass3CalSucceeded NOTIFY compass3CalSucceededChanged) + + Q_PROPERTY(double compass1CalFitness READ compass1CalFitness NOTIFY compass1CalFitnessChanged) + Q_PROPERTY(double compass2CalFitness READ compass2CalFitness NOTIFY compass2CalFitnessChanged) + Q_PROPERTY(double compass3CalFitness READ compass3CalFitness NOTIFY compass3CalFitnessChanged) + Q_INVOKABLE void calibrateCompass(void); Q_INVOKABLE void calibrateAccel(void); Q_INVOKABLE void calibrateMotorInterference(void); + Q_INVOKABLE void levelHorizon(void); + Q_INVOKABLE void calibratePressure(void); Q_INVOKABLE void cancelCalibration(void); Q_INVOKABLE void nextClicked(void); Q_INVOKABLE bool usingUDPLink(void); bool compassSetupNeeded(void) const; bool accelSetupNeeded(void) const; - + + typedef enum { + CalTypeAccel, + CalTypeOnboardCompass, + CalTypeOffboardCompass, + CalTypeLevelHorizon, + CalTypeCompassMot, + CalTypePressure, + CalTypeNone + } CalType_t; + Q_ENUM(CalType_t) + + bool compass1CalSucceeded(void) const { return _rgCompassCalSucceeded[0]; } + bool compass2CalSucceeded(void) const { return _rgCompassCalSucceeded[1]; } + bool compass3CalSucceeded(void) const { return _rgCompassCalSucceeded[2]; } + + double compass1CalFitness(void) const { return _rgCompassCalFitness[0]; } + double compass2CalFitness(void) const { return _rgCompassCalFitness[1]; } + double compass3CalFitness(void) const { return _rgCompassCalFitness[2]; } + signals: void showGyroCalAreaChanged(void); void showOrientationCalAreaChanged(void); @@ -95,11 +128,19 @@ signals: void resetStatusTextArea(void); void waitingForCancelChanged(void); void setupNeededChanged(void); - void calibrationComplete(void); - + void calibrationComplete(CalType_t calType); + void compass1CalSucceededChanged(bool compass1CalSucceeded); + void compass2CalSucceededChanged(bool compass2CalSucceeded); + void compass3CalSucceededChanged(bool compass3CalSucceeded); + void compass1CalFitnessChanged(double compass1CalFitness); + void compass2CalFitnessChanged(double compass2CalFitness); + void compass3CalFitnessChanged(double compass3CalFitness); + private slots: void _handleUASTextMessage(int uasId, int compId, int severity, QString text); - + void _mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message); + void _mavCommandResult(int vehicleId, int component, int command, int result, bool noReponseFromVehicle); + private: void _startLogCalibration(void); void _startVisualCalibration(void); @@ -107,9 +148,14 @@ private: void _refreshParams(void); void _hideAllCalAreas(void); void _resetInternalState(void); - + void _handleCommandAck(mavlink_message_t& message); + void _handleMagCalProgress(mavlink_message_t& message); + void _handleMagCalReport(mavlink_message_t& message); + void _restorePreviousCompassCalFitness(void); + enum StopCalibrationCode { StopCalibrationSuccess, + StopCalibrationSuccessShowLog, StopCalibrationFailed, StopCalibrationCancelled }; @@ -125,6 +171,8 @@ private: QQuickItem* _compassButton; QQuickItem* _accelButton; QQuickItem* _compassMotButton; + QQuickItem* _levelButton; + QQuickItem* _calibratePressureButton; QQuickItem* _nextButton; QQuickItem* _cancelButton; QQuickItem* _setOrientationsButton; @@ -132,10 +180,13 @@ private: bool _showOrientationCalArea; - bool _magCalInProgress; - bool _accelCalInProgress; - bool _compassMotCalInProgress; - + CalType_t _calTypeInProgress; + + uint8_t _rgCompassCalProgress[3]; + bool _rgCompassCalComplete[3]; + bool _rgCompassCalSucceeded[3]; + float _rgCompassCalFitness[3]; + bool _orientationCalDownSideDone; bool _orientationCalUpsideDownSideDone; bool _orientationCalLeftSideDone; @@ -165,6 +216,10 @@ private: bool _orientationCalTailDownSideRotate; bool _waitingForCancel; + + bool _restoreCompassCalFitness; + float _previousCompassCalFitness; + static const char* _compassCalFitnessParam; static const int _supportedFirmwareCalVersion = 2; }; diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponentSummary.qml b/src/AutoPilotPlugins/APM/APMSensorsComponentSummary.qml index 37d0738ff3921c893570360426a88bcff0eb1390..85bd337309c1de6fe8eedc6b0a8f8b6e27969869 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponentSummary.qml +++ b/src/AutoPilotPlugins/APM/APMSensorsComponentSummary.qml @@ -7,6 +7,7 @@ import QGroundControl.FactControls 1.0 import QGroundControl.Controls 1.0 import QGroundControl.Palette 1.0 import QGroundControl.Controllers 1.0 +import QGroundControl.ArduPilot 1.0 /* IMPORTANT NOTE: Any changes made here must also be made to SensorsComponentSummary.qml @@ -18,55 +19,35 @@ FactPanel { color: qgcPal.windowShadeDark QGCPalette { id: qgcPal; colorGroupEnabled: enabled } - APMSensorsComponentController { id: controller; factPanel: panel } - - property Fact compass1IdFact: controller.getParameterFact(-1, "COMPASS_DEV_ID") - property Fact compass2IdFact: controller.getParameterFact(-1, "COMPASS_DEV_ID2") - property Fact compass3IdFact: controller.getParameterFact(-1, "COMPASS_DEV_ID3") - - property Fact compass1OfsXFact: controller.getParameterFact(-1, "COMPASS_OFS_X") - property Fact compass1OfsYFact: controller.getParameterFact(-1, "COMPASS_OFS_Y") - property Fact compass1OfsZFact: controller.getParameterFact(-1, "COMPASS_OFS_Z") - property Fact compass2OfsXFact: controller.getParameterFact(-1, "COMPASS_OFS2_X") - property Fact compass2OfsYFact: controller.getParameterFact(-1, "COMPASS_OFS2_Y") - property Fact compass2OfsZFact: controller.getParameterFact(-1, "COMPASS_OFS2_Z") - property Fact compass3OfsXFact: controller.getParameterFact(-1, "COMPASS_OFS3_X") - property Fact compass3OfsYFact: controller.getParameterFact(-1, "COMPASS_OFS3_Y") - property Fact compass3OfsZFact: controller.getParameterFact(-1, "COMPASS_OFS3_Z") - - property bool compass1Available: compass1IdFact.value !== 0 - property bool compass2Available: compass2IdFact.value !== 0 - property bool compass3Available: compass3IdFact.value !== 0 - property bool compass1Calibrated: compass1Available ? compass1OfsXFact.value != 0.0 && compass1OfsYFact.value != 0.0 &&compass1OfsZFact.value != 0.0 : false - property bool compass2Calibrated: compass2Available ? compass2OfsXFact.value != 0.0 && compass2OfsYFact.value != 0.0 &&compass2OfsZFact.value != 0.0 : false - property bool compass3Calibrated: compass3Available ? compass3OfsXFact.value != 0.0 && compass3OfsYFact.value != 0.0 &&compass3OfsZFact.value != 0.0 : false + APMSensorsComponentController { id: controller; factPanel: panel } - property bool compassCalNeeded: controller.compassSetupNeeded + APMSensorParams { + id: sensorParams + factPanelController: controller + } Column { anchors.fill: parent - VehicleSummaryRow { - labelText: qsTr("Compass 1:") - visible: compass1Available - valueText: compass1Calibrated ? qsTr("Ready") : qsTr("Setup required") - } - - VehicleSummaryRow { - labelText: qsTr("Compass 2:") - visible: compass2Available - valueText: compass2Calibrated ? qsTr("Ready") : qsTr("Setup required") - } - - VehicleSummaryRow { - labelText: qsTr("Compass 3:") - visible: compass3Available - valueText: compass3Calibrated ? qsTr("Ready") : qsTr("Setup required") + Repeater { + model: 3 + + VehicleSummaryRow { + labelText: qsTr("Compass ") + (index + 1) + ":" + valueText: sensorParams.rgCompassAvailable[index] ? + (sensorParams.rgCompassCalibrated[index] ? + (sensorParams.rgCompassPrimary[index] ? "Primary" : "Secondary") + + (sensorParams.rgCompassExternalParamAvailable[index] ? + (sensorParams.rgCompassExternal[index] ? ", External" : ", Internal" ) : + "") : + qsTr("Setup required")) : + qsTr("Not installed") + } } VehicleSummaryRow { - labelText: qsTr("Accelerometer:") + labelText: qsTr("Accelerometer(s):") valueText: controller.accelSetupNeeded ? qsTr("Setup required") : qsTr("Ready") } } diff --git a/src/AutoPilotPlugins/APM/APMSubFrameComponent.cc b/src/AutoPilotPlugins/APM/APMSubFrameComponent.cc new file mode 100644 index 0000000000000000000000000000000000000000..9d88274446879f9136b74817f8e0426b035f7f37 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMSubFrameComponent.cc @@ -0,0 +1,71 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +/// @file +/// @author Don Gagne +/// @author Jacob Walser + +#include "APMSubFrameComponent.h" +#include "QGCQmlWidgetHolder.h" +#include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" + +APMSubFrameComponent::APMSubFrameComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) + : VehicleComponent(vehicle, autopilot, parent) + , _name(tr("Frame")) +{ +} + +QString APMSubFrameComponent::name(void) const +{ + return _name; +} + +QString APMSubFrameComponent::description(void) const +{ + return tr("Frame setup allows you to choose your vehicle's motor configuration. Install clockwise" \ + "\npropellers on the green thrusters and counter-clockwise propellers on the blue thrusters" \ + "\n(or vice-versa). The flight controller will need to be rebooted to apply changes."); +} + +QString APMSubFrameComponent::iconResource(void) const +{ + return QStringLiteral("/qmlimages/SubFrameComponentIcon.png"); +} + +bool APMSubFrameComponent::requiresSetup(void) const +{ + return false; +} + +bool APMSubFrameComponent::setupComplete(void) const +{ + return true; +} + +QStringList APMSubFrameComponent::setupCompleteChangedTriggerList(void) const +{ + return QStringList(); +} + +QUrl APMSubFrameComponent::setupSource(void) const +{ + return QUrl::fromUserInput(QStringLiteral("qrc:/qml/APMSubFrameComponent.qml")); +} + +QUrl APMSubFrameComponent::summaryQmlSource(void) const +{ + return QUrl::fromUserInput(QStringLiteral("qrc:/qml/APMSubFrameComponentSummary.qml")); +} + +QString APMSubFrameComponent::prerequisiteSetup(void) const +{ + return QString(); +} diff --git a/src/AutoPilotPlugins/APM/APMSubFrameComponent.h b/src/AutoPilotPlugins/APM/APMSubFrameComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..68b3eabb1fa89605f2096aefbb57eedd61f3381f --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMSubFrameComponent.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +#ifndef APMSubFrameComponent_H +#define APMSubFrameComponent_H + +#include "VehicleComponent.h" + +class APMSubFrameComponent : public VehicleComponent +{ + Q_OBJECT + +public: + APMSubFrameComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent = NULL); + + // Virtuals from VehicleComponent + QStringList setupCompleteChangedTriggerList(void) const final; + + // Virtuals from VehicleComponent + QString name(void) const final; + QString description(void) const final; + QString iconResource(void) const final; + bool requiresSetup(void) const final; + bool setupComplete(void) const final; + QUrl setupSource(void) const final; + QUrl summaryQmlSource(void) const final; + QString prerequisiteSetup(void) const final; + +private: + const QString _name; +}; + +#endif diff --git a/src/AutoPilotPlugins/APM/APMSubFrameComponent.qml b/src/AutoPilotPlugins/APM/APMSubFrameComponent.qml new file mode 100644 index 0000000000000000000000000000000000000000..df06fec69595a36fae33cd6ebc766a233748a4b3 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMSubFrameComponent.qml @@ -0,0 +1,151 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.2 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 + +SetupPage { + id: subFramePage + pageComponent: subFramePageComponent + + Component { + id: subFramePageComponent + + Column { + id: mainColumn + width: availableWidth + + FactPanelController { id: controller; factPanel: subFramePage.viewPanel } + + QGCPalette { id: palette; colorGroupEnabled: true } + + property Fact _frameConfig: controller.getParameterFact(-1, "FRAME_CONFIG") + + function setFrameConfig(frame) { + _frameConfig.value = frame; + } + + property real _minW: ScreenTools.defaultFontPixelWidth * 30 + property real _boxWidth: _minW + property real _boxSpace: ScreenTools.defaultFontPixelWidth + + onWidthChanged: { + computeDimensions() + } + + Component.onCompleted: computeDimensions() + + function computeDimensions() { + var sw = 0 + var rw = 0 + var idx = Math.floor(mainColumn.width / (_minW + ScreenTools.defaultFontPixelWidth)) + if(idx < 1) { + _boxWidth = mainColumn.width + _boxSpace = 0 + } else { + _boxSpace = 0 + if(idx > 1) { + _boxSpace = ScreenTools.defaultFontPixelWidth + sw = _boxSpace * (idx - 1) + } + rw = mainColumn.width - sw + _boxWidth = rw / idx + } + } + + ListModel { + id: subFrameModel + + ListElement { + name: "BlueROV1" + resource: "qrc:///qmlimages/Frames/BlueROV1.png" + paramValue: 0 + } + + ListElement { + name: "BlueROV2/Vectored" + resource: "qrc:///qmlimages/Frames/Vectored.png" + paramValue: 1 + } + + ListElement { + name: "Vectored-6DOF" + resource: "qrc:///qmlimages/Frames/Vectored6DOF.png" + paramValue: 2 + } + + ListElement { + name: "SimpleROV-3" + resource: "qrc:///qmlimages/Frames/SimpleROV-3.png" + paramValue: 4 + } + + ListElement { + name: "SimpleROV-4" + resource: "qrc:///qmlimages/Frames/SimpleROV-4.png" + paramValue: 5 + } + } + + Flow { + id: flowView + width: parent.width + spacing: _boxSpace + + Repeater { + model: subFrameModel + + Rectangle { + width: _boxWidth + height: ScreenTools.defaultFontPixelHeight * 14 + color: qgcPal.window + + QGCLabel { + id: title + text: subFrameModel.get(index).name + } + + Rectangle { + anchors.topMargin: ScreenTools.defaultFontPixelHeight / 2 + anchors.top: title.bottom + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + color: subFrameModel.get(index).paramValue == _frameConfig.value ? qgcPal.buttonHighlight: qgcPal.windowShade + + Image { + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: true + source: subFrameModel.get(index).resource + } + + MouseArea { + anchors.fill: parent + onClicked: setFrameConfig(subFrameModel.get(index).paramValue) + } + } + } + }// Repeater + }// Flow + } // Column + } // Component +} // SetupPage diff --git a/src/AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml b/src/AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml new file mode 100644 index 0000000000000000000000000000000000000000..e2b33b2fa14f8724eedafd11a9167bfeaa24a7ff --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml @@ -0,0 +1,62 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.2 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Controllers 1.0 +import QGroundControl.Palette 1.0 + +FactPanel { + id: panel + anchors.fill: parent + color: qgcPal.windowShadeDark + + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + + FactPanelController { id: controller; factPanel: panel } + + property Fact frameFact: controller.getParameterFact(-1, "FRAME_CONFIG") + + function frameName() { + switch(frameFact.value) { + case 0: + return "BlueROV1" + case 1: + return "Vectored/BlueROV2" + case 2: + return "Vectored 6DOF" + case 3: + return "Vectored 6DOF 90Degree" + case 4: + return "SimpleROV-3" + case 5: + return "SimpleROV-4" + case 6: + return "SimpleROV-5" + case 7: + return "Custom" + default: + return "Unknown" + } + } + + Column { + anchors.fill: parent + VehicleSummaryRow { + id: nameRow; + labelText: qsTr("Frame Type:") + valueText: frameName() + } + + VehicleSummaryRow { + labelText: qsTr("Firmware Version:") + valueText: activeVehicle.firmwareMajorVersion == -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + "-" + activeVehicle.firmwareVersionTypeString + } + + VehicleSummaryRow { + labelText: qsTr("Git Revision:") + valueText: activeVehicle.gitHash == -1 ? qsTr("Unknown") : activeVehicle.gitHash + } + } +} diff --git a/src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml b/src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml index 2bb09e601575cd4a0efb35ac1c86024b50a03def..4547fbd3cf18c4be1efb3527e6c98cdf448d1139 100644 --- a/src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml +++ b/src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml @@ -84,7 +84,7 @@ SetupPage { calcAutoTuneChannel() } - /// The AutoTune switch is stored in one of the RC#_FUNCTION parameters. We need to loop through those + /// The AutoTune switch is stored in one of the CH#_OPT parameters. We need to loop through those /// to find them and setup the ui accordindly. function calcAutoTuneChannel() { _autoTuneSwitchChannelIndex = 0 diff --git a/src/AutoPilotPlugins/APM/Images/SubFrameComponentIcon.png b/src/AutoPilotPlugins/APM/Images/SubFrameComponentIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..6401e093c8591eb554f2dccb99a717d12124ae20 Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/SubFrameComponentIcon.png differ diff --git a/src/AutoPilotPlugins/APM/Images/bluerov-frame.png b/src/AutoPilotPlugins/APM/Images/bluerov-frame.png new file mode 100644 index 0000000000000000000000000000000000000000..5a5edaf360c11b6fa76cf2b54351f66f62ac0faf Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/bluerov-frame.png differ diff --git a/src/AutoPilotPlugins/APM/Images/simple3-frame.png b/src/AutoPilotPlugins/APM/Images/simple3-frame.png new file mode 100644 index 0000000000000000000000000000000000000000..c7368a3e228044513282810f12bc45f1d13e60d0 Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/simple3-frame.png differ diff --git a/src/AutoPilotPlugins/APM/Images/simple4-frame.png b/src/AutoPilotPlugins/APM/Images/simple4-frame.png new file mode 100644 index 0000000000000000000000000000000000000000..793b36521c292297e622bae17728d69a83780a4f Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/simple4-frame.png differ diff --git a/src/AutoPilotPlugins/APM/Images/vectored-frame.png b/src/AutoPilotPlugins/APM/Images/vectored-frame.png new file mode 100644 index 0000000000000000000000000000000000000000..aa1c3cf9edf75fbf4b1c18df39ae4a3aa8301fad Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/vectored-frame.png differ diff --git a/src/AutoPilotPlugins/APM/Images/vectored6dof-frame.png b/src/AutoPilotPlugins/APM/Images/vectored6dof-frame.png new file mode 100644 index 0000000000000000000000000000000000000000..c690be96964d9ac4f8b2930f6b88cd7a69d5c2bd Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/vectored6dof-frame.png differ diff --git a/src/AutoPilotPlugins/AutoPilotPluginManager.cc b/src/AutoPilotPlugins/AutoPilotPluginManager.cc deleted file mode 100644 index b45391758ef3f81abb691600cf5cce7d72c09228..0000000000000000000000000000000000000000 --- a/src/AutoPilotPlugins/AutoPilotPluginManager.cc +++ /dev/null @@ -1,29 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/// @file -/// @author Don Gagne - -#include "AutoPilotPluginManager.h" -#include "PX4/PX4AutoPilotPlugin.h" -#include "APM/APMAutoPilotPlugin.h" -#include "Generic/GenericAutoPilotPlugin.h" - -AutoPilotPlugin* AutoPilotPluginManager::newAutopilotPluginForVehicle(Vehicle* vehicle) -{ - switch (vehicle->firmwareType()) { - case MAV_AUTOPILOT_PX4: - return new PX4AutoPilotPlugin(vehicle, vehicle); - case MAV_AUTOPILOT_ARDUPILOTMEGA: - return new APMAutoPilotPlugin(vehicle, vehicle); - default: - return new GenericAutoPilotPlugin(vehicle, vehicle); - } -} diff --git a/src/AutoPilotPlugins/AutoPilotPluginManager.h b/src/AutoPilotPlugins/AutoPilotPluginManager.h deleted file mode 100644 index 4927cfbc216b6d5d6ebac930a12de4266dc850b7..0000000000000000000000000000000000000000 --- a/src/AutoPilotPlugins/AutoPilotPluginManager.h +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/// @file -/// @author Don Gagne - -#ifndef AUTOPILOTPLUGINMANAGER_H -#define AUTOPILOTPLUGINMANAGER_H - -#include -#include -#include - -#include "AutoPilotPlugin.h" -#include "Vehicle.h" -#include "QGCToolbox.h" - -class QGCApplication; - -class AutoPilotPluginManager : public QGCTool -{ - Q_OBJECT - -public: - AutoPilotPluginManager(QGCApplication* app) : QGCTool(app) { } - - AutoPilotPlugin* newAutopilotPluginForVehicle(Vehicle* vehicle); -}; - -#endif diff --git a/src/AutoPilotPlugins/Common/ESP8266ComponentController.cc b/src/AutoPilotPlugins/Common/ESP8266ComponentController.cc index bfe76f3849af86ca781b737ae4358d2fe2cf96d6..1e7c937d148372ccd8b2a8b1d0b7ab15c338d8b9 100644 --- a/src/AutoPilotPlugins/Common/ESP8266ComponentController.cc +++ b/src/AutoPilotPlugins/Common/ESP8266ComponentController.cc @@ -13,7 +13,6 @@ /// @author Gus Grubba #include "ESP8266ComponentController.h" -#include "AutoPilotPluginManager.h" #include "QGCApplication.h" #include "UAS.h" #include "ParameterManager.h" @@ -38,8 +37,7 @@ ESP8266ComponentController::ESP8266ComponentController() _baudRates.append("230400"); _baudRates.append("460800"); _baudRates.append("921600"); - connect(&_timer, &QTimer::timeout, this, &ESP8266ComponentController::_processTimeout); - connect(_vehicle, &Vehicle::commandLongAck, this, &ESP8266ComponentController::_commandAck); + connect(_vehicle, &Vehicle::mavCommandResult, this, &ESP8266ComponentController::_mavCommandResult); Fact* ssid = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID4"); connect(ssid, &Fact::valueChanged, this, &ESP8266ComponentController::_ssidChanged); Fact* paswd = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD4"); @@ -317,86 +315,36 @@ ESP8266ComponentController::restoreDefaults() void ESP8266ComponentController::_reboot() { - mavlink_message_t msg; - - mavlink_msg_command_long_pack_chan( - qgcApp()->toolbox()->mavlinkProtocol()->getSystemId(), - qgcApp()->toolbox()->mavlinkProtocol()->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - _vehicle->id(), - MAV_COMP_ID_UDP_BRIDGE, - MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, - 1.0f, // Confirmation - 0.0f, // Param1 - 1.0f, // Param2 - 0.0f,0.0f,0.0f,0.0f,0.0f); + _vehicle->sendMavCommand(MAV_COMP_ID_UDP_BRIDGE, MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, true /* showError */, 0.0f, 1.0f); qCDebug(ESP8266ComponentControllerLog) << "_reboot()"; - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); - _timer.start(1000); } //----------------------------------------------------------------------------- void ESP8266ComponentController::_restoreDefaults() { - mavlink_message_t msg; - mavlink_msg_command_long_pack_chan( - qgcApp()->toolbox()->mavlinkProtocol()->getSystemId(), - qgcApp()->toolbox()->mavlinkProtocol()->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - _vehicle->id(), - MAV_COMP_ID_UDP_BRIDGE, - MAV_CMD_PREFLIGHT_STORAGE, - 1.0f, // Confirmation - 2.0f, // Param1 - 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f); + _vehicle->sendMavCommand(MAV_COMP_ID_UDP_BRIDGE, MAV_CMD_PREFLIGHT_STORAGE, true /* showError */, 2.0f); qCDebug(ESP8266ComponentControllerLog) << "_restoreDefaults()"; - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); - _timer.start(1000); } //----------------------------------------------------------------------------- void -ESP8266ComponentController::_processTimeout() +ESP8266ComponentController::_mavCommandResult(int vehicleId, int component, int command, int result, bool noReponseFromVehicle) { - if(!--_retries) { - qCDebug(ESP8266ComponentControllerLog) << "_processTimeout Giving Up"; - _timer.stop(); - _waitType = WAIT_FOR_NOTHING; - emit busyChanged(); - } else { - switch(_waitType) { - case WAIT_FOR_REBOOT: - qCDebug(ESP8266ComponentControllerLog) << "_processTimeout for Reboot"; - _reboot(); - break; - case WAIT_FOR_RESTORE: - qCDebug(ESP8266ComponentControllerLog) << "_processTimeout for Restore Defaults"; - _restoreDefaults(); - break; - } - } -} + Q_UNUSED(vehicleId); + Q_UNUSED(noReponseFromVehicle); -//----------------------------------------------------------------------------- -void -ESP8266ComponentController::_commandAck(uint8_t compID, uint16_t command, uint8_t result) -{ - if(compID == MAV_COMP_ID_UDP_BRIDGE) { - if(result != MAV_RESULT_ACCEPTED) { + if (component == MAV_COMP_ID_UDP_BRIDGE) { + if (result != MAV_RESULT_ACCEPTED) { qWarning() << "ESP8266ComponentController command" << command << "rejected."; return; } - if((_waitType == WAIT_FOR_REBOOT && command == MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN) || - (_waitType == WAIT_FOR_RESTORE && command == MAV_CMD_PREFLIGHT_STORAGE)) - { - _timer.stop(); + if ((_waitType == WAIT_FOR_REBOOT && command == MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN) || + (_waitType == WAIT_FOR_RESTORE && command == MAV_CMD_PREFLIGHT_STORAGE)) { _waitType = WAIT_FOR_NOTHING; emit busyChanged(); qCDebug(ESP8266ComponentControllerLog) << "_commandAck for" << command; - if(command == MAV_CMD_PREFLIGHT_STORAGE) { + if (command == MAV_CMD_PREFLIGHT_STORAGE) { _vehicle->parameterManager()->refreshAllParameters(MAV_COMP_ID_UDP_BRIDGE); } } diff --git a/src/AutoPilotPlugins/Common/ESP8266ComponentController.h b/src/AutoPilotPlugins/Common/ESP8266ComponentController.h index d0b82db400233543e9ef7c0cab684cab50bc57a8..1093eb2676f4600163b0a7237376e0c6666e2517 100644 --- a/src/AutoPilotPlugins/Common/ESP8266ComponentController.h +++ b/src/AutoPilotPlugins/Common/ESP8266ComponentController.h @@ -82,8 +82,7 @@ signals: void busyChanged (); private slots: - void _processTimeout (); - void _commandAck (uint8_t compID, uint16_t command, uint8_t result); + void _mavCommandResult(int vehicleId, int component, int command, int result, bool noReponseFromVehicle); void _ssidChanged (QVariant value); void _passwordChanged (QVariant value); void _baudChanged (QVariant value); @@ -94,7 +93,6 @@ private: void _restoreDefaults (); private: - QTimer _timer; QStringList _channels; QStringList _baudRates; QString _ipAddress; diff --git a/src/AutoPilotPlugins/Common/MixersComponent.cc b/src/AutoPilotPlugins/Common/MixersComponent.cc new file mode 100644 index 0000000000000000000000000000000000000000..efe440b97bf90832f067cf242465cef33a60562e --- /dev/null +++ b/src/AutoPilotPlugins/Common/MixersComponent.cc @@ -0,0 +1,62 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "MixersComponent.h" +#include "ParameterManager.h" + +MixersComponent::MixersComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) + : VehicleComponent(vehicle, autopilot, parent) + , _name(tr("Mixers")) +{ +} + +QString MixersComponent::name(void) const +{ + return _name; +} + +QString MixersComponent::description(void) const +{ + return tr("Mixers tuning is used to blah, blah, blah... [WIP]"); +} + +QString MixersComponent::iconResource(void) const +{ + return QStringLiteral("/qmlimages/TuningComponentIcon.png"); +} + +bool MixersComponent::requiresSetup(void) const +{ + return false; +} + +bool MixersComponent::setupComplete(void) const +{ + return true; +} + +QStringList MixersComponent::setupCompleteChangedTriggerList(void) const +{ + return QStringList(); +} + +QUrl MixersComponent::setupSource(void) const +{ + return QUrl::fromUserInput(QStringLiteral("qrc:/qml/MixersComponent.qml")); +} + +QUrl MixersComponent::summaryQmlSource(void) const +{ + return QUrl(); +} + +QString MixersComponent::prerequisiteSetup(void) const +{ + return QString(); +} diff --git a/src/AutoPilotPlugins/Common/MixersComponent.h b/src/AutoPilotPlugins/Common/MixersComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..5a624d6f76b9ada0bde5f00f613cd6935787ca67 --- /dev/null +++ b/src/AutoPilotPlugins/Common/MixersComponent.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef MixersComponent_H +#define MixersComponent_H + +#include "VehicleComponent.h" + +// Mixers Tuning vehicle component +class MixersComponent : public VehicleComponent +{ + Q_OBJECT + +public: + MixersComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent = NULL); + + // Virtuals from VehicleComponent + QStringList setupCompleteChangedTriggerList(void) const final; + + // Virtuals from VehicleComponent + QString name(void) const final; + QString description(void) const final; + QString iconResource(void) const final; + bool requiresSetup(void) const final; + bool setupComplete(void) const final; + QUrl setupSource(void) const final; + QUrl summaryQmlSource(void) const final; + QString prerequisiteSetup(void) const final; + bool allowSetupWhileArmed(void) const final { return true; } + +private: + const QString _name; + QVariantList _summaryItems; +}; + +#endif diff --git a/src/AutoPilotPlugins/Common/MixersComponent.qml b/src/AutoPilotPlugins/Common/MixersComponent.qml new file mode 100644 index 0000000000000000000000000000000000000000..84034427b3faf0fc486eee7bde72c68ac090c98e --- /dev/null +++ b/src/AutoPilotPlugins/Common/MixersComponent.qml @@ -0,0 +1,38 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 + +// Mixer Tuning setup page +SetupPage { + id: tuningPage + pageComponent: tuningPageComponent + + Component { + id: tuningPageComponent + + Column { + width: availableWidth + spacing: _margins + + FactPanelController { id: controller; factPanel: tuningPage.viewPanel } + + QGCPalette { id: palette; colorGroupEnabled: true } + + QGCLabel { text: qsTr("Lot of Qml code goes here...") } + } // Column + } // Component +} // SetupView diff --git a/src/AutoPilotPlugins/Common/MotorComponent.cc b/src/AutoPilotPlugins/Common/MotorComponent.cc index fe7b611d207cfcbdb49f378f2986ce5ca02e1b4e..972d243fff7a48e0bf219f50a0a69e3f38343578 100644 --- a/src/AutoPilotPlugins/Common/MotorComponent.cc +++ b/src/AutoPilotPlugins/Common/MotorComponent.cc @@ -7,10 +7,7 @@ * ****************************************************************************/ - #include "MotorComponent.h" -#include "APMAutoPilotPlugin.h" -#include "APMAirframeComponent.h" MotorComponent::MotorComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : VehicleComponent(vehicle, autopilot, parent), diff --git a/src/AutoPilotPlugins/Common/RadioComponent.qml b/src/AutoPilotPlugins/Common/RadioComponent.qml index 75e038a5eea02b0de993f3aebcd285d7afff5a3e..2d4bd7fc6ddc7c344b1234052ab862dbe69fa849 100644 --- a/src/AutoPilotPlugins/Common/RadioComponent.qml +++ b/src/AutoPilotPlugins/Common/RadioComponent.qml @@ -423,7 +423,11 @@ SetupPage { } Repeater { - model: QGroundControl.multiVehicleManager.activeVehicle.px4Firmware ? [ "RC_MAP_FLAPS", "RC_MAP_AUX1", "RC_MAP_AUX2", "RC_MAP_PARAM1", "RC_MAP_PARAM2", "RC_MAP_PARAM3"] : 0 + model: QGroundControl.multiVehicleManager.activeVehicle.px4Firmware ? + (QGroundControl.multiVehicleManager.activeVehicle.multiRotor ? + [ "RC_MAP_AUX1", "RC_MAP_AUX2", "RC_MAP_PARAM1", "RC_MAP_PARAM2", "RC_MAP_PARAM3"] : + [ "RC_MAP_FLAPS", "RC_MAP_AUX1", "RC_MAP_AUX2", "RC_MAP_PARAM1", "RC_MAP_PARAM2", "RC_MAP_PARAM3"]) : + 0 Row { spacing: ScreenTools.defaultFontPixelWidth diff --git a/src/AutoPilotPlugins/Common/RadioComponentController.cc b/src/AutoPilotPlugins/Common/RadioComponentController.cc index a6f69d44fe671dba5c9786dd73a6977f263b01bd..f64f29517c5a87ad5b7933c916e2434f672eb7d5 100644 --- a/src/AutoPilotPlugins/Common/RadioComponentController.cc +++ b/src/AutoPilotPlugins/Common/RadioComponentController.cc @@ -13,12 +13,12 @@ /// @author Don Gagne QGC_LOGGING_CATEGORY(RadioComponentControllerLog, "RadioComponentControllerLog") +QGC_LOGGING_CATEGORY(RadioComponentControllerVerboseLog, "RadioComponentControllerVerboseLog") #ifdef UNITTEST_BUILD // Nasty hack to expose controller to unit test code @@ -27,78 +27,78 @@ RadioComponentController* RadioComponentController::_unitTestController = NULL; const int RadioComponentController::_updateInterval = 150; ///< Interval for timer which updates radio channel widgets const int RadioComponentController::_rcCalPWMCenterPoint = ((RadioComponentController::_rcCalPWMValidMaxValue - RadioComponentController::_rcCalPWMValidMinValue) / 2.0f) + RadioComponentController::_rcCalPWMValidMinValue; -// FIXME: Double check these mins againt 150% throws -const int RadioComponentController::_rcCalPWMValidMinValue = 1300; ///< Largest valid minimum PWM Min range value -const int RadioComponentController::_rcCalPWMValidMaxValue = 1700; ///< Smallest valid maximum PWM Max range value -const int RadioComponentController::_rcCalPWMDefaultMinValue = 1000; ///< Default value for Min if not set -const int RadioComponentController::_rcCalPWMDefaultMaxValue = 2000; ///< Default value for Max if not set -const int RadioComponentController::_rcCalRoughCenterDelta = 50; ///< Delta around center point which is considered to be roughly centered -const int RadioComponentController::_rcCalMoveDelta = 300; ///< Amount of delta past center which is considered stick movement -const int RadioComponentController::_rcCalSettleDelta = 20; ///< Amount of delta which is considered no stick movement -const int RadioComponentController::_rcCalMinDelta = 100; ///< Amount of delta allowed around min value to consider channel at min +const int RadioComponentController::_rcCalPWMValidMinValue = 1300; ///< Largest valid minimum PWM Min range value +const int RadioComponentController::_rcCalPWMValidMaxValue = 1700; ///< Smallest valid maximum PWM Max range value +const int RadioComponentController::_rcCalPWMDefaultMinValue = 1000; ///< Default value for Min if not set +const int RadioComponentController::_rcCalPWMDefaultMaxValue = 2000; ///< Default value for Max if not set +const int RadioComponentController::_rcCalRoughCenterDelta = 50; ///< Delta around center point which is considered to be roughly centered +const int RadioComponentController::_rcCalMoveDelta = 300; ///< Amount of delta past center which is considered stick movement +const int RadioComponentController::_rcCalSettleDelta = 20; ///< Amount of delta which is considered no stick movement +const int RadioComponentController::_rcCalMinDelta = 100; ///< Amount of delta allowed around min value to consider channel at min const int RadioComponentController::_stickDetectSettleMSecs = 500; -const char* RadioComponentController::_imageFilePrefix = "calibration/"; +const char* RadioComponentController::_imageFilePrefix = "calibration/"; const char* RadioComponentController::_imageFileMode1Dir = "mode1/"; const char* RadioComponentController::_imageFileMode2Dir = "mode2/"; -const char* RadioComponentController::_imageCenter = "radioCenter.png"; -const char* RadioComponentController::_imageHome = "radioHome.png"; -const char* RadioComponentController::_imageThrottleUp = "radioThrottleUp.png"; +const char* RadioComponentController::_imageCenter = "radioCenter.png"; +const char* RadioComponentController::_imageHome = "radioHome.png"; +const char* RadioComponentController::_imageThrottleUp = "radioThrottleUp.png"; const char* RadioComponentController::_imageThrottleDown = "radioThrottleDown.png"; -const char* RadioComponentController::_imageYawLeft = "radioYawLeft.png"; -const char* RadioComponentController::_imageYawRight = "radioYawRight.png"; -const char* RadioComponentController::_imageRollLeft = "radioRollLeft.png"; -const char* RadioComponentController::_imageRollRight = "radioRollRight.png"; -const char* RadioComponentController::_imagePitchUp = "radioPitchUp.png"; -const char* RadioComponentController::_imagePitchDown = "radioPitchDown.png"; +const char* RadioComponentController::_imageYawLeft = "radioYawLeft.png"; +const char* RadioComponentController::_imageYawRight = "radioYawRight.png"; +const char* RadioComponentController::_imageRollLeft = "radioRollLeft.png"; +const char* RadioComponentController::_imageRollRight = "radioRollRight.png"; +const char* RadioComponentController::_imagePitchUp = "radioPitchUp.png"; +const char* RadioComponentController::_imagePitchDown = "radioPitchDown.png"; const char* RadioComponentController::_imageSwitchMinMax = "radioSwitchMinMax.png"; -const char* RadioComponentController::_settingsGroup = "RadioCalibration"; +const char* RadioComponentController::_settingsGroup = "RadioCalibration"; const char* RadioComponentController::_settingsKeyTransmitterMode = "TransmitterMode"; +const char* RadioComponentController::_px4RevParamFormat = "RC%1_REV"; +const char* RadioComponentController::_apmNewRevParamFormat = "RC%1_REVERSED"; + const struct RadioComponentController::FunctionInfo RadioComponentController::_rgFunctionInfoPX4[RadioComponentController::rcCalFunctionMax] = { - //Parameter required - { "RC_MAP_ROLL" }, - { "RC_MAP_PITCH" }, - { "RC_MAP_YAW" }, - { "RC_MAP_THROTTLE" }, - { "RC_MAP_MODE_SW" }, - { "RC_MAP_POSCTL_SW" }, - { "RC_MAP_LOITER_SW" }, - { "RC_MAP_RETURN_SW" }, - { "RC_MAP_ACRO_SW" }, +{ "RC_MAP_ROLL" }, +{ "RC_MAP_PITCH" }, +{ "RC_MAP_YAW" }, +{ "RC_MAP_THROTTLE" } }; const struct RadioComponentController::FunctionInfo RadioComponentController::_rgFunctionInfoAPM[RadioComponentController::rcCalFunctionMax] = { - //Parameter required - { "RCMAP_ROLL" }, - { "RCMAP_PITCH" }, - { "RCMAP_YAW" }, - { "RCMAP_THROTTLE" }, - { NULL }, - { NULL }, - { NULL }, - { NULL }, - { NULL }, +{ "RCMAP_ROLL" }, +{ "RCMAP_PITCH" }, +{ "RCMAP_YAW" }, +{ "RCMAP_THROTTLE" } }; -RadioComponentController::RadioComponentController(void) : - _currentStep(-1), - _transmitterMode(2), - _chanCount(0), - _rcCalState(rcCalStateChannelWait), - _unitTestMode(false), - _statusText(NULL), - _cancelButton(NULL), - _nextButton(NULL), - _skipButton(NULL) +RadioComponentController::RadioComponentController(void) + : _currentStep(-1) + , _transmitterMode(2) + , _chanCount(0) + , _rcCalState(rcCalStateChannelWait) + , _unitTestMode(false) + , _statusText(NULL) + , _cancelButton(NULL) + , _nextButton(NULL) + , _skipButton(NULL) { #ifdef UNITTEST_BUILD // Nasty hack to expose controller to unit test code _unitTestController = this; #endif + if (parameterExists(FactSystem::defaultComponentId, QStringLiteral("RC1_REVERSED"))) { + // Newer ardupilot firmwares have a different reverse param naming scheme and value scheme + _revParamFormat = _apmNewRevParamFormat; + _revParamIsBool = true; // param value is boolean 0/1 for reversed or not + } else { + // Older ardupilot firmwares share the same naming convention as PX4 + _revParamFormat = _px4RevParamFormat; + _revParamIsBool = false; // paeram value if -1 indicates reversed + } + connect(_vehicle, &Vehicle::rcChannelsChanged, this, &RadioComponentController::_rcChannelsChanged); _loadSettings(); @@ -239,7 +239,7 @@ void RadioComponentController::_rcChannelsChanged(int channelCount, int pwmValue int channelValue = pwmValues[channel]; if (channelValue != -1) { - qCDebug(RadioComponentControllerLog) << "Raw value" << channel << channelValue; + qCDebug(RadioComponentControllerVerboseLog) << "Raw value" << channel << channelValue; _rcRawValue[channel] = channelValue; emit channelRCValueChanged(channel, channelValue); @@ -272,9 +272,12 @@ void RadioComponentController::_rcChannelsChanged(int channelCount, int pwmValue } } else { const stateMachineEntry* state = _getStateMachineEntry(_currentStep); - Q_ASSERT(state); - if (state->rcInputFn) { - (this->*state->rcInputFn)(state->function, channel, channelValue); + if (state) { + if (state->rcInputFn) { + (this->*state->rcInputFn)(state->function, channel, channelValue); + } + } else { + qWarning() << "Internal error: NULL _getStateMachineEntry return"; } } } @@ -296,20 +299,27 @@ void RadioComponentController::nextButtonClicked(void) _startCalibration(); } else { const stateMachineEntry* state = _getStateMachineEntry(_currentStep); - Q_ASSERT(state); - Q_ASSERT(state->nextFn); - (this->*state->nextFn)(); + if (state && state->nextFn) { + (this->*state->nextFn)(); + } else { + qWarning() << "Internal error: NULL _getStateMachineEntry return"; + } } } void RadioComponentController::skipButtonClicked(void) { - Q_ASSERT(_currentStep != -1); + if (_currentStep == -1) { + qWarning() << "Internal error: _currentStep == -1"; + return; + } const stateMachineEntry* state = _getStateMachineEntry(_currentStep); - Q_ASSERT(state); - Q_ASSERT(state->skipFn); - (this->*state->skipFn)(); + if (state && state->skipFn) { + (this->*state->skipFn)(); + } else { + qWarning() << "Internal error: NULL _getStateMachineEntry return"; + } } void RadioComponentController::cancelButtonClicked(void) @@ -572,38 +582,6 @@ void RadioComponentController::_resetInternalCalibrationValues(void) _rgFunctionChannelMapping[i] = _chanMax(); } - if (_px4Vehicle()) { - // Reserve the existing Flight Mode switch settings channels so we don't re-use them - - static const rcCalFunctions rgFlightModeFunctions[] = { - rcCalFunctionModeSwitch, - rcCalFunctionPosCtlSwitch, - rcCalFunctionLoiterSwitch, - rcCalFunctionReturnSwitch }; - static const size_t crgFlightModeFunctions = sizeof(rgFlightModeFunctions) / sizeof(rgFlightModeFunctions[0]); - - for (size_t i=0; i < crgFlightModeFunctions; i++) { - QVariant value; - enum rcCalFunctions curFunction = rgFlightModeFunctions[i]; - - Fact* paramFact = getParameterFact(FactSystem::defaultComponentId, _functionInfo()[curFunction].parameterName); - if (paramFact) { - bool ok; - int switchChannel = paramFact->rawValue().toInt(&ok); - Q_ASSERT(ok); - - // Parameter: 1-based channel, 0=not mapped - // _rgFunctionChannelMapping: 0-based channel, _chanMax=not mapped - - if (switchChannel != 0) { - qCDebug(RadioComponentControllerLog) << "Reserving 0-based switch channel" << switchChannel - 1; - _rgFunctionChannelMapping[curFunction] = switchChannel - 1; - _rgChannelInfo[switchChannel - 1].function = curFunction; - } - } - } - } - _signalAllAttiudeValueChanges(); } @@ -626,9 +604,6 @@ void RadioComponentController::_setInternalCalibrationValuesFromParameters(void) QString minTpl("RC%1_MIN"); QString maxTpl("RC%1_MAX"); QString trimTpl("RC%1_TRIM"); - QString revTpl("RC%1_REV"); - - bool convertOk; for (int i = 0; i < _chanMax(); ++i) { struct ChannelInfo* info = &_rgChannelInfo[i]; @@ -646,29 +621,20 @@ void RadioComponentController::_setInternalCalibrationValuesFromParameters(void) Fact* paramFact = getParameterFact(FactSystem::defaultComponentId, trimTpl.arg(i+1)); if (paramFact) { - info->rcTrim = paramFact->rawValue().toInt(&convertOk); - Q_ASSERT(convertOk); + info->rcTrim = paramFact->rawValue().toInt(); } paramFact = getParameterFact(FactSystem::defaultComponentId, minTpl.arg(i+1)); if (paramFact) { - info->rcMin = paramFact->rawValue().toInt(&convertOk); - Q_ASSERT(convertOk); + info->rcMin = paramFact->rawValue().toInt(); } paramFact = getParameterFact(FactSystem::defaultComponentId, maxTpl.arg(i+1)); if (paramFact) { - info->rcMax = getParameterFact(FactSystem::defaultComponentId, maxTpl.arg(i+1))->rawValue().toInt(&convertOk); - Q_ASSERT(convertOk); + info->rcMax = getParameterFact(FactSystem::defaultComponentId, maxTpl.arg(i+1))->rawValue().toInt(); } - paramFact = getParameterFact(FactSystem::defaultComponentId, revTpl.arg(i+1)); - if (paramFact) { - float floatReversed = paramFact->rawValue().toFloat(&convertOk); - Q_ASSERT(convertOk); - Q_ASSERT(floatReversed == 1.0f || floatReversed == -1.0f); - info->reversed = floatReversed == -1.0f; - } + info->reversed = _channelReversedParamValue(i); } for (int i=0; irawValue().toInt(&convertOk); - Q_ASSERT(convertOk); + paramChannel = paramFact->rawValue().toInt(); if (paramChannel != 0) { _rgFunctionChannelMapping[i] = paramChannel - 1; @@ -713,21 +678,21 @@ void RadioComponentController::_validateCalibration(void) info->rcTrim = info->rcMin + ((info->rcMax - info->rcMin) / 2); } else { switch (_rgChannelInfo[chan].function) { - case rcCalFunctionThrottle: - case rcCalFunctionYaw: - case rcCalFunctionRoll: - case rcCalFunctionPitch: - // Make sure trim is within min/max - if (info->rcTrim < info->rcMin) { - info->rcTrim = info->rcMin; - } else if (info->rcTrim > info->rcMax) { - info->rcTrim = info->rcMax; - } - break; - default: - // Non-attitude control channels have calculated trim - info->rcTrim = info->rcMin + ((info->rcMax - info->rcMin) / 2); - break; + case rcCalFunctionThrottle: + case rcCalFunctionYaw: + case rcCalFunctionRoll: + case rcCalFunctionPitch: + // Make sure trim is within min/max + if (info->rcTrim < info->rcMin) { + info->rcTrim = info->rcMin; + } else if (info->rcTrim > info->rcMax) { + info->rcTrim = info->rcMax; + } + break; + default: + // Non-attitude control channels have calculated trim + info->rcTrim = info->rcMin + ((info->rcMax - info->rcMin) / 2); + break; } } @@ -762,7 +727,6 @@ void RadioComponentController::_writeCalibration(void) QString minTpl("RC%1_MIN"); QString maxTpl("RC%1_MAX"); QString trimTpl("RC%1_TRIM"); - QString revTpl("RC%1_REV"); // Note that the rc parameters are all float, so you must cast to float in order to get the right QVariant for (int chan = 0; chan<_chanMax(); chan++) { @@ -788,19 +752,16 @@ void RadioComponentController::_writeCalibration(void) } // For multi-rotor we can determine reverse setting during radio cal. For anything other than multi-rotor, servo installation - // may affect channel reversing so we can't automatically determine it. - if (_vehicle->multiRotor()) { + // may affect channel reversing so we can't automatically determine it. This is ok for PX4 given how it uses mixers, but not for ArduPilot. + if (_vehicle->px4Firmware() || _vehicle->multiRotor()) { // APM multi-rotor has a backwards interpretation of "reversed" on the Pitch control. So be careful. - float reversedParamValue; + bool reversed; if (_px4Vehicle() || info->function != rcCalFunctionPitch) { - reversedParamValue = info->reversed ? -1.0f : 1.0f; + reversed = info->reversed; } else { - reversedParamValue = info->reversed ? 1.0f : -1.0f; - } - paramFact = getParameterFact(FactSystem::defaultComponentId, revTpl.arg(oneBasedChannel)); - if (paramFact) { - paramFact->setRawValue(reversedParamValue); + reversed = !info->reversed; } + _setChannelReversedParamValue(chan, reversed); } } @@ -842,7 +803,10 @@ void RadioComponentController::_writeCalibration(void) /// @brief Starts the calibration process void RadioComponentController::_startCalibration(void) { - Q_ASSERT(_chanCount >= _chanMinimum); + if (_chanCount < _chanMinimum) { + qWarning() << "Call to RadioComponentController::_startCalibration with _chanCount < _chanMinimum"; + return; + } _resetInternalCalibrationValues(); @@ -898,7 +862,7 @@ void RadioComponentController::_rcCalSave(void) _statusText->setProperty("text", "The current calibration settings are now displayed for each channel on screen.\n\n" - "Click the Next button to upload calibration to board. Click Cancel if you don't want to save these values."); + "Click the Next button to upload calibration to board. Click Cancel if you don't want to save these values."); _nextButton->setEnabled(true); _skipButton->setEnabled(false); @@ -940,7 +904,8 @@ void RadioComponentController::_setHelpImage(const char* imageFile) } else if (_transmitterMode == 2) { file += _imageFileMode2Dir; } else { - Q_ASSERT(false); + qWarning() << "Internal error: Bad _transmitterMode value"; + return; } file += imageFile; @@ -1090,3 +1055,34 @@ int RadioComponentController::_chanMax(void) const { return _px4Vehicle() ? _chanMaxPX4 : _chanMaxAPM; } + +bool RadioComponentController::_channelReversedParamValue(int channel) +{ + Fact* paramFact = getParameterFact(FactSystem::defaultComponentId, _revParamFormat.arg(channel+1)); + if (paramFact) { + if (_revParamIsBool) { + return paramFact->rawValue().toBool(); + } else { + bool convertOk; + float floatReversed = paramFact->rawValue().toFloat(&convertOk); + if (!convertOk) { + floatReversed = 1.0f; + } + return floatReversed == -1.0f; + } + } + + return false; +} + +void RadioComponentController::_setChannelReversedParamValue(int channel, bool reversed) +{ + Fact* paramFact = getParameterFact(FactSystem::defaultComponentId, _revParamFormat.arg(channel+1)); + if (paramFact) { + if (_revParamIsBool) { + paramFact->setRawValue(reversed); + } else { + paramFact->setRawValue(reversed ? -1.0f : 1.0f); + } + } +} diff --git a/src/AutoPilotPlugins/Common/RadioComponentController.h b/src/AutoPilotPlugins/Common/RadioComponentController.h index bd3c056cf3ab450b852b1985f210acdbff9978ba..57f0ff02c403a5ecad54cea36ea82314b7b31739 100644 --- a/src/AutoPilotPlugins/Common/RadioComponentController.h +++ b/src/AutoPilotPlugins/Common/RadioComponentController.h @@ -24,6 +24,7 @@ #include "AutoPilotPlugin.h" Q_DECLARE_LOGGING_CATEGORY(RadioComponentControllerLog) +Q_DECLARE_LOGGING_CATEGORY(RadioComponentControllerVerboseLog) class RadioConfigest; @@ -149,20 +150,7 @@ private: rcCalFunctionPitch, rcCalFunctionYaw, rcCalFunctionThrottle, - rcCalFunctionModeSwitch, - rcCalFunctionPosCtlSwitch, - rcCalFunctionLoiterSwitch, - rcCalFunctionReturnSwitch, - rcCalFunctionAcroSwitch, rcCalFunctionMax, - - // Attitude functions are roll/pitch/yaw/throttle - rcCalFunctionFirstAttitudeFunction = rcCalFunctionRoll, - rcCalFunctionLastAttitudeFunction = rcCalFunctionThrottle, - - // Non-Attitude functions are everything else - rcCalFunctionFirstNonAttitudeFunction = rcCalFunctionModeSwitch, - rcCalFunctionLastNonAttitudeFunction = rcCalFunctionAcroSwitch, }; /// @brief The states of the calibration state machine. @@ -245,7 +233,10 @@ private: void _signalAllAttiudeValueChanges(void); int _chanMax(void) const; - + + bool _channelReversedParamValue(int channel); + void _setChannelReversedParamValue(int channel, bool reversed); + // @brief Called by unit test code to set the mode to unit testing void _setUnitTestMode(void){ _unitTestMode = true; } @@ -272,20 +263,20 @@ private: int _transmitterMode; ///< 1: transmitter is mode 1, 2: transmitted is mode 2 static const int _updateInterval; ///< Interval for ui update timer - + static const struct FunctionInfo _rgFunctionInfoAPM[rcCalFunctionMax]; ///< Information associated with each function, PX4 firmware static const struct FunctionInfo _rgFunctionInfoPX4[rcCalFunctionMax]; ///< Information associated with each function, APM firmware int _rgFunctionChannelMapping[rcCalFunctionMax]; ///< Maps from rcCalFunctions to channel index. _chanMax indicates channel not set for this function. static const int _attitudeControls = 5; - + int _chanCount; ///< Number of actual rc channels available static const int _chanMaxPX4 = 18; ///< Maximum number of supported rc channels, PX4 Firmware static const int _chanMaxAPM = 14; ///< Maximum number of supported rc channels, APM firmware static const int _chanMaxAny = 18; ///< Maximum number of support rc channels by this implementation static const int _chanMinimum = 5; ///< Minimum numner of channels required to run - + struct ChannelInfo _rgChannelInfo[_chanMaxAny]; ///< Information associated with each rc channel QList _apmPossibleMissingRCChannelParams; ///< List of possible missing RC*_* params for APM stack @@ -305,7 +296,12 @@ private: static const int _rcCalMoveDelta; static const int _rcCalSettleDelta; static const int _rcCalMinDelta; - + + static const char* _px4RevParamFormat; + static const char* _apmNewRevParamFormat; + QString _revParamFormat; + bool _revParamIsBool; + int _rcValueSave[_chanMaxAny]; ///< Saved values prior to detecting channel movement int _rcRawValue[_chanMaxAny]; ///< Current set of raw channel values diff --git a/src/AutoPilotPlugins/PX4/AirframeComponent.qml b/src/AutoPilotPlugins/PX4/AirframeComponent.qml index 048b045dfac1441cd2672fcfb24d2ca5a1bcd504..13a3f3b8f83cdf0d8d8aaeef78bc869e9241f583 100644 --- a/src/AutoPilotPlugins/PX4/AirframeComponent.qml +++ b/src/AutoPilotPlugins/PX4/AirframeComponent.qml @@ -208,6 +208,7 @@ Your vehicle will also be restarted in order to complete the process.") onCheckedChanged: { if (checked && combo.currentIndex != -1) { + console.log("check box change", combo.currentIndex) controller.autostartId = modelData.airframes[combo.currentIndex].autostartId } } @@ -230,8 +231,9 @@ Your vehicle will also be restarted in order to complete the process.") onActivated: { applyButton.primary = true - controller.autostartId = modelData.airframes[index].autostartId airframeCheckBox.checked = true; + console.log("combo change", index) + controller.autostartId = modelData.airframes[index].autostartId } } } diff --git a/src/AutoPilotPlugins/PX4/AirframeComponentController.cc b/src/AutoPilotPlugins/PX4/AirframeComponentController.cc index 2048101a02e0ece35dca432e06621fdfabbf8fe9..bbcb97b471b9bcd0bd75b1bcde7ff6588f3f7c10 100644 --- a/src/AutoPilotPlugins/PX4/AirframeComponentController.cc +++ b/src/AutoPilotPlugins/PX4/AirframeComponentController.cc @@ -15,7 +15,6 @@ #include "AirframeComponentAirframes.h" #include "QGCMAVLink.h" #include "MultiVehicleManager.h" -#include "AutoPilotPluginManager.h" #include "QGCApplication.h" #include @@ -118,7 +117,7 @@ void AirframeComponentController::_waitParamWriteSignal(QVariant value) void AirframeComponentController::_rebootAfterStackUnwind(void) { - _uas->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0); + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, true /* showError */, 1.0f); qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents); for (unsigned i = 0; i < 2000; i++) { QGC::SLEEP::usleep(500); diff --git a/src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml b/src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml index 67f947e6750d252492bcd973cc9aebe47a6c978f..81d6019f7b77cf89858c667cfe63a9e45c7495f7 100644 --- a/src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml +++ b/src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml @@ -82,6 +82,17 @@ Flying Wing + + + Bart Slinger <bartslinger@gmail.com> + Helicopter + main motor + front swashplate servo + right swashplate servo + left swashplate servo + tail-rotor servo + + Anton Babushkin <anton@px4.io> @@ -185,9 +196,17 @@ Simon Wilks <simon@px4.io> Quadrotor Wide - - Anton Matosov <anton.matosov@gmail.com> - Quadrotor Wide + + + + Mark Whitehorn <kd0aij@gmail.com> + Quadrotor asymmetric + motor1 (front right: CCW) + motor2 (back left: CCW) + motor3 (front left: CW) + motor4 (back right: CW) + feed-through of RC AUX1 channel + feed-through of RC AUX2 channel @@ -195,6 +214,10 @@ Lorenz Meier <lorenz@px4.io> Quadrotor x + + Leon Mueller <thedevleon> + Quadrotor x + Lorenz Meier <lorenz@px4.io> Quadrotor x @@ -209,8 +232,8 @@ feed-through of RC AUX2 channel feed-through of RC AUX3 channel - - Lorenz Meier <lorenz@px4.io> + + Leon Mueller <thedevleon> Quadrotor x @@ -219,6 +242,11 @@ feed-through of RC AUX1 channel feed-through of RC AUX2 channel feed-through of RC AUX3 channel + feed-through of RC FLAPS channel + motor1 (front right: CCW) + motor2 (back left: CCW) + motor3 (front left: CW) + motor4 (back right: CW) Lorenz Meier <lorenz@px4.io> @@ -238,14 +266,6 @@ Pavel Kirienko <pavel@px4.io> Quadrotor x - - Thomas Gubler <thomas@px4.io> - Quadrotor x - - - Andreas Antener <andreas@uaventure.com> - Quadrotor x - Blankered Quadrotor x @@ -256,6 +276,11 @@ feed-through of RC AUX1 channel feed-through of RC AUX2 channel feed-through of RC AUX3 channel + feed-through of RC FLAPS channel + motor1 (front right: CCW) + motor2 (back left: CCW) + motor3 (front left: CW) + motor4 (back right: CW) James Goppert <james.goppert@gmail.com> @@ -264,6 +289,12 @@ feed-through of RC AUX2 channel feed-through of RC AUX3 channel + + Anton Matosov <anton.matosov@gmail.com> + Quadrotor x + feed-through of RC AUX1 channel + feed-through of RC AUX2 channel + @@ -287,14 +318,6 @@ Anton Babushkin <anton@px4.io> Simulation - - Thomas Gubler <thomas@px4.io> - Simulation - - - Thomas Gubler <thomas@px4.io> - Simulation - @@ -363,13 +386,29 @@ - + Simon Wilks <simon@uaventure.com> Standard VTOL - - + Aileron 1 + Aileron 2 + Elevator + Rudder + Throttle + Front right motor: CCW + Back left motor: CCW + Front left motor: CW + Back right motor: CW + + Simon Wilks <simon@uaventure.com> Standard VTOL + Right elevon + Left elevon + Motor + Front right motor: CCW + Back left motor: CCW + Front left motor: CW + Back right motor: CW Sander Smeets <sander@droneslab.com> @@ -417,14 +456,36 @@ - - Roman Bapst <roman@px4.io> + + Roman Bapst <roman@uaventure.com> VTOL Tiltrotor + Tilt servo + Elevon 1 + Elevon 2 + Gear + Front right motor bottom + Front right motor top + Back motor bottom + Back motor top + Front left motor bottom + Front left motor top Samay Siga <samay_s@icloud.com> VTOL Tiltrotor + + Andreas Antener <andreas@uaventure.com> + VTOL Tiltrotor + Motor right + Motor left + Motor back + empty + Tilt servo right + Tilt servo left + Elevon right + Elevon left + diff --git a/src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.cc b/src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.cc index e8044064e7af5d0be06349d415150a2e75506566..57818a6de2bb600aff38c721f55523d07d3bce32 100644 --- a/src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.cc +++ b/src/AutoPilotPlugins/PX4/PX4AdvancedFlightModesController.cc @@ -13,7 +13,6 @@ #include "PX4AdvancedFlightModesController.h" #include "QGCMAVLink.h" -#include "AutoPilotPluginManager.h" #include #include diff --git a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc index af9d98d3c560bb6ccbff79ca6f1075b2b781e593..3036a15767497451c365b317e05e144ec3045f81 100644 --- a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc @@ -9,7 +9,6 @@ #include "PX4AutoPilotPlugin.h" -#include "AutoPilotPluginManager.h" #include "PX4AirframeLoader.h" #include "PX4AdvancedFlightModesController.h" #include "AirframeComponentController.h" @@ -32,6 +31,8 @@ PX4AutoPilotPlugin::PX4AutoPilotPlugin(Vehicle* vehicle, QObject* parent) , _safetyComponent(NULL) , _powerComponent(NULL) , _motorComponent(NULL) + , _tuningComponent(NULL) + , _mixersComponent(NULL) , _incorrectParameterVersion(false) { Q_ASSERT(vehicle); @@ -90,6 +91,10 @@ const QVariantList& PX4AutoPilotPlugin::vehicleComponents(void) _tuningComponent->setupTriggerSignals(); _components.append(QVariant::fromValue((VehicleComponent*)_tuningComponent)); + _mixersComponent = new MixersComponent(_vehicle, this); + _mixersComponent->setupTriggerSignals(); + _components.append(QVariant::fromValue((VehicleComponent*)_mixersComponent)); + //-- Is there support for cameras? if(_vehicle->parameterManager()->parameterExists(_vehicle->id(), "TRIG_MODE")) { _cameraComponent = new CameraComponent(_vehicle, this); diff --git a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h index 32f63dd14f6680b23b4c41dbc8f9dbed283f333d..e5f0efa6c103c8101823807ec04cf96192738952 100644 --- a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h +++ b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h @@ -23,6 +23,7 @@ #include "PowerComponent.h" #include "MotorComponent.h" #include "PX4TuningComponent.h" +#include "MixersComponent.h" #include "Vehicle.h" #include @@ -54,6 +55,7 @@ public: PowerComponent* powerComponent(void) { return _powerComponent; } MotorComponent* motorComponent(void) { return _motorComponent; } PX4TuningComponent* tuningComponent(void) { return _tuningComponent; } + MixersComponent* mixersComponent(void) { return _mixersComponent; } private: PX4AirframeLoader* _airframeFacts; @@ -68,6 +70,7 @@ private: PowerComponent* _powerComponent; MotorComponent* _motorComponent; PX4TuningComponent* _tuningComponent; + MixersComponent* _mixersComponent; bool _incorrectParameterVersion; ///< true: parameter version incorrect, setup not allowed }; diff --git a/src/AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml b/src/AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml index 17eb6fefb7fa7796e940b7fd7599983e8e171cf6..6704f871f572c5db171c1d7a1016904479334b92 100644 --- a/src/AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml +++ b/src/AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml @@ -46,8 +46,9 @@ FactPanel { } VehicleSummaryRow { - labelText: qsTr("Flaps:") - valueText: mapFlapsFact ? (mapFlapsFact.value === 0 ? qsTr("Disabled") : mapFlapsFact.valueString) : "" + labelText: qsTr("Flaps:") + valueText: mapFlapsFact ? (mapFlapsFact.value === 0 ? qsTr("Disabled") : mapFlapsFact.valueString) : "" + visible: !controller.vehicle.multiRotor } VehicleSummaryRow { diff --git a/src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.cc b/src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.cc index 8f0bebfd525663d0142678f6ed007b87593c8ba9..65ae2e7f12e277eabe1a6043d57867da9223782a 100644 --- a/src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.cc +++ b/src/AutoPilotPlugins/PX4/PX4SimpleFlightModesController.cc @@ -10,7 +10,6 @@ #include "PX4SimpleFlightModesController.h" #include "QGCMAVLink.h" -#include "AutoPilotPluginManager.h" #include #include diff --git a/src/AutoPilotPlugins/PX4/PowerComponent.qml b/src/AutoPilotPlugins/PX4/PowerComponent.qml index 1cc89d81c8a6210ab36a5512dfe217c1b57fb3d1..7d992a40f8bed6d59126b36eb8fe459af91fef3e 100644 --- a/src/AutoPilotPlugins/PX4/PowerComponent.qml +++ b/src/AutoPilotPlugins/PX4/PowerComponent.qml @@ -7,11 +7,6 @@ * ****************************************************************************/ - -/// @file -/// @brief Battery, propeller and magnetometer settings -/// @author Gus Grubba - import QtQuick 2.2 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 @@ -30,524 +25,485 @@ SetupPage { Component { id: pageComponent - Column { - id: innerColumn - width: availableWidth - spacing: ScreenTools.defaultFontPixelHeight * 0.5 - - property int textEditWidth: ScreenTools.defaultFontPixelWidth * 8 - - property Fact battNumCells: controller.getParameterFact(-1, "BAT_N_CELLS") - property Fact battHighVolt: controller.getParameterFact(-1, "BAT_V_CHARGED") - property Fact battLowVolt: controller.getParameterFact(-1, "BAT_V_EMPTY") - property Fact battVoltLoadDrop: controller.getParameterFact(-1, "BAT_V_LOAD_DROP") - property Fact battVoltageDivider: controller.getParameterFact(-1, "BAT_V_DIV") - property Fact battAmpsPerVolt: controller.getParameterFact(-1, "BAT_A_PER_V") - property Fact uavcanEnable: controller.getParameterFact(-1, "UAVCAN_ENABLE", false) - - readonly property string highlightPrefix: "" - readonly property string highlightSuffix: "" - - - 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"; + Item { + width: Math.max(availableWidth, innerColumn.width) + height: innerColumn.height + + ColumnLayout { + id: innerColumn + anchors.horizontalCenter: parent.horizontalCenter + spacing: ScreenTools.defaultFontPixelHeight + + property int textEditWidth: ScreenTools.defaultFontPixelWidth * 8 + + property Fact battNumCells: controller.getParameterFact(-1, "BAT_N_CELLS") + property Fact battHighVolt: controller.getParameterFact(-1, "BAT_V_CHARGED") + property Fact battLowVolt: controller.getParameterFact(-1, "BAT_V_EMPTY") + property Fact battVoltLoadDrop: controller.getParameterFact(-1, "BAT_V_LOAD_DROP") + property Fact battVoltageDivider: controller.getParameterFact(-1, "BAT_V_DIV") + property Fact battAmpsPerVolt: controller.getParameterFact(-1, "BAT_A_PER_V") + property Fact uavcanEnable: controller.getParameterFact(-1, "UAVCAN_ENABLE", false) + + readonly property string highlightPrefix: "" + readonly property string highlightSuffix: "" + + + 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(); - ctx.beginPath(); - ctx.translate(x,y); - ctx.rotate(radians); - ctx.moveTo(0,0); - ctx.lineTo(5,10); - ctx.lineTo(-5,10); - ctx.closePath(); - ctx.restore(); - ctx.fill(); - } - - function drawLineWithArrow(ctx, x1, y1, x2, y2) - { - ctx.beginPath(); - ctx.moveTo(x1, y1); - ctx.lineTo(x2, y2); - ctx.stroke(); - var rd = Math.atan((y2 - y1) / (x2 - x1)); - rd += ((x2 > x1) ? 90 : -90) * Math.PI/180; - drawArrowhead(ctx, x2, y2, rd); - } - - PowerComponentController { - id: controller - factPanel: powerPage.viewPanel - - onOldFirmware: showMessage(qsTr("ESC Calibration"), qsTr("QGroundControl cannot perform ESC Calibration with this version of firmware. You will need to upgrade to a newer firmware."), StandardButton.Ok) - onNewerFirmware: showMessage(qsTr("ESC Calibration"), qsTr("QGroundControl cannot perform ESC Calibration with this version of firmware. You will need to upgrade QGroundControl."), StandardButton.Ok) - onBatteryConnected: showMessage(qsTr("ESC Calibration"), qsTr("Performing calibration. This will take a few seconds.."), 0) - onCalibrationFailed: showMessage(qsTr("ESC Calibration failed"), errorMessage, StandardButton.Ok) - onCalibrationSuccess: showMessage(qsTr("ESC Calibration"), qsTr("Calibration complete. You can disconnect your battery now if you like."), StandardButton.Ok) - onConnectBattery: showMessage(qsTr("ESC Calibration"), highlightPrefix + qsTr("WARNING: Props must be removed from vehicle prior to performing ESC calibration.") + highlightSuffix + qsTr(" Connect the battery now and calibration will begin."), 0) - onDisconnectBattery: showMessage(qsTr("ESC Calibration failed"), qsTr("You must disconnect the battery prior to performing ESC Calibration. Disconnect your battery and try again."), StandardButton.Ok) - } - - Component { - id: calcVoltageDividerDlgComponent - - QGCViewDialog { - id: calcVoltageDividerDlg - - QGCFlickable { - anchors.fill: parent - contentHeight: column.height - contentWidth: column.width - - Column { - id: column - width: calcVoltageDividerDlg.width - spacing: ScreenTools.defaultFontPixelHeight - QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - text: "Measure battery voltage using an external voltmeter and enter the value below. Click Calculate to set the new voltage multiplier." - } + function drawArrowhead(ctx, x, y, radians) + { + ctx.save(); + ctx.beginPath(); + ctx.translate(x,y); + ctx.rotate(radians); + ctx.moveTo(0,0); + ctx.lineTo(5,10); + ctx.lineTo(-5,10); + ctx.closePath(); + ctx.restore(); + ctx.fill(); + } + + function drawLineWithArrow(ctx, x1, y1, x2, y2) + { + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.stroke(); + var rd = Math.atan((y2 - y1) / (x2 - x1)); + rd += ((x2 > x1) ? 90 : -90) * Math.PI/180; + drawArrowhead(ctx, x2, y2, rd); + } + + PowerComponentController { + id: controller + factPanel: powerPage.viewPanel + + onOldFirmware: showMessage(qsTr("ESC Calibration"), qsTr("QGroundControl cannot perform ESC Calibration with this version of firmware. You will need to upgrade to a newer firmware."), StandardButton.Ok) + onNewerFirmware: showMessage(qsTr("ESC Calibration"), qsTr("QGroundControl cannot perform ESC Calibration with this version of firmware. You will need to upgrade QGroundControl."), StandardButton.Ok) + onBatteryConnected: showMessage(qsTr("ESC Calibration"), qsTr("Performing calibration. This will take a few seconds.."), 0) + onCalibrationFailed: showMessage(qsTr("ESC Calibration failed"), errorMessage, StandardButton.Ok) + onCalibrationSuccess: showMessage(qsTr("ESC Calibration"), qsTr("Calibration complete. You can disconnect your battery now if you like."), StandardButton.Ok) + onConnectBattery: showMessage(qsTr("ESC Calibration"), highlightPrefix + qsTr("WARNING: Props must be removed from vehicle prior to performing ESC calibration.") + highlightSuffix + qsTr(" Connect the battery now and calibration will begin."), 0) + onDisconnectBattery: showMessage(qsTr("ESC Calibration failed"), qsTr("You must disconnect the battery prior to performing ESC Calibration. Disconnect your battery and try again."), StandardButton.Ok) + } - Grid { - columns: 2 - spacing: ScreenTools.defaultFontPixelHeight / 2 - verticalItemAlignment: Grid.AlignVCenter + Component { + id: calcVoltageDividerDlgComponent + + QGCViewDialog { + id: calcVoltageDividerDlg + + QGCFlickable { + anchors.fill: parent + contentHeight: column.height + contentWidth: column.width + + Column { + id: column + width: calcVoltageDividerDlg.width + spacing: ScreenTools.defaultFontPixelHeight QGCLabel { - text: "Measured voltage:" + width: parent.width + wrapMode: Text.WordWrap + text: "Measure battery voltage using an external voltmeter and enter the value below. Click Calculate to set the new voltage multiplier." } - QGCTextField { id: measuredVoltage } - QGCLabel { text: "Vehicle voltage:" } - QGCLabel { text: controller.vehicle.battery.voltage.valueString } + Grid { + columns: 2 + spacing: ScreenTools.defaultFontPixelHeight / 2 + verticalItemAlignment: Grid.AlignVCenter - QGCLabel { text: "Voltage divider:" } - FactLabel { fact: battVoltageDivider } - } + QGCLabel { + text: "Measured voltage:" + } + QGCTextField { id: measuredVoltage } - QGCButton { - text: "Calculate" + QGCLabel { text: "Vehicle voltage:" } + QGCLabel { text: controller.vehicle.battery.voltage.valueString } - onClicked: { - var measuredVoltageValue = parseFloat(measuredVoltage.text) - if (measuredVoltageValue == 0) { - return - } - var newVoltageDivider = (measuredVoltageValue * battVoltageDivider.value) / controller.vehicle.battery.voltage.value - if (newVoltageDivider != 0) { - battVoltageDivider.value = newVoltageDivider - } + QGCLabel { text: "Voltage divider:" } + FactLabel { fact: battVoltageDivider } } - } - } // Column - } // QGCFlickable - } // QGCViewDialog - } // Component - calcVoltageDividerDlgComponent - - Component { - id: calcAmpsPerVoltDlgComponent - QGCViewDialog { - id: calcAmpsPerVoltDlg + QGCButton { + text: "Calculate" + + onClicked: { + var measuredVoltageValue = parseFloat(measuredVoltage.text) + if (measuredVoltageValue == 0 || isNaN(measuredVoltageValue)) { + return + } + var newVoltageDivider = (measuredVoltageValue * battVoltageDivider.value) / controller.vehicle.battery.voltage.value + if (newVoltageDivider > 0) { + battVoltageDivider.value = newVoltageDivider + } + } + } + } // Column + } // QGCFlickable + } // QGCViewDialog + } // Component - calcVoltageDividerDlgComponent - QGCFlickable { - anchors.fill: parent - contentHeight: column.height - contentWidth: column.width + Component { + id: calcAmpsPerVoltDlgComponent - Column { - id: column - width: calcAmpsPerVoltDlg.width - spacing: ScreenTools.defaultFontPixelHeight + QGCViewDialog { + id: calcAmpsPerVoltDlg - QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - text: "Measure current draw using an external current meter and enter the value below. Click Calculate to set the new amps per volt value." - } + QGCFlickable { + anchors.fill: parent + contentHeight: column.height + contentWidth: column.width - Grid { - columns: 2 - spacing: ScreenTools.defaultFontPixelHeight / 2 - verticalItemAlignment: Grid.AlignVCenter + Column { + id: column + width: calcAmpsPerVoltDlg.width + spacing: ScreenTools.defaultFontPixelHeight QGCLabel { - text: "Measured current:" + width: parent.width + wrapMode: Text.WordWrap + text: "Measure current draw using an external current meter and enter the value below. Click Calculate to set the new amps per volt value." } - QGCTextField { id: measuredCurrent } - QGCLabel { text: "Vehicle current:" } - QGCLabel { text: controller.vehicle.battery.current.valueString } + Grid { + columns: 2 + spacing: ScreenTools.defaultFontPixelHeight / 2 + verticalItemAlignment: Grid.AlignVCenter - QGCLabel { text: "Amps per volt:" } - FactLabel { fact: battAmpsPerVolt } - } + QGCLabel { + text: "Measured current:" + } + QGCTextField { id: measuredCurrent } - QGCButton { - text: "Calculate" + QGCLabel { text: "Vehicle current:" } + QGCLabel { text: controller.vehicle.battery.current.valueString } - onClicked: { - var measuredCurrentValue = parseFloat(measuredCurrent.text) - if (measuredCurrentValue == 0) { - return - } - var newAmpsPerVolt = (measuredCurrentValue * battAmpsPerVolt.value) / controller.vehicle.battery.current.value - if (newAmpsPerVolt != 0) { - battAmpsPerVolt.value = newAmpsPerVolt + QGCLabel { text: "Amps per volt:" } + FactLabel { fact: battAmpsPerVolt } + } + + QGCButton { + text: "Calculate" + + onClicked: { + var measuredCurrentValue = parseFloat(measuredCurrent.text) + if (measuredCurrentValue == 0) { + return + } + var newAmpsPerVolt = (measuredCurrentValue * battAmpsPerVolt.value) / controller.vehicle.battery.current.value + if (newAmpsPerVolt != 0) { + battAmpsPerVolt.value = newAmpsPerVolt + } } } - } - } // Column - } // QGCFlickable - } // QGCViewDialog - } // Component - calcAmpsPerVoltDlgComponent - - - QGCLabel { - text: qsTr("Battery") - font.family: ScreenTools.demiboldFontFamily - } - - Rectangle { - width: parent.width - height: batteryGrid.height + ScreenTools.defaultFontPixelHeight - color: qgcPal.windowShade - - GridLayout { - id: batteryGrid - anchors.margins: ScreenTools.defaultFontPixelHeight / 2 - anchors.left: parent.left - anchors.top: parent.top - columns: 5 - columnSpacing: ScreenTools.defaultFontPixelWidth - - QGCLabel { - text: qsTr("Number of Cells (in Series)") - } + } // Column + } // QGCFlickable + } // QGCViewDialog + } // Component - calcAmpsPerVoltDlgComponent - FactTextField { - id: cellsField - width: textEditWidth - fact: battNumCells - showUnits: true - } + QGCGroupBox { + id: batteryGroup + title: qsTr("Battery") - QGCColoredImage { - id: batteryImage - Layout.rowSpan: 3 - width: height * 0.75 - height: 100 - sourceSize.height: height - fillMode: Image.PreserveAspectFit - smooth: true - color: qgcPal.text - cache: false - source: getBatteryImage(); - } + GridLayout { + id: batteryGrid + columns: 5 + columnSpacing: ScreenTools.defaultFontPixelWidth - Item { width: 1; height: 1; Layout.columnSpan: 2 } + QGCLabel { + text: qsTr("Number of Cells (in Series)") + } - QGCLabel { - id: battHighLabel - text: qsTr("Full Voltage (per cell)") - } + FactTextField { + id: cellsField + width: textEditWidth + fact: battNumCells + showUnits: true + } - FactTextField { - id: battHighField - width: textEditWidth - fact: battHighVolt - showUnits: true - } + QGCColoredImage { + id: batteryImage + Layout.rowSpan: 3 + width: height * 0.75 + height: 100 + sourceSize.height: height + fillMode: Image.PreserveAspectFit + smooth: true + color: qgcPal.text + cache: false + source: getBatteryImage(); + } - QGCLabel { - text: qsTr("Battery Max:") - } + Item { width: 1; height: 1; Layout.columnSpan: 2 } - QGCLabel { - text: (battNumCells.value * battHighVolt.value).toFixed(1) + ' V' - } + QGCLabel { + id: battHighLabel + text: qsTr("Full Voltage (per cell)") + } - QGCLabel { - id: battLowLabel - text: qsTr("Empty Voltage (per cell)") - } + FactTextField { + id: battHighField + width: textEditWidth + fact: battHighVolt + showUnits: true + } - FactTextField { - id: battLowField - width: textEditWidth - fact: battLowVolt - showUnits: true - } + QGCLabel { + text: qsTr("Battery Max:") + } - QGCLabel { - text: qsTr("Battery Min:") - } + QGCLabel { + text: (battNumCells.value * battHighVolt.value).toFixed(1) + ' V' + } - QGCLabel { - text: (battNumCells.value * battLowVolt.value).toFixed(1) + ' V' - } + QGCLabel { + id: battLowLabel + text: qsTr("Empty Voltage (per cell)") + } - QGCLabel { - text: qsTr("Voltage divider") - } + FactTextField { + id: battLowField + width: textEditWidth + fact: battLowVolt + showUnits: true + } - FactTextField { - id: voltMultField - fact: battVoltageDivider - } + QGCLabel { + text: qsTr("Battery Min:") + } - QGCButton { - id: voltMultCalculateButton - text: "Calculate" - onClicked: showDialog(calcVoltageDividerDlgComponent, qsTr("Calculate Voltage Divider"), powerPage.showDialogDefaultWidth, StandardButton.Close) - } + QGCLabel { + text: (battNumCells.value * battLowVolt.value).toFixed(1) + ' V' + } - Item { width: 1; height: 1; Layout.columnSpan: 2 } + QGCLabel { + text: qsTr("Voltage divider") + } - QGCLabel { - id: voltMultHelp - Layout.columnSpan: batteryGrid.columns - Layout.fillWidth: true - font.pointSize: ScreenTools.smallFontPointSize - wrapMode: Text.WordWrap - text: "If the battery voltage reported by the vehicle is largely different than the voltage read externally using a voltmeter you can adjust the voltage multiplier value to correct this. " + - "Click the Calculate button for help with calculating a new value." - } + FactTextField { + id: voltMultField + fact: battVoltageDivider + } - QGCLabel { - id: ampPerVoltLabel - text: qsTr("Amps per volt") - } + QGCButton { + id: voltMultCalculateButton + text: "Calculate" + onClicked: showDialog(calcVoltageDividerDlgComponent, qsTr("Calculate Voltage Divider"), powerPage.showDialogDefaultWidth, StandardButton.Close) + } - FactTextField { - id: ampPerVoltField - fact: battAmpsPerVolt - } + Item { width: 1; height: 1; Layout.columnSpan: 2 } - QGCButton { - id: ampPerVoltCalculateButton - text: "Calculate" - onClicked: showDialog(calcAmpsPerVoltDlgComponent, qsTr("Calculate Amps per Volt"), powerPage.showDialogDefaultWidth, StandardButton.Close) - } + QGCLabel { + id: voltMultHelp + Layout.columnSpan: batteryGrid.columns + Layout.fillWidth: true + font.pointSize: ScreenTools.smallFontPointSize + wrapMode: Text.WordWrap + text: "If the battery voltage reported by the vehicle is largely different than the voltage read externally using a voltmeter you can adjust the voltage multiplier value to correct this. " + + "Click the Calculate button for help with calculating a new value." + } - Item { width: 1; height: 1; Layout.columnSpan: 2 } + QGCLabel { + id: ampPerVoltLabel + text: qsTr("Amps per volt") + } - QGCLabel { - id: ampPerVoltHelp - Layout.columnSpan: batteryGrid.columns - Layout.fillWidth: true - font.pointSize: ScreenTools.smallFontPointSize - wrapMode: Text.WordWrap - text: "If the current draw reported by the vehicle is largely different than the current read externally using a current meter you can adjust the amps per volt value to correct this. " + - "Click the Calculate button for help with calculating a new value." - } - } // Grid - } // Rectangle - Battery settings - - QGCLabel { - text: qsTr("ESC PWM Minimum and Maximum Calibration") - font.family: ScreenTools.demiboldFontFamily - } - - Rectangle { - width: parent.width - height: escCalColumn.height + ScreenTools.defaultFontPixelHeight - color: qgcPal.windowShade - - Column { - id : escCalColumn - anchors.margins: ScreenTools.defaultFontPixelHeight / 2 - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: ScreenTools.defaultFontPixelWidth - - QGCLabel { - width: parent.width - color: qgcPal.warningText - wrapMode: Text.WordWrap - text: qsTr("WARNING: Propellers must be removed from vehicle prior to performing ESC calibration.") - } + FactTextField { + id: ampPerVoltField + fact: battAmpsPerVolt + } - QGCLabel { - text: qsTr("You must use USB connection for this operation.") - } + QGCButton { + id: ampPerVoltCalculateButton + text: "Calculate" + onClicked: showDialog(calcAmpsPerVoltDlgComponent, qsTr("Calculate Amps per Volt"), powerPage.showDialogDefaultWidth, StandardButton.Close) + } - QGCButton { - text: qsTr("Calibrate") - width: ScreenTools.defaultFontPixelWidth * 20 - onClicked: controller.calibrateEsc() - } - } - } - - QGCCheckBox { - id: showUAVCAN - text: qsTr("Show UAVCAN Settings") - visible: uavcanEnable !== -1 - } - - QGCLabel { - text: qsTr("UAVCAN Bus Configuration") - font.family: ScreenTools.demiboldFontFamily - visible: showUAVCAN.checked - } - - Rectangle { - width: parent.width - height: uavCanConfigColumn.height + ScreenTools.defaultFontPixelHeight - color: qgcPal.windowShade - visible: showUAVCAN.checked - - Column { - id: uavCanConfigColumn - anchors.margins: ScreenTools.defaultFontPixelHeight / 2 - anchors.left: parent.left - anchors.top: parent.top - spacing: ScreenTools.defaultFontPixelWidth - - FactCheckBox { - id: uavcanEnabledCheckBox - width: ScreenTools.defaultFontPixelWidth * 20 - fact: uavcanEnable - checkedValue: 3 - uncheckedValue: 0 - text: qsTr("Enable UAVCAN as the default MAIN output bus (requires autopilot restart)") - } - } - } - - QGCLabel { - text: qsTr("UAVCAN Motor Index and Direction Assignment") - font.family: ScreenTools.demiboldFontFamily - visible: showUAVCAN.checked - } - - Rectangle { - width: parent.width - height: uavCanEscCalColumn.height + ScreenTools.defaultFontPixelHeight - color: qgcPal.windowShade - visible: showUAVCAN.checked - enabled: uavcanEnabledCheckBox.checked - - Column { - id: uavCanEscCalColumn - anchors.margins: ScreenTools.defaultFontPixelHeight / 2 - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: ScreenTools.defaultFontPixelWidth - - QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - color: qgcPal.warningText - text: qsTr("WARNING: Propellers must be removed from vehicle prior to performing UAVCAN ESC configuration.") - } + Item { width: 1; height: 1; Layout.columnSpan: 2 } - QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - text: qsTr("ESC parameters will only be accessible in the editor after assignment.") - } + QGCLabel { + id: ampPerVoltHelp + Layout.columnSpan: batteryGrid.columns + Layout.fillWidth: true + font.pointSize: ScreenTools.smallFontPointSize + wrapMode: Text.WordWrap + text: "If the current draw reported by the vehicle is largely different than the current read externally using a current meter you can adjust the amps per volt value to correct this. " + + "Click the Calculate button for help with calculating a new value." + } + } // Grid + } // QGCGroupBox - Battery settings - QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - text: qsTr("Start the process, then turn each motor into its turn direction, in the order of their motor indices.") - } + QGCGroupBox { + anchors.left: batteryGroup.left + anchors.right: batteryGroup.right + title: qsTr("ESC PWM Minimum and Maximum Calibration") - QGCButton { - text: qsTr("Start Assignment") - width: ScreenTools.defaultFontPixelWidth * 20 - onClicked: controller.busConfigureActuators() - } + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelWidth + + QGCLabel { + color: qgcPal.warningText + wrapMode: Text.WordWrap + text: qsTr("WARNING: Propellers must be removed from vehicle prior to performing ESC calibration.") + Layout.fillWidth: true + } - QGCButton { - text: qsTr("Stop Assignment") - width: ScreenTools.defaultFontPixelWidth * 20 - onClicked: controller.stopBusConfigureActuators() + QGCLabel { + text: qsTr("You must use USB connection for this operation.") + } + + QGCButton { + text: qsTr("Calibrate") + width: ScreenTools.defaultFontPixelWidth * 20 + onClicked: controller.calibrateEsc() + } } } - } - - QGCCheckBox { - id: showAdvanced - text: qsTr("Show Advanced Settings") - } - - QGCLabel { - text: qsTr("Advanced Power Settings") - font.family: ScreenTools.demiboldFontFamily - visible: showAdvanced.checked - } - - Rectangle { - id: batteryRectangle - width: parent.width - height: advBatteryColumn.height + ScreenTools.defaultFontPixelHeight - color: qgcPal.windowShade - visible: showAdvanced.checked - - Column { - id: advBatteryColumn - anchors.margins: ScreenTools.defaultFontPixelHeight / 2 - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - spacing: ScreenTools.defaultFontPixelWidth - Row { - spacing: ScreenTools.defaultFontPixelWidth + QGCCheckBox { + id: showUAVCAN + text: qsTr("Show UAVCAN Settings") + checked: uavcanEnable.rawValue != 0 + } - QGCLabel { - text: qsTr("Voltage Drop on Full Load (per cell)") - anchors.baseline: battDropField.baseline + QGCGroupBox { + anchors.left: batteryGroup.left + anchors.right: batteryGroup.right + title: qsTr("UAVCAN Bus Configuration") + visible: showUAVCAN.checked + + Row { + id: uavCanConfigRow + spacing: ScreenTools.defaultFontPixelWidth + + FactComboBox { + id: uavcanEnabledCheckBox + width: ScreenTools.defaultFontPixelWidth * 20 + fact: uavcanEnable + indexModel: false } - FactTextField { - id: battDropField - width: textEditWidth - fact: battVoltLoadDrop - showUnits: true + QGCLabel { + anchors.verticalCenter: parent.verticalCenter + text: qsTr("Change required restart") } } + } - QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - text: qsTr("Batteries show less voltage at high throttle. Enter the difference in Volts between idle throttle and full ") + - qsTr("throttle, divided by the number of battery cells. Leave at the default if unsure. ") + - highlightPrefix + qsTr("If this value is set too high, the battery might be deep discharged and damaged.") + highlightSuffix - } + QGCGroupBox { + anchors.left: batteryGroup.left + anchors.right: batteryGroup.right + title: qsTr("UAVCAN Motor Index and Direction Assignment") + visible: showUAVCAN.checked - Row { - spacing: ScreenTools.defaultFontPixelWidth + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelWidth + + QGCLabel { + wrapMode: Text.WordWrap + color: qgcPal.warningText + text: qsTr("WARNING: Propellers must be removed from vehicle prior to performing UAVCAN ESC configuration.") + Layout.fillWidth: true + } QGCLabel { - text: qsTr("Compensated Minimum Voltage:") + wrapMode: Text.WordWrap + text: qsTr("ESC parameters will only be accessible in the editor after assignment.") + Layout.fillWidth: true } QGCLabel { - text: ((battNumCells.value * battLowVolt.value) - (battNumCells.value * battVoltLoadDrop.value)).toFixed(1) + qsTr(" V") + wrapMode: Text.WordWrap + text: qsTr("Start the process, then turn each motor into its turn direction, in the order of their motor indices.") + Layout.fillWidth: true + } + + QGCButton { + text: qsTr("Start Assignment") + width: ScreenTools.defaultFontPixelWidth * 20 + onClicked: controller.busConfigureActuators() + } + + QGCButton { + text: qsTr("Stop Assignment") + width: ScreenTools.defaultFontPixelWidth * 20 + onClicked: controller.stopBusConfigureActuators() } } } - } // Rectangle - Advanced power settings - } // Column + + QGCCheckBox { + id: showAdvanced + text: qsTr("Show Advanced Settings") + } + + QGCGroupBox { + anchors.left: batteryGroup.left + anchors.right: batteryGroup.right + title: qsTr("Advanced Power Settings") + visible: showAdvanced.checked + + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelWidth + + Row { + spacing: ScreenTools.defaultFontPixelWidth + + QGCLabel { + text: qsTr("Voltage Drop on Full Load (per cell)") + anchors.baseline: battDropField.baseline + } + + FactTextField { + id: battDropField + width: textEditWidth + fact: battVoltLoadDrop + showUnits: true + } + } + + QGCLabel { + wrapMode: Text.WordWrap + text: qsTr("Batteries show less voltage at high throttle. Enter the difference in Volts between idle throttle and full ") + + qsTr("throttle, divided by the number of battery cells. Leave at the default if unsure. ") + + highlightPrefix + qsTr("If this value is set too high, the battery might be deep discharged and damaged.") + highlightSuffix + Layout.fillWidth: true + } + + Row { + spacing: ScreenTools.defaultFontPixelWidth + + QGCLabel { + text: qsTr("Compensated Minimum Voltage:") + } + + QGCLabel { + text: ((battNumCells.value * battLowVolt.value) - (battNumCells.value * battVoltLoadDrop.value)).toFixed(1) + qsTr(" V") + } + } + } // Column + } // QGCGroupBox - Advanced power settings + } // Column + } // Item } // Component } // SetupPage diff --git a/src/AutoPilotPlugins/PX4/SensorsComponent.qml b/src/AutoPilotPlugins/PX4/SensorsComponent.qml index e798565c471fde0d6ab8dca455d79407f26727a3..7a732d786fb68995fe733751de4b83b4d74e4adc 100644 --- a/src/AutoPilotPlugins/PX4/SensorsComponent.qml +++ b/src/AutoPilotPlugins/PX4/SensorsComponent.qml @@ -97,6 +97,8 @@ SetupPage { property Fact sens_board_rot: controller.getParameterFact(-1, "SENS_BOARD_ROT") property Fact sens_board_x_off: controller.getParameterFact(-1, "SENS_BOARD_X_OFF") + property Fact sens_board_y_off: controller.getParameterFact(-1, "SENS_BOARD_Y_OFF") + property Fact sens_board_z_off: controller.getParameterFact(-1, "SENS_BOARD_Z_OFF") property Fact sens_dpres_off: controller.getParameterFact(-1, "SENS_DPRES_OFF") // Id > = signals compass available, rot < 0 signals internal compass @@ -372,7 +374,7 @@ SetupPage { id: levelButton width: parent.buttonWidth text: qsTr("Level Horizon") - indicatorGreen: sens_board_x_off.value != 0 + 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 onClicked: { diff --git a/src/FactSystem/Fact.h b/src/FactSystem/Fact.h index 4d50786953404a9e9967d5a578d874db6d63858d..c3db1f46b3571cddc9ca7db709e293901f9cd5e3 100644 --- a/src/FactSystem/Fact.h +++ b/src/FactSystem/Fact.h @@ -55,7 +55,6 @@ public: Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(bool rebootRequired READ rebootRequired CONSTANT) Q_PROPERTY(QString shortDescription READ shortDescription CONSTANT) - Q_PROPERTY(FactMetaData::ValueType_t type READ type CONSTANT) Q_PROPERTY(QString units READ cookedUnits CONSTANT) Q_PROPERTY(QVariant value READ cookedValue WRITE setCookedValue NOTIFY valueChanged) Q_PROPERTY(QVariant rawValue READ rawValue WRITE setRawValue NOTIFY rawValueChanged) @@ -63,6 +62,8 @@ public: Q_PROPERTY(QString valueString READ cookedValueString NOTIFY valueChanged) Q_PROPERTY(QString enumOrValueString READ enumOrValueString NOTIFY valueChanged) Q_PROPERTY(double increment READ increment CONSTANT) + Q_PROPERTY(bool typeIsString READ typeIsString CONSTANT) + Q_PROPERTY(bool typeIsBool READ typeIsBool CONSTANT) /// Convert and validate value /// @param convertOnly true: validate type conversion only, false: validate against meta data as well @@ -103,6 +104,8 @@ public: bool rebootRequired (void) const; QString enumOrValueString (void); // This is not const, since an unknown value can modify the enum lists double increment (void) const; + bool typeIsString (void) const { return type() == FactMetaData::valueTypeString; } + bool typeIsBool (void) const { return type() == FactMetaData::valueTypeBool; } /// Returns the values as a string with full 18 digit precision if float/double. QString rawValueStringFullPrecision(void) const; diff --git a/src/FactSystem/FactControls/FactCheckBox.qml b/src/FactSystem/FactControls/FactCheckBox.qml index cd421ad5efebd53b87c13f5b0b48e95aaafc3258..f64d20041a0dcfb784144daa32be2679cd5346cd 100644 --- a/src/FactSystem/FactControls/FactCheckBox.qml +++ b/src/FactSystem/FactControls/FactCheckBox.qml @@ -11,12 +11,13 @@ QGCCheckBox { property variant checkedValue: 1 property variant uncheckedValue: 0 - partiallyCheckedEnabled: fact.value != checkedValue && fact.value != uncheckedValue - checkedState: fact.value == checkedValue ? Qt.Checked : (fact.value == uncheckedValue ? Qt.Unchecked : Qt.PartiallyChecked) + checkedState: fact ? + (fact.typeIsBool ? + (fact.value === true ? Qt.Checked : Qt.Unchecked) : + (fact.value === checkedValue ? Qt.Checked : Qt.Unchecked)) : + Qt.Unchecked text: qsTr("Label") - onClicked: { - fact.value = checked ? checkedValue : uncheckedValue - } + onClicked: fact.value = checked ? checkedValue : uncheckedValue } diff --git a/src/FactSystem/FactControls/FactPanelController.cc b/src/FactSystem/FactControls/FactPanelController.cc index 7e77599333d5dd7aa33926bacb76b14750b8bb95..b7059d7768c8f1b6c8757a78b24b2ea3c5442172 100644 --- a/src/FactSystem/FactControls/FactPanelController.cc +++ b/src/FactSystem/FactControls/FactPanelController.cc @@ -127,8 +127,9 @@ Fact* FactPanelController::getParameterFact(int componentId, const QString& name QQmlEngine::setObjectOwnership(fact, QQmlEngine::CppOwnership); return fact; } else { - if(reportMissing) + if (reportMissing) { _reportMissingParameter(componentId, name); + } return NULL; } } diff --git a/src/FactSystem/FactControls/FactTextField.qml b/src/FactSystem/FactControls/FactTextField.qml index bf0b4f956cbbc83a36ef85c99584bd20716e84bf..58a7093609898675b3ced471dddbd437d0768162 100644 --- a/src/FactSystem/FactControls/FactTextField.qml +++ b/src/FactSystem/FactControls/FactTextField.qml @@ -16,16 +16,20 @@ QGCTextField { showUnits: true showHelp: true - property Fact fact: null + property Fact fact: null + property string _validateString // At this point all Facts are numeric - validator: DoubleValidator {} - inputMethodHints: ScreenTools.isiOS ? - Qt.ImhNone : // iOS numeric keyboard has not done button, we can't use it - Qt.ImhFormattedNumbersOnly // Forces use of virtual numeric keyboard + inputMethodHints: (fact.typeIsString || ScreenTools.isiOS) ? + Qt.ImhNone : // iOS numeric keyboard has no done button, we can't use it + Qt.ImhFormattedNumbersOnly // Forces use of virtual numeric keyboard onEditingFinished: { + if (ScreenTools.isMobile) { + // Toss focus on mobile after Done on virtual keyboard. Prevent strange interactions. + focus = false + } if (typeof qgcView !== 'undefined' && qgcView) { var errorString = fact.validate(text, false /* convertOnly */) if (errorString == "") { @@ -40,7 +44,7 @@ QGCTextField { } } - onHelpClicked: qgcView.showDialog(helpDialogComponent, qsTr("Value Details"), qgcView.showDialogDefaultWidth, StandardButton.Save) + onHelpClicked: qgcView.showDialog(helpDialogComponent, qsTr("Value Details"), qgcView.showDialogDefaultWidth, StandardButton.Save | StandardButton.Cancel) Component { diff --git a/src/FactSystem/FactMetaData.cc b/src/FactSystem/FactMetaData.cc index 51fe0d09f7ef0b267c80b1e7794125c0bce808d5..dc9651422c11992cbe255fc996b4b8b32a6f4784 100644 --- a/src/FactSystem/FactMetaData.cc +++ b/src/FactSystem/FactMetaData.cc @@ -7,15 +7,10 @@ * ****************************************************************************/ - -/// @file -/// @brief Object which exposes a FactMetaData -/// -/// @author Don Gagne - #include "FactMetaData.h" -#include "QGroundControlQmlGlobal.h" +#include "SettingsManager.h" #include "JsonHelper.h" +#include "QGCApplication.h" #include #include @@ -45,21 +40,21 @@ const FactMetaData::BuiltInTranslation_s FactMetaData::_rgBuiltInTranslations[] // Translations driven by app settings const FactMetaData::AppSettingsTranslation_s FactMetaData::_rgAppSettingsTranslations[] = { - { "m", "m", false, QGroundControlQmlGlobal::DistanceUnitsMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator }, - { "meters", "meters", false, QGroundControlQmlGlobal::DistanceUnitsMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator }, - { "m/s", "m/s", true, QGroundControlQmlGlobal::SpeedUnitsMetersPerSecond, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator }, - { "m^2", "m^2", false, QGroundControlQmlGlobal::AreaUnitsSquareMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator }, - { "m", "ft", false, QGroundControlQmlGlobal::DistanceUnitsFeet, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters }, - { "meters", "ft", false, QGroundControlQmlGlobal::DistanceUnitsFeet, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters }, - { "m^2", "km^2", false, QGroundControlQmlGlobal::AreaUnitsSquareKilometers, FactMetaData::_squareMetersToSquareKilometers, FactMetaData::_squareKilometersToSquareMeters }, - { "m^2", "ha", false, QGroundControlQmlGlobal::AreaUnitsHectares, FactMetaData::_squareMetersToHectares, FactMetaData::_hectaresToSquareMeters }, - { "m^2", "ft^2", false, QGroundControlQmlGlobal::AreaUnitsSquareFeet, FactMetaData::_squareMetersToSquareFeet, FactMetaData::_squareFeetToSquareMeters }, - { "m^2", "ac", false, QGroundControlQmlGlobal::AreaUnitsAcres, FactMetaData::_squareMetersToAcres, FactMetaData::_acresToSquareMeters }, - { "m^2", "mi^2", false, QGroundControlQmlGlobal::AreaUnitsSquareMiles, FactMetaData::_squareMetersToSquareMiles, FactMetaData::_squareMilesToSquareMeters }, - { "m/s", "ft/s", true, QGroundControlQmlGlobal::SpeedUnitsFeetPerSecond, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters }, - { "m/s", "mph", true, QGroundControlQmlGlobal::SpeedUnitsMilesPerHour, FactMetaData::_metersPerSecondToMilesPerHour, FactMetaData::_milesPerHourToMetersPerSecond }, - { "m/s", "km/h", true, QGroundControlQmlGlobal::SpeedUnitsKilometersPerHour, FactMetaData::_metersPerSecondToKilometersPerHour, FactMetaData::_kilometersPerHourToMetersPerSecond }, - { "m/s", "kn", true, QGroundControlQmlGlobal::SpeedUnitsKnots, FactMetaData::_metersPerSecondToKnots, FactMetaData::_knotsToMetersPerSecond }, + { "m", "m", false, UnitsSettings::DistanceUnitsMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator }, + { "meters", "meters", false, UnitsSettings::DistanceUnitsMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator }, + { "m/s", "m/s", true, UnitsSettings::SpeedUnitsMetersPerSecond, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator }, + { "m^2", "m^2", false, UnitsSettings::AreaUnitsSquareMeters, FactMetaData::_defaultTranslator, FactMetaData::_defaultTranslator }, + { "m", "ft", false, UnitsSettings::DistanceUnitsFeet, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters }, + { "meters", "ft", false, UnitsSettings::DistanceUnitsFeet, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters }, + { "m^2", "km^2", false, UnitsSettings::AreaUnitsSquareKilometers, FactMetaData::_squareMetersToSquareKilometers, FactMetaData::_squareKilometersToSquareMeters }, + { "m^2", "ha", false, UnitsSettings::AreaUnitsHectares, FactMetaData::_squareMetersToHectares, FactMetaData::_hectaresToSquareMeters }, + { "m^2", "ft^2", false, UnitsSettings::AreaUnitsSquareFeet, FactMetaData::_squareMetersToSquareFeet, FactMetaData::_squareFeetToSquareMeters }, + { "m^2", "ac", false, UnitsSettings::AreaUnitsAcres, FactMetaData::_squareMetersToAcres, FactMetaData::_acresToSquareMeters }, + { "m^2", "mi^2", false, UnitsSettings::AreaUnitsSquareMiles, FactMetaData::_squareMetersToSquareMiles, FactMetaData::_squareMilesToSquareMeters }, + { "m/s", "ft/s", true, UnitsSettings::SpeedUnitsFeetPerSecond, FactMetaData::_metersToFeet, FactMetaData::_feetToMeters }, + { "m/s", "mph", true, UnitsSettings::SpeedUnitsMilesPerHour, FactMetaData::_metersPerSecondToMilesPerHour, FactMetaData::_milesPerHourToMetersPerSecond }, + { "m/s", "km/h", true, UnitsSettings::SpeedUnitsKilometersPerHour, FactMetaData::_metersPerSecondToKilometersPerHour, FactMetaData::_kilometersPerHourToMetersPerSecond }, + { "m/s", "kn", true, UnitsSettings::SpeedUnitsKnots, FactMetaData::_metersPerSecondToKnots, FactMetaData::_knotsToMetersPerSecond }, }; const char* FactMetaData::_decimalPlacesJsonKey = "decimalPlaces"; @@ -156,7 +151,7 @@ QVariant FactMetaData::rawDefaultValue(void) const void FactMetaData::setRawDefaultValue(const QVariant& rawDefaultValue) { - if (_rawMin <= rawDefaultValue && rawDefaultValue <= _rawMax) { + if (_type == valueTypeString || (_rawMin <= rawDefaultValue && rawDefaultValue <= _rawMax)) { _rawDefaultValue = rawDefaultValue; _defaultValueAvailable = true; } else { @@ -207,6 +202,10 @@ QVariant FactMetaData::_minForType(void) const return QVariant(-std::numeric_limits::max()); case valueTypeDouble: return QVariant(-std::numeric_limits::max()); + case valueTypeString: + return QVariant(); + case valueTypeBool: + return QVariant(0); } // Make windows compiler happy, even switch is full cased @@ -232,6 +231,10 @@ QVariant FactMetaData::_maxForType(void) const return QVariant(std::numeric_limits::max()); case valueTypeDouble: return QVariant(std::numeric_limits::max()); + case valueTypeString: + return QVariant(); + case valueTypeBool: + return QVariant(1); } // Make windows compiler happy, even switch is full cased @@ -284,6 +287,14 @@ bool FactMetaData::convertAndValidateRaw(const QVariant& rawValue, bool convertO } } break; + case FactMetaData::valueTypeString: + convertOk = true; + typedValue = QVariant(rawValue.toString()); + break; + case FactMetaData::valueTypeBool: + convertOk = true; + typedValue = QVariant(rawValue.toBool()); + break; } if (!convertOk) { @@ -339,6 +350,14 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co } } break; + case FactMetaData::valueTypeString: + convertOk = true; + typedValue = QVariant(cookedValue.toString()); + break; + case FactMetaData::valueTypeBool: + convertOk = true; + typedValue = QVariant(cookedValue.toBool()); + break; } if (!convertOk) { @@ -555,7 +574,9 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString, << QStringLiteral("Uint32") << QStringLiteral("Int32") << QStringLiteral("Float") - << QStringLiteral("Double"); + << QStringLiteral("Double") + << QStringLiteral("String") + << QStringLiteral("Bool"); knownTypes << valueTypeUint8 << valueTypeInt8 @@ -564,7 +585,9 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString, << valueTypeUint32 << valueTypeInt32 << valueTypeFloat - << valueTypeDouble; + << valueTypeDouble + << valueTypeString + << valueTypeBool; for (int i=0; irawUnits == _rawUnits.toLower() && - ((pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == QGroundControlQmlGlobal::speedUnits()->rawValue().toUInt()) || - (!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == QGroundControlQmlGlobal::distanceUnits()->rawValue().toUInt()))) { + ((pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == qgcApp()->toolbox()->settingsManager()->unitsSettings()->speedUnits()->rawValue().toUInt()) || + (!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == qgcApp()->toolbox()->settingsManager()->unitsSettings()->distanceUnits()->rawValue().toUInt()))) { _cookedUnits = pAppSettingsTranslation->cookedUnits; setTranslators(pAppSettingsTranslation->rawTranslator, pAppSettingsTranslation->cookedTranslator); return; @@ -628,7 +651,7 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsDist const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i]; if (pAppSettingsTranslation->rawUnits == rawUnits && - (!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == QGroundControlQmlGlobal::distanceUnits()->rawValue().toUInt())) { + (!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == qgcApp()->toolbox()->settingsManager()->unitsSettings()->distanceUnits()->rawValue().toUInt())) { return pAppSettingsTranslation; } } @@ -642,7 +665,7 @@ const FactMetaData::AppSettingsTranslation_s* FactMetaData::_findAppSettingsArea const AppSettingsTranslation_s* pAppSettingsTranslation = &_rgAppSettingsTranslations[i]; if (pAppSettingsTranslation->rawUnits == rawUnits && - (!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == QGroundControlQmlGlobal::areaUnits()->rawValue().toUInt()) + (!pAppSettingsTranslation->speed && pAppSettingsTranslation->speedOrDistanceUnits == qgcApp()->toolbox()->settingsManager()->unitsSettings()->areaUnits()->rawValue().toUInt()) ) { return pAppSettingsTranslation; } @@ -765,8 +788,8 @@ FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QObjec // Validate key types QStringList keys; QList types; - keys << _nameJsonKey << _decimalPlacesJsonKey << _typeJsonKey << _shortDescriptionJsonKey << _longDescriptionJsonKey << _unitsJsonKey << _defaultValueJsonKey << _minJsonKey << _maxJsonKey; - types << QJsonValue::String << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Double << QJsonValue::Double << QJsonValue::Double; + keys << _nameJsonKey << _decimalPlacesJsonKey << _typeJsonKey << _shortDescriptionJsonKey << _longDescriptionJsonKey << _unitsJsonKey << _minJsonKey << _maxJsonKey; + types << QJsonValue::String << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Double << QJsonValue::Double; if (!JsonHelper::validateKeyTypes(json, keys, types, errorString)) { qWarning() << errorString; return new FactMetaData(valueTypeUint32, metaDataParent); @@ -810,13 +833,19 @@ FactMetaData* FactMetaData::createFromJsonObject(const QJsonObject& json, QObjec metaData->setRawUnits(json[_unitsJsonKey].toString()); } if (json.contains(_defaultValueJsonKey)) { - metaData->setRawDefaultValue(json[_defaultValueJsonKey].toDouble()); + metaData->setRawDefaultValue(json[_defaultValueJsonKey].toVariant()); } if (json.contains(_minJsonKey)) { - metaData->setRawMin(json[_minJsonKey].toDouble()); + QVariant typedValue; + QString errorString; + metaData->convertAndValidateRaw(json[_minJsonKey].toVariant(), true /* convertOnly */, typedValue, errorString); + metaData->setRawMin(typedValue); } if (json.contains(_maxJsonKey)) { - metaData->setRawMax(json[_maxJsonKey].toDouble()); + QVariant typedValue; + QString errorString; + metaData->convertAndValidateRaw(json[_maxJsonKey].toVariant(), true /* convertOnly */, typedValue, errorString); + metaData->setRawMax(typedValue); } return metaData; diff --git a/src/FactSystem/FactMetaData.h b/src/FactSystem/FactMetaData.h index 07d4b4d23897d50dab53e4a51d8dd2987b1ffb90..3bc51f29546979d4eb9adc5d191c122fc77d8764 100644 --- a/src/FactSystem/FactMetaData.h +++ b/src/FactSystem/FactMetaData.h @@ -37,7 +37,9 @@ public: valueTypeUint32, valueTypeInt32, valueTypeFloat, - valueTypeDouble + valueTypeDouble, + valueTypeString, + valueTypeBool } ValueType_t; typedef QVariant (*Translator)(const QVariant& from); diff --git a/src/FactSystem/FactSystem.cc b/src/FactSystem/FactSystem.cc index e88b8ce552f5b85486222e9835c3458a826d8fe0..0b9cb3de3b8668536cbce719282f41bc09f23684 100644 --- a/src/FactSystem/FactSystem.cc +++ b/src/FactSystem/FactSystem.cc @@ -30,6 +30,7 @@ void FactSystem::setToolbox(QGCToolbox *toolbox) QGCTool::setToolbox(toolbox); qmlRegisterType (_factSystemQmlUri, 1, 0, "Fact"); + qmlRegisterType (_factSystemQmlUri, 1, 0, "FactMetaData"); qmlRegisterType(_factSystemQmlUri, 1, 0, "FactPanelController"); qmlRegisterUncreatableType(_factSystemQmlUri, 1, 0, "FactGroup", "ReferenceOnly"); diff --git a/src/FactSystem/FactSystemTest.qml b/src/FactSystem/FactSystemTest.qml index 127c2470c5658c029a2caa7b771a9fc2e2c67206..8ac4d9ada73ac7759b67e27573bd4d3b462b69c9 100644 --- a/src/FactSystem/FactSystemTest.qml +++ b/src/FactSystem/FactSystemTest.qml @@ -32,7 +32,7 @@ FactPanel { TextInput { text: fact2.value - property Fact fact2: controller.getParameterFact(50, "RC_MAP_THROTTLE") + property Fact fact2: controller.getParameterFact(200, "RC_MAP_THROTTLE") onAccepted: fact2.value = text } diff --git a/src/FactSystem/FactSystemTestBase.cc b/src/FactSystem/FactSystemTestBase.cc index 41cb1195c4979fff4100308feb97ce49f85d68ff..35f920229c75525a020779519bf4127f9e11b170 100644 --- a/src/FactSystem/FactSystemTestBase.cc +++ b/src/FactSystem/FactSystemTestBase.cc @@ -58,8 +58,8 @@ void FactSystemTestBase::_parameter_default_component_id_test(void) void FactSystemTestBase::_parameter_specific_component_id_test(void) { - QVERIFY(_vehicle->parameterManager()->parameterExists(50, "RC_MAP_THROTTLE")); - Fact* fact = _vehicle->parameterManager()->getParameter(50, "RC_MAP_THROTTLE"); + QVERIFY(_vehicle->parameterManager()->parameterExists(200, "RC_MAP_THROTTLE")); + Fact* fact = _vehicle->parameterManager()->getParameter(200, "RC_MAP_THROTTLE"); QVERIFY(fact != NULL); QVariant factValue = fact->rawValue(); QCOMPARE(factValue.isValid(), true); diff --git a/src/FactSystem/ParameterManager.cc b/src/FactSystem/ParameterManager.cc index f286e54eb41c93c13f463e13b68a346929d70a33..4d3e73cd68aca3852726bb292b5f7e2b0d1543c7 100644 --- a/src/FactSystem/ParameterManager.cc +++ b/src/FactSystem/ParameterManager.cc @@ -17,7 +17,6 @@ #include "QGCApplication.h" #include "UASMessageHandler.h" #include "FirmwarePlugin.h" -#include "APMFirmwarePlugin.h" #include "UAS.h" #include "JsonHelper.h" @@ -32,7 +31,8 @@ typedef QPair ParamTypeVal; typedef QPair NamedParam; typedef QMap MapID2NamedParam; -QGC_LOGGING_CATEGORY(ParameterManagerVerboseLog, "ParameterManagerVerboseLog") +QGC_LOGGING_CATEGORY(ParameterManagerVerbose1Log, "ParameterManagerVerbose1Log") +QGC_LOGGING_CATEGORY(ParameterManagerVerbose2Log, "ParameterManagerVerbose2Log") Fact ParameterManager::_defaultFact; @@ -46,18 +46,19 @@ ParameterManager::ParameterManager(Vehicle* vehicle) : QObject(vehicle) , _vehicle(vehicle) , _mavlink(NULL) + , _loadProgress(0.0) , _parametersReady(false) , _missingParameters(false) , _initialLoadComplete(false) , _waitingForDefaultComponent(false) , _saveRequired(false) - , _defaultComponentId(MAV_COMP_ID_ALL) , _parameterSetMajorVersion(-1) , _parameterMetaData(NULL) , _prevWaitingReadParamIndexCount(0) , _prevWaitingReadParamNameCount(0) , _prevWaitingWriteParamNameCount(0) , _initialRequestRetryCount(0) + , _disableAllRetries(false) , _totalParamCount(0) { _versionParam = vehicle->firmwarePlugin()->getVersionParam(); @@ -69,22 +70,16 @@ ParameterManager::ParameterManager(Vehicle* vehicle) _mavlink = qgcApp()->toolbox()->mavlinkProtocol(); - // We signal this to ouselves in order to start timer on our thread - connect(this, &ParameterManager::restartWaitingParamTimer, this, &ParameterManager::_restartWaitingParamTimer); - _initialRequestTimeoutTimer.setSingleShot(true); - _initialRequestTimeoutTimer.setInterval(6000); + _initialRequestTimeoutTimer.setInterval(5000); connect(&_initialRequestTimeoutTimer, &QTimer::timeout, this, &ParameterManager::_initialRequestTimeout); _waitingParamTimeoutTimer.setSingleShot(true); - _waitingParamTimeoutTimer.setInterval(1000); + _waitingParamTimeoutTimer.setInterval(3000); connect(&_waitingParamTimeoutTimer, &QTimer::timeout, this, &ParameterManager::_waitingParamTimeout); connect(_vehicle->uas(), &UASInterface::parameterUpdate, this, &ParameterManager::_parameterUpdate); - _defaultComponentIdParam = vehicle->firmwarePlugin()->getDefaultComponentIdParam(); - qCDebug(ParameterManagerLog) << "Default component param" << _defaultComponentIdParam; - // Ensure the cache directory exists QFileInfo(QSettings().fileName()).dir().mkdir("ParamCache"); refreshAllParameters(); @@ -103,28 +98,16 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString return; } - _initialRequestTimeoutTimer.stop(); + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) << + "_parameterUpdate" << + "name:" << parameterName << + "count:" << parameterCount << + "index:" << parameterId << + "mavType:" << mavType << + "value:" << value << + ")"; - if (_initialLoadComplete) { - qCDebug(ParameterManagerLog) << "_parameterUpdate (id:" << vehicleId << - "componentId:" << componentId << - "name:" << parameterName << - "count:" << parameterCount << - "index:" << parameterId << - "mavType:" << mavType << - "value:" << value << - ")"; - } else { - // This is too noisy during initial load - qCDebug(ParameterManagerVerboseLog) << "_parameterUpdate (id:" << vehicleId << - "componentId:" << componentId << - "name:" << parameterName << - "count:" << parameterCount << - "index:" << parameterId << - "mavType:" << mavType << - "value:" << value << - ")"; - } + _initialRequestTimeoutTimer.stop(); #if 0 // Handy for testing retry logic @@ -147,6 +130,10 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString _tryCacheHashLoad(vehicleId, componentId, value); return; } + + _initialRequestTimeoutTimer.stop(); + _waitingParamTimeoutTimer.stop(); + _dataMutex.lock(); // Update our total parameter counts @@ -169,13 +156,7 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString _waitingReadParamNameMap[componentId] = QMap(); _waitingWriteParamNameMap[componentId] = QMap(); - qCDebug(ParameterManagerLog) << "Seeing component for first time, id:" << componentId << "parameter count:" << parameterCount; - } - - // Determine default component id - if (!_defaultComponentIdParam.isEmpty() && _defaultComponentIdParam == parameterName) { - qCDebug(ParameterManagerLog) << "Default component id determined" << componentId; - _defaultComponentId = componentId; + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "Seeing component for first time - paramcount:" << parameterCount; } bool componentParamsComplete = false; @@ -184,21 +165,25 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString componentParamsComplete = true; } - if (_waitingReadParamIndexMap[componentId].contains(parameterId) || - _waitingReadParamNameMap[componentId].contains(parameterName) || - _waitingWriteParamNameMap[componentId].contains(parameterName)) { - // We were waiting for this parameter, restart wait timer. Otherwise it is a spurious parameter update which - // means we should not reset the wait timer. - _waitingParamTimeoutTimer.start(); + if (!_waitingReadParamIndexMap[componentId].contains(parameterId) && + !_waitingReadParamNameMap[componentId].contains(parameterName) && + !_waitingWriteParamNameMap[componentId].contains(parameterName)) { + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix() << "Unrequested param update" << parameterName; } // Remove this parameter from the waiting lists _waitingReadParamIndexMap[componentId].remove(parameterId); _waitingReadParamNameMap[componentId].remove(parameterName); _waitingWriteParamNameMap[componentId].remove(parameterName); - qCDebug(ParameterManagerVerboseLog) << "_waitingReadParamIndexMap:" << _waitingReadParamIndexMap[componentId]; - qCDebug(ParameterManagerLog) << "_waitingReadParamNameMap" << _waitingReadParamNameMap[componentId]; - qCDebug(ParameterManagerLog) << "_waitingWriteParamNameMap" << _waitingWriteParamNameMap[componentId]; + if (_waitingReadParamIndexMap[componentId].count()) { + qCDebug(ParameterManagerVerbose2Log) << _logVehiclePrefix(componentId) << "_waitingReadParamIndexMap:" << _waitingReadParamIndexMap[componentId]; + } + if (_waitingReadParamNameMap[componentId].count()) { + qCDebug(ParameterManagerVerbose2Log) << _logVehiclePrefix(componentId) << "_waitingReadParamNameMap" << _waitingReadParamNameMap[componentId]; + } + if (_waitingWriteParamNameMap[componentId].count()) { + qCDebug(ParameterManagerVerbose2Log) << _logVehiclePrefix(componentId) << "_waitingWriteParamNameMap" << _waitingWriteParamNameMap[componentId]; + } // Track how many parameters we are still waiting for @@ -210,32 +195,37 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString waitingReadParamIndexCount += _waitingReadParamIndexMap[waitingComponentId].count(); } if (waitingReadParamIndexCount) { - qCDebug(ParameterManagerLog) << "waitingReadParamIndexCount:" << waitingReadParamIndexCount; + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) << "waitingReadParamIndexCount:" << waitingReadParamIndexCount; } - foreach(int waitingComponentId, _waitingReadParamNameMap.keys()) { waitingReadParamNameCount += _waitingReadParamNameMap[waitingComponentId].count(); } if (waitingReadParamNameCount) { - qCDebug(ParameterManagerLog) << "waitingReadParamNameCount:" << waitingReadParamNameCount; + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) << "waitingReadParamNameCount:" << waitingReadParamNameCount; } foreach(int waitingComponentId, _waitingWriteParamNameMap.keys()) { waitingWriteParamNameCount += _waitingWriteParamNameMap[waitingComponentId].count(); } if (waitingWriteParamNameCount) { - qCDebug(ParameterManagerLog) << "waitingWriteParamNameCount:" << waitingWriteParamNameCount; + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) << "waitingWriteParamNameCount:" << waitingWriteParamNameCount; } int readWaitingParamCount = waitingReadParamIndexCount + waitingReadParamNameCount; int totalWaitingParamCount = readWaitingParamCount + waitingWriteParamNameCount; if (totalWaitingParamCount) { - qCDebug(ParameterManagerLog) << "totalWaitingParamCount:" << totalWaitingParamCount; - } else if (_defaultComponentId != MAV_COMP_ID_ALL) { - // No more parameters to wait for, stop the timeout. Be careful to not stop timer if we don't have the default - // component yet. - _waitingParamTimeoutTimer.stop(); + // More params to wait for, restart timer + _waitingParamTimeoutTimer.start(); + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix() << "Restarting _waitingParamTimeoutTimer: totalWaitingParamCount:" << totalWaitingParamCount; + } else { + if (!_mapParameterName2Variant.contains(_vehicle->defaultComponentId())) { + // Still waiting for parameters from default component + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "Restarting _waitingParamTimeoutTimer (still waiting for default component params)"; + _waitingParamTimeoutTimer.start(); + } else { + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix() << "Not restarting _waitingParamTimeoutTimer (all requests satisfied)"; + } } // Update progress bar for waiting reads @@ -243,10 +233,10 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString // We are no longer waiting for any reads to complete if (_prevWaitingReadParamIndexCount + _prevWaitingReadParamNameCount != 0) { // Set progress to 0 if not already there - emit parameterListProgress(0); + _setLoadProgress(0.0); } } else { - emit parameterListProgress((float)(_totalParamCount - readWaitingParamCount) / (float)_totalParamCount); + _setLoadProgress((double)(_totalParamCount - readWaitingParamCount) / (double)_totalParamCount); } // Get parameter set version @@ -255,7 +245,7 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString } if (!_mapParameterName2Variant.contains(componentId) || !_mapParameterName2Variant[componentId].contains(parameterName)) { - qCDebug(ParameterManagerLog) << "Adding new fact"; + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) << "Adding new fact" << parameterName; FactMetaData::ValueType_t factType; switch (mavType) { @@ -306,7 +296,7 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString fact->_containerSetRawValue(value); if (componentParamsComplete) { - if (componentId == _defaultComponentId) { + if (componentId == _vehicle->defaultComponentId()) { // Add meta data to default component. We need to do this before we setup the group map since group // map requires meta data. _addMetaDataToDefaultComponent(); @@ -337,8 +327,9 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString _prevWaitingReadParamNameCount = waitingReadParamNameCount; _prevWaitingWriteParamNameCount = waitingWriteParamNameCount; - // Don't fail initial load complete if default component isn't found yet. That will be handled in wait timeout check. - _checkInitialLoadComplete(false /* failIfNoDefaultComponent */); + _checkInitialLoadComplete(); + + qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(componentId) << "_parameterUpdate complete"; } /// Connected to Fact::valueUpdated @@ -363,14 +354,14 @@ void ParameterManager::_valueUpdated(const QVariant& value) _dataMutex.unlock(); _writeParameterRaw(componentId, fact->name(), value); - qCDebug(ParameterManagerLog) << "Set parameter (componentId:" << componentId << "name:" << name << value << ")"; + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "Set parameter - name:" << name << value << "(_waitingParamTimeoutTimer started)"; if (fact->rebootRequired() && !qgcApp()->runningUnitTests()) { qgcApp()->showMessage(QStringLiteral("Change of parameter %1 requires a Vehicle reboot to take effect").arg(name)); } } -void ParameterManager::refreshAllParameters(uint8_t componentID) +void ParameterManager::refreshAllParameters(uint8_t componentId) { _dataMutex.lock(); @@ -381,7 +372,7 @@ void ParameterManager::refreshAllParameters(uint8_t componentID) // Reset index wait lists foreach (int cid, _paramCountMap.keys()) { // Add/Update all indices to the wait list, parameter index is 0-based - if(componentID != MAV_COMP_ID_ALL && componentID != cid) + if(componentId != MAV_COMP_ID_ALL && componentId != cid) continue; for (int waitingIndex = 0; waitingIndex < _paramCountMap[cid]; waitingIndex++) { // This will add a new waiting index if needed and set the retry count for that index to 0 @@ -400,42 +391,20 @@ void ParameterManager::refreshAllParameters(uint8_t componentID) _vehicle->priorityLink()->mavlinkChannel(), &msg, _vehicle->id(), - componentID); + componentId); _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); - QString what = (componentID == MAV_COMP_ID_ALL) ? "MAV_COMP_ID_ALL" : QString::number(componentID); - qCDebug(ParameterManagerLog) << "Request to refresh all parameters for component ID:" << what; -} - -void ParameterManager::_determineDefaultComponentId(void) -{ - if (_defaultComponentId == MAV_COMP_ID_ALL) { - // We don't have a default component id yet. That means the plugin can't provide - // the param to trigger off of. Instead we use the most prominent component id in - // the set of parameters. Better than nothing! - - int largestCompParamCount = 0; - foreach(int componentId, _mapParameterName2Variant.keys()) { - int compParamCount = _mapParameterName2Variant[componentId].count(); - if (compParamCount > largestCompParamCount) { - largestCompParamCount = compParamCount; - _defaultComponentId = componentId; - } - } - - if (_defaultComponentId == MAV_COMP_ID_ALL) { - qWarning() << "All parameters missing, unable to determine default componet id"; - } - } + QString what = (componentId == MAV_COMP_ID_ALL) ? "MAV_COMP_ID_ALL" : QString::number(componentId); + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "Request to refresh all parameters for component ID:" << what; } /// Translates FactSystem::defaultComponentId to real component id if needed int ParameterManager::_actualComponentId(int componentId) { if (componentId == FactSystem::defaultComponentId) { - componentId = _defaultComponentId; + componentId = _vehicle->defaultComponentId(); if (componentId == FactSystem::defaultComponentId) { - qWarning() << "Default component id not set"; + qWarning() << _logVehiclePrefix() << "Default component id not set"; } } @@ -445,7 +414,7 @@ int ParameterManager::_actualComponentId(int componentId) void ParameterManager::refreshParameter(int componentId, const QString& name) { componentId = _actualComponentId(componentId); - qCDebug(ParameterManagerLog) << "refreshParameter (component id:" << componentId << "name:" << name << ")"; + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "refreshParameter - name:" << name << ")"; _dataMutex.lock(); @@ -456,7 +425,8 @@ void ParameterManager::refreshParameter(int componentId, const QString& name) _waitingReadParamNameMap[componentId].remove(mappedParamName); // Remove old wait entry if there _waitingReadParamNameMap[componentId][mappedParamName] = 0; // Add new wait entry and update retry count - emit restartWaitingParamTimer(); + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "restarting _waitingParamTimeout"; + _waitingParamTimeoutTimer.start(); } _dataMutex.unlock(); @@ -467,7 +437,7 @@ void ParameterManager::refreshParameter(int componentId, const QString& name) void ParameterManager::refreshParametersPrefix(int componentId, const QString& namePrefix) { componentId = _actualComponentId(componentId); - qCDebug(ParameterManagerLog) << "refreshParametersPrefix (component id:" << componentId << "name:" << namePrefix << ")"; + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "refreshParametersPrefix - name:" << namePrefix << ")"; foreach(const QString &name, _mapParameterName2Variant[componentId].keys()) { if (name.startsWith(namePrefix)) { @@ -536,40 +506,47 @@ void ParameterManager::_waitingParamTimeout(void) const int maxBatchSize = 10; int batchCount = 0; + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "_waitingParamTimeout"; + // First check for any missing parameters from the initial index based load + batchCount = 0; foreach(int componentId, _waitingReadParamIndexMap.keys()) { - foreach(int paramIndex, _waitingReadParamIndexMap[componentId].keys()) { + if (_waitingReadParamIndexMap[componentId].count()) { + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "_waitingReadParamIndexMap" << _waitingReadParamIndexMap[componentId]; + } + + foreach(int paramIndex, _waitingReadParamIndexMap[componentId].keys()) { + if (++batchCount > maxBatchSize) { + goto Out; + } + _waitingReadParamIndexMap[componentId][paramIndex]++; // Bump retry count - if (_waitingReadParamIndexMap[componentId][paramIndex] > _maxInitialLoadRetrySingleParam) { + if (_disableAllRetries || _waitingReadParamIndexMap[componentId][paramIndex] > _maxInitialLoadRetrySingleParam) { // Give up on this index _failedReadParamIndexMap[componentId] << paramIndex; - qCDebug(ParameterManagerLog) << "Giving up on (componentId:" << componentId << "paramIndex:" << paramIndex << "retryCount:" << _waitingReadParamIndexMap[componentId][paramIndex] << ")"; + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "Giving up on (paramIndex:" << paramIndex << "retryCount:" << _waitingReadParamIndexMap[componentId][paramIndex] << ")"; _waitingReadParamIndexMap[componentId].remove(paramIndex); } else { // Retry again paramsRequested = true; _readParameterRaw(componentId, "", paramIndex); - qCDebug(ParameterManagerLog) << "Read re-request for (componentId:" << componentId << "paramIndex:" << paramIndex << "retryCount:" << _waitingReadParamIndexMap[componentId][paramIndex] << ")"; - - if (++batchCount > maxBatchSize) { - goto Out; - } + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "Read re-request for (paramIndex:" << paramIndex << "retryCount:" << _waitingReadParamIndexMap[componentId][paramIndex] << ")"; } } } - if (!paramsRequested && _defaultComponentId == MAV_COMP_ID_ALL && !_waitingForDefaultComponent) { - // Initial load is complete but we still don't have default component params. Wait one more cycle to see if the - // default component finally shows up. + if (!paramsRequested && !_waitingForDefaultComponent && !_mapParameterName2Variant.contains(_vehicle->defaultComponentId())) { + // Initial load is complete but we still don't have any default component params. Wait one more cycle to see if the + // any show up. + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "Restarting _waitingParamTimeoutTimer - still don't have default component params"; _waitingParamTimeoutTimer.start(); _waitingForDefaultComponent = true; return; } _waitingForDefaultComponent = false; - // Check for initial load complete success/failure. Fail load if we don't have a default component at this point. - _checkInitialLoadComplete(true /* failIfNoDefaultComponent */); + _checkInitialLoadComplete(); if (!paramsRequested) { foreach(int componentId, _waitingWriteParamNameMap.keys()) { @@ -578,14 +555,16 @@ void ParameterManager::_waitingParamTimeout(void) _waitingWriteParamNameMap[componentId][paramName]++; // Bump retry count if (_waitingWriteParamNameMap[componentId][paramName] <= _maxReadWriteRetry) { _writeParameterRaw(componentId, paramName, getParameter(componentId, paramName)->rawValue()); - qCDebug(ParameterManagerLog) << "Write resend for (componentId:" << componentId << "paramName:" << paramName << "retryCount:" << _waitingWriteParamNameMap[componentId][paramName] << ")"; + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "Write resend for (paramName:" << paramName << "retryCount:" << _waitingWriteParamNameMap[componentId][paramName] << ")"; if (++batchCount > maxBatchSize) { goto Out; } } else { // Exceeded max retry count, notify user _waitingWriteParamNameMap[componentId].remove(paramName); - qgcApp()->showMessage(tr("Parameter write failed: comp:%1 param:%2").arg(componentId).arg(paramName)); + QString errorMsg = tr("Parameter write failed: veh:%1 comp:%2 param:%3").arg(_vehicle->id()).arg(componentId).arg(paramName); + qCDebug(ParameterManagerLog) << errorMsg; + qgcApp()->showMessage(errorMsg); } } } @@ -598,14 +577,16 @@ void ParameterManager::_waitingParamTimeout(void) _waitingReadParamNameMap[componentId][paramName]++; // Bump retry count if (_waitingReadParamNameMap[componentId][paramName] <= _maxReadWriteRetry) { _readParameterRaw(componentId, paramName, -1); - qCDebug(ParameterManagerLog) << "Read re-request for (componentId:" << componentId << "paramName:" << paramName << "retryCount:" << _waitingReadParamNameMap[componentId][paramName] << ")"; + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "Read re-request for (paramName:" << paramName << "retryCount:" << _waitingReadParamNameMap[componentId][paramName] << ")"; if (++batchCount > maxBatchSize) { goto Out; } } else { // Exceeded max retry count, notify user _waitingReadParamNameMap[componentId].remove(paramName); - qgcApp()->showMessage(tr("Parameter read failed: comp:%1 param:%2").arg(componentId).arg(paramName)); + QString errorMsg = tr("Parameter read failed: veh:%1 comp:%2 param:%3").arg(_vehicle->id()).arg(componentId).arg(paramName); + qCDebug(ParameterManagerLog) << errorMsg; + qgcApp()->showMessage(errorMsg); } } } @@ -613,6 +594,7 @@ void ParameterManager::_waitingParamTimeout(void) Out: if (paramsRequested) { + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "Restarting _waitingParamTimeoutTimer - re-request"; _waitingParamTimeoutTimer.start(); } } @@ -781,13 +763,13 @@ void ParameterManager::_tryCacheHashLoad(int vehicleId, int componentId, QVarian ani->setDuration(750); connect(ani, &QVariantAnimation::valueChanged, [this](const QVariant &value) { - emit parameterListProgress(value.toFloat()); + _setLoadProgress(value.toDouble()); }); // Hide 500ms after animation finishes connect(ani, &QVariantAnimation::finished, [this](){ QTimer::singleShot(500, [this]() { - emit parameterListProgress(0); + _setLoadProgress(0); }); }); @@ -800,18 +782,14 @@ void ParameterManager::_saveToEEPROM(void) if (_saveRequired) { _saveRequired = false; if (_vehicle->firmwarePlugin()->isCapable(_vehicle, FirmwarePlugin::MavCmdPreflightStorageCapability)) { - mavlink_message_t msg; - mavlink_msg_command_long_pack_chan(_mavlink->getSystemId(), - _mavlink->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - _vehicle->id(), - 0, - MAV_CMD_PREFLIGHT_STORAGE, 1, 1, -1, -1, -1, 0, 0, 0); - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); - qCDebug(ParameterManagerLog) << "_saveToEEPROM"; + _vehicle->sendMavCommand(MAV_COMP_ID_ALL, + MAV_CMD_PREFLIGHT_STORAGE, + true, // showError + 1, // Write parameters to EEPROM + -1); // Don't do anything with mission storage + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "_saveToEEPROM"; } else { - qCDebug(ParameterManagerLog) << "_saveToEEPROM skipped due to FirmwarePlugin::isCapable"; + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "_saveToEEPROM skipped due to FirmwarePlugin::isCapable"; } } } @@ -863,9 +841,20 @@ QString ParameterManager::readParametersFromStream(QTextStream& stream) void ParameterManager::writeParametersToStream(QTextStream &stream) { - stream << "# Onboard parameters for vehicle " << _vehicle->id() << "\n"; + stream << "# Onboard parameters for Vehicle " << _vehicle->id() << "\n"; stream << "#\n"; - stream << "# MAV ID COMPONENT ID PARAM NAME VALUE (FLOAT)\n"; + + stream << "# Stack: " << _vehicle->firmwareTypeString() << "\n"; + stream << "# Vehicle: " << _vehicle->vehicleTypeString() << "\n"; + stream << "# Version: " + << _vehicle->firmwareMajorVersion() << "." + << _vehicle->firmwareMinorVersion() << "." + << _vehicle->firmwarePatchVersion() << " " + << _vehicle->firmwareVersionTypeString() << "\n"; + stream << "# Git Revision: " << _vehicle->gitHash() << "\n"; + + stream << "#\n"; + stream << "# Vehicle-Id Component-Id Name Value Type\n"; foreach (int componentId, _mapParameterName2Variant.keys()) { foreach (const QString ¶mName, _mapParameterName2Variant[componentId].keys()) { @@ -941,46 +930,29 @@ FactMetaData::ValueType_t ParameterManager::_mavTypeToFactType(MAV_PARAM_TYPE ma } } -void ParameterManager::_restartWaitingParamTimer(void) -{ - _waitingParamTimeoutTimer.start(); -} - void ParameterManager::_addMetaDataToDefaultComponent(void) { - if (_defaultComponentId == MAV_COMP_ID_ALL) { - // We don't know what the default component is so we can't support meta data - return; - } - if (_parameterMetaData) { return; } QString metaDataFile; int majorVersion, minorVersion; - if (_vehicle->firmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { - // Parameter versioning is still not really figured out correctly. We need to handle ArduPilot specially based on vehicle version. - // The current three version are hardcoded in. - metaDataFile = ((APMFirmwarePlugin*)_vehicle->firmwarePlugin())->getParameterMetaDataFile(_vehicle); - qCDebug(ParameterManagerLog) << "Adding meta data to Vehicle file:major:minor" << metaDataFile; - } else { - // Load best parameter meta data set - metaDataFile = parameterMetaDataFile(_vehicle->firmwareType(), _parameterSetMajorVersion, majorVersion, minorVersion); - qCDebug(ParameterManagerLog) << "Adding meta data to Vehicle file:major:minor" << metaDataFile << majorVersion << minorVersion; - } + + // Load best parameter meta data set + metaDataFile = parameterMetaDataFile(_vehicle, _vehicle->firmwareType(), _parameterSetMajorVersion, majorVersion, minorVersion); + qCDebug(ParameterManagerLog) << "Adding meta data to Vehicle file:major:minor" << metaDataFile << majorVersion << minorVersion; _parameterMetaData = _vehicle->firmwarePlugin()->loadParameterMetaData(metaDataFile); // Loop over all parameters in default component adding meta data - QVariantMap& factMap = _mapParameterName2Variant[_defaultComponentId]; + QVariantMap& factMap = _mapParameterName2Variant[_vehicle->defaultComponentId()]; foreach (const QString& key, factMap.keys()) { _vehicle->firmwarePlugin()->addMetaDataToFact(_parameterMetaData, factMap[key].value(), _vehicle->vehicleType()); } } -/// @param failIfNoDefaultComponent true: Fails parameter load if no default component but we should have one -void ParameterManager::_checkInitialLoadComplete(bool failIfNoDefaultComponent) +void ParameterManager::_checkInitialLoadComplete(void) { // Already processed? if (_initialLoadComplete) { @@ -994,14 +966,16 @@ void ParameterManager::_checkInitialLoadComplete(bool failIfNoDefaultComponent) } } - if (!failIfNoDefaultComponent && _defaultComponentId == MAV_COMP_ID_ALL) { - // We are still waiting for default component to show up + if (!_mapParameterName2Variant.contains(_vehicle->defaultComponentId())) { + // No default component params yet, not done yet return; } // We aren't waiting for any more initial parameter updates, initial parameter loading is complete _initialLoadComplete = true; + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "Initial load complete"; + // Check for index based load failures QString indexList; bool initialLoadFailures = false; @@ -1012,35 +986,26 @@ void ParameterManager::_checkInitialLoadComplete(bool failIfNoDefaultComponent) } indexList += QString("%1").arg(paramIndex); initialLoadFailures = true; - qCDebug(ParameterManagerLog) << "Gave up on initial load after max retries (componentId:" << componentId << "paramIndex:" << paramIndex << ")"; + qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "Gave up on initial load after max retries (paramIndex:" << paramIndex << ")"; } } _missingParameters = false; if (initialLoadFailures) { _missingParameters = true; - qgcApp()->showMessage("QGroundControl was unable to retrieve the full set of parameters from the vehicle. " + QString errorMsg = tr("QGroundControl was unable to retrieve the full set of parameters from vehicle %1. " "This will cause QGroundControl to be unable to display its full user interface. " "If you are using modified firmware, you may need to resolve any vehicle startup errors to resolve the issue. " - "If you are using standard firmware, you may need to upgrade to a newer version to resolve the issue."); + "If you are using standard firmware, you may need to upgrade to a newer version to resolve the issue.").arg(_vehicle->id()); + qCDebug(ParameterManagerLog) << errorMsg; + qgcApp()->showMessage(errorMsg); if (!qgcApp()->runningUnitTests()) { - qCWarning(ParameterManagerLog) << "The following parameter indices could not be loaded after the maximum number of retries: " << indexList; - } - } else if (_defaultComponentId == FactSystem::defaultComponentId && !_defaultComponentIdParam.isEmpty()) { - // Missing default component when we should have one - _missingParameters = true; - qgcApp()->showMessage("QGroundControl did not receive parameters from the default component. " - "This will cause QGroundControl to be unable to display its full user interface. " - "If you are using modified firmware, you may need to resolve any vehicle startup errors to resolve the issue. " - "If you are using standard firmware, you may need to upgrade to a newer version to resolve the issue."); - if (!qgcApp()->runningUnitTests()) { - qCWarning(ParameterManagerLog) << "Default component was never found, param:" << _defaultComponentIdParam; + qCWarning(ParameterManagerLog) << _logVehiclePrefix() << "The following parameter indices could not be loaded after the maximum number of retries: " << indexList; } } // Signal load complete _parametersReady = true; - _determineDefaultComponentId(); _vehicle->autopilotPlugin()->parametersReadyPreChecks(); emit parametersReadyChanged(true); emit missingParametersChanged(_missingParameters); @@ -1048,17 +1013,21 @@ void ParameterManager::_checkInitialLoadComplete(bool failIfNoDefaultComponent) void ParameterManager::_initialRequestTimeout(void) { - if (!_vehicle->genericFirmware()) { - // Generic vehicles (like BeBop) may not have any parameters, so don't annoy the user - qgcApp()->showMessage("Vehicle did not respond to request for parameters, retrying"); - } - if (++_initialRequestRetryCount <= _maxInitialRequestListRetry) { + if (!_disableAllRetries && ++_initialRequestRetryCount <= _maxInitialRequestListRetry) { + qCDebug(ParameterManagerLog) << _logVehiclePrefix() << "Retrying initial parameter request list"; refreshAllParameters(); _initialRequestTimeoutTimer.start(); + } else { + if (!_vehicle->genericFirmware()) { + QString errorMsg = tr("Vehicle %1 did not respond to request for parameters. " + "This will cause QGroundControl to be unable to display its full user interface.").arg(_vehicle->id()); + qCDebug(ParameterManagerLog) << errorMsg; + qgcApp()->showMessage(errorMsg); + } } } -QString ParameterManager::parameterMetaDataFile(MAV_AUTOPILOT firmwareType, int wantedMajorVersion, int& majorVersion, int& minorVersion) +QString ParameterManager::parameterMetaDataFile(Vehicle* vehicle, MAV_AUTOPILOT firmwareType, int wantedMajorVersion, int& majorVersion, int& minorVersion) { bool cacheHit = false; FirmwarePlugin* plugin = qgcApp()->toolbox()->firmwarePluginManager()->firmwarePluginForAutopilot(firmwareType, MAV_TYPE_QUADROTOR); @@ -1115,7 +1084,7 @@ QString ParameterManager::parameterMetaDataFile(MAV_AUTOPILOT firmwareType, int } int internalMinorVersion, internalMajorVersion; - QString internalMetaDataFile = plugin->internalParameterMetaDataFile(); + QString internalMetaDataFile = plugin->internalParameterMetaDataFile(vehicle); plugin->getParameterMetaDataVersionInfo(internalMetaDataFile, internalMajorVersion, internalMinorVersion); qCDebug(ParameterManagerLog) << "Internal meta data file:major:minor" << internalMetaDataFile << internalMajorVersion << internalMinorVersion; if (cacheHit) { @@ -1164,7 +1133,7 @@ void ParameterManager::cacheMetaDataFile(const QString& metaDataFile, MAV_AUTOPI // Find the cache hit closest to this new file int cacheMajorVersion, cacheMinorVersion; - QString cacheHit = ParameterManager::parameterMetaDataFile(firmwareType, newMajorVersion, cacheMajorVersion, cacheMinorVersion); + QString cacheHit = ParameterManager::parameterMetaDataFile(NULL, firmwareType, newMajorVersion, cacheMajorVersion, cacheMinorVersion); qCDebug(ParameterManagerLog) << "ParameterManager::cacheMetaDataFile cacheHit file:firmware:major;minor" << cacheHit << cacheMajorVersion << cacheMinorVersion; bool cacheNewFile = false; @@ -1270,7 +1239,8 @@ void ParameterManager::_loadOfflineEditingParams(void) QStringList paramData = line.split("\t"); Q_ASSERT(paramData.count() == 5); - _defaultComponentId = paramData.at(1).toInt(); + int defaultComponentId = paramData.at(1).toInt(); + _vehicle->setOfflineEditingDefaultComponentId(defaultComponentId); QString paramName = paramData.at(2); QString valStr = paramData.at(3); MAV_PARAM_TYPE paramType = static_cast(paramData.at(4).toUInt()); @@ -1309,8 +1279,8 @@ void ParameterManager::_loadOfflineEditingParams(void) _parameterSetMajorVersion = paramValue.toInt(); } - Fact* fact = new Fact(_defaultComponentId, paramName, _mavTypeToFactType(paramType), this); - _mapParameterName2Variant[_defaultComponentId][paramName] = QVariant::fromValue(fact); + Fact* fact = new Fact(defaultComponentId, paramName, _mavTypeToFactType(paramType), this); + _mapParameterName2Variant[defaultComponentId][paramName] = QVariant::fromValue(fact); } _addMetaDataToDefaultComponent(); @@ -1426,21 +1396,24 @@ bool ParameterManager::loadFromJson(const QJsonObject& json, bool required, QStr void ParameterManager::resetAllParametersToDefaults(void) { - mavlink_message_t msg; - MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol(); + _vehicle->sendMavCommand(MAV_COMP_ID_ALL, + MAV_CMD_PREFLIGHT_STORAGE, + true, // showError + 2, // Reset params to default + -1); // Don't do anything with mission storage +} - mavlink_msg_command_long_pack_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - _vehicle->id(), // Target systeem - _vehicle->defaultComponentId(), // Target component - MAV_CMD_PREFLIGHT_STORAGE, - 0, // Confirmation - 2, // 2 = Reset params to default - -1, // -1 = No change to mission storage - 0, // 0 = Ignore - 0, 0, 0, 0); // Unused - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); +QString ParameterManager::_logVehiclePrefix(int componentId) +{ + if (componentId == -1) { + return QString("V:%1").arg(_vehicle->id()); + } else { + return QString("V:%1 C:%2").arg(_vehicle->id()).arg(componentId); + } } +void ParameterManager::_setLoadProgress(double loadProgress) +{ + _loadProgress = loadProgress; + emit loadProgressChanged(loadProgress); +} diff --git a/src/FactSystem/ParameterManager.h b/src/FactSystem/ParameterManager.h index 2f46da4b4d114366c378071bb02e86e099f50644..a2c65c015dea67afdbf6014152eb1664d57f12e8 100644 --- a/src/FactSystem/ParameterManager.h +++ b/src/FactSystem/ParameterManager.h @@ -28,7 +28,8 @@ /// @file /// @author Don Gagne -Q_DECLARE_LOGGING_CATEGORY(ParameterManagerVerboseLog) +Q_DECLARE_LOGGING_CATEGORY(ParameterManagerVerbose1Log) +Q_DECLARE_LOGGING_CATEGORY(ParameterManagerVerbose2Log) /// Connects to Parameter Manager to load/update Facts class ParameterManager : public QObject @@ -48,6 +49,9 @@ public: Q_PROPERTY(bool missingParameters READ missingParameters NOTIFY missingParametersChanged) bool missingParameters(void) { return _missingParameters; } + Q_PROPERTY(double loadProgress READ loadProgress NOTIFY loadProgressChanged) + double loadProgress(void) const { return _loadProgress; } + /// @return Directory of parameter caches static QDir parameterCacheDir(); @@ -95,13 +99,11 @@ public: /// @param[out] majorVersion Major version for found meta data /// @param[out] minorVersion Minor version for found meta data /// @return Meta data file name of best match, emptyString is none found - static QString parameterMetaDataFile(MAV_AUTOPILOT firmwareType, int wantedMajorVersion, int& majorVersion, int& minorVersion); + static QString parameterMetaDataFile(Vehicle* vehicle, MAV_AUTOPILOT firmwareType, int wantedMajorVersion, int& majorVersion, int& minorVersion); /// If this file is newer than anything in the cache, cache it as the latest version static void cacheMetaDataFile(const QString& metaDataFile, MAV_AUTOPILOT firmwareType); - int defaultComponentId(void) { return _defaultComponentId; } - /// Saves the specified param set to the json object. /// @param componentId Component id which contains params, MAV_COMP_ID_ALL to save all components /// @param paramsToSave List of params names to save, empty to save all for component @@ -120,12 +122,7 @@ public: signals: void parametersReadyChanged(bool parametersReady); void missingParametersChanged(bool missingParameters); - - /// Signalled to update progress of full parameter list request - void parameterListProgress(float value); - - /// Signalled to ourselves in order to get call on our own thread - void restartWaitingParamTimer(void); + void loadProgressChanged(float value); protected: Vehicle* _vehicle; @@ -133,7 +130,6 @@ protected: void _parameterUpdate(int vehicleId, int componentId, QString parameterName, int parameterCount, int parameterId, int mavType, QVariant value); void _valueUpdated(const QVariant& value); - void _restartWaitingParamTimer(void); void _waitingParamTimeout(void); void _tryCacheLookup(void); void _initialRequestTimeout(void); @@ -141,7 +137,6 @@ protected: private: static QVariant _stringToTypedVariant(const QString& string, FactMetaData::ValueType_t type, bool failOk = false); int _actualComponentId(int componentId); - void _determineDefaultComponentId(void); void _setupGroupMap(void); void _readParameterRaw(int componentId, const QString& paramName, int paramIndex); void _writeParameterRaw(int componentId, const QString& paramName, const QVariant& value); @@ -150,11 +145,13 @@ private: void _addMetaDataToDefaultComponent(void); QString _remapParamNameToVersion(const QString& paramName); void _loadOfflineEditingParams(void); + QString _logVehiclePrefix(int componentId = -1); + void _setLoadProgress(double loadProgress); MAV_PARAM_TYPE _factTypeToMavType(FactMetaData::ValueType_t factType); FactMetaData::ValueType_t _mavTypeToFactType(MAV_PARAM_TYPE mavType); void _saveToEEPROM(void); - void _checkInitialLoadComplete(bool failIfNoDefaultComponent); + void _checkInitialLoadComplete(void); /// First mapping is by component id /// Second mapping is parameter name, to Fact* in QVariant @@ -166,13 +163,12 @@ private: /// Second mapping is group name, to Fact QMap > _mapGroup2ParameterName; + double _loadProgress; ///< Parameter load progess, [0.0,1.0] bool _parametersReady; ///< true: parameter load complete bool _missingParameters; ///< true: parameter missing from initial load 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 - int _defaultComponentId; - QString _defaultComponentIdParam; ///< Parameter which identifies default component 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 @@ -183,10 +179,11 @@ private: int _prevWaitingWriteParamNameCount; - static const int _maxInitialRequestListRetry = 4; ///< Maximum retries for request list - int _initialRequestRetryCount; ///< Current retry count for request list - static const int _maxInitialLoadRetrySingleParam = 10; ///< Maximum retries for initial index based load of a single param - static const int _maxReadWriteRetry = 5; ///< Maximum retries read/write + static const int _maxInitialRequestListRetry = 4; ///< Maximum retries for request list + int _initialRequestRetryCount; ///< Current retry count for request list + static const int _maxInitialLoadRetrySingleParam = 5; ///< Maximum retries for initial index based load of a single param + static const int _maxReadWriteRetry = 5; ///< Maximum retries read/write + bool _disableAllRetries; ///< true: Don't retry any requests (used for testing) QMap _paramCountMap; ///< Key: Component id, Value: count of parameters in this component QMap > _waitingReadParamIndexMap; ///< Key: Component id, Value: Map { Key: parameter index still waiting for, Value: retry count } diff --git a/src/FactSystem/ParameterManagerTest.cc b/src/FactSystem/ParameterManagerTest.cc index c47d8bed32280d06f0144c043b01ee425e64c7bc..9ed18f0cdefd10f01ea56bc0a3e91bf422283273 100644 --- a/src/FactSystem/ParameterManagerTest.cc +++ b/src/FactSystem/ParameterManagerTest.cc @@ -34,7 +34,7 @@ void ParameterManagerTest::_noFailureWorker(MockConfiguration::FailureMode_t fai QVERIFY(vehicle); // We should get progress bar updates during load - QSignalSpy spyProgress(vehicle->parameterManager(), SIGNAL(parameterListProgress(float))); + QSignalSpy spyProgress(vehicle->parameterManager(), SIGNAL(loadProgressChanged(float))); QCOMPARE(spyProgress.wait(2000), true); arguments = spyProgress.takeFirst(); QCOMPARE(arguments.count(), 1); @@ -67,6 +67,9 @@ void ParameterManagerTest::_requestListMissingParamSuccess(void) // Test no response to param_request_list void ParameterManagerTest::_requestListNoResponse(void) { + // Will pop error about request failure + setExpectedMessageBox(QMessageBox::Ok); + Q_ASSERT(!_mockLink); _mockLink = MockLink::startPX4MockLink(false, MockConfiguration::FailParamNoReponseToRequestList); @@ -85,14 +88,14 @@ void ParameterManagerTest::_requestListNoResponse(void) QVERIFY(vehicle); QSignalSpy spyParamsReady(vehicleMgr, SIGNAL(parameterReadyVehicleAvailableChanged(bool))); - QSignalSpy spyProgress(vehicle->parameterManager(), SIGNAL(parameterListProgress(float))); + QSignalSpy spyProgress(vehicle->parameterManager(), SIGNAL(loadProgressChanged(float))); // We should not get any progress bar updates, nor a parameter ready signal QCOMPARE(spyProgress.wait(500), false); QCOMPARE(spyParamsReady.wait(40000), false); // User should have been notified - checkMultipleExpectedMessageBox(5); + checkExpectedMessageBox(); } // MockLink will fail to send a param on initial request, it will also fail to send it on subsequent @@ -120,7 +123,7 @@ void ParameterManagerTest::_requestListMissingParamFail(void) QVERIFY(vehicle); QSignalSpy spyParamsReady(vehicleMgr, SIGNAL(parameterReadyVehicleAvailableChanged(bool))); - QSignalSpy spyProgress(vehicle->parameterManager(), SIGNAL(parameterListProgress(float))); + QSignalSpy spyProgress(vehicle->parameterManager(), SIGNAL(loadProgressChanged(float))); // We will get progress bar updates, since it will fail after getting partially through the request QCOMPARE(spyProgress.wait(2000), true); diff --git a/src/FactSystem/SettingsFact.cc b/src/FactSystem/SettingsFact.cc index a3fb1821b9e1e7d374f70958bfdde1627a5d2555..eb4c4fc86f43c80550e9d3ffa7c576faef9c3cf5 100644 --- a/src/FactSystem/SettingsFact.cc +++ b/src/FactSystem/SettingsFact.cc @@ -9,18 +9,21 @@ #include "SettingsFact.h" +#include "QGCCorePlugin.h" +#include "QGCApplication.h" #include SettingsFact::SettingsFact(QObject* parent) : Fact(parent) { - + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); } -SettingsFact::SettingsFact(QString settingGroup, QString settingName, FactMetaData::ValueType_t type, const QVariant& defaultValue, QObject* parent) - : Fact(0, settingName, type, parent) +SettingsFact::SettingsFact(QString settingGroup, FactMetaData* metaData, QObject* parent) + : Fact(0, metaData->name(), metaData->type(), parent) , _settingGroup(settingGroup) + , _visible(true) { QSettings settings; @@ -28,7 +31,14 @@ SettingsFact::SettingsFact(QString settingGroup, QString settingName, FactMetaDa settings.beginGroup(_settingGroup); } - _rawValue = settings.value(_name, defaultValue); + // Allow core plugin a chance to override the default value + _visible = qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(*metaData); + setMetaData(metaData); + + QVariant typedValue; + QString errorString; + metaData->convertAndValidateRaw(settings.value(_name, metaData->rawDefaultValue()), true /* conertOnly */, typedValue, errorString); + _rawValue = typedValue; connect(this, &Fact::rawValueChanged, this, &SettingsFact::_rawValueChanged); } diff --git a/src/FactSystem/SettingsFact.h b/src/FactSystem/SettingsFact.h index 70582454ab0d6081a735e713fb40eac2beb06f1a..cb6e8330f5dcfab731070e2533de2092f00940f2 100644 --- a/src/FactSystem/SettingsFact.h +++ b/src/FactSystem/SettingsFact.h @@ -23,16 +23,19 @@ class SettingsFact : public Fact public: SettingsFact(QObject* parent = NULL); - SettingsFact(QString settingGroup, QString settingName, FactMetaData::ValueType_t type, const QVariant& defaultValue, QObject* parent = NULL); + SettingsFact(QString settingGroup, FactMetaData* metaData, QObject* parent = NULL); SettingsFact(const SettingsFact& other, QObject* parent = NULL); const SettingsFact& operator=(const SettingsFact& other); + Q_PROPERTY(bool visible MEMBER _visible CONSTANT) + private slots: void _rawValueChanged(QVariant value); private: QString _settingGroup; + bool _visible; }; #endif diff --git a/src/FirmwarePlugin/APM/APMFirmwarePlugin.cc b/src/FirmwarePlugin/APM/APMFirmwarePlugin.cc index 526df49bc42b1fbe43418c2cb7a0e9dd6c91a6f7..ebe40c0838dc788a8f07e0c7b3da2ea9c0a4306d 100644 --- a/src/FirmwarePlugin/APM/APMFirmwarePlugin.cc +++ b/src/FirmwarePlugin/APM/APMFirmwarePlugin.cc @@ -12,9 +12,12 @@ /// @author Don Gagne #include "APMFirmwarePlugin.h" -#include "AutoPilotPlugins/APM/APMAutoPilotPlugin.h" // FIXME: Hack +#include "APMAutoPilotPlugin.h" #include "QGCMAVLink.h" #include "QGCApplication.h" +#include "APMFlightModesComponentController.h" +#include "APMAirframeComponentController.h" +#include "APMSensorsComponentController.h" #include @@ -140,7 +143,14 @@ APMFirmwarePlugin::APMFirmwarePlugin(void) : _coaxialMotors(false) , _textSeverityAdjustmentNeeded(false) { + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMFlightModesComponentController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMAirframeComponentController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMSensorsComponentController"); +} +AutoPilotPlugin* APMFirmwarePlugin::autopilotPlugin(Vehicle* vehicle) +{ + return new APMAutoPilotPlugin(vehicle, vehicle); } bool APMFirmwarePlugin::isCapable(const Vehicle* /*vehicle*/, FirmwareCapabilities capabilities) @@ -654,8 +664,8 @@ QList APMFirmwarePlugin::supportedMissionCommands(void) << MAV_CMD_DO_AUTOTUNE_ENABLE << MAV_CMD_NAV_VTOL_TAKEOFF << MAV_CMD_NAV_VTOL_LAND << MAV_CMD_DO_VTOL_TRANSITION; #if 0 - // Waiting for module update - << MAV_CMD_DO_SET_REVERSE; + // Waiting for module update + << MAV_CMD_DO_SET_REVERSE; #endif return list; @@ -723,8 +733,11 @@ void APMFirmwarePlugin::_artooSocketError(QAbstractSocket::SocketError socketErr qgcApp()->showMessage(tr("Error during Solo video link setup: %1").arg(socketError)); } -QString APMFirmwarePlugin::getParameterMetaDataFile(Vehicle* vehicle) +QString APMFirmwarePlugin::internalParameterMetaDataFile(Vehicle* vehicle) { + int majorVersion = vehicle->firmwareMajorVersion(); + int minorVersion = vehicle->firmwareMinorVersion(); + switch (vehicle->vehicleType()) { case MAV_TYPE_QUADROTOR: case MAV_TYPE_HEXAROTOR: @@ -732,23 +745,74 @@ QString APMFirmwarePlugin::getParameterMetaDataFile(Vehicle* vehicle) case MAV_TYPE_TRICOPTER: case MAV_TYPE_COAXIAL: case MAV_TYPE_HELICOPTER: - if (vehicle->firmwareMajorVersion() < 3 || (vehicle->firmwareMajorVersion() == 3 && vehicle->firmwareMinorVersion() <= 3)) { + if (majorVersion < 3) { return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.3.xml"); - } else { - return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.4.xml"); + } else if (majorVersion == 3) { + switch (minorVersion) { + case 3: + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.3.xml"); + case 4: + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.4.xml"); + case 5: + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.5.xml"); + default: + if (minorVersion < 3) { + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.3.xml"); + } + } } + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.5.xml"); case MAV_TYPE_FIXED_WING: - if (vehicle->firmwareMajorVersion() < 3 || (vehicle->firmwareMajorVersion() == 3 && vehicle->firmwareMinorVersion() <= 3)) { + if (majorVersion < 3) { return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.3.xml"); - } else { - return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.5.xml"); + } else if (majorVersion == 3) { + switch (minorVersion) { + case 3: + case 4: + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.3.xml"); + case 5: + case 6: + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.5.xml"); + case 7: + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.7.xml"); + default: + if (minorVersion < 3) { + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.3.xml"); + } + } } + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.8.xml"); case MAV_TYPE_GROUND_ROVER: case MAV_TYPE_SURFACE_BOAT: - return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.0.xml"); + if (majorVersion < 3) { + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.0.xml"); + } else if (majorVersion == 3) { + switch (minorVersion) { + case 0: + case 1: + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.0.xml"); + default: + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.2.xml"); + } + } + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.2.xml"); case MAV_TYPE_SUBMARINE: - return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.4.xml"); + if (vehicle->firmwareMajorVersion() < 3 || (vehicle->firmwareMajorVersion() == 3 && vehicle->firmwareMinorVersion() <= 4)) { + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.4.xml"); + } else { + return QStringLiteral(":/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.5.xml"); + } default: return QString(); } } + +QString APMFirmwarePlugin::missionFlightMode(void) +{ + return QStringLiteral("Auto"); +} + +QString APMFirmwarePlugin::rtlFlightMode(void) +{ + return QStringLiteral("RTL"); +} diff --git a/src/FirmwarePlugin/APM/APMFirmwarePlugin.h b/src/FirmwarePlugin/APM/APMFirmwarePlugin.h index f9ca107ca98399cd9488fa8c3129c26623c5351e..6ea8bc4d21c3c53ca1394c6cf66b402a1a99ef2e 100644 --- a/src/FirmwarePlugin/APM/APMFirmwarePlugin.h +++ b/src/FirmwarePlugin/APM/APMFirmwarePlugin.h @@ -75,6 +75,7 @@ public: QList componentsForVehicle(AutoPilotPlugin* vehicle) final; QList supportedMissionCommands(void) final; + AutoPilotPlugin* autopilotPlugin (Vehicle* vehicle) final; bool isCapable (const Vehicle *vehicle, FirmwareCapabilities capabilities); QStringList flightModes (Vehicle* vehicle) final; QString flightMode (uint8_t base_mode, uint32_t custom_mode) const final; @@ -87,17 +88,16 @@ public: void initializeVehicle (Vehicle* vehicle) final; bool sendHomePositionToVehicle (void) final; void addMetaDataToFact (QObject* parameterMetaData, Fact* fact, MAV_TYPE vehicleType) final; - QString getDefaultComponentIdParam (void) const final { return QString("SYSID_SW_TYPE"); } QString missionCommandOverrides (MAV_TYPE vehicleType) const; QString getVersionParam (void) final { return QStringLiteral("SYSID_SW_MREV"); } - QString internalParameterMetaDataFile (void) final { return QString(":/FirmwarePlugin/APM/APMParameterFactMetaData.xml"); } + QString internalParameterMetaDataFile (Vehicle* vehicle) final; void getParameterMetaDataVersionInfo (const QString& metaDataFile, int& majorVersion, int& minorVersion) final { APMParameterMetaData::getParameterMetaDataVersionInfo(metaDataFile, majorVersion, minorVersion); } QObject* loadParameterMetaData (const QString& metaDataFile); GeoFenceManager* newGeoFenceManager (Vehicle* vehicle) { return new APMGeoFenceManager(vehicle); } RallyPointManager* newRallyPointManager (Vehicle* vehicle) { return new APMRallyPointManager(vehicle); } QString brandImage (const Vehicle* vehicle) const { Q_UNUSED(vehicle); return QStringLiteral("/qmlimages/APM/BrandImage"); } - - QString getParameterMetaDataFile(Vehicle* vehicle); + QString missionFlightMode (void) final; + QString rtlFlightMode (void) final; protected: /// All access to singleton is through stack specific implementation diff --git a/src/FirmwarePlugin/APM/APMFirmwarePluginFactory.cc b/src/FirmwarePlugin/APM/APMFirmwarePluginFactory.cc new file mode 100644 index 0000000000000000000000000000000000000000..8c78ea79d2b59374e540aa1d45ff3a2683ac677f --- /dev/null +++ b/src/FirmwarePlugin/APM/APMFirmwarePluginFactory.cc @@ -0,0 +1,71 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "APMFirmwarePluginFactory.h" +#include "APM/ArduCopterFirmwarePlugin.h" +#include "APM/ArduPlaneFirmwarePlugin.h" +#include "APM/ArduRoverFirmwarePlugin.h" +#include "APM/ArduSubFirmwarePlugin.h" + +APMFirmwarePluginFactory APMFirmwarePluginFactory; + +APMFirmwarePluginFactory::APMFirmwarePluginFactory(void) + : _arduCopterPluginInstance(NULL) + , _arduPlanePluginInstance(NULL) + , _arduRoverPluginInstance(NULL) + , _arduSubPluginInstance(NULL) +{ + +} + +QList APMFirmwarePluginFactory::supportedFirmwareTypes(void) const +{ + QList list; + + list.append(MAV_AUTOPILOT_ARDUPILOTMEGA); + return list; +} + +FirmwarePlugin* APMFirmwarePluginFactory::firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType) +{ + if (autopilotType == MAV_AUTOPILOT_ARDUPILOTMEGA) { + switch (vehicleType) { + case MAV_TYPE_QUADROTOR: + case MAV_TYPE_HEXAROTOR: + case MAV_TYPE_OCTOROTOR: + case MAV_TYPE_TRICOPTER: + case MAV_TYPE_COAXIAL: + case MAV_TYPE_HELICOPTER: + if (!_arduCopterPluginInstance) { + _arduCopterPluginInstance = new ArduCopterFirmwarePlugin; + } + return _arduCopterPluginInstance; + case MAV_TYPE_FIXED_WING: + if (!_arduPlanePluginInstance) { + _arduPlanePluginInstance = new ArduPlaneFirmwarePlugin; + } + return _arduPlanePluginInstance; + case MAV_TYPE_GROUND_ROVER: + case MAV_TYPE_SURFACE_BOAT: + if (!_arduRoverPluginInstance) { + _arduRoverPluginInstance = new ArduRoverFirmwarePlugin; + } + return _arduRoverPluginInstance; + case MAV_TYPE_SUBMARINE: + if (!_arduSubPluginInstance) { + _arduSubPluginInstance = new ArduSubFirmwarePlugin; + } + return _arduSubPluginInstance; + default: + break; + } + } + + return NULL; +} diff --git a/src/FirmwarePlugin/APM/APMFirmwarePluginFactory.h b/src/FirmwarePlugin/APM/APMFirmwarePluginFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..3ef5b36156a31e108af1e2d1fa9f4bc23c7ecd6a --- /dev/null +++ b/src/FirmwarePlugin/APM/APMFirmwarePluginFactory.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef APMFirmwarePluginFactory_H +#define APMFirmwarePluginFactory_H + +#include "FirmwarePlugin.h" + +class ArduCopterFirmwarePlugin; +class ArduPlaneFirmwarePlugin; +class ArduRoverFirmwarePlugin; +class ArduSubFirmwarePlugin; + +class APMFirmwarePluginFactory : public FirmwarePluginFactory +{ + Q_OBJECT + +public: + APMFirmwarePluginFactory(void); + + QList supportedFirmwareTypes (void) const final; + FirmwarePlugin* firmwarePluginForAutopilot (MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType) final; + +private: + ArduCopterFirmwarePlugin* _arduCopterPluginInstance; + ArduPlaneFirmwarePlugin* _arduPlanePluginInstance; + ArduRoverFirmwarePlugin* _arduRoverPluginInstance; + ArduSubFirmwarePlugin* _arduSubPluginInstance; +}; + +#endif diff --git a/src/FirmwarePlugin/APM/APMGeoFenceManager.cc b/src/FirmwarePlugin/APM/APMGeoFenceManager.cc index 7b019f73be3030872af4faa5ec65ab6b2a4a1c7b..f707bc32da80097fa4b6d816bb059dc63baac057 100644 --- a/src/FirmwarePlugin/APM/APMGeoFenceManager.cc +++ b/src/FirmwarePlugin/APM/APMGeoFenceManager.cc @@ -14,20 +14,22 @@ #include "QGCApplication.h" #include "ParameterManager.h" -const char* APMGeoFenceManager::_fenceTotalParam = "FENCE_TOTAL"; -const char* APMGeoFenceManager::_fenceActionParam = "FENCE_ACTION"; -const char* APMGeoFenceManager::_fenceEnableParam = "FENCE_ENABLE"; +const char* APMGeoFenceManager::_fenceTotalParam = "FENCE_TOTAL"; +const char* APMGeoFenceManager::_fenceActionParam = "FENCE_ACTION"; +const char* APMGeoFenceManager::_fenceEnableParam = "FENCE_ENABLE"; APMGeoFenceManager::APMGeoFenceManager(Vehicle* vehicle) : GeoFenceManager(vehicle) , _fenceSupported(false) - , _breachReturnSupported(vehicle->fixedWing()) + , _breachReturnEnabled(vehicle->fixedWing()) + , _circleEnabled(false) + , _polygonEnabled(false) , _firstParamLoadComplete(false) - , _circleRadiusFact(NULL) , _readTransactionInProgress(false) , _writeTransactionInProgress(false) - , _fenceEnableFact(NULL) , _fenceTypeFact(NULL) + , _fenceEnableFact(NULL) + , _circleRadiusFact(NULL) { connect(_vehicle, &Vehicle::mavlinkMessageReceived, this, &APMGeoFenceManager::_mavlinkMessageReceived); connect(_vehicle->parameterManager(), &ParameterManager::parametersReadyChanged, this, &APMGeoFenceManager::_parametersReady); @@ -53,15 +55,15 @@ void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const return; } - if (!_geoFenceSupported()) { + if (!_fenceSupported) { return; } // Validate - int validatedPolygonCount = polygon.count(); - if (polygonSupported()) { - if (polygon.count() < 3) { - validatedPolygonCount = 0; + int validatedPolygonCount = 0; + if (polygonEnabled()) { + if (polygon.count() >= 3) { + validatedPolygonCount = polygon.count(); } if (polygon.count() > std::numeric_limits::max()) { _sendError(TooManyPoints, QStringLiteral("Geo-Fence polygon has too many points: %1.").arg(_polygon.count())); @@ -70,17 +72,14 @@ void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const } _breachReturnPoint = breachReturn; - _polygon = polygon; - - // First thing is to turn off geo fence while we are updating. This prevents the vehicle from going haywire it is in the air. - // Unfortunately the param to do this with differs between plane and copter. - const char* enableParam = _vehicle->fixedWing() ? _fenceActionParam : _fenceEnableParam; - Fact* fenceEnableFact = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, enableParam); - QVariant savedEnableState = fenceEnableFact->rawValue(); - fenceEnableFact->setRawValue(0); + if (validatedPolygonCount) { + _polygon = polygon; + } else { + _polygon.clear(); + } // Total point count, +1 polygon close in last index, +1 for breach in index 0 - _cWriteFencePoints = (validatedPolygonCount ? (validatedPolygonCount + 1) : 0) + 1 ; + _cWriteFencePoints = validatedPolygonCount ? validatedPolygonCount + 1 + 1 : 0; _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _fenceTotalParam)->setRawValue(_cWriteFencePoints); // FIXME: No validation of correct fence received @@ -88,8 +87,6 @@ void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const _sendFencePoint(index); } - fenceEnableFact->setRawValue(savedEnableState); - emit loadComplete(_breachReturnPoint, _polygon); } @@ -102,15 +99,15 @@ void APMGeoFenceManager::loadFromVehicle(void) _breachReturnPoint = QGeoCoordinate(); _polygon.clear(); - if (!_geoFenceSupported()) { + if (!_fenceSupported) { return; } - // Point 0: Breach return point (ArduPlane only) + // Point 0: Breach return point (always sent, but supported by ArduPlane only) // Point [1,N]: Polygon points // Point N+1: Close polygon point (same as point 1) int cFencePoints = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _fenceTotalParam)->rawValue().toInt(); - int minFencePoints = 6; + int minFencePoints = 5; qCDebug(GeoFenceManagerLog) << "APMGeoFenceManager::loadFromVehicle" << cFencePoints; if (cFencePoints == 0) { // No fence @@ -225,25 +222,28 @@ bool APMGeoFenceManager::inProgress(void) const return _readTransactionInProgress || _writeTransactionInProgress; } -bool APMGeoFenceManager::_geoFenceSupported(void) +void APMGeoFenceManager::_updateEnabledFlags(void) { - // FIXME: MockLink doesn't support geo fence yet - if (qgcApp()->runningUnitTests()) { - return false; + bool fenceEnabled; + if (_fenceEnableFact) { + fenceEnabled = _fenceEnableFact->rawValue().toBool(); + } else { + fenceEnabled = true; } - if (!_vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, _fenceTotalParam) || - !_vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, _fenceActionParam)) { - return false; - } else { - return true; + bool newCircleEnabled = _fenceSupported && fenceEnabled && _fenceTypeFact && (_fenceTypeFact->rawValue().toInt() & 2); + if (newCircleEnabled != _circleEnabled) { + _circleEnabled = newCircleEnabled; + emit circleEnabledChanged(newCircleEnabled); } -} -void APMGeoFenceManager::_updateSupportedFlags(void) -{ - emit circleSupportedChanged(circleSupported()); - emit polygonSupportedChanged(polygonSupported()); + bool newPolygonEnabled = _fenceSupported && fenceEnabled && + ((_vehicle->multiRotor() && _fenceTypeFact && (_fenceTypeFact->rawValue().toInt() & 4)) || + _vehicle->fixedWing()); + if (newPolygonEnabled != _polygonEnabled) { + _polygonEnabled = newPolygonEnabled; + emit polygonEnabledChanged(newPolygonEnabled); + } } void APMGeoFenceManager::_parametersReady(void) @@ -251,18 +251,22 @@ void APMGeoFenceManager::_parametersReady(void) if (!_firstParamLoadComplete) { _firstParamLoadComplete = true; - _fenceSupported = _vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, QStringLiteral("FENCE_ACTION")); + _fenceSupported = _vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, _fenceTotalParam) && + _vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, _fenceActionParam) && + !qgcApp()->runningUnitTests(); if (_fenceSupported) { QStringList paramNames; QStringList paramLabels; + if (_vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, _fenceEnableParam)) { + _fenceEnableFact = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _fenceEnableParam); + connect(_fenceEnableFact, &Fact::rawValueChanged, this, &APMGeoFenceManager::_updateEnabledFlags); + } + if (_vehicle->multiRotor()) { - _fenceEnableFact = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, QStringLiteral("FENCE_ENABLE")); _fenceTypeFact = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, QStringLiteral("FENCE_TYPE")); - - connect(_fenceEnableFact, &Fact::rawValueChanged, this, &APMGeoFenceManager::_updateSupportedFlags); - connect(_fenceTypeFact, &Fact::rawValueChanged, this, &APMGeoFenceManager::_updateSupportedFlags); + connect(_fenceTypeFact, &Fact::rawValueChanged, this, &APMGeoFenceManager::_updateEnabledFlags); _circleRadiusFact = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, QStringLiteral("FENCE_RADIUS")); connect(_circleRadiusFact, &Fact::rawValueChanged, this, &APMGeoFenceManager::_circleRadiusRawValueChanged); @@ -292,19 +296,17 @@ void APMGeoFenceManager::_parametersReady(void) emit paramsChanged(_params); emit paramLabelsChanged(_paramLabels); - emit fenceSupportedChanged(_fenceSupported); - emit circleSupportedChanged(circleSupported()); - emit polygonSupportedChanged(polygonSupported()); + _updateEnabledFlags(); } - qCDebug(GeoFenceManagerLog) << "fenceSupported:circleSupported:polygonSupported:breachReturnSupported" << - _fenceSupported << circleSupported() << polygonSupported() << _breachReturnSupported; + qCDebug(GeoFenceManagerLog) << "fenceSupported:circleEnabled:polygonEnabled:breachReturnEnabled" << + _fenceSupported << _circleEnabled << _polygonEnabled << _breachReturnEnabled; } } float APMGeoFenceManager::circleRadius(void) const { - if (_circleRadiusFact) { + if (_circleEnabled) { return _circleRadiusFact->rawValue().toFloat(); } else { return 0.0; @@ -316,33 +318,13 @@ void APMGeoFenceManager::_circleRadiusRawValueChanged(QVariant value) emit circleRadiusChanged(value.toFloat()); } -bool APMGeoFenceManager::circleSupported(void) const -{ - if (_fenceSupported && _vehicle->multiRotor() && _fenceEnableFact && _fenceTypeFact) { - return _fenceEnableFact->rawValue().toBool() && (_fenceTypeFact->rawValue().toInt() & 2); - } - - return false; -} - -bool APMGeoFenceManager::polygonSupported(void) const +QString APMGeoFenceManager::editorQml(void) const { if (_fenceSupported) { - if (_vehicle->multiRotor()) { - if (_fenceEnableFact && _fenceTypeFact) { - return _fenceEnableFact->rawValue().toBool() && (_fenceTypeFact->rawValue().toInt() & 4); - } - } else if (_vehicle->fixedWing()) { - return true; - } + return _vehicle->multiRotor() ? + QStringLiteral("qrc:/FirmwarePlugin/APM/CopterGeoFenceEditor.qml") : + QStringLiteral("qrc:/FirmwarePlugin/APM/PlaneGeoFenceEditor.qml"); + } else { + return QStringLiteral("qrc:/FirmwarePlugin/NoGeoFenceEditor.qml"); } - - return false; -} - -QString APMGeoFenceManager::editorQml(void) const -{ - return _vehicle->multiRotor() ? - QStringLiteral("qrc:/FirmwarePlugin/APM/CopterGeoFenceEditor.qml") : - QStringLiteral("qrc:/FirmwarePlugin/APM/PlaneGeoFenceEditor.qml"); } diff --git a/src/FirmwarePlugin/APM/APMGeoFenceManager.h b/src/FirmwarePlugin/APM/APMGeoFenceManager.h index fe98aaeb93c00395b597910178aa774869c57ea7..0540c3e68ec8a40e03180b873f72dedf940180ab 100644 --- a/src/FirmwarePlugin/APM/APMGeoFenceManager.h +++ b/src/FirmwarePlugin/APM/APMGeoFenceManager.h @@ -23,39 +23,37 @@ public: ~APMGeoFenceManager(); // Overrides from GeoFenceManager - bool inProgress (void) const final; - void loadFromVehicle (void) final; - void sendToVehicle (const QGeoCoordinate& breachReturn, const QList& polygon) final; - bool fenceSupported (void) const final { return _fenceSupported; } - bool circleSupported (void) const final; - bool polygonSupported (void) const final; - bool breachReturnSupported (void) const final { return _breachReturnSupported; } - float circleRadius (void) const final; - QVariantList params (void) const final { return _params; } - QStringList paramLabels (void) const final { return _paramLabels; } - QString editorQml (void) const final; + bool inProgress (void) const final; + void loadFromVehicle (void) final; + void sendToVehicle (const QGeoCoordinate& breachReturn, const QList& polygon) final; + bool circleEnabled (void) const final { return _circleEnabled; } + bool polygonEnabled (void) const final { return _polygonEnabled; } + bool breachReturnEnabled (void) const final { return _breachReturnEnabled; } + float circleRadius (void) const final; + QVariantList params (void) const final { return _params; } + QStringList paramLabels (void) const final { return _paramLabels; } + QString editorQml (void) const final; private slots: void _mavlinkMessageReceived(const mavlink_message_t& message); - void _updateSupportedFlags(void); + void _updateEnabledFlags(void); void _circleRadiusRawValueChanged(QVariant value); void _parametersReady(void); private: void _requestFencePoint(uint8_t pointIndex); void _sendFencePoint(uint8_t pointIndex); - bool _geoFenceSupported(void); private: bool _fenceSupported; - bool _breachReturnSupported; + bool _breachReturnEnabled; + bool _circleEnabled; + bool _polygonEnabled; bool _firstParamLoadComplete; QVariantList _params; QStringList _paramLabels; - Fact* _circleRadiusFact; - bool _readTransactionInProgress; bool _writeTransactionInProgress; @@ -63,8 +61,9 @@ private: uint8_t _cWriteFencePoints; uint8_t _currentFencePoint; - Fact* _fenceEnableFact; Fact* _fenceTypeFact; + Fact* _fenceEnableFact; + Fact* _circleRadiusFact; static const char* _fenceTotalParam; static const char* _fenceActionParam; diff --git a/src/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.5.xml b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.5.xml new file mode 100644 index 0000000000000000000000000000000000000000..91f87f90fda231c636912b9c077dc5fae61f4993 --- /dev/null +++ b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Copter.3.5.xml @@ -0,0 +1,8496 @@ + + + + + + + + +True + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +1 10 +1 + + +0 30 +1 +seconds + + +0:Roll,1:Pitch,2:Yaw + + +0 1 +0.01 + + +0 5 +0.01 + + +0 15 +0.1 +Degrees + + +0 1000 +1 +meters + + +0 100 +1 +meters + + + +Disabled +FBWMixing +DirectMixing + + + + +Disabled +Enabled + + + +0 30 +0.1 +m/s + + +0 30 +0.1 +m/s/s + + +0 127 +1 +0.1 seconds + + +-100 100 +1 +Percent + + +0 30 +0.1 +m/s + + +0 30 +0.1 +m/s + + +0 127 +1 +percent + + +0 10 +0.5 +seconds + + +0 100 +Percent + + + + +0 45 +1 +degrees + + +0:AUTO_ALWAYS,1:AUTO_LAND,2:AUTO_LOITER_TO_ALT,3:AUTO_LOITER_ALL,4:AUTO_WAYPOINTS,5:LOITER,6:RTL,7:CIRCLE,8:CRUISE,9:FBWB,10:GUIDED + + + +Default +L1Controller + + + + +Automatic + + + +-32767 32767 +1 +Meters + + +1 32767 +1 +Meters + + +0 32767 +1 +Meters + + +-32767 32767 +1 +Meters + + +-32767 32767 +1 +Meters + + + +None +GuidedMode +ReportOnly +GuidedModeThrPass +RTL_Mode + + + + + + + +0 32767 +1 +meters + + +0 32767 +1 +meters + + +0 32767 +1 +meters + + + +NoAutoEnable +AutoEnable +AutoEnableDisableFloorOnly + + + + +FenceReturnPoint +NearestRallyPoint + + + + +Disabled +Enabled + + + +5 100 +1 +m/s + + +5 100 +1 +m/s + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0 10000 +meters + + +1 10 +0.1 +m/s + + +-100 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 127 +1 +Percent + + +0 100 +1 +Percent + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +925 2200 +1 + + +0 100 +1 +Percent + + + +Disabled +Enabled + + + + +CIRCLE/no change(if already in AUTO|GUIDED|LOITER) +CIRCLE +FBWA + + + +1 100 +0.5 +seconds + + + +Continue +ReturnToLaunch +Glide +Deploy Parachute + + + +1 300 +0.5 +seconds + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Heartbeat +HeartbeatAndREMRSSI +HeartbeatAndAUTO + + + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + +0 9000 +1 +centi-Degrees + + +0 9000 +1 +centi-Degrees + + +-9000 0 +1 +centi-Degrees + + +10 500 +1 +degrees/second + + +10 500 +1 +degrees/second + + + +Disabled +Enabled + + + +-100 100 +0.1 +Meters + + +10 360 +1 +degrees/second + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + +0.5 1.2 + + + +Disabled +Enabled + + + +-1000 1000 +percent + + +-1000 1000 +percent + + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:MODE,7:IMU,8:CMD,9:CURRENT,10:COMPASS,11:TECS,12:CAMERA,13:RC,14:SONAR,15:ARM/DISARM,19:IMU_RAW + +Disabled +PX4/Pixhawk-Default + + + + + + + +cm/s + + +m/s + + +cm/s + + +centi-Degrees + + +centimeters + + +centimeters + + + +Disabled +Enabled + + + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + +0 100 +Percent + + +0 100 +1 +m/s + + +0 100 +Percent + + +0 100 +1 +m/s + + + + + + + +Disabled +Channel1 +Channel2 +Channel3 +Channel4 +Channel5 +Channel6 +Channel7 +Channel8 + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0 90 +0.1 +degrees + + + +Disable +Enable - go HOME then land +Enable - go directly to landing sequence + + + + +Disable +Enable + + + +10 127 +m/s/s + + +0:Disarm + + + + + +Disabled +Enabled + + + + + +True + + +True + +ArduPlane +AntennaTracker +Copter +Rover + + + +1 255 + + + +Mission Planner and DroidPlanner + AP Planner 2 + + + + +Disabled +Enabled + + + +0 10 +.5 +Hz + + +0.0 1000.0 +10 +Centimeters + + +0.0 500.0 +10 + + +0:Feedback from mid stick,1:High throttle cancels landing,2:Disarm on land detection + +None +Feedback from mid stick +High throttle cancels landing +Disarm on land detection + + + +0 30 +1 +seconds + + +0:Roll,1:Pitch,2:Yaw + +None +Roll +Pitch +Yaw + + + +0 8000 +1 +Centimeters + + +0.5 10.0 + +Disabled +Shallow +Steep + +.1 + + +0 2000 +50 +cm/s + + +0.01 2.0 +0.01 + + + +Disabled +Land +RTL + + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Enabled always RTL +Enabled Continue with Mission in Auto Mode + + + +100 900 + + + +Disabled +Enabled + + + + +Disabled +Mode1 +Mode2 +Mode1+2 +Mode3 +Mode1+3 +Mode2+3 +Mode1+2+3 +Mode4 +Mode1+4 +Mode2+4 +Mode1+2+4 +Mode3+4 +Mode1+3+4 +Mode2+3+4 +Mode1+2+3+4 +Mode5 +Mode1+5 +Mode2+5 +Mode1+2+5 +Mode3+5 +Mode1+3+5 +Mode2+3+5 +Mode1+2+3+5 +Mode4+5 +Mode1+4+5 +Mode2+4+5 +Mode1+2+4+5 +Mode3+4+5 +Mode1+3+4+5 +Mode2+3+4+5 +Mode1+2+3+4+5 +Mode6 +Mode1+6 +Mode2+6 +Mode1+2+6 +Mode3+6 +Mode1+3+6 +Mode2+3+6 +Mode1+2+3+6 +Mode4+6 +Mode1+4+6 +Mode2+4+6 +Mode1+2+4+6 +Mode3+4+6 +Mode1+3+4+6 +Mode2+3+4+6 +Mode1+2+3+4+6 +Mode5+6 +Mode1+5+6 +Mode2+5+6 +Mode1+2+5+6 +Mode3+5+6 +Mode1+3+5+6 +Mode2+3+5+6 +Mode1+2+3+5+6 +Mode4+5+6 +Mode1+4+5+6 +Mode2+4+5+6 +Mode1+2+4+5+6 +Mode3+4+5+6 +Mode1+3+4+5+6 +Mode2+3+4+5+6 +Mode1+2+3+4+5+6 + + + +-1 1000 +1 +Centimeters + + +0 3000 +10 +Centimeters + + + +Never change yaw +Face next waypoint +Face next waypoint except RTL +Face along GPS course + + + +0 60000 +1000 +ms + + +30 200 +10 +cm/s + + +0 500 +10 +cm/s + + +50 500 +10 +Centimeters/Second + + +50 500 +10 +cm/s/s + + + +Disabled +Enabled always RTL +Enabled Continue with Mission in Auto Mode +Enabled always LAND + + + +925 1100 +1 +pwm + + +0 300 +1 +pwm + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:RCIN,7:IMU,8:CMD,9:CURRENT,10:RCOUT,11:OPTFLOW,12:PID,13:COMPASS,14:INAV,15:CAMERA,17:MOTBATT,18:IMU_FAST,19:IMU_RAW + +Default +Default+RCIN +Default+IMU +Default+Motors +NearlyAll-AC315 +NearlyAll +All+FastATT +All+MotBatt +All+FastIMU +All+FastIMU+PID +All+FullIMU +Disabled + + + + +Normal Start-up +Start-up in ESC Calibration mode if throttle high +Start-up in ESC Calibration mode regardless of throttle +Start-up and automatically calibrate ESCs +Disabled + + + + +None +Stab Roll/Pitch kP +Rate Roll/Pitch kP +Rate Roll/Pitch kI +Rate Roll/Pitch kD +Stab Yaw kP +Rate Yaw kP +Rate Yaw kD +Altitude Hold kP +Throttle Rate kP +Throttle Accel kP +Throttle Accel kI +Throttle Accel kD +Loiter Speed +Loiter Pos kP +Velocity XY kP +Velocity XY kI +WP Speed +Acro RollPitch kP +Acro Yaw kP +Heli Ext Gyro +OF Loiter kP +OF Loiter kI +OF Loiter kD +Declination +Circle Rate +RangeFinder Gain +Rate Pitch kP +Rate Pitch kI +Rate Pitch kD +Rate Roll kP +Rate Roll kI +Rate Roll kD +Rate Pitch FF +Rate Roll FF +Rate Yaw FF + + + +0 32767 + + +0 32767 + + + +Plus +X +V +H +V-Tail +A-Tail +Y6B + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + +0 127 +Seconds + + +1000 8000 +Centi-degrees + + +0 100 + +Very Soft +Soft +Medium +Crisp +Very Crisp + +10 + + +4 12 +deg/sec + + +2000 4500 +Centi-degrees + + + +No repositioning +Repositioning + + + + +Land +AltHold +Land even in Stabilize + + + +0.6:Strict, 0.8:Default, 1.0:Relaxed + + + +Disabled +Enabled + + + +50 490 +1 +Hz + + +1 10 + + +1 10 + + +0 3 +0.1 + + +0 3 +0.1 + + + +Disabled +Leveling +Leveling and Limited + + + +-0.5 1.0 + +Disabled +Very Low +Low +Medium +High +Very High + + + +0.1 6.0 +0.1 + + +0.02 1.00 +0.01 + + +0 4500 +10 +cm/s/s + + +1.000 8.000 + + +0.500 1.500 +0.05 + + +0.000 3.000 + + +0 1000 +Percent*10 + + +0.000 0.400 + + +1.000 100.000 +Hz + + +1.000 3.000 + + +0.500 2.000 + + +0:Roll,1:Pitch,2:Yaw + +All +Roll Only +Pitch Only +Yaw Only +Roll and Pitch +Roll and Yaw +Pitch and Yaw + + + +0.05 0.10 + + +0.001 0.006 + + + +Stopped +Running + + + + +Do Not Use in RTL and Land +Use in RTL and Land + + + +0 5 + + + +Auto +Guided +RTL +Land +Brake +Throw + + + + +Upward Throw +Drop + + + + +Disabled +Enabled + + + +0:ADSBMavlinkProcessing + + +-0.5 1.0 + +Disabled +Very Low +Low +Medium +High +Very High + + + +0 1 + + + +Undefined +Quad +Hexa +Octa +OctaQuad +Y6 +Heli +Tri +SingleCopter +CoaxCopter + + + + + + + +True + +ArduPlane +AntennaTracker +Copter +Rover + + + +1 255 + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +0 20 +0.1 +seconds + + +0 20 +0.1 +seconds + + +0 100 +1 +degrees/second + + +0 20 +1 +seconds + + +-90 90 +0.000001 +degrees + + +-180 180 +0.000001 +degrees + + +0 10 +0.1 +seconds + + + +Position +OnOff +ContinuousRotation + + + + +Position +OnOff +ContinuousRotation + + + +0 50 +0.1 +degrees/second + + +0 50 +0.1 +degrees/second + + +0 2 +0.01 +seconds + + +0 2 +0.01 +seconds + + +-10 10 +0.1 +degrees + + +-10 10 +0.1 +degrees + + +0 360 +0.1 +degrees + + +0 100 +1 +meters + + + +Barometer +GPS +GPS vehicle only + + + +1 10 +1 +Hz + + +-90 0 +1 +Degrees + + +0 90 +1 +Degrees + + +0:ATTITUDE,1:GPS,2:RCIN,3:IMU,4:RCOUT,5:COMPASS + +Default +Disabled + + + +0.0 3.0 +0.01 + + +0.0 3.0 +0.01 + + +0 4000 +10 +Percent*10 + + +0.001 0.1 +0.001 + + +0.0 3.0 +0.01 + + +0.0 3.0 +0.01 + + +0 4000 +10 +Percent*10 + + +0.001 0.1 +0.001 + + +1 255 + + + + + + +True + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:MODE,7:IMU,8:CMD,9:CURRENT,10:COMPASS,11:TECS,12:CAMERA,13:RC,14:SONAR,15:ARM/DISARM,19:IMU_RAW + +Disabled +APM2-Default +PX4/Pixhawk-Default + + + + + + + + +MANUAL +LEARNING +STEERING +HOLD +AUTO +RTL +GUIDED + + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +0 30 +1 +seconds + + +0:Steering,1:Throttle + +None +Steering +Throttle + + + + +Disabled +Enabled + + + + +Disabled +APM TriggerPin0 +APM TriggerPin1 +APM TriggerPin2 +APM TriggerPin3 +APM TriggerPin4 +APM TriggerPin5 +APM TriggerPin6 +APM TriggerPin7 +APM TriggerPin8 +Pixhawk TriggerPin50 +Pixhawk TriggerPin51 +Pixhawk TriggerPin52 +Pixhawk TriggerPin53 +Pixhawk TriggerPin54 +Pixhawk TriggerPin55 + + + +0 20 +0.1 +m/s/s + + +0 100 +0.1 +m/s + + +0 100 +1 +percent + + +0 100 +0.1 +meters + + +0 100 +1 +percent + + +0 100 +1 +m/s + + +0 360 +1 +degrees + + + +Nothing +LearnWaypoint + + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + + +Disabled +SkidSteeringOutput + + + + +Disabled +SkidSteeringInput + + + + +Nothing +RTL +HOLD + + + +seconds + + + +Disabled +Enabled + + + +925 1100 +1 + + + +Disabled +Enabled + + + + +Disabled +HOLD +HoldAndDisarm + + + +0 1000 +1 +centimeters + + +-45 45 +1 +centimeters + + +0 100 +0.1 +seconds + + +1 100 +1 + + + + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + +0 1000 +0.1 +meters + + +0.2 10 +0.1 +gravities + + + + + +Disabled +Enabled + + + +1 100 + + +1 100000 + + +-1 16777215 + + + +NoInfo +Light +Small +Large +HighVortexlarge +Heavy +HighlyManuv +Rotocraft +RESERVED +Glider +LightAir +Parachute +UltraLight +RESERVED +UAV +Space +RESERVED +EmergencySurface +ServiceSurface +PointObstacle + + + + +NO_DATA +L15W23 +L25W28P5 +L25W34 +L35W33 +L35W38 +L45W39P5 +L45W45 +L55W45 +L55W52 +L65W59P5 +L65W67 +L75W72P5 +L75W80 +L85W80 +L85W90 + + + + +NoData +Left2m +Left4m +Left6m +Center +Right2m +Right4m +Right6m + + + + +NO_DATA +AppliedBySensor + + + + +Disabled +Rx-Only +Tx-Only +Rx and Tx Enabled + + + + + + + + + + + + + + + + + + + + + +meters + + +meters + + +millibar + + + + + + + + + + + + + + +seconds + + + + +0.0 1.0 +.01 + + + +Disabled +Enabled + + + +0.1 0.4 +.01 + + +0.1 0.4 +.01 + + +0 127 +1 +m/s + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 + + + +0.001 0.5 +.01 + + +0 10 +1 + + + +Disabled +Enable EKF2 +Enable EKF3 + + + + + + +Disabled +THR_MIN PWM when disarmed +0 PWM when disarmed + + + +0:All,1:Barometer,2:Compass,3:GPS lock,4:INS,5:Parameters,6:RC,7:Board voltage,8:Battery Level,9:Airspeed,10:Logging Available,11:Hardware safety switch,12:GPS Configuration + +None +All +Barometer +Compass +GPS Lock +INS(INertial Sensors - accels & gyros) +Parameters(unused) +RC Failsafe +Board voltage +Battery Level +Airspeed +LoggingAvailable +Hardware safety switch +GPS configuration + + + +0.25 3.0 +m/s/s + + +0.1 +Volts + + +0.1 +Volts + + + + + +None +I2C-MS4525D0 +Analog +I2C-MS5525 + + + + +Use +Don't Use + + + +0.1 + + +0.1 + + + + + + + + + +Disable +Enable + + + + + + +Bus0 +Bus1 + + + + + +500 18000 +100 +Centi-Degrees/Sec + + +0 72000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +3.000 12.000 + + +3.000 12.000 + + +3.000 6.000 + + +0.5 10.0 + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + +0.5 0.9 + + + +Disabled 1 + + + +0 1000 +Centi-Degrees + + +0.08 0.35 +0.005 + + +0.01 0.6 +0.01 + + +0 1 +0.01 + + +0.001 0.03 +0.001 + + +1 20 +1 +Hz + + +0.08 0.35 +0.005 + + +0.01 0.6 +0.01 + + +0 1 +0.01 + + +0.001 0.03 +0.001 + + +1 20 +1 +Hz + + +0.180 0.60 +0.005 + + +0.01 0.06 +0.01 + + +0 1 +0.01 + + +0.000 0.02 +0.001 + + +1 20 +1 +Hz + + + + + +Disabled +Enabled + + + + +Remain in AVOID_ADSB +Resume previous flight mode +RTL +Resume if AUTO else Loiter + + + + + +seconds + + +seconds + + +meters + + +meters + + +meters + + +meters + + + + +0:StopAtFence,1:UseProximitySensor + +None +StopAtFence +UseProximitySensor +All + + + +0 4500 + + +3 30 +meters + + + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +Solo +Bebop +SMBus-Maxell + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Watts + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +Solo +Bebop +SMBus-Maxell + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Amps + + + + + +None +Pozyx + + + +-90 90 +0.000001 +degrees + + +-180 180 +0.000001 +degrees + + +0 10000 +1 +meters + + +-180 +180 +1 +degrees + + + + + +No PWMs +Two PWMs +Four PWMs +Six PWMs +Three PWMs and One Capture + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled + +True + + + +Disabled +50Hz +75Hz +100Hz +150Hz +200Hz +250Hz +300Hz + +True + + +-32767 32768 + + + +Disabled +Enabled +Dynamic ID/Update + + + +0:Ch1,1:Ch2,2:Ch3,3:Ch4,4:Ch5,5:Ch6,6:Ch7,7:Ch8,8:Ch9,9:Ch10,10:Ch11,11:Ch12,12:Ch13,13:Ch14 + +Disabled +Enabled + +True + + +-1 80 +degreesC + + + +AUTO +PX4V1 +Pixhawk +Pixhawk2 +Pixracer +PixhawkMini +Pixhawk2Slim +VRBrain 5.1 +VRBrain 5.2 +VR Micro Brain 5.1 +VR Micro Brain 5.2 +VRBrain Core 1.0 +VRBrain 5.4 + +True + + + + + +Disabled +Enabled + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +0 3600 + + + + + +Servo +Relay + + + +0 50 +deciseconds + + +1000 2000 +pwm + + +1000 2000 +pwm + + +0 1000 +meters + + + +Low +High + + + +0 10000 +milliseconds + + +0 180 +Degrees + + + +Disabled +PX4 AUX1 +PX4 AUX2 +PX4 AUX3 +PX4 AUX4(fast capture) +PX4 AUX5 +PX4 AUX6 + + + + +TriggerLow +TriggerHigh + + + + + + +Disabled +Enabled + + + + +First Relay +Second Relay +Third Relay +Fourth Relay +Servo + + + +1000 2000 +1 +pwm + + +1000 2000 +1 +pwm + + +0 32000 +1 +Meters + + +0 5000 +1 +Milliseconds + + + + +0 10000 +100 +cm + + +-90 90 +1 +deg/s + + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-3.142 3.142 +0.01 +Radians + + + +Disabled +Internal-Learning +EKF-Learning + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Use Throttle +Use Current + + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +FirstCompass +SecondCompass +ThirdCompass + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + + + + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 32 + +Very Strict +Strict +Default +Relaxed + +0.1 + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + +0 250 +10 +milliseconds + + + +Use Baro +Use Range Finder +Use GPS +Use Range Beacon + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.000001 0.001 +1/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +50 200 +% + + +0.5 50.0 +m + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +0.05 1.0 +0.05 +rad + + +100 1000 +25 + + +10 50 +5 +cs + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +2.0 6.0 +0.5 +m/s + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + + +Use Baro +Use Range Finder +Use GPS +Use Range Beacon + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +50 200 +% + + +0.5 50.0 +m + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +0.05 1.0 +0.05 +rad + + +100 1000 +25 + + +10 50 +5 +cs + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +2.0 6.0 +0.5 +m/s + + +0.5 2.5 +0.1 +m/s/s + + + + + +Disabled +Enabled + + + +0:Altitude,1:Circle,2:Polygon + +None +Altitude +Circle +Altitude and Circle +Polygon +Altitude and Polygon +Circle and Polygon +All + + + + +Report Only +RTL or Land + + + +10 1000 +1 +Meters + + +30 10000 +Meters + + +1 10 +Meters + + +1 20 + + + + + +Disabled +Enabled + + + +-200 +200 +1 + + +-200 +200 +1 + + +-18000 +18000 +1 + + +m + + +m + + +m + + +0 255 + + + + +True +True +1 +pascals + + +True +True +1 +degrees celsius + + +0.1 +meters + + + +FirstBaro +2ndBaro +3rdBaro + + + + +Disabled +Bus0 + + + + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF +QURT +ERB +MAV +NOVA + +True + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF +QURT +ERB +MAV +NOVA + +True + + + +Portable +Stationary +Pedestrian +Automotive +Sea +Airborne1G +Airborne2G +Airborne4G + + + + +Disabled +Enabled + + + + +Any +FloatRTK +IntegerRTK + +True + + + +Disabled +Enabled +NoChange + + + +-100 90 +Degrees + + + +send to first GPS +send to 2nd GPS +send to all + + + + +None +All +External only + + + + +Disabled +log every sample +log every 5 samples + +True + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Do not save config +Save config +Save only when needed + + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Disables automatic configuration +Enable automatic configuration + + + + +10Hz +8Hz +5Hz + +milliseconds + + + +10Hz +8Hz +5Hz + +milliseconds + + +m + + +m + + +m + + +m + + +m + + +m + + +0 250 +milliseconds + + +0 250 +milliseconds + + + + + +Disabled +Enabled + + + + +None +Servo +EPM + + + +1000 2000 +PWM + + +1000 2000 +PWM + + +1000 2000 +PWM + + +0 255 +seconds + + +0 255 + + + + +-180 180 +1 +Degrees + + +-180 180 +1 +Degrees + + +-180 180 +1 +Degrees + + + +Servo only +Servo with ExtGyro +DirectDrive VarPitch +DirectDrive FixedPitch + + + + +3-Servo CCPM +H1 Mechanical Mixing + + + +0 1000 +1 +PWM + + +-90 90 +1 +Degrees + + +-10 10 +0.1 + + + +NoFlybar +Flybar + + + +0 1000 +1 +PWM + + +0 1000 +1 +PWM + + +0 2000 + + +0 2000 + + + +Reversed +Normal + + + +1000 2000 +1 +PWM + + +1000 2000 +1 +PWM + + +1000 2000 +1 +PWM + + + +Disabled +Passthrough +Max collective +Mid collective +Min collective + + + +0 1000 +10 +PWM + + + +Ch8 Input +SetPoint +Throttle Curve + + + +0 500 +1 +pwm + + +0 60 +Seconds + + +0 60 +Seconds + + +0 1000 +10 + + +0 500 +10 + + +0 1000 +10 + + +0 1000 +10 + + +0 18000 +100 +Centi-Degrees + + +0 10 +1 + + +1 1000 +10 + + +0 500 +10 + + + + + +Disabled +Enabled + + + + +None +Chan1 +Chan2 +Chan3 +Chan4 +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + +0.1 5 +Seconds + + +1 10 +Seconds + + +100 100000 + + +1000 2000 + + +1000 2000 + + +1000 2000 + + +1000 2000 + + + +None +RPM1 +RPM2 + + + +0 100 + + + + +0 500 +1 +Percent*10 + + +0 500 +1 +Percent*10 + + +500 1000 +1 +Percent*10 + + +500 1000 +1 +Percent*10 + + + +Disabled +Very Low +Low +Medium +High +Very High + + + + + + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0 127 +Hz + + +0 127 +Hz + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0.05 50 + + + +Never +Start-up only + + + + +Don't adjust the trims +Assume first orientation was level +Assume ACC_BODYFIX is perfectly aligned to the vehicle + + + + +IMU 1 +IMU 2 +IMU 3 + + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +True + + +True + + +True + + +True + + +True + + +True + + + + + + +0 5 +0.5 +meters + + +0 90 +0.1 +degrees + + +centi-Degrees + + +0.1 +meters + + +0.1 +seconds + + +0 30 +0.1 +meters + + +0 10 +0.1 +seconds + + +0 30 +0.1 +m/s + + +0 127 +1 +percent + + +0 127 +1 +seconds + + + +Disabled +Servos to Neutral +Servos to Zero PWM + + + + +Disabled +Enabled + + + +0 100 +Percent + + + +Standard Glide Slope + + + + + +1000 2000 +1 +pwm + + +1000 2000 +1 +pwm + + + + + +None +File +MAVLink +BothFileAndMAVLink + + + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + + +0 32766 +1 + + + +Resume Mission +Restart Mission + + + + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0 100 +1 + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + +True + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + + + + + +0 500 +pwm + + +0.25 0.8 + + +0.9:Low, 0.95:Default, 1.0:High + + +6 35 +Volts + + +6 35 +Volts + + +0 200 +Amps + + + +Normal +OneShot +OneShot125 +Brushed16kHz + +True + + +0 2000 + + +0 2000 + + +0.0:Low, 0.15:Default, 0.3:High + + +0.0:Low, 0.1:Default, 0.2:High + + +0 10 +Seconds + + +0.2 0.8 + + + +Disabled +Learn +LearnAndSave + + + + +PWM enabled while disarmed +PWM disabled while disarmed + + + +5 80 +1 +Degrees + + +0 2 +0.1 +Seconds + + + + +1 60 +1 +seconds + + +0.6 1.0 +0.05 + + +0 0.1 +0.01 + + + + + +Off +Low +Medium +High + + + + +Disable +Enable + + + + +Disable +Enable + + + + +Disable +ssd1306 +sh1106 + + + + + + +Disabled +Enabled Always Land +Enabled Strict + + + + +None +CompanionComputer +IRLock +SITL_Gazebo +SITL + + + +0 360 +1 +Centi-degrees + + +-20 20 +1 +Centimeters + + +-20 20 +1 +Centimeters + + + + +0.5 5 +0.1 +Hz + + + + + +None +LightWareSF40C +MAVLink +TeraRangerTower + + + + +Default +Upside Down + + + +-180 180 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + + +None +LightWareSF40C +MAVLink + + + + +Default +Upside Down + + + +-180 180 +degrees + + + + +0.4 1.0 +0.1 +seconds + + +0.1 3.0 +0.1 + + +0 0.1 +0.01 + + +0 0.5 +0.05 + + +0 100 +1 +degrees/second + + +0 100 +1 +degrees/second + + +0.7 1.5 +0.05 + + +0 4500 +1 + + +0.1 4.0 +0.1 + + + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + +0.5 0.9 + + + + + + +0.1 +kilometers + + + +DoNotIncludeHome +IncludeHome + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Off +On +NoChange + + + + + +0.4 1.0 +0.1 +seconds + + +0.1 4.0 +0.1 + + +0 0.1 +0.01 + + +0 1.0 +0.05 + + +0 180 +1 +degrees/second + + +0 4500 +1 + + +0.1 4.0 +0.1 + + + + + +None +Analog +MaxbotixI2C +PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial +TrOneI2C + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 32767 +meters + + +5 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +MaxbotixI2C +PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial +TrOneI2C + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + + + +None +PX4-PWM + + + +0.001 + + +1 + + +1 + + +0.1 + + + +None +PX4-PWM + + + +0.001 + + + + + +Disabled +AnalogPin +RCChannelPwmValue + + + + +APM2 A0 +APM2 A1 +APM2 A13 +Pixracer +Pixhawk ADC4 +Pixhawk ADC3 + Pixhawk ADC6 +Pixhawk SBUS + + + +0 5.0 +0.01 +Volt + + +0 5.0 +0.01 +Volt + + + + + +0 2000 +Microseconds + + +0 2000 +Microseconds + + + + + +Disabled +ShowSlips +ShowOverruns + + + + +50Hz +100Hz +200Hz +250Hz +300Hz +400Hz + +True + + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +MAVlink1 +MAVLink2 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + + + +Disable +Enable + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + + + + + + + + + + + + +Disabled +Enabled + + + +0 100 +percentage + + +1000 2000 +ms + + +0 1000 +cm/s + + +0 100 +percentage + + + + + + +seconds + + +seconds + + +seconds + + + + +0.4 1.0 +0.1 +seconds + + +0.1 10.0 +0.1 + + +0 1.0 +0.05 + + +0 0.1 +0.01 + + +0 4500 +1 + + +0 5 +0.1 +m/s + + +0.0 10.0 +0.1 + + +0.0 30.0 +0.1 +m/s + + +0.0 50.0 +0.1 +degree/(m/s) + + +0.0 4500.0 +0.1 +Centidegrees + + + + +0.1 20.0 +0.1 + + +0.1 10.0 +0.1 + + +3.0 10.0 +0.2 + + +0.1 1.0 +0.1 + + +0.0 0.5 +0.02 + + +1.0 10.0 +0.5 + + +1.0 5.0 +0.05 + + +0.5 2.0 +0.05 + + +5.0 30.0 +1.0 + + +0.0 2.0 +0.1 + + +0.1 1.0 +0.1 + + +0.0 20.0 +0.1 + + +-1 127 +1 + + +-1 100 +0.1 + + +-1.0 2.0 +0.1 + + +0 45 +1 + + +-45 0 +1 + + +0.0 2.0 +0.1 + + +1.0 5.0 +0.2 + + +0.1 1.0 +0.1 + + +-5 40 +1 + + +0.0 20.0 +0.1 +m/s + + +-2.0 2.0 +0.1 +m/s/m + + +0.1 1.0 +0.1 + + +0.0 0.5 +0.02 + + +0.0 0.5 +0.02 + + +0.1 1.0 +0.1 + + + +Disable +Enable + + + + + + +Disable +Enable + + + +1 +meters + + + + + +Disable +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + +900 2100 + + +900 2100 + + + +Disable +Chan1 +Chan3 +Chan3 +Chan4 +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + + + + +Disable +Enable + + + +0 1 + + + + +20 2000 +50 +cm/s + + +100 1000 +1 +cm + + +0 1000 +50 +cm/s + + +0 500 +10 +cm/s + + +0 2000 +50 +cm/s + + +50 500 +10 +cm/s/s + + +50 500 +10 +cm/s/s + + +500 5000 +1 +cm/s/s/s + + +100 981 +1 +cm/s/s + + +25 250 +1 +cm/s/s + + + +Disable +Enable + + + + + +0 4 +0.25 + + +0 2 +0.25 + + +0 2 +0.25 + + +0.8 1.2 +0.05 + + +0 4500 +1 + + + diff --git a/src/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.7.xml b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.7.xml new file mode 100644 index 0000000000000000000000000000000000000000..07622b617cde41e03e019116b95adf6ef7bc2430 --- /dev/null +++ b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.7.xml @@ -0,0 +1,7137 @@ + + + + + + + + +True + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +1 10 +1 + + +0 30 +1 +seconds + + +0:Roll,1:Pitch,2:Yaw + +None +Roll +Pitch +Yaw + + + +0 1 +0.01 + + +0 5 +0.01 + + +0 15 +0.1 +Degrees + + +0 1000 +1 +meters + + +0 100 +1 +meters + + + +Disabled +FBWMixing +DirectMixing + + + + +Disabled +Enabled + + + +0 30 +0.1 +m/s + + +0 30 +0.1 +m/s/s + + +0 127 +1 +0.1 seconds + + +-100 100 +1 +Percent + + +0 30 +0.1 +m/s + + +0 30 +0.1 +m/s + + +0 127 +1 +percent + + +0 10 +0.5 +seconds + + +0 127 +1 +percent + + +0 100 +Percent + + + + +0 45 +1 +degrees + + +0 5 +0.5 +meters + + +0 90 +0.1 +degrees + + +centi-Degrees + + +0.1 +meters + + +0.1 +seconds + + +0 30 +0.1 +meters + + +0 10 +0.1 +seconds + + +0 30 +0.1 +m/s + + +0:AUTO_ALWAYS,1:AUTO_LAND,2:AUTO_LOITER_TO_ALT,3:AUTO_LOITER_ALL,4:AUTO_WAYPOINTS,5:LOITER,6:RTL,7:CIRCLE,8:CRUISE,9:FBWB,10:GUIDED + +Disabled +AlwaysAllowedInAuto +Auto_LandApproach +Auto_LoiterToAlt +Auto_Loiter +Auto_Waypoint +Loiter +RTL +Circle +Cruise +FBWB +Guided + + + +0 127 +1 +seconds + + + +Disabled +Servos to Neutral +Servos to Zero PWM + + + + +Disabled +Enabled + + + + +Default +L1Controller + + + +0 1 +0.1 +Percent + + + +Automatic + + + +-32767 32767 +1 +Meters + + +1 32767 +1 +Meters + + +0 32767 +1 +Meters + + +-32767 32767 +1 +Meters + + +-32767 32767 +1 +Meters + + + +None +GuidedMode +ReportOnly +GuidedModeThrPass +RTL_Mode + + + + + + + +0 32767 +1 +meters + + +0 32767 +1 +meters + + +0 32767 +1 +meters + + + +NoAutoEnable +AutoEnable +AutoEnableDisableFloorOnly + + + + +FenceReturnPoint +NearestRallyPoint + + + + +Disabled +Enabled + + + +5 100 +1 +m/s + + +5 100 +1 +m/s + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0 10000 +meters + + +1 10 +0.1 +m/s + + +-100 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 127 +1 +Percent + + +0 100 +1 +Percent + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +925 2200 +1 + + +0 100 +1 +Percent + + + +Disabled +Enabled + + + + +CIRCLE/no change(if already in AUTO|GUIDED|LOITER) +CIRCLE +FBWA + + + +1 100 +0.5 +seconds + + + +Continue +ReturnToLaunch +Glide +Deploy Parachute + + + +1 300 +0.5 +seconds + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Heartbeat +HeartbeatAndREMRSSI +HeartbeatAndAUTO + + + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + +0 9000 +1 +centi-Degrees + + +0 9000 +1 +centi-Degrees + + +-9000 0 +1 +centi-Degrees + + +10 500 +1 +degrees/second + + +10 500 +1 +degrees/second + + + +Disabled +Enabled + + + +-100 100 +0.1 +Meters + + +10 360 +1 +degrees/second + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +UpUp +UpDown +DownUp +DownDown + + + + +Disabled +UpUp +UpDown +DownUp +DownDown + + + +0.5 1.2 + + + +Disabled +Enabled + + + +-1000 1000 +percent + + +-1000 1000 +percent + + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:MODE,7:IMU,8:CMD,9:CURRENT,10:COMPASS,11:TECS,12:CAMERA,13:RC,14:SONAR,15:ARM/DISARM,19:IMU_RAW + +Disabled +APM2-Default +PX4/Pixhawk-Default + + + + + + + +cm/s + + +m/s + + +cm/s + + +centi-Degrees + + +centimeters + + +centimeters + + + +Disabled +Enabled + + + + + + +Disabled +UpUp +UpDown +DownUp +DownDown + + + +0 100 +Percent + + +0 100 +1 +m/s + + +0 100 +Percent + + +0 100 +1 +m/s + + +0 100 +Percent + + + + + + + +Disabled +Channel1 +Channel2 +Channel3 +Channel4 +Channel5 +Channel6 +Channel7 +Channel8 + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0 90 +0.1 +degrees + + + +Disable +Enable - go HOME then land +Enable - go directly to landing sequence + + + + +Disable +Enable + + + +10 127 +m/s/s + + +0:Disarm + +Disabled +Disarm + + + + + + +Disabled +Enabled + + + + + +True + + +True + +ArduPlane +AntennaTracker +Copter +Rover + + + +1 255 + + + +Mission Planner and DroidPlanner + AP Planner 2 + + + + +Disabled +Enabled + + + +0 10 +.5 +Hz + + +0.0 1000.0 +10 +Centimeters + + +0.0 500.0 +10 + + +0:Feedback from mid stick,1:High throttle cancels landing,2:Disarm on land detection + +None +Feedback from mid stick +High throttle cancels landing +Disarm on land detection + + + +0 30 +1 +seconds + + +0:Roll,1:Pitch,2:Yaw + +None +Roll +Pitch +Yaw + + + +0 8000 +1 +Centimeters + + +0.5 10.0 + +Disabled +Shallow +Steep + +.1 + + +0 2000 +50 +cm/s + + +0.01 2.0 +0.01 + + + +Disabled +Land +RTL + + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Enabled always RTL +Enabled Continue with Mission in Auto Mode + + + +100 900 + + + +Disabled +Enabled + + + + +Disabled +Mode1 +Mode2 +Mode1+2 +Mode3 +Mode1+3 +Mode2+3 +Mode1+2+3 +Mode4 +Mode1+4 +Mode2+4 +Mode1+2+4 +Mode3+4 +Mode1+3+4 +Mode2+3+4 +Mode1+2+3+4 +Mode5 +Mode1+5 +Mode2+5 +Mode1+2+5 +Mode3+5 +Mode1+3+5 +Mode2+3+5 +Mode1+2+3+5 +Mode4+5 +Mode1+4+5 +Mode2+4+5 +Mode1+2+4+5 +Mode3+4+5 +Mode1+3+4+5 +Mode2+3+4+5 +Mode1+2+3+4+5 +Mode6 +Mode1+6 +Mode2+6 +Mode1+2+6 +Mode3+6 +Mode1+3+6 +Mode2+3+6 +Mode1+2+3+6 +Mode4+6 +Mode1+4+6 +Mode2+4+6 +Mode1+2+4+6 +Mode3+4+6 +Mode1+3+4+6 +Mode2+3+4+6 +Mode1+2+3+4+6 +Mode5+6 +Mode1+5+6 +Mode2+5+6 +Mode1+2+5+6 +Mode3+5+6 +Mode1+3+5+6 +Mode2+3+5+6 +Mode1+2+3+5+6 +Mode4+5+6 +Mode1+4+5+6 +Mode2+4+5+6 +Mode1+2+4+5+6 +Mode3+4+5+6 +Mode1+3+4+5+6 +Mode2+3+4+5+6 +Mode1+2+3+4+5+6 + + + +-1 1000 +1 +Centimeters + + +0 3000 +10 +Centimeters + + + +Never change yaw +Face next waypoint +Face next waypoint except RTL +Face along GPS course + + + +0 60000 +1000 +ms + + +30 200 +10 +cm/s + + +0 500 +10 +cm/s + + +50 500 +10 +Centimeters/Second + + +50 500 +10 +cm/s/s + + + +Disabled +Enabled always RTL +Enabled Continue with Mission in Auto Mode +Enabled always LAND + + + +925 1100 +1 +pwm + + +0 300 +1 +pwm + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:RCIN,7:IMU,8:CMD,9:CURRENT,10:RCOUT,11:OPTFLOW,12:PID,13:COMPASS,14:INAV,15:CAMERA,17:MOTBATT,18:IMU_FAST,19:IMU_RAW + +Default +Default+RCIN +Default+IMU +Default+Motors +NearlyAll-AC315 +NearlyAll +All+FastATT +All+MotBatt +All+FastIMU +All+FastIMU+PID +All+FullIMU +Disabled + + + + +Normal Start-up +Start-up in ESC Calibration mode if throttle high +Start-up in ESC Calibration mode regardless of throttle +Start-up and automatically calibrate ESCs +Disabled + + + + +None +Stab Roll/Pitch kP +Rate Roll/Pitch kP +Rate Roll/Pitch kI +Rate Roll/Pitch kD +Stab Yaw kP +Rate Yaw kP +Rate Yaw kD +Altitude Hold kP +Throttle Rate kP +Throttle Accel kP +Throttle Accel kI +Throttle Accel kD +Loiter Speed +Loiter Pos kP +Velocity XY kP +Velocity XY kI +WP Speed +Acro RollPitch kP +Acro Yaw kP +Heli Ext Gyro +OF Loiter kP +OF Loiter kI +OF Loiter kD +Declination +Circle Rate +RangeFinder Gain +Rate Pitch kP +Rate Pitch kI +Rate Pitch kD +Rate Roll kP +Rate Roll kI +Rate Roll kD +Rate Pitch FF +Rate Roll FF +Rate Yaw FF + + + +0 32767 + + +0 32767 + + + +Plus +X +V +H +V-Tail +A-Tail +Y6B (New) + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +EPM +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +EPM +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +EPM +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +EPM +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +EPM +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +EPM +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance + + + +0:All,1:Baro,2:Compass,3:GPS,4:INS,5:Parameters+Rangefinder,6:RC,7:Voltage + +Disabled +Enabled +Skip Baro +Skip Compass +Skip GPS +Skip INS +Skip Params/Rangefinder +Skip RC +Skip Voltage + + + +0 127 +Seconds + + +1000 8000 +Centi-degrees + + +0 100 + +Very Soft +Soft +Medium +Crisp +Very Crisp + +10 + + +4 12 +deg/sec + + +2000 4500 +Centi-degrees + + + +No repositioning +Repositioning + + + + +Land +AltHold +Land even in Stabilize + + + +0.6:Strict, 0.8:Default, 1.0:Relaxed + + + +Disabled +Enabled + + + +50 490 +1 +Hz + + +1 10 + + +1 10 + + +0 3 +0.1 + + +0 3 +0.1 + + + +Disabled +Leveling +Leveling and Limited + + + + +Disabled +Very Low +Low +Medium +High +Very High + + + +0.1 6.0 +0.1 + + +0.02 1.00 +0.01 + + +0 4500 +10 +cm/s/s + + +1.000 8.000 + + +0.500 1.500 +0.05 + + +0.000 3.000 + + +0 1000 +Percent*10 + + +0.000 0.400 + + +1.000 100.000 +Hz + + +1.000 3.000 + + +0.500 2.000 + + +0:Roll,1:Pitch,2:Yaw + +All +Roll Only +Pitch Only +Yaw Only +Roll and Pitch +Roll and Yaw +Pitch and Yaw + + + +0.05 0.10 + + +0.001 0.006 + + + +Stopped +Running + + + + +Do Not Use in RTL and Land +Use in RTL and Land + + + +0 5 + + + +Auto +Guided +RTL +Land +Brake +Throw + + + + +Upward Throw +Drop + + + + +Disabled +Enabled + + + + + + + +True + +ArduPlane +AntennaTracker +Copter +Rover + + + +1 255 + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +0 20 +0.1 +seconds + + +0 20 +0.1 +seconds + + +0 100 +1 +degrees/second + + +0 20 +1 +seconds + + +-90 90 +0.000001 +degrees + + +-180 180 +0.000001 +degrees + + +0 10 +0.1 +seconds + + + +Position +OnOff +ContinuousRotation + + + + +Position +OnOff +ContinuousRotation + + + +0 50 +0.1 +degrees/second + + +0 50 +0.1 +degrees/second + + +0 2 +0.01 +seconds + + +0 2 +0.01 +seconds + + +-10 10 +0.1 +degrees + + +-10 10 +0.1 +degrees + + +0 360 +0.1 +degrees + + +0 100 +1 +meters + + + +Barometer +GPS +GPS vehicle only + + + +1 10 +1 +Hz + + +-90 0 +1 +Degrees + + +0 90 +1 +Degrees + + +0:ATTITUDE,1:GPS,2:RCIN,3:IMU,4:RCOUT,5:COMPASS + +Default +Disabled + + + +0.0 3.0 +0.01 + + +0.0 3.0 +0.01 + + +0 4000 +10 +Percent*10 + + +0.001 0.1 +0.001 + + +0.0 3.0 +0.01 + + +0.0 3.0 +0.01 + + +0 4000 +10 +Percent*10 + + +0.001 0.1 +0.001 + + +1 255 + + + + + + +True + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:MODE,7:IMU,8:CMD,9:CURRENT,10:COMPASS,11:TECS,12:CAMERA,13:RC,14:SONAR,15:ARM/DISARM,19:IMU_RAW + +Disabled +APM2-Default +PX4/Pixhawk-Default + + + + + + + + +MANUAL +LEARNING +STEERING +HOLD +AUTO +RTL +GUIDED + + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +0 30 +1 +seconds + + +0:Steering,1:Throttle + +None +Steering +Throttle + + + + +Disabled +Enabled + + + + +Disabled +APM TriggerPin + Pixhawk TriggerPin + + + +0 20 +0.1 +m/s/s + + +0 100 +0.1 +m/s + + +0 100 +1 +percent + + +0 100 +0.1 +meters + + +0 100 +1 +percent + + +0 100 +1 +m/s + + +0 360 +1 +degrees + + + +Nothing +LearnWaypoint + + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + + +Disabled +SkidSteeringOutput + + + + +Disabled +SkidSteeringInput + + + + +Nothing +RTL +HOLD + + + +seconds + + + +Disabled +Enabled + + + +925 1100 +1 + + + +Disabled +Enabled + + + +0 1000 +1 +centimeters + + +-45 45 +1 +centimeters + + +0 100 +0.1 +seconds + + +1 100 +1 + + + + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + +0 1000 +0.1 +meters + + +0.2 10 +0.1 +gravities + + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +MAVlink1 +MAVLink2 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + + +True +True +1 +pascals + + +True +True +1 +degrees celsius + + +meters +0.1 + + + +FirstBaro +2ndBaro +3rdBaro + + + + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF + +True + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF + +True + + + +Portable +Stationary +Pedestrian +Automotive +Sea +Airborne1G +Airborne2G +Airborne4G + + + + +Disabled +Enabled + + + + +Any +FloatRTK +IntegerRTK + +True + + + +Disabled +Enabled +NoChange + + + +-100 90 +Degrees + + + +send to first GPS +send to 2nd GPS +send to all + + + + +None +All +External only + + + + +Disabled +log every sample +log every 5 samples + +True + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Do not save config +Save config +Save only when needed + + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Disables automatic configuration +Enable automatic configuration + + + + + + +Servo +Relay + + + +0 50 +seconds + + +1000 2000 +pwm + + +1000 2000 +pwm + + +0 1000 +meters + + + +Low +High + + + +0 10000 +milliseconds + + +0 180 +Degrees + + + +Disabled +PX4 AUX1 +PX4 AUX2 +PX4 AUX3 +PX4 AUX4(fast capture) +PX4 AUX5 +PX4 AUX6 + + + + +TriggerLow +TriggerHigh + + + + + + +Disabled +THR_MIN PWM when disarmed +0 PWM when disarmed + + + +0:All,1:Barometer,2:Compass,3:GPS lock,4:INS,5:Parameters,6:RC,7:Board voltage,8:Battery Level,9:Airspeed,10:Logging Available,11:Hardware safety switch,12:GPS Configuration + +None +All +Barometer +Compass +GPS Lock +INS(INertial Sensors - accels & gyros) +Parameters(unused) +RC Failsafe +Board voltage +Battery Level +Airspeed +LoggingAvailable +Hardware safety switch +GPS configuration + + + +0.25 3.0 +m/s/s + + +0.1 +Volts + + +0.1 +Volts + + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Off +On +NoChange + + + + + + +Disabled +Enabled + + + + +First Relay +Second Relay +Third Relay +Fourth Relay +Servo + + + +1000 2000 +1 +pwm + + +1000 2000 +1 +pwm + + +0 32000 +1 +Meters + + +0 5000 +1 +Milliseconds + + + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-I2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 32767 +meters + + +0 127 +1 +centimeters + + +0 127 +1 + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-I2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-I2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +meters/Volt +0.001 + + +Volts +0.001 + + + +Linear +Inverted +Hyperbolic + + + +centimeters +1 + + +centimeters +1 + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +milliseconds +1 + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-I2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +meters/Volt +0.001 + + +Volts +0.001 + + + +Linear +Inverted +Hyperbolic + + + +centimeters +1 + + +centimeters +1 + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +milliseconds +1 + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + + + + +Disable +Enable + + + +meters +1 + + + + + +Disabled +Enabled + + + +1 100 + + +1 100000 + + +-1 16777215 + + + +NoInfo +Light +Small +Large +HighVortexlarge +Heavy +HighlyManuv +Rotocraft +RESERVED +Glider +LightAir +Parachute +UltraLight +RESERVED +UAV +Space +RESERVED +EmergencySurface +ServiceSurface +PointObstacle + + + + +NO_DATA +L15W23 +L25W28P5 +L25W34 +L35W33 +L35W38 +L45W39P5 +L45W45 +L55W45 +L55W52 +L65W59P5 +L65W67 +L75W72P5 +L75W80 +L85W80 +L85W90 + + + + +NoData +Left2m +Left4m +Left6m +Center +Right2m +Right4m +Right6m + + + + +NO_DATA +AppliedBySensor + + + + +Disabled +Rx-Only +Tx-Only +Rx and Tx Enabled + + + + + + +Disabled +Enabled + + + + +Remain in AVOID_ADSB +Resume previous flight mode +RTL +Resume if AUTO else Loiter + + + + + + + + + + + + + + + + + + + + +Disable +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + +900 2100 + + +900 2100 + + + +Disable +Chan1 +Chan3 +Chan3 +Chan4 +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + + + + +Disable +Enable + + + +0 1 + + + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Reversed +Normal + + + +0 200 +pwm + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle + + + + + +0.4 1.0 +0.1 +seconds + + +0.1 4.0 +0.1 + + +0 0.1 +0.01 + + +0 1.0 +0.05 + + +0 180 +1 +degrees/second + + +0 4500 +1 + + +0.1 4.0 +0.1 + + + + +0.4 1.0 +0.1 +seconds + + +0.1 3.0 +0.1 + + +0 0.1 +0.01 + + +0 0.5 +0.05 + + +0 100 +1 +degrees/second + + +0 100 +1 +degrees/second + + +0.7 1.5 +0.05 + + +0 4500 +1 + + +0.1 4.0 +0.1 + + + + +0 4 +0.25 + + +0 2 +0.25 + + +0 2 +0.25 + + +0.8 1.2 +0.05 + + +0 4500 +1 + + + + +0.4 1.0 +0.1 +seconds + + +0.1 10.0 +0.1 + + +0 1.0 +0.05 + + +0 0.1 +0.01 + + +0 4500 +1 + + +0 5 +0.1 +m/s + + +0.0 10.0 +0.1 + + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-3.142 3.142 +0.01 +Radians + + + +Disabled +Internal-Learning +EKF-Learning + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Use Throttle +Use Current + + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +FirstCompass +SecondCompass +ThirdCompass + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + + + + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 20 +0.1 + + + + + +Disabled +ShowSlips +ShowOverruns + + + + +50Hz +100Hz +200Hz +250Hz +300Hz +400Hz + +True + + + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + + + + +Unknown +unused +unused +unused +SITL +PX4v1 +PX4v2 +unused +Linux + + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0 127 +Hz + + +0 127 +Hz + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0.05 50 + + + +Never +Start-up only + + + + +Don't adjust the trims +Assume first orientation was level +Assume ACC_BODYFIX is perfectly aligned to the vehicle + + + + +IMU 1 +IMU 2 +IMU 3 + + + + + +0.0 1.0 +.01 + + + +Disabled +Enabled + + + +0.1 0.4 +.01 + + +0.1 0.4 +.01 + + +0 127 +1 +m/s + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 + + + +0.001 0.5 +.01 + + +0 10 +1 + + + +Disabled +Enabled +Enable EKF2 + + + + + + +Disable +Enable + + + + +Use +Don't Use + + + +0.1 + + +0.1 + + + + + + + + + +Disable +Enable + + + + + + + +1 60 +1 +seconds + + +0.6 1.0 +0.05 + + +0 0.1 +0.01 + + + + +0.1 20.0 +0.1 + + +0.1 10.0 +0.1 + + +3.0 10.0 +0.2 + + +0.1 1.0 +0.1 + + +0.0 0.5 +0.02 + + +1.0 10.0 +0.5 + + +1.0 5.0 +0.05 + + +0.5 2.0 +0.05 + + +5.0 30.0 +1.0 + + +0.0 2.0 +0.1 + + +0.1 1.0 +0.1 + + +0.0 20.0 +0.1 + + +-1 127 +1 + + +-1 100 +0.1 + + +-1.0 2.0 +0.1 + + +0 45 +1 + + +-45 0 +1 + + +0.0 2.0 +0.1 + + +1.0 5.0 +0.2 + + +0.1 1.0 +0.1 + + +-5 40 +1 + + +0.0 20.0 +0.1 +m/s + + +-2.0 2.0 +0.1 +m/s/m + + +0.1 1.0 +0.1 + + +0.0 0.5 +0.02 + + +0.0 0.5 +0.02 + + +0.1 1.0 +0.1 + + + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0 100 +1 + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + +True + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + + + + + + +None +File +MAVLink +BothFileAndMAVLink + + + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +SMBus +Bebop + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Watts + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +SMBus +Bebop + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Amps + + + + + +No PWMs +Two PWMs +Four PWMs +Six PWMs +Three PWMs and One Capture + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled + +True + + + +Disabled +50Hz +75Hz +100Hz +150Hz +200Hz +250Hz +300Hz + +True + + +-32767 32768 + + + +Disabled +Enabled + + + +0:Ch1,1:Ch2,2:Ch3,3:Ch4,4:Ch5,5:Ch6,6:Ch7,7:Ch8 + +Disabled +Enabled + +True + + +degreesC +-1 80 + + + +AUTO +PX4V1 +Pixhawk +Pixhawk2 +Pixracer +PixhawkMini +Pixhawk2Slim +VRBrain 5.1 +VRBrain 5.2 +VR Micro Brain 5.1 +VR Micro Brain 5.2 +VRBrain Core 1.0 +VRBrain 5.4 + +True + + + + + + + + + + + + + + + + + + + + +meters + + +meters + + +millibar + + + + + + + + + + + + + + +seconds + + + + + +Disabled +Enabled + + + +-200 +200 +1 + + +-200 +200 +1 + + +-18000 +18000 +1 + + + + +0 32766 +1 + + + +Resume Mission +Restart Mission + + + + + + + +0.1 +kilometers + + + +DoNotIncludeHome +IncludeHome + + + + + + +Disabled +Enabled + + + +0.05 5.0 +0.05 + + +0.05 5.0 +0.05 + + +0.1 10.0 +0.1 +meters + + +0.1 10.0 +0.1 +meters + + +0.01 0.5 +0.01 + + +0.5 5.0 +0.1 +m/s + + +0.01 1.0 +0.1 + + +0.0 1.0 +0.1 + + +0.001 0.05 +0.001 +rad/s + + +0.05 1.0 +0.01 +m/s/s + + +0.0000001 0.00001 +rad/s + + +0.00001 0.001 +m/s/s + + +0.0001 0.01 +gauss/s + + +0.0001 0.01 +gauss/s + + +0 500 +10 +milliseconds + + +0 500 +10 +milliseconds + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS use optical flow + + + +1 100 +1 + + +1 100 +1 + + +1 100 +1 + + +1 100 +1 + + +1 100 +1 + + + +Speed and Height +Acceleration +Never +Always + + + +100 500 +50 + + +10 50 +5 +meters + + +1 50 +1 + + +0.05 1.0 +0.05 +rad/s + + +1 100 +1 + + +0 500 +10 +milliseconds + + +1 100 +1 + + +1.0 4.0 +0.1 + + + +Trust EKF more +Trust DCM more + + + + +Use Baro +Use Range Finder + + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS use optical flow + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + +0 250 +10 +msec + + + +Use Baro +Use Range Finder +Use GPS + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +msec + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +msec + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.000001 0.001 +1/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +1 127 + + +50 200 +% + + +0.5 50.0 +m/s + + + +Disabled +FirstIMU +FirstAndSecondIMU +AllIMUs + + + +0.05 1.0 +0.05 +gauss + + +100 1000 +25 + + +10 50 +5 + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + + + + +None +PX4-PWM + + + +0.001 + + +1 + + +1 + + +0.1 + + + +None +PX4-PWM + + + +0.001 + + + + + +Disabled +AnalogPin +RCChannelPwmValue + + + + +APM2 A0 +APM2 A1 +APM2 A13 +Pixracer +Pixhawk ADC4 +Pixhawk ADC3 + Pixhawk ADC6 +Pixhawk SBUS + + + +0 5.0 +0.01 +Volt + + +0 5.0 +0.01 +Volt + + + + + +0 2000 +Microseconds + + +0 2000 +Microseconds + + + + + +Off +Low +Medium +High + + + + +Disable +Enable + + + + +Disable +Enable + + + + + + +Disabled +Enabled + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +0 3600 + + + + + +Disabled +Enabled + + + + +None +Chan1 +Chan2 +Chan3 +Chan4 +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + +0.1 5 +Seconds + + +1 10 +Seconds + + +100 100000 + + +1000 2000 + + +1000 2000 + + +1000 2000 + + +1000 2000 + + + +None +RPM1 +RPM2 + + + +0 100 + + + + + +Disabled +Enabled + + + +1000 2000 + + +1000 2000 + + +1000 2000 + + +0 255 + + +0 255 + + + + +1000 2000 +1 +pwm + + +1000 2000 +1 +pwm + + + + +0 500 +1 +Percent*10 + + +0 500 +1 +Percent*10 + + +500 1000 +1 +Percent*10 + + +500 1000 +1 +Percent*10 + + + +Disabled +Very Low +Low +Medium +High +Very High + + + + + +0 2000 +50 +cm/s + + +100 1000 +1 +cm + + +0 1000 +50 +cm/s + + +0 500 +10 +cm/s + + +0 2000 +50 +cm/s + + +50 500 +10 +cm/s/s + + +50 500 +10 +cm/s/s + + +500 5000 +1 +cm/s/s/s + + +100 981 +1 +cm/s/s + + +25 250 +1 +cm/s/s + + + +Disable +Enable + + + + + +0 10000 +100 +cm + + +-90 90 +1 +deg/s + + + + +500 18000 +100 +Centi-Degrees/Sec + + +0 72000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +3.000 12.000 + + +3.000 12.000 + + +3.000 6.000 + + +0.5 10.0 + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + + + +0.5 5 +0.1 +Hz + + + + + +Disabled +Enabled + + + +0 100 +percentage + + +1000 2000 +ms + + +0 1000 +cm/s + + +0 100 +percentage + + + + + +Disabled +Enabled + + + +0:Altitude,1:Circle,2:Polygon + +None +Altitude +Circle +Altitude and Circle +Polygon +Altitude and Polygon +Circle and Polygon +All + + + + +Report Only +RTL or Land + + + +10 1000 +1 +Meters + + +30 10000 +Meters + + +1 10 +Meters + + +1 20 + + + + + +None +StopAtFence + + + + + +-180 180 +1 +Degrees + + +-180 180 +1 +Degrees + + +-180 180 +1 +Degrees + + + +Servo only +Servo with ExtGyro +DirectDrive VarPitch +DirectDrive FixedPitch + + + + +3-Servo CCPM +H1 Mechanical Mixing + + + +0 1000 +1 +PWM + + +-90 90 +1 +Degrees + + +-10 10 +0.1 + + + +NoFlybar +Flybar + + + +0 1000 +1 +PWM + + +0 1000 +1 +PWM + + +0 2000 + + +0 2000 + + + +Reversed +Normal + + + + + +0 500 +pwm + + +0.25 0.8 + + +0.9:Low, 0.95:Default, 1.0:High + + +6 35 +Volts + + +6 35 +Volts + + +0 200 +Amps + + + +Normal +OneShot +OneShot125 + + + +0 2000 + + +0 2000 + + +0.0:Low, 0.15:Default, 0.3:High + + +0.0:Low, 0.1:Default, 0.2:High + + +0 10 +Seconds + + +0.2 0.8 + + + +Disabled +Learn +LearnAndSave + + + + + + +Disabled +Enabled Always Land +Enabled Strict + + + + +None +CompanionComputer +IRLock + + + + diff --git a/src/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.8.xml b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.8.xml new file mode 100644 index 0000000000000000000000000000000000000000..91f87f90fda231c636912b9c077dc5fae61f4993 --- /dev/null +++ b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Plane.3.8.xml @@ -0,0 +1,8496 @@ + + + + + + + + +True + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +1 10 +1 + + +0 30 +1 +seconds + + +0:Roll,1:Pitch,2:Yaw + + +0 1 +0.01 + + +0 5 +0.01 + + +0 15 +0.1 +Degrees + + +0 1000 +1 +meters + + +0 100 +1 +meters + + + +Disabled +FBWMixing +DirectMixing + + + + +Disabled +Enabled + + + +0 30 +0.1 +m/s + + +0 30 +0.1 +m/s/s + + +0 127 +1 +0.1 seconds + + +-100 100 +1 +Percent + + +0 30 +0.1 +m/s + + +0 30 +0.1 +m/s + + +0 127 +1 +percent + + +0 10 +0.5 +seconds + + +0 100 +Percent + + + + +0 45 +1 +degrees + + +0:AUTO_ALWAYS,1:AUTO_LAND,2:AUTO_LOITER_TO_ALT,3:AUTO_LOITER_ALL,4:AUTO_WAYPOINTS,5:LOITER,6:RTL,7:CIRCLE,8:CRUISE,9:FBWB,10:GUIDED + + + +Default +L1Controller + + + + +Automatic + + + +-32767 32767 +1 +Meters + + +1 32767 +1 +Meters + + +0 32767 +1 +Meters + + +-32767 32767 +1 +Meters + + +-32767 32767 +1 +Meters + + + +None +GuidedMode +ReportOnly +GuidedModeThrPass +RTL_Mode + + + + + + + +0 32767 +1 +meters + + +0 32767 +1 +meters + + +0 32767 +1 +meters + + + +NoAutoEnable +AutoEnable +AutoEnableDisableFloorOnly + + + + +FenceReturnPoint +NearestRallyPoint + + + + +Disabled +Enabled + + + +5 100 +1 +m/s + + +5 100 +1 +m/s + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0 10000 +meters + + +1 10 +0.1 +m/s + + +-100 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 127 +1 +Percent + + +0 100 +1 +Percent + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +925 2200 +1 + + +0 100 +1 +Percent + + + +Disabled +Enabled + + + + +CIRCLE/no change(if already in AUTO|GUIDED|LOITER) +CIRCLE +FBWA + + + +1 100 +0.5 +seconds + + + +Continue +ReturnToLaunch +Glide +Deploy Parachute + + + +1 300 +0.5 +seconds + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Heartbeat +HeartbeatAndREMRSSI +HeartbeatAndAUTO + + + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + +0 9000 +1 +centi-Degrees + + +0 9000 +1 +centi-Degrees + + +-9000 0 +1 +centi-Degrees + + +10 500 +1 +degrees/second + + +10 500 +1 +degrees/second + + + +Disabled +Enabled + + + +-100 100 +0.1 +Meters + + +10 360 +1 +degrees/second + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + +0.5 1.2 + + + +Disabled +Enabled + + + +-1000 1000 +percent + + +-1000 1000 +percent + + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:MODE,7:IMU,8:CMD,9:CURRENT,10:COMPASS,11:TECS,12:CAMERA,13:RC,14:SONAR,15:ARM/DISARM,19:IMU_RAW + +Disabled +PX4/Pixhawk-Default + + + + + + + +cm/s + + +m/s + + +cm/s + + +centi-Degrees + + +centimeters + + +centimeters + + + +Disabled +Enabled + + + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + +0 100 +Percent + + +0 100 +1 +m/s + + +0 100 +Percent + + +0 100 +1 +m/s + + + + + + + +Disabled +Channel1 +Channel2 +Channel3 +Channel4 +Channel5 +Channel6 +Channel7 +Channel8 + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0 90 +0.1 +degrees + + + +Disable +Enable - go HOME then land +Enable - go directly to landing sequence + + + + +Disable +Enable + + + +10 127 +m/s/s + + +0:Disarm + + + + + +Disabled +Enabled + + + + + +True + + +True + +ArduPlane +AntennaTracker +Copter +Rover + + + +1 255 + + + +Mission Planner and DroidPlanner + AP Planner 2 + + + + +Disabled +Enabled + + + +0 10 +.5 +Hz + + +0.0 1000.0 +10 +Centimeters + + +0.0 500.0 +10 + + +0:Feedback from mid stick,1:High throttle cancels landing,2:Disarm on land detection + +None +Feedback from mid stick +High throttle cancels landing +Disarm on land detection + + + +0 30 +1 +seconds + + +0:Roll,1:Pitch,2:Yaw + +None +Roll +Pitch +Yaw + + + +0 8000 +1 +Centimeters + + +0.5 10.0 + +Disabled +Shallow +Steep + +.1 + + +0 2000 +50 +cm/s + + +0.01 2.0 +0.01 + + + +Disabled +Land +RTL + + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Enabled always RTL +Enabled Continue with Mission in Auto Mode + + + +100 900 + + + +Disabled +Enabled + + + + +Disabled +Mode1 +Mode2 +Mode1+2 +Mode3 +Mode1+3 +Mode2+3 +Mode1+2+3 +Mode4 +Mode1+4 +Mode2+4 +Mode1+2+4 +Mode3+4 +Mode1+3+4 +Mode2+3+4 +Mode1+2+3+4 +Mode5 +Mode1+5 +Mode2+5 +Mode1+2+5 +Mode3+5 +Mode1+3+5 +Mode2+3+5 +Mode1+2+3+5 +Mode4+5 +Mode1+4+5 +Mode2+4+5 +Mode1+2+4+5 +Mode3+4+5 +Mode1+3+4+5 +Mode2+3+4+5 +Mode1+2+3+4+5 +Mode6 +Mode1+6 +Mode2+6 +Mode1+2+6 +Mode3+6 +Mode1+3+6 +Mode2+3+6 +Mode1+2+3+6 +Mode4+6 +Mode1+4+6 +Mode2+4+6 +Mode1+2+4+6 +Mode3+4+6 +Mode1+3+4+6 +Mode2+3+4+6 +Mode1+2+3+4+6 +Mode5+6 +Mode1+5+6 +Mode2+5+6 +Mode1+2+5+6 +Mode3+5+6 +Mode1+3+5+6 +Mode2+3+5+6 +Mode1+2+3+5+6 +Mode4+5+6 +Mode1+4+5+6 +Mode2+4+5+6 +Mode1+2+4+5+6 +Mode3+4+5+6 +Mode1+3+4+5+6 +Mode2+3+4+5+6 +Mode1+2+3+4+5+6 + + + +-1 1000 +1 +Centimeters + + +0 3000 +10 +Centimeters + + + +Never change yaw +Face next waypoint +Face next waypoint except RTL +Face along GPS course + + + +0 60000 +1000 +ms + + +30 200 +10 +cm/s + + +0 500 +10 +cm/s + + +50 500 +10 +Centimeters/Second + + +50 500 +10 +cm/s/s + + + +Disabled +Enabled always RTL +Enabled Continue with Mission in Auto Mode +Enabled always LAND + + + +925 1100 +1 +pwm + + +0 300 +1 +pwm + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:RCIN,7:IMU,8:CMD,9:CURRENT,10:RCOUT,11:OPTFLOW,12:PID,13:COMPASS,14:INAV,15:CAMERA,17:MOTBATT,18:IMU_FAST,19:IMU_RAW + +Default +Default+RCIN +Default+IMU +Default+Motors +NearlyAll-AC315 +NearlyAll +All+FastATT +All+MotBatt +All+FastIMU +All+FastIMU+PID +All+FullIMU +Disabled + + + + +Normal Start-up +Start-up in ESC Calibration mode if throttle high +Start-up in ESC Calibration mode regardless of throttle +Start-up and automatically calibrate ESCs +Disabled + + + + +None +Stab Roll/Pitch kP +Rate Roll/Pitch kP +Rate Roll/Pitch kI +Rate Roll/Pitch kD +Stab Yaw kP +Rate Yaw kP +Rate Yaw kD +Altitude Hold kP +Throttle Rate kP +Throttle Accel kP +Throttle Accel kI +Throttle Accel kD +Loiter Speed +Loiter Pos kP +Velocity XY kP +Velocity XY kI +WP Speed +Acro RollPitch kP +Acro Yaw kP +Heli Ext Gyro +OF Loiter kP +OF Loiter kI +OF Loiter kD +Declination +Circle Rate +RangeFinder Gain +Rate Pitch kP +Rate Pitch kI +Rate Pitch kD +Rate Roll kP +Rate Roll kI +Rate Roll kD +Rate Pitch FF +Rate Roll FF +Rate Yaw FF + + + +0 32767 + + +0 32767 + + + +Plus +X +V +H +V-Tail +A-Tail +Y6B + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + +0 127 +Seconds + + +1000 8000 +Centi-degrees + + +0 100 + +Very Soft +Soft +Medium +Crisp +Very Crisp + +10 + + +4 12 +deg/sec + + +2000 4500 +Centi-degrees + + + +No repositioning +Repositioning + + + + +Land +AltHold +Land even in Stabilize + + + +0.6:Strict, 0.8:Default, 1.0:Relaxed + + + +Disabled +Enabled + + + +50 490 +1 +Hz + + +1 10 + + +1 10 + + +0 3 +0.1 + + +0 3 +0.1 + + + +Disabled +Leveling +Leveling and Limited + + + +-0.5 1.0 + +Disabled +Very Low +Low +Medium +High +Very High + + + +0.1 6.0 +0.1 + + +0.02 1.00 +0.01 + + +0 4500 +10 +cm/s/s + + +1.000 8.000 + + +0.500 1.500 +0.05 + + +0.000 3.000 + + +0 1000 +Percent*10 + + +0.000 0.400 + + +1.000 100.000 +Hz + + +1.000 3.000 + + +0.500 2.000 + + +0:Roll,1:Pitch,2:Yaw + +All +Roll Only +Pitch Only +Yaw Only +Roll and Pitch +Roll and Yaw +Pitch and Yaw + + + +0.05 0.10 + + +0.001 0.006 + + + +Stopped +Running + + + + +Do Not Use in RTL and Land +Use in RTL and Land + + + +0 5 + + + +Auto +Guided +RTL +Land +Brake +Throw + + + + +Upward Throw +Drop + + + + +Disabled +Enabled + + + +0:ADSBMavlinkProcessing + + +-0.5 1.0 + +Disabled +Very Low +Low +Medium +High +Very High + + + +0 1 + + + +Undefined +Quad +Hexa +Octa +OctaQuad +Y6 +Heli +Tri +SingleCopter +CoaxCopter + + + + + + + +True + +ArduPlane +AntennaTracker +Copter +Rover + + + +1 255 + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +0 20 +0.1 +seconds + + +0 20 +0.1 +seconds + + +0 100 +1 +degrees/second + + +0 20 +1 +seconds + + +-90 90 +0.000001 +degrees + + +-180 180 +0.000001 +degrees + + +0 10 +0.1 +seconds + + + +Position +OnOff +ContinuousRotation + + + + +Position +OnOff +ContinuousRotation + + + +0 50 +0.1 +degrees/second + + +0 50 +0.1 +degrees/second + + +0 2 +0.01 +seconds + + +0 2 +0.01 +seconds + + +-10 10 +0.1 +degrees + + +-10 10 +0.1 +degrees + + +0 360 +0.1 +degrees + + +0 100 +1 +meters + + + +Barometer +GPS +GPS vehicle only + + + +1 10 +1 +Hz + + +-90 0 +1 +Degrees + + +0 90 +1 +Degrees + + +0:ATTITUDE,1:GPS,2:RCIN,3:IMU,4:RCOUT,5:COMPASS + +Default +Disabled + + + +0.0 3.0 +0.01 + + +0.0 3.0 +0.01 + + +0 4000 +10 +Percent*10 + + +0.001 0.1 +0.001 + + +0.0 3.0 +0.01 + + +0.0 3.0 +0.01 + + +0 4000 +10 +Percent*10 + + +0.001 0.1 +0.001 + + +1 255 + + + + + + +True + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:MODE,7:IMU,8:CMD,9:CURRENT,10:COMPASS,11:TECS,12:CAMERA,13:RC,14:SONAR,15:ARM/DISARM,19:IMU_RAW + +Disabled +APM2-Default +PX4/Pixhawk-Default + + + + + + + + +MANUAL +LEARNING +STEERING +HOLD +AUTO +RTL +GUIDED + + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +0 30 +1 +seconds + + +0:Steering,1:Throttle + +None +Steering +Throttle + + + + +Disabled +Enabled + + + + +Disabled +APM TriggerPin0 +APM TriggerPin1 +APM TriggerPin2 +APM TriggerPin3 +APM TriggerPin4 +APM TriggerPin5 +APM TriggerPin6 +APM TriggerPin7 +APM TriggerPin8 +Pixhawk TriggerPin50 +Pixhawk TriggerPin51 +Pixhawk TriggerPin52 +Pixhawk TriggerPin53 +Pixhawk TriggerPin54 +Pixhawk TriggerPin55 + + + +0 20 +0.1 +m/s/s + + +0 100 +0.1 +m/s + + +0 100 +1 +percent + + +0 100 +0.1 +meters + + +0 100 +1 +percent + + +0 100 +1 +m/s + + +0 360 +1 +degrees + + + +Nothing +LearnWaypoint + + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + + +Disabled +SkidSteeringOutput + + + + +Disabled +SkidSteeringInput + + + + +Nothing +RTL +HOLD + + + +seconds + + + +Disabled +Enabled + + + +925 1100 +1 + + + +Disabled +Enabled + + + + +Disabled +HOLD +HoldAndDisarm + + + +0 1000 +1 +centimeters + + +-45 45 +1 +centimeters + + +0 100 +0.1 +seconds + + +1 100 +1 + + + + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + +0 1000 +0.1 +meters + + +0.2 10 +0.1 +gravities + + + + + +Disabled +Enabled + + + +1 100 + + +1 100000 + + +-1 16777215 + + + +NoInfo +Light +Small +Large +HighVortexlarge +Heavy +HighlyManuv +Rotocraft +RESERVED +Glider +LightAir +Parachute +UltraLight +RESERVED +UAV +Space +RESERVED +EmergencySurface +ServiceSurface +PointObstacle + + + + +NO_DATA +L15W23 +L25W28P5 +L25W34 +L35W33 +L35W38 +L45W39P5 +L45W45 +L55W45 +L55W52 +L65W59P5 +L65W67 +L75W72P5 +L75W80 +L85W80 +L85W90 + + + + +NoData +Left2m +Left4m +Left6m +Center +Right2m +Right4m +Right6m + + + + +NO_DATA +AppliedBySensor + + + + +Disabled +Rx-Only +Tx-Only +Rx and Tx Enabled + + + + + + + + + + + + + + + + + + + + + +meters + + +meters + + +millibar + + + + + + + + + + + + + + +seconds + + + + +0.0 1.0 +.01 + + + +Disabled +Enabled + + + +0.1 0.4 +.01 + + +0.1 0.4 +.01 + + +0 127 +1 +m/s + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 + + + +0.001 0.5 +.01 + + +0 10 +1 + + + +Disabled +Enable EKF2 +Enable EKF3 + + + + + + +Disabled +THR_MIN PWM when disarmed +0 PWM when disarmed + + + +0:All,1:Barometer,2:Compass,3:GPS lock,4:INS,5:Parameters,6:RC,7:Board voltage,8:Battery Level,9:Airspeed,10:Logging Available,11:Hardware safety switch,12:GPS Configuration + +None +All +Barometer +Compass +GPS Lock +INS(INertial Sensors - accels & gyros) +Parameters(unused) +RC Failsafe +Board voltage +Battery Level +Airspeed +LoggingAvailable +Hardware safety switch +GPS configuration + + + +0.25 3.0 +m/s/s + + +0.1 +Volts + + +0.1 +Volts + + + + + +None +I2C-MS4525D0 +Analog +I2C-MS5525 + + + + +Use +Don't Use + + + +0.1 + + +0.1 + + + + + + + + + +Disable +Enable + + + + + + +Bus0 +Bus1 + + + + + +500 18000 +100 +Centi-Degrees/Sec + + +0 72000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +3.000 12.000 + + +3.000 12.000 + + +3.000 6.000 + + +0.5 10.0 + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + +0.5 0.9 + + + +Disabled 1 + + + +0 1000 +Centi-Degrees + + +0.08 0.35 +0.005 + + +0.01 0.6 +0.01 + + +0 1 +0.01 + + +0.001 0.03 +0.001 + + +1 20 +1 +Hz + + +0.08 0.35 +0.005 + + +0.01 0.6 +0.01 + + +0 1 +0.01 + + +0.001 0.03 +0.001 + + +1 20 +1 +Hz + + +0.180 0.60 +0.005 + + +0.01 0.06 +0.01 + + +0 1 +0.01 + + +0.000 0.02 +0.001 + + +1 20 +1 +Hz + + + + + +Disabled +Enabled + + + + +Remain in AVOID_ADSB +Resume previous flight mode +RTL +Resume if AUTO else Loiter + + + + + +seconds + + +seconds + + +meters + + +meters + + +meters + + +meters + + + + +0:StopAtFence,1:UseProximitySensor + +None +StopAtFence +UseProximitySensor +All + + + +0 4500 + + +3 30 +meters + + + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +Solo +Bebop +SMBus-Maxell + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Watts + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +Solo +Bebop +SMBus-Maxell + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Amps + + + + + +None +Pozyx + + + +-90 90 +0.000001 +degrees + + +-180 180 +0.000001 +degrees + + +0 10000 +1 +meters + + +-180 +180 +1 +degrees + + + + + +No PWMs +Two PWMs +Four PWMs +Six PWMs +Three PWMs and One Capture + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled + +True + + + +Disabled +50Hz +75Hz +100Hz +150Hz +200Hz +250Hz +300Hz + +True + + +-32767 32768 + + + +Disabled +Enabled +Dynamic ID/Update + + + +0:Ch1,1:Ch2,2:Ch3,3:Ch4,4:Ch5,5:Ch6,6:Ch7,7:Ch8,8:Ch9,9:Ch10,10:Ch11,11:Ch12,12:Ch13,13:Ch14 + +Disabled +Enabled + +True + + +-1 80 +degreesC + + + +AUTO +PX4V1 +Pixhawk +Pixhawk2 +Pixracer +PixhawkMini +Pixhawk2Slim +VRBrain 5.1 +VRBrain 5.2 +VR Micro Brain 5.1 +VR Micro Brain 5.2 +VRBrain Core 1.0 +VRBrain 5.4 + +True + + + + + +Disabled +Enabled + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +0 3600 + + + + + +Servo +Relay + + + +0 50 +deciseconds + + +1000 2000 +pwm + + +1000 2000 +pwm + + +0 1000 +meters + + + +Low +High + + + +0 10000 +milliseconds + + +0 180 +Degrees + + + +Disabled +PX4 AUX1 +PX4 AUX2 +PX4 AUX3 +PX4 AUX4(fast capture) +PX4 AUX5 +PX4 AUX6 + + + + +TriggerLow +TriggerHigh + + + + + + +Disabled +Enabled + + + + +First Relay +Second Relay +Third Relay +Fourth Relay +Servo + + + +1000 2000 +1 +pwm + + +1000 2000 +1 +pwm + + +0 32000 +1 +Meters + + +0 5000 +1 +Milliseconds + + + + +0 10000 +100 +cm + + +-90 90 +1 +deg/s + + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-3.142 3.142 +0.01 +Radians + + + +Disabled +Internal-Learning +EKF-Learning + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Use Throttle +Use Current + + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +FirstCompass +SecondCompass +ThirdCompass + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + + + + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 32 + +Very Strict +Strict +Default +Relaxed + +0.1 + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + +0 250 +10 +milliseconds + + + +Use Baro +Use Range Finder +Use GPS +Use Range Beacon + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.000001 0.001 +1/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +50 200 +% + + +0.5 50.0 +m + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +0.05 1.0 +0.05 +rad + + +100 1000 +25 + + +10 50 +5 +cs + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +2.0 6.0 +0.5 +m/s + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + + +Use Baro +Use Range Finder +Use GPS +Use Range Beacon + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +50 200 +% + + +0.5 50.0 +m + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +0.05 1.0 +0.05 +rad + + +100 1000 +25 + + +10 50 +5 +cs + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +2.0 6.0 +0.5 +m/s + + +0.5 2.5 +0.1 +m/s/s + + + + + +Disabled +Enabled + + + +0:Altitude,1:Circle,2:Polygon + +None +Altitude +Circle +Altitude and Circle +Polygon +Altitude and Polygon +Circle and Polygon +All + + + + +Report Only +RTL or Land + + + +10 1000 +1 +Meters + + +30 10000 +Meters + + +1 10 +Meters + + +1 20 + + + + + +Disabled +Enabled + + + +-200 +200 +1 + + +-200 +200 +1 + + +-18000 +18000 +1 + + +m + + +m + + +m + + +0 255 + + + + +True +True +1 +pascals + + +True +True +1 +degrees celsius + + +0.1 +meters + + + +FirstBaro +2ndBaro +3rdBaro + + + + +Disabled +Bus0 + + + + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF +QURT +ERB +MAV +NOVA + +True + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF +QURT +ERB +MAV +NOVA + +True + + + +Portable +Stationary +Pedestrian +Automotive +Sea +Airborne1G +Airborne2G +Airborne4G + + + + +Disabled +Enabled + + + + +Any +FloatRTK +IntegerRTK + +True + + + +Disabled +Enabled +NoChange + + + +-100 90 +Degrees + + + +send to first GPS +send to 2nd GPS +send to all + + + + +None +All +External only + + + + +Disabled +log every sample +log every 5 samples + +True + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Do not save config +Save config +Save only when needed + + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Disables automatic configuration +Enable automatic configuration + + + + +10Hz +8Hz +5Hz + +milliseconds + + + +10Hz +8Hz +5Hz + +milliseconds + + +m + + +m + + +m + + +m + + +m + + +m + + +0 250 +milliseconds + + +0 250 +milliseconds + + + + + +Disabled +Enabled + + + + +None +Servo +EPM + + + +1000 2000 +PWM + + +1000 2000 +PWM + + +1000 2000 +PWM + + +0 255 +seconds + + +0 255 + + + + +-180 180 +1 +Degrees + + +-180 180 +1 +Degrees + + +-180 180 +1 +Degrees + + + +Servo only +Servo with ExtGyro +DirectDrive VarPitch +DirectDrive FixedPitch + + + + +3-Servo CCPM +H1 Mechanical Mixing + + + +0 1000 +1 +PWM + + +-90 90 +1 +Degrees + + +-10 10 +0.1 + + + +NoFlybar +Flybar + + + +0 1000 +1 +PWM + + +0 1000 +1 +PWM + + +0 2000 + + +0 2000 + + + +Reversed +Normal + + + +1000 2000 +1 +PWM + + +1000 2000 +1 +PWM + + +1000 2000 +1 +PWM + + + +Disabled +Passthrough +Max collective +Mid collective +Min collective + + + +0 1000 +10 +PWM + + + +Ch8 Input +SetPoint +Throttle Curve + + + +0 500 +1 +pwm + + +0 60 +Seconds + + +0 60 +Seconds + + +0 1000 +10 + + +0 500 +10 + + +0 1000 +10 + + +0 1000 +10 + + +0 18000 +100 +Centi-Degrees + + +0 10 +1 + + +1 1000 +10 + + +0 500 +10 + + + + + +Disabled +Enabled + + + + +None +Chan1 +Chan2 +Chan3 +Chan4 +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + +0.1 5 +Seconds + + +1 10 +Seconds + + +100 100000 + + +1000 2000 + + +1000 2000 + + +1000 2000 + + +1000 2000 + + + +None +RPM1 +RPM2 + + + +0 100 + + + + +0 500 +1 +Percent*10 + + +0 500 +1 +Percent*10 + + +500 1000 +1 +Percent*10 + + +500 1000 +1 +Percent*10 + + + +Disabled +Very Low +Low +Medium +High +Very High + + + + + + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0 127 +Hz + + +0 127 +Hz + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0.05 50 + + + +Never +Start-up only + + + + +Don't adjust the trims +Assume first orientation was level +Assume ACC_BODYFIX is perfectly aligned to the vehicle + + + + +IMU 1 +IMU 2 +IMU 3 + + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +True + + +True + + +True + + +True + + +True + + +True + + + + + + +0 5 +0.5 +meters + + +0 90 +0.1 +degrees + + +centi-Degrees + + +0.1 +meters + + +0.1 +seconds + + +0 30 +0.1 +meters + + +0 10 +0.1 +seconds + + +0 30 +0.1 +m/s + + +0 127 +1 +percent + + +0 127 +1 +seconds + + + +Disabled +Servos to Neutral +Servos to Zero PWM + + + + +Disabled +Enabled + + + +0 100 +Percent + + + +Standard Glide Slope + + + + + +1000 2000 +1 +pwm + + +1000 2000 +1 +pwm + + + + + +None +File +MAVLink +BothFileAndMAVLink + + + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + + +0 32766 +1 + + + +Resume Mission +Restart Mission + + + + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0 100 +1 + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + +True + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + + + + + +0 500 +pwm + + +0.25 0.8 + + +0.9:Low, 0.95:Default, 1.0:High + + +6 35 +Volts + + +6 35 +Volts + + +0 200 +Amps + + + +Normal +OneShot +OneShot125 +Brushed16kHz + +True + + +0 2000 + + +0 2000 + + +0.0:Low, 0.15:Default, 0.3:High + + +0.0:Low, 0.1:Default, 0.2:High + + +0 10 +Seconds + + +0.2 0.8 + + + +Disabled +Learn +LearnAndSave + + + + +PWM enabled while disarmed +PWM disabled while disarmed + + + +5 80 +1 +Degrees + + +0 2 +0.1 +Seconds + + + + +1 60 +1 +seconds + + +0.6 1.0 +0.05 + + +0 0.1 +0.01 + + + + + +Off +Low +Medium +High + + + + +Disable +Enable + + + + +Disable +Enable + + + + +Disable +ssd1306 +sh1106 + + + + + + +Disabled +Enabled Always Land +Enabled Strict + + + + +None +CompanionComputer +IRLock +SITL_Gazebo +SITL + + + +0 360 +1 +Centi-degrees + + +-20 20 +1 +Centimeters + + +-20 20 +1 +Centimeters + + + + +0.5 5 +0.1 +Hz + + + + + +None +LightWareSF40C +MAVLink +TeraRangerTower + + + + +Default +Upside Down + + + +-180 180 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + + +None +LightWareSF40C +MAVLink + + + + +Default +Upside Down + + + +-180 180 +degrees + + + + +0.4 1.0 +0.1 +seconds + + +0.1 3.0 +0.1 + + +0 0.1 +0.01 + + +0 0.5 +0.05 + + +0 100 +1 +degrees/second + + +0 100 +1 +degrees/second + + +0.7 1.5 +0.05 + + +0 4500 +1 + + +0.1 4.0 +0.1 + + + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + +0.5 0.9 + + + + + + +0.1 +kilometers + + + +DoNotIncludeHome +IncludeHome + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Off +On +NoChange + + + + + +0.4 1.0 +0.1 +seconds + + +0.1 4.0 +0.1 + + +0 0.1 +0.01 + + +0 1.0 +0.05 + + +0 180 +1 +degrees/second + + +0 4500 +1 + + +0.1 4.0 +0.1 + + + + + +None +Analog +MaxbotixI2C +PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial +TrOneI2C + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 32767 +meters + + +5 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +MaxbotixI2C +PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial +TrOneI2C + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + + + +None +PX4-PWM + + + +0.001 + + +1 + + +1 + + +0.1 + + + +None +PX4-PWM + + + +0.001 + + + + + +Disabled +AnalogPin +RCChannelPwmValue + + + + +APM2 A0 +APM2 A1 +APM2 A13 +Pixracer +Pixhawk ADC4 +Pixhawk ADC3 + Pixhawk ADC6 +Pixhawk SBUS + + + +0 5.0 +0.01 +Volt + + +0 5.0 +0.01 +Volt + + + + + +0 2000 +Microseconds + + +0 2000 +Microseconds + + + + + +Disabled +ShowSlips +ShowOverruns + + + + +50Hz +100Hz +200Hz +250Hz +300Hz +400Hz + +True + + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +MAVlink1 +MAVLink2 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + + + +Disable +Enable + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + + + + + + + + + + + + +Disabled +Enabled + + + +0 100 +percentage + + +1000 2000 +ms + + +0 1000 +cm/s + + +0 100 +percentage + + + + + + +seconds + + +seconds + + +seconds + + + + +0.4 1.0 +0.1 +seconds + + +0.1 10.0 +0.1 + + +0 1.0 +0.05 + + +0 0.1 +0.01 + + +0 4500 +1 + + +0 5 +0.1 +m/s + + +0.0 10.0 +0.1 + + +0.0 30.0 +0.1 +m/s + + +0.0 50.0 +0.1 +degree/(m/s) + + +0.0 4500.0 +0.1 +Centidegrees + + + + +0.1 20.0 +0.1 + + +0.1 10.0 +0.1 + + +3.0 10.0 +0.2 + + +0.1 1.0 +0.1 + + +0.0 0.5 +0.02 + + +1.0 10.0 +0.5 + + +1.0 5.0 +0.05 + + +0.5 2.0 +0.05 + + +5.0 30.0 +1.0 + + +0.0 2.0 +0.1 + + +0.1 1.0 +0.1 + + +0.0 20.0 +0.1 + + +-1 127 +1 + + +-1 100 +0.1 + + +-1.0 2.0 +0.1 + + +0 45 +1 + + +-45 0 +1 + + +0.0 2.0 +0.1 + + +1.0 5.0 +0.2 + + +0.1 1.0 +0.1 + + +-5 40 +1 + + +0.0 20.0 +0.1 +m/s + + +-2.0 2.0 +0.1 +m/s/m + + +0.1 1.0 +0.1 + + +0.0 0.5 +0.02 + + +0.0 0.5 +0.02 + + +0.1 1.0 +0.1 + + + +Disable +Enable + + + + + + +Disable +Enable + + + +1 +meters + + + + + +Disable +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + +900 2100 + + +900 2100 + + + +Disable +Chan1 +Chan3 +Chan3 +Chan4 +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + + + + +Disable +Enable + + + +0 1 + + + + +20 2000 +50 +cm/s + + +100 1000 +1 +cm + + +0 1000 +50 +cm/s + + +0 500 +10 +cm/s + + +0 2000 +50 +cm/s + + +50 500 +10 +cm/s/s + + +50 500 +10 +cm/s/s + + +500 5000 +1 +cm/s/s/s + + +100 981 +1 +cm/s/s + + +25 250 +1 +cm/s/s + + + +Disable +Enable + + + + + +0 4 +0.25 + + +0 2 +0.25 + + +0 2 +0.25 + + +0.8 1.2 +0.05 + + +0 4500 +1 + + + diff --git a/src/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.2.xml b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.2.xml new file mode 100644 index 0000000000000000000000000000000000000000..91f87f90fda231c636912b9c077dc5fae61f4993 --- /dev/null +++ b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Rover.3.2.xml @@ -0,0 +1,8496 @@ + + + + + + + + +True + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +1 10 +1 + + +0 30 +1 +seconds + + +0:Roll,1:Pitch,2:Yaw + + +0 1 +0.01 + + +0 5 +0.01 + + +0 15 +0.1 +Degrees + + +0 1000 +1 +meters + + +0 100 +1 +meters + + + +Disabled +FBWMixing +DirectMixing + + + + +Disabled +Enabled + + + +0 30 +0.1 +m/s + + +0 30 +0.1 +m/s/s + + +0 127 +1 +0.1 seconds + + +-100 100 +1 +Percent + + +0 30 +0.1 +m/s + + +0 30 +0.1 +m/s + + +0 127 +1 +percent + + +0 10 +0.5 +seconds + + +0 100 +Percent + + + + +0 45 +1 +degrees + + +0:AUTO_ALWAYS,1:AUTO_LAND,2:AUTO_LOITER_TO_ALT,3:AUTO_LOITER_ALL,4:AUTO_WAYPOINTS,5:LOITER,6:RTL,7:CIRCLE,8:CRUISE,9:FBWB,10:GUIDED + + + +Default +L1Controller + + + + +Automatic + + + +-32767 32767 +1 +Meters + + +1 32767 +1 +Meters + + +0 32767 +1 +Meters + + +-32767 32767 +1 +Meters + + +-32767 32767 +1 +Meters + + + +None +GuidedMode +ReportOnly +GuidedModeThrPass +RTL_Mode + + + + + + + +0 32767 +1 +meters + + +0 32767 +1 +meters + + +0 32767 +1 +meters + + + +NoAutoEnable +AutoEnable +AutoEnableDisableFloorOnly + + + + +FenceReturnPoint +NearestRallyPoint + + + + +Disabled +Enabled + + + +5 100 +1 +m/s + + +5 100 +1 +m/s + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0 10000 +meters + + +1 10 +0.1 +m/s + + +-100 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 127 +1 +Percent + + +0 100 +1 +Percent + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +925 2200 +1 + + +0 100 +1 +Percent + + + +Disabled +Enabled + + + + +CIRCLE/no change(if already in AUTO|GUIDED|LOITER) +CIRCLE +FBWA + + + +1 100 +0.5 +seconds + + + +Continue +ReturnToLaunch +Glide +Deploy Parachute + + + +1 300 +0.5 +seconds + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Heartbeat +HeartbeatAndREMRSSI +HeartbeatAndAUTO + + + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + + +Manual +CIRCLE +STABILIZE +TRAINING +ACRO +FBWA +FBWB +CRUISE +AUTOTUNE +Auto +RTL +Loiter +AVOID_ADSB +Guided +QSTABILIZE +QHOVER +QLOITER +QLAND +QRTL + + + +0 9000 +1 +centi-Degrees + + +0 9000 +1 +centi-Degrees + + +-9000 0 +1 +centi-Degrees + + +10 500 +1 +degrees/second + + +10 500 +1 +degrees/second + + + +Disabled +Enabled + + + +-100 100 +0.1 +Meters + + +10 360 +1 +degrees/second + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + +0.5 1.2 + + + +Disabled +Enabled + + + +-1000 1000 +percent + + +-1000 1000 +percent + + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:MODE,7:IMU,8:CMD,9:CURRENT,10:COMPASS,11:TECS,12:CAMERA,13:RC,14:SONAR,15:ARM/DISARM,19:IMU_RAW + +Disabled +PX4/Pixhawk-Default + + + + + + + +cm/s + + +m/s + + +cm/s + + +centi-Degrees + + +centimeters + + +centimeters + + + +Disabled +Enabled + + + + + + +Disabled +UpUp +UpDown +DownUp +DownDown +UpUpSwap +UpDownSwap +DownUpSwap +DownDownSwap + + + +0 100 +Percent + + +0 100 +1 +m/s + + +0 100 +Percent + + +0 100 +1 +m/s + + + + + + + +Disabled +Channel1 +Channel2 +Channel3 +Channel4 +Channel5 +Channel6 +Channel7 +Channel8 + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0 90 +0.1 +degrees + + + +Disable +Enable - go HOME then land +Enable - go directly to landing sequence + + + + +Disable +Enable + + + +10 127 +m/s/s + + +0:Disarm + + + + + +Disabled +Enabled + + + + + +True + + +True + +ArduPlane +AntennaTracker +Copter +Rover + + + +1 255 + + + +Mission Planner and DroidPlanner + AP Planner 2 + + + + +Disabled +Enabled + + + +0 10 +.5 +Hz + + +0.0 1000.0 +10 +Centimeters + + +0.0 500.0 +10 + + +0:Feedback from mid stick,1:High throttle cancels landing,2:Disarm on land detection + +None +Feedback from mid stick +High throttle cancels landing +Disarm on land detection + + + +0 30 +1 +seconds + + +0:Roll,1:Pitch,2:Yaw + +None +Roll +Pitch +Yaw + + + +0 8000 +1 +Centimeters + + +0.5 10.0 + +Disabled +Shallow +Steep + +.1 + + +0 2000 +50 +cm/s + + +0.01 2.0 +0.01 + + + +Disabled +Land +RTL + + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Enabled always RTL +Enabled Continue with Mission in Auto Mode + + + +100 900 + + + +Disabled +Enabled + + + + +Disabled +Mode1 +Mode2 +Mode1+2 +Mode3 +Mode1+3 +Mode2+3 +Mode1+2+3 +Mode4 +Mode1+4 +Mode2+4 +Mode1+2+4 +Mode3+4 +Mode1+3+4 +Mode2+3+4 +Mode1+2+3+4 +Mode5 +Mode1+5 +Mode2+5 +Mode1+2+5 +Mode3+5 +Mode1+3+5 +Mode2+3+5 +Mode1+2+3+5 +Mode4+5 +Mode1+4+5 +Mode2+4+5 +Mode1+2+4+5 +Mode3+4+5 +Mode1+3+4+5 +Mode2+3+4+5 +Mode1+2+3+4+5 +Mode6 +Mode1+6 +Mode2+6 +Mode1+2+6 +Mode3+6 +Mode1+3+6 +Mode2+3+6 +Mode1+2+3+6 +Mode4+6 +Mode1+4+6 +Mode2+4+6 +Mode1+2+4+6 +Mode3+4+6 +Mode1+3+4+6 +Mode2+3+4+6 +Mode1+2+3+4+6 +Mode5+6 +Mode1+5+6 +Mode2+5+6 +Mode1+2+5+6 +Mode3+5+6 +Mode1+3+5+6 +Mode2+3+5+6 +Mode1+2+3+5+6 +Mode4+5+6 +Mode1+4+5+6 +Mode2+4+5+6 +Mode1+2+4+5+6 +Mode3+4+5+6 +Mode1+3+4+5+6 +Mode2+3+4+5+6 +Mode1+2+3+4+5+6 + + + +-1 1000 +1 +Centimeters + + +0 3000 +10 +Centimeters + + + +Never change yaw +Face next waypoint +Face next waypoint except RTL +Face along GPS course + + + +0 60000 +1000 +ms + + +30 200 +10 +cm/s + + +0 500 +10 +cm/s + + +50 500 +10 +Centimeters/Second + + +50 500 +10 +cm/s/s + + + +Disabled +Enabled always RTL +Enabled Continue with Mission in Auto Mode +Enabled always LAND + + + +925 1100 +1 +pwm + + +0 300 +1 +pwm + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + +Stabilize +Acro +AltHold +Auto +Guided +Loiter +RTL +Circle +Land +Drift +Sport +Flip +AutoTune +PosHold +Brake +Throw +Avoid_ADSB +Guided_NoGPS + + + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:RCIN,7:IMU,8:CMD,9:CURRENT,10:RCOUT,11:OPTFLOW,12:PID,13:COMPASS,14:INAV,15:CAMERA,17:MOTBATT,18:IMU_FAST,19:IMU_RAW + +Default +Default+RCIN +Default+IMU +Default+Motors +NearlyAll-AC315 +NearlyAll +All+FastATT +All+MotBatt +All+FastIMU +All+FastIMU+PID +All+FullIMU +Disabled + + + + +Normal Start-up +Start-up in ESC Calibration mode if throttle high +Start-up in ESC Calibration mode regardless of throttle +Start-up and automatically calibrate ESCs +Disabled + + + + +None +Stab Roll/Pitch kP +Rate Roll/Pitch kP +Rate Roll/Pitch kI +Rate Roll/Pitch kD +Stab Yaw kP +Rate Yaw kP +Rate Yaw kD +Altitude Hold kP +Throttle Rate kP +Throttle Accel kP +Throttle Accel kI +Throttle Accel kD +Loiter Speed +Loiter Pos kP +Velocity XY kP +Velocity XY kI +WP Speed +Acro RollPitch kP +Acro Yaw kP +Heli Ext Gyro +OF Loiter kP +OF Loiter kI +OF Loiter kD +Declination +Circle Rate +RangeFinder Gain +Rate Pitch kP +Rate Pitch kI +Rate Pitch kD +Rate Roll kP +Rate Roll kI +Rate Roll kD +Rate Pitch FF +Rate Roll FF +Rate Yaw FF + + + +0 32767 + + +0 32767 + + + +Plus +X +V +H +V-Tail +A-Tail +Y6B + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +Super Simple Mode +Acro Trainer +Sprayer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost Copter Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw +Avoidance +PrecLoiter +Object Avoidance +ArmDisarm + + + +0 127 +Seconds + + +1000 8000 +Centi-degrees + + +0 100 + +Very Soft +Soft +Medium +Crisp +Very Crisp + +10 + + +4 12 +deg/sec + + +2000 4500 +Centi-degrees + + + +No repositioning +Repositioning + + + + +Land +AltHold +Land even in Stabilize + + + +0.6:Strict, 0.8:Default, 1.0:Relaxed + + + +Disabled +Enabled + + + +50 490 +1 +Hz + + +1 10 + + +1 10 + + +0 3 +0.1 + + +0 3 +0.1 + + + +Disabled +Leveling +Leveling and Limited + + + +-0.5 1.0 + +Disabled +Very Low +Low +Medium +High +Very High + + + +0.1 6.0 +0.1 + + +0.02 1.00 +0.01 + + +0 4500 +10 +cm/s/s + + +1.000 8.000 + + +0.500 1.500 +0.05 + + +0.000 3.000 + + +0 1000 +Percent*10 + + +0.000 0.400 + + +1.000 100.000 +Hz + + +1.000 3.000 + + +0.500 2.000 + + +0:Roll,1:Pitch,2:Yaw + +All +Roll Only +Pitch Only +Yaw Only +Roll and Pitch +Roll and Yaw +Pitch and Yaw + + + +0.05 0.10 + + +0.001 0.006 + + + +Stopped +Running + + + + +Do Not Use in RTL and Land +Use in RTL and Land + + + +0 5 + + + +Auto +Guided +RTL +Land +Brake +Throw + + + + +Upward Throw +Drop + + + + +Disabled +Enabled + + + +0:ADSBMavlinkProcessing + + +-0.5 1.0 + +Disabled +Very Low +Low +Medium +High +Very High + + + +0 1 + + + +Undefined +Quad +Hexa +Octa +OctaQuad +Y6 +Heli +Tri +SingleCopter +CoaxCopter + + + + + + + +True + +ArduPlane +AntennaTracker +Copter +Rover + + + +1 255 + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +0 20 +0.1 +seconds + + +0 20 +0.1 +seconds + + +0 100 +1 +degrees/second + + +0 20 +1 +seconds + + +-90 90 +0.000001 +degrees + + +-180 180 +0.000001 +degrees + + +0 10 +0.1 +seconds + + + +Position +OnOff +ContinuousRotation + + + + +Position +OnOff +ContinuousRotation + + + +0 50 +0.1 +degrees/second + + +0 50 +0.1 +degrees/second + + +0 2 +0.01 +seconds + + +0 2 +0.01 +seconds + + +-10 10 +0.1 +degrees + + +-10 10 +0.1 +degrees + + +0 360 +0.1 +degrees + + +0 100 +1 +meters + + + +Barometer +GPS +GPS vehicle only + + + +1 10 +1 +Hz + + +-90 0 +1 +Degrees + + +0 90 +1 +Degrees + + +0:ATTITUDE,1:GPS,2:RCIN,3:IMU,4:RCOUT,5:COMPASS + +Default +Disabled + + + +0.0 3.0 +0.01 + + +0.0 3.0 +0.01 + + +0 4000 +10 +Percent*10 + + +0.001 0.1 +0.001 + + +0.0 3.0 +0.01 + + +0.0 3.0 +0.01 + + +0 4000 +10 +Percent*10 + + +0.001 0.1 +0.001 + + +1 255 + + + + + + +True + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:MODE,7:IMU,8:CMD,9:CURRENT,10:COMPASS,11:TECS,12:CAMERA,13:RC,14:SONAR,15:ARM/DISARM,19:IMU_RAW + +Disabled +APM2-Default +PX4/Pixhawk-Default + + + + + + + + +MANUAL +LEARNING +STEERING +HOLD +AUTO +RTL +GUIDED + + + +1 255 + + +1 255 + + + +Disabled +Enabled + + + +0 30 +1 +seconds + + +0:Steering,1:Throttle + +None +Steering +Throttle + + + + +Disabled +Enabled + + + + +Disabled +APM TriggerPin0 +APM TriggerPin1 +APM TriggerPin2 +APM TriggerPin3 +APM TriggerPin4 +APM TriggerPin5 +APM TriggerPin6 +APM TriggerPin7 +APM TriggerPin8 +Pixhawk TriggerPin50 +Pixhawk TriggerPin51 +Pixhawk TriggerPin52 +Pixhawk TriggerPin53 +Pixhawk TriggerPin54 +Pixhawk TriggerPin55 + + + +0 20 +0.1 +m/s/s + + +0 100 +0.1 +m/s + + +0 100 +1 +percent + + +0 100 +0.1 +meters + + +0 100 +1 +percent + + +0 100 +1 +m/s + + +0 360 +1 +degrees + + + +Nothing +LearnWaypoint + + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + +0 100 +1 +Percent + + + +Disabled +SkidSteeringOutput + + + + +Disabled +SkidSteeringInput + + + + +Nothing +RTL +HOLD + + + +seconds + + + +Disabled +Enabled + + + +925 1100 +1 + + + +Disabled +Enabled + + + + +Disabled +HOLD +HoldAndDisarm + + + +0 1000 +1 +centimeters + + +-45 45 +1 +centimeters + + +0 100 +0.1 +seconds + + +1 100 +1 + + + + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + + +Manual +LEARNING +STEERING +HOLD +Auto +RTL +Guided + + + +0 1000 +0.1 +meters + + +0.2 10 +0.1 +gravities + + + + + +Disabled +Enabled + + + +1 100 + + +1 100000 + + +-1 16777215 + + + +NoInfo +Light +Small +Large +HighVortexlarge +Heavy +HighlyManuv +Rotocraft +RESERVED +Glider +LightAir +Parachute +UltraLight +RESERVED +UAV +Space +RESERVED +EmergencySurface +ServiceSurface +PointObstacle + + + + +NO_DATA +L15W23 +L25W28P5 +L25W34 +L35W33 +L35W38 +L45W39P5 +L45W45 +L55W45 +L55W52 +L65W59P5 +L65W67 +L75W72P5 +L75W80 +L85W80 +L85W90 + + + + +NoData +Left2m +Left4m +Left6m +Center +Right2m +Right4m +Right6m + + + + +NO_DATA +AppliedBySensor + + + + +Disabled +Rx-Only +Tx-Only +Rx and Tx Enabled + + + + + + + + + + + + + + + + + + + + + +meters + + +meters + + +millibar + + + + + + + + + + + + + + +seconds + + + + +0.0 1.0 +.01 + + + +Disabled +Enabled + + + +0.1 0.4 +.01 + + +0.1 0.4 +.01 + + +0 127 +1 +m/s + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 + + + +0.001 0.5 +.01 + + +0 10 +1 + + + +Disabled +Enable EKF2 +Enable EKF3 + + + + + + +Disabled +THR_MIN PWM when disarmed +0 PWM when disarmed + + + +0:All,1:Barometer,2:Compass,3:GPS lock,4:INS,5:Parameters,6:RC,7:Board voltage,8:Battery Level,9:Airspeed,10:Logging Available,11:Hardware safety switch,12:GPS Configuration + +None +All +Barometer +Compass +GPS Lock +INS(INertial Sensors - accels & gyros) +Parameters(unused) +RC Failsafe +Board voltage +Battery Level +Airspeed +LoggingAvailable +Hardware safety switch +GPS configuration + + + +0.25 3.0 +m/s/s + + +0.1 +Volts + + +0.1 +Volts + + + + + +None +I2C-MS4525D0 +Analog +I2C-MS5525 + + + + +Use +Don't Use + + + +0.1 + + +0.1 + + + + + + + + + +Disable +Enable + + + + + + +Bus0 +Bus1 + + + + + +500 18000 +100 +Centi-Degrees/Sec + + +0 72000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +3.000 12.000 + + +3.000 12.000 + + +3.000 6.000 + + +0.5 10.0 + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + +0.5 0.9 + + + +Disabled 1 + + + +0 1000 +Centi-Degrees + + +0.08 0.35 +0.005 + + +0.01 0.6 +0.01 + + +0 1 +0.01 + + +0.001 0.03 +0.001 + + +1 20 +1 +Hz + + +0.08 0.35 +0.005 + + +0.01 0.6 +0.01 + + +0 1 +0.01 + + +0.001 0.03 +0.001 + + +1 20 +1 +Hz + + +0.180 0.60 +0.005 + + +0.01 0.06 +0.01 + + +0 1 +0.01 + + +0.000 0.02 +0.001 + + +1 20 +1 +Hz + + + + + +Disabled +Enabled + + + + +Remain in AVOID_ADSB +Resume previous flight mode +RTL +Resume if AUTO else Loiter + + + + + +seconds + + +seconds + + +meters + + +meters + + +meters + + +meters + + + + +0:StopAtFence,1:UseProximitySensor + +None +StopAtFence +UseProximitySensor +All + + + +0 4500 + + +3 30 +meters + + + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +Solo +Bebop +SMBus-Maxell + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Watts + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +Solo +Bebop +SMBus-Maxell + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Amps + + + + + +None +Pozyx + + + +-90 90 +0.000001 +degrees + + +-180 180 +0.000001 +degrees + + +0 10000 +1 +meters + + +-180 +180 +1 +degrees + + + + + +No PWMs +Two PWMs +Four PWMs +Six PWMs +Three PWMs and One Capture + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled + +True + + + +Disabled +50Hz +75Hz +100Hz +150Hz +200Hz +250Hz +300Hz + +True + + +-32767 32768 + + + +Disabled +Enabled +Dynamic ID/Update + + + +0:Ch1,1:Ch2,2:Ch3,3:Ch4,4:Ch5,5:Ch6,6:Ch7,7:Ch8,8:Ch9,9:Ch10,10:Ch11,11:Ch12,12:Ch13,13:Ch14 + +Disabled +Enabled + +True + + +-1 80 +degreesC + + + +AUTO +PX4V1 +Pixhawk +Pixhawk2 +Pixracer +PixhawkMini +Pixhawk2Slim +VRBrain 5.1 +VRBrain 5.2 +VR Micro Brain 5.1 +VR Micro Brain 5.2 +VRBrain Core 1.0 +VRBrain 5.4 + +True + + + + + +Disabled +Enabled + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +0 3600 + + + + + +Servo +Relay + + + +0 50 +deciseconds + + +1000 2000 +pwm + + +1000 2000 +pwm + + +0 1000 +meters + + + +Low +High + + + +0 10000 +milliseconds + + +0 180 +Degrees + + + +Disabled +PX4 AUX1 +PX4 AUX2 +PX4 AUX3 +PX4 AUX4(fast capture) +PX4 AUX5 +PX4 AUX6 + + + + +TriggerLow +TriggerHigh + + + + + + +Disabled +Enabled + + + + +First Relay +Second Relay +Third Relay +Fourth Relay +Servo + + + +1000 2000 +1 +pwm + + +1000 2000 +1 +pwm + + +0 32000 +1 +Meters + + +0 5000 +1 +Milliseconds + + + + +0 10000 +100 +cm + + +-90 90 +1 +deg/s + + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-3.142 3.142 +0.01 +Radians + + + +Disabled +Internal-Learning +EKF-Learning + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Use Throttle +Use Current + + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +FirstCompass +SecondCompass +ThirdCompass + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + + + + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 32 + +Very Strict +Strict +Default +Relaxed + +0.1 + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + +0 250 +10 +milliseconds + + + +Use Baro +Use Range Finder +Use GPS +Use Range Beacon + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.000001 0.001 +1/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +50 200 +% + + +0.5 50.0 +m + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +0.05 1.0 +0.05 +rad + + +100 1000 +25 + + +10 50 +5 +cs + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +2.0 6.0 +0.5 +m/s + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + + +Use Baro +Use Range Finder +Use GPS +Use Range Beacon + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +50 200 +% + + +0.5 50.0 +m + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +0.05 1.0 +0.05 +rad + + +100 1000 +25 + + +10 50 +5 +cs + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +2.0 6.0 +0.5 +m/s + + +0.5 2.5 +0.1 +m/s/s + + + + + +Disabled +Enabled + + + +0:Altitude,1:Circle,2:Polygon + +None +Altitude +Circle +Altitude and Circle +Polygon +Altitude and Polygon +Circle and Polygon +All + + + + +Report Only +RTL or Land + + + +10 1000 +1 +Meters + + +30 10000 +Meters + + +1 10 +Meters + + +1 20 + + + + + +Disabled +Enabled + + + +-200 +200 +1 + + +-200 +200 +1 + + +-18000 +18000 +1 + + +m + + +m + + +m + + +0 255 + + + + +True +True +1 +pascals + + +True +True +1 +degrees celsius + + +0.1 +meters + + + +FirstBaro +2ndBaro +3rdBaro + + + + +Disabled +Bus0 + + + + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF +QURT +ERB +MAV +NOVA + +True + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF +QURT +ERB +MAV +NOVA + +True + + + +Portable +Stationary +Pedestrian +Automotive +Sea +Airborne1G +Airborne2G +Airborne4G + + + + +Disabled +Enabled + + + + +Any +FloatRTK +IntegerRTK + +True + + + +Disabled +Enabled +NoChange + + + +-100 90 +Degrees + + + +send to first GPS +send to 2nd GPS +send to all + + + + +None +All +External only + + + + +Disabled +log every sample +log every 5 samples + +True + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Do not save config +Save config +Save only when needed + + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Disables automatic configuration +Enable automatic configuration + + + + +10Hz +8Hz +5Hz + +milliseconds + + + +10Hz +8Hz +5Hz + +milliseconds + + +m + + +m + + +m + + +m + + +m + + +m + + +0 250 +milliseconds + + +0 250 +milliseconds + + + + + +Disabled +Enabled + + + + +None +Servo +EPM + + + +1000 2000 +PWM + + +1000 2000 +PWM + + +1000 2000 +PWM + + +0 255 +seconds + + +0 255 + + + + +-180 180 +1 +Degrees + + +-180 180 +1 +Degrees + + +-180 180 +1 +Degrees + + + +Servo only +Servo with ExtGyro +DirectDrive VarPitch +DirectDrive FixedPitch + + + + +3-Servo CCPM +H1 Mechanical Mixing + + + +0 1000 +1 +PWM + + +-90 90 +1 +Degrees + + +-10 10 +0.1 + + + +NoFlybar +Flybar + + + +0 1000 +1 +PWM + + +0 1000 +1 +PWM + + +0 2000 + + +0 2000 + + + +Reversed +Normal + + + +1000 2000 +1 +PWM + + +1000 2000 +1 +PWM + + +1000 2000 +1 +PWM + + + +Disabled +Passthrough +Max collective +Mid collective +Min collective + + + +0 1000 +10 +PWM + + + +Ch8 Input +SetPoint +Throttle Curve + + + +0 500 +1 +pwm + + +0 60 +Seconds + + +0 60 +Seconds + + +0 1000 +10 + + +0 500 +10 + + +0 1000 +10 + + +0 1000 +10 + + +0 18000 +100 +Centi-Degrees + + +0 10 +1 + + +1 1000 +10 + + +0 500 +10 + + + + + +Disabled +Enabled + + + + +None +Chan1 +Chan2 +Chan3 +Chan4 +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + +0.1 5 +Seconds + + +1 10 +Seconds + + +100 100000 + + +1000 2000 + + +1000 2000 + + +1000 2000 + + +1000 2000 + + + +None +RPM1 +RPM2 + + + +0 100 + + + + +0 500 +1 +Percent*10 + + +0 500 +1 +Percent*10 + + +500 1000 +1 +Percent*10 + + +500 1000 +1 +Percent*10 + + + +Disabled +Very Low +Low +Medium +High +Very High + + + + + + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0 127 +Hz + + +0 127 +Hz + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0.05 50 + + + +Never +Start-up only + + + + +Don't adjust the trims +Assume first orientation was level +Assume ACC_BODYFIX is perfectly aligned to the vehicle + + + + +IMU 1 +IMU 2 +IMU 3 + + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +True + + +True + + +True + + +True + + +True + + +True + + + + + + +0 5 +0.5 +meters + + +0 90 +0.1 +degrees + + +centi-Degrees + + +0.1 +meters + + +0.1 +seconds + + +0 30 +0.1 +meters + + +0 10 +0.1 +seconds + + +0 30 +0.1 +m/s + + +0 127 +1 +percent + + +0 127 +1 +seconds + + + +Disabled +Servos to Neutral +Servos to Zero PWM + + + + +Disabled +Enabled + + + +0 100 +Percent + + + +Standard Glide Slope + + + + + +1000 2000 +1 +pwm + + +1000 2000 +1 +pwm + + + + + +None +File +MAVLink +BothFileAndMAVLink + + + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + + +0 32766 +1 + + + +Resume Mission +Restart Mission + + + + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0 100 +1 + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + +True + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + + + + + +0 500 +pwm + + +0.25 0.8 + + +0.9:Low, 0.95:Default, 1.0:High + + +6 35 +Volts + + +6 35 +Volts + + +0 200 +Amps + + + +Normal +OneShot +OneShot125 +Brushed16kHz + +True + + +0 2000 + + +0 2000 + + +0.0:Low, 0.15:Default, 0.3:High + + +0.0:Low, 0.1:Default, 0.2:High + + +0 10 +Seconds + + +0.2 0.8 + + + +Disabled +Learn +LearnAndSave + + + + +PWM enabled while disarmed +PWM disabled while disarmed + + + +5 80 +1 +Degrees + + +0 2 +0.1 +Seconds + + + + +1 60 +1 +seconds + + +0.6 1.0 +0.05 + + +0 0.1 +0.01 + + + + + +Off +Low +Medium +High + + + + +Disable +Enable + + + + +Disable +Enable + + + + +Disable +ssd1306 +sh1106 + + + + + + +Disabled +Enabled Always Land +Enabled Strict + + + + +None +CompanionComputer +IRLock +SITL_Gazebo +SITL + + + +0 360 +1 +Centi-degrees + + +-20 20 +1 +Centimeters + + +-20 20 +1 +Centimeters + + + + +0.5 5 +0.1 +Hz + + + + + +None +LightWareSF40C +MAVLink +TeraRangerTower + + + + +Default +Upside Down + + + +-180 180 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + + +None +LightWareSF40C +MAVLink + + + + +Default +Upside Down + + + +-180 180 +degrees + + + + +0.4 1.0 +0.1 +seconds + + +0.1 3.0 +0.1 + + +0 0.1 +0.01 + + +0 0.5 +0.05 + + +0 100 +1 +degrees/second + + +0 100 +1 +degrees/second + + +0.7 1.5 +0.05 + + +0 4500 +1 + + +0.1 4.0 +0.1 + + + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + +0.5 0.9 + + + + + + +0.1 +kilometers + + + +DoNotIncludeHome +IncludeHome + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Off +On +NoChange + + + + + +0.4 1.0 +0.1 +seconds + + +0.1 4.0 +0.1 + + +0 0.1 +0.01 + + +0 1.0 +0.05 + + +0 180 +1 +degrees/second + + +0 4500 +1 + + +0.1 4.0 +0.1 + + + + + +None +Analog +MaxbotixI2C +PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial +TrOneI2C + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 32767 +meters + + +5 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +MaxbotixI2C +PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial +TrOneI2C + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + + + +None +PX4-PWM + + + +0.001 + + +1 + + +1 + + +0.1 + + + +None +PX4-PWM + + + +0.001 + + + + + +Disabled +AnalogPin +RCChannelPwmValue + + + + +APM2 A0 +APM2 A1 +APM2 A13 +Pixracer +Pixhawk ADC4 +Pixhawk ADC3 + Pixhawk ADC6 +Pixhawk SBUS + + + +0 5.0 +0.01 +Volt + + +0 5.0 +0.01 +Volt + + + + + +0 2000 +Microseconds + + +0 2000 +Microseconds + + + + + +Disabled +ShowSlips +ShowOverruns + + + + +50Hz +100Hz +200Hz +250Hz +300Hz +400Hz + +True + + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +MAVlink1 +MAVLink2 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + + + +Disable +Enable + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch + + + + + + + + + + + + + + + + +Disabled +Enabled + + + +0 100 +percentage + + +1000 2000 +ms + + +0 1000 +cm/s + + +0 100 +percentage + + + + + + +seconds + + +seconds + + +seconds + + + + +0.4 1.0 +0.1 +seconds + + +0.1 10.0 +0.1 + + +0 1.0 +0.05 + + +0 0.1 +0.01 + + +0 4500 +1 + + +0 5 +0.1 +m/s + + +0.0 10.0 +0.1 + + +0.0 30.0 +0.1 +m/s + + +0.0 50.0 +0.1 +degree/(m/s) + + +0.0 4500.0 +0.1 +Centidegrees + + + + +0.1 20.0 +0.1 + + +0.1 10.0 +0.1 + + +3.0 10.0 +0.2 + + +0.1 1.0 +0.1 + + +0.0 0.5 +0.02 + + +1.0 10.0 +0.5 + + +1.0 5.0 +0.05 + + +0.5 2.0 +0.05 + + +5.0 30.0 +1.0 + + +0.0 2.0 +0.1 + + +0.1 1.0 +0.1 + + +0.0 20.0 +0.1 + + +-1 127 +1 + + +-1 100 +0.1 + + +-1.0 2.0 +0.1 + + +0 45 +1 + + +-45 0 +1 + + +0.0 2.0 +0.1 + + +1.0 5.0 +0.2 + + +0.1 1.0 +0.1 + + +-5 40 +1 + + +0.0 20.0 +0.1 +m/s + + +-2.0 2.0 +0.1 +m/s/m + + +0.1 1.0 +0.1 + + +0.0 0.5 +0.02 + + +0.0 0.5 +0.02 + + +0.1 1.0 +0.1 + + + +Disable +Enable + + + + + + +Disable +Enable + + + +1 +meters + + + + + +Disable +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + +900 2100 + + +900 2100 + + + +Disable +Chan1 +Chan3 +Chan3 +Chan4 +Chan5 +Chan6 +Chan7 +Chan8 +Chan9 +Chan10 +Chan11 +Chan12 +Chan13 +Chan14 +Chan15 +Chan16 + + + + + + +Disable +Enable + + + +0 1 + + + + +20 2000 +50 +cm/s + + +100 1000 +1 +cm + + +0 1000 +50 +cm/s + + +0 500 +10 +cm/s + + +0 2000 +50 +cm/s + + +50 500 +10 +cm/s/s + + +50 500 +10 +cm/s/s + + +500 5000 +1 +cm/s/s/s + + +100 981 +1 +cm/s/s + + +25 250 +1 +cm/s/s + + + +Disable +Enable + + + + + +0 4 +0.25 + + +0 2 +0.25 + + +0 2 +0.25 + + +0.8 1.2 +0.05 + + +0 4500 +1 + + + diff --git a/src/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.4.xml b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.4.xml index ac42cc78220b7a0d261dc72efa77eebef56813c0..e8f2e01eb77430256b084f8d5fbc3e1c86914901 100644 --- a/src/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.4.xml +++ b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.4.xml @@ -16,6 +16,7 @@ AntennaTracker Copter Rover +ArduSub @@ -38,29 +39,6 @@ .5 Hz - -0.0 1000.0 -10 -Centimeters - - -0.0 500.0 -10 - - -0:Feedback from mid stick,1:High throttle cancels landing,2:Disarm on land detection - -None -Feedback from mid stick -High throttle cancels landing -Disarm on land detection - - - -0 10 -1 -seconds - 0:Roll,1:Pitch,2:Yaw @@ -70,25 +48,6 @@ Yaw - -0 8000 -1 -Centimeters - - -0.5 10.0 - -Disabled -Shallow -Steep - -.1 - - -0 2000 -50 -cm/s - 0.01 2.0 0.01 @@ -161,84 +120,6 @@ Enabled - - -Disabled -Mode1 -Mode2 -Mode1+2 -Mode3 -Mode1+3 -Mode2+3 -Mode1+2+3 -Mode4 -Mode1+4 -Mode2+4 -Mode1+2+4 -Mode3+4 -Mode1+3+4 -Mode2+3+4 -Mode1+2+3+4 -Mode5 -Mode1+5 -Mode2+5 -Mode1+2+5 -Mode3+5 -Mode1+3+5 -Mode2+3+5 -Mode1+2+3+5 -Mode4+5 -Mode1+4+5 -Mode2+4+5 -Mode1+2+4+5 -Mode3+4+5 -Mode1+3+4+5 -Mode2+3+4+5 -Mode1+2+3+4+5 -Mode6 -Mode1+6 -Mode2+6 -Mode1+2+6 -Mode3+6 -Mode1+3+6 -Mode2+3+6 -Mode1+2+3+6 -Mode4+6 -Mode1+4+6 -Mode2+4+6 -Mode1+2+4+6 -Mode3+4+6 -Mode1+3+4+6 -Mode2+3+4+6 -Mode1+2+3+4+6 -Mode5+6 -Mode1+5+6 -Mode2+5+6 -Mode1+2+5+6 -Mode3+5+6 -Mode1+3+5+6 -Mode2+3+5+6 -Mode1+2+3+5+6 -Mode4+5+6 -Mode1+4+5+6 -Mode2+4+5+6 -Mode1+2+4+5+6 -Mode3+4+5+6 -Mode1+3+4+5+6 -Mode2+3+4+5+6 -Mode1+2+3+4+5+6 - - - --1 1000 -1 -Centimeters - - -0 3000 -10 -Centimeters - Never change yaw @@ -247,21 +128,6 @@ Face along GPS course - -0 60000 -1000 -ms - - -30 200 -10 -cm/s - - -0 500 -10 -cm/s - 50 500 10 @@ -272,19 +138,6 @@ 10 cm/s/s - - -Disabled -Enabled always RTL -Enabled Continue with Mission in Auto Mode -Enabled always LAND - - - -925 1100 -1 -pwm - 0 300 1 @@ -332,8 +185,6 @@ Manual - - 0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:RCIN,7:IMU,8:CMD,9:CURRENT,10:RCOUT,11:OPTFLOW,12:PID,13:COMPASS,14:INAV,15:CAMERA,17:MOTBATT,18:IMU_FAST,19:IMU_RAW @@ -405,17 +256,6 @@ 0 32767 - - -Plus -X -V -H -V-Tail -A-Tail -Y6B (New) - - Do Nothing @@ -433,7 +273,7 @@ Auto AutoTune Land -EPM +Gripper Parachute Enable Parachute Release Parachute 3pos @@ -470,7 +310,7 @@ Auto AutoTune Land -EPM +Gripper Parachute Enable Parachute Release Parachute 3pos @@ -507,7 +347,7 @@ Auto AutoTune Land -EPM +Gripper Parachute Enable Parachute Release Parachute 3pos @@ -544,7 +384,7 @@ Auto AutoTune Land -EPM +Gripper Parachute Enable Parachute Release Parachute 3pos @@ -581,7 +421,7 @@ Auto AutoTune Land -EPM +Gripper Parachute Enable Parachute Release Parachute 3pos @@ -618,7 +458,7 @@ Auto AutoTune Land -EPM +Gripper Parachute Enable Parachute Release Parachute 3pos @@ -671,20 +511,6 @@ 10 - -4 12 -deg/sec - - -2000 4500 -Centi-degrees - - - -No repositioning -Repositioning - - Land @@ -701,6 +527,30 @@ Enabled + +0.1 1.0 + + +0.2 1.0 + + +0.1 0.8 + + +1 10 + + +30 400 + + +30 400 + + +0.5 4.0 + + +1000 2000 + 50 490 1 @@ -750,6 +600,11 @@ 10 cm/s/s + +0 4500 +10 +cm/s/s + 1.000 8.000 @@ -767,7 +622,7 @@ 0.000 0.400 - + 1.000 100.000 Hz @@ -795,19 +650,13 @@ 0.001 0.006 - - -Stopped -Running - - Do Not Use in RTL and Land Use in RTL and Land - + 0 5 @@ -837,14 +686,18 @@ None -MAVlink1 +MAVLink1 MAVLink2 -Frsky D-PORT -Frsky S-PORT +Frsky D +Frsky SPort GPS Alexmos Gimbal Serial SToRM32 Gimbal Serial Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon @@ -866,14 +719,18 @@ None -MAVlink1 +MAVLink1 MAVLink2 -Frsky D-PORT -Frsky S-PORT +Frsky D +Frsky SPort GPS Alexmos Gimbal Serial SToRM32 Gimbal Serial Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon @@ -895,14 +752,18 @@ None -MAVlink1 +MAVLink1 MAVLink2 -Frsky D-PORT -Frsky S-PORT +Frsky D +Frsky SPort GPS Alexmos Gimbal Serial SToRM32 Gimbal Serial Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon @@ -924,14 +785,18 @@ None -MAVlink1 +MAVLink1 MAVLink2 -Frsky D-PORT -Frsky S-PORT +Frsky D +Frsky SPort GPS Alexmos Gimbal Serial SToRM32 Gimbal Serial Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon @@ -953,14 +818,18 @@ None -MAVlink1 +MAVLink1 MAVLink2 -Frsky D-PORT -Frsky S-PORT +Frsky D +Frsky SPort GPS Alexmos Gimbal Serial SToRM32 Gimbal Serial Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon @@ -1141,7 +1010,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1170,6 +1039,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1226,7 +1099,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1255,6 +1128,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1311,7 +1188,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1340,6 +1217,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1396,7 +1277,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1425,6 +1306,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1481,7 +1366,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1510,6 +1395,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1566,7 +1455,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1595,6 +1484,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1651,7 +1544,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1680,6 +1573,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1736,7 +1633,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1765,6 +1662,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1821,7 +1722,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1850,6 +1751,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -1906,7 +1811,7 @@ Flaperon2 GroundSteering Parachute -EPM +Gripper LandingGear EngineRunEnable HeliRSC @@ -1935,6 +1840,10 @@ RCIN14 RCIN15 RCIN16 +Ignition +Choke +Starter +Throttle @@ -3678,92 +3587,18 @@ - - - -Disabled -Enabled - - - -1000 2000 - - -1000 2000 - - -1000 2000 - - - -Never -every 15 seconds -every 30 seconds -once per minute - - - - - - -Disabled -Enabled - - - - -First Relay -Second Relay -Third Relay -Fourth Relay -Servo - - - -1000 2000 -1 -pwm - - -1000 2000 -1 -pwm - - -0 32000 -1 -Meters - - -0 5000 -1 -Milliseconds - - - - -1000 2000 -1 -pwm - - -1000 2000 -1 -pwm - - - + -400 400 1 milligauss - + -400 400 1 milligauss - + -400 400 1 milligauss @@ -3799,17 +3634,17 @@ Use Current - + -1000 1000 1 Offset per Amp or at Full Throttle - + -1000 1000 1 Offset per Amp or at Full Throttle - + -1000 1000 1 Offset per Amp or at Full Throttle @@ -3864,32 +3699,32 @@ ForcedExternal - + -400 400 1 milligauss - + -400 400 1 milligauss - + -400 400 1 milligauss - + -1000 1000 1 Offset per Amp or at Full Throttle - + -1000 1000 1 Offset per Amp or at Full Throttle - + -1000 1000 1 Offset per Amp or at Full Throttle @@ -3901,41 +3736,41 @@ ThirdCompass - + -400 400 1 milligauss - + -400 400 1 milligauss - + -400 400 1 milligauss - + -1000 1000 1 Offset per Amp or at Full Throttle - + -1000 1000 1 Offset per Amp or at Full Throttle - + -1000 1000 1 Offset per Amp or at Full Throttle - + - + - + @@ -4049,60 +3884,55 @@ ForcedExternal - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + -4 20 +4 32 + +Very Strict +Default +Relaxed +Very Relaxed + 0.1 - - -Unknown -unused -unused -unused -SITL -PX4v1 -PX4v2 -unused -Linux - + rad/s @@ -4243,6 +4073,53 @@ IMU 3 + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +True + + +True + + +True + + +True + + +True + + +True + + + @@ -4291,10 +4168,16 @@ cm/s/s -100 981 +25 250 1 cm/s/s + + +Disable +Enable + + @@ -4325,6 +4208,17 @@ 1000 Centi-Degrees/Sec/Sec + +0 72000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + Disabled @@ -4388,7 +4282,7 @@ 0.0 0.02 0.001 - + 1 100 1 Hz @@ -4410,7 +4304,7 @@ 0.0 0.02 0.001 - + 1 100 1 Hz @@ -4432,7 +4326,7 @@ 0.000 0.02 0.001 - + 1 100 1 Hz @@ -4444,8 +4338,8 @@ 0.5 0.9 - - + + 0.5 5 0.1 Hz @@ -4497,11 +4391,6 @@ 1 Hz - -0 50 -1 -Hz - @@ -4549,11 +4438,6 @@ 1 Hz - -0 50 -1 -Hz - @@ -4601,11 +4485,6 @@ 1 Hz - -0 50 -1 -Hz - @@ -4653,14 +4532,9 @@ 1 Hz - -0 50 -1 -Hz - - + 0.0 1.0 .01 @@ -4670,25 +4544,25 @@ Enabled - + 0.1 0.4 .01 - + 0.1 0.4 .01 - + 0 127 1 m/s - + -0.1745 +0.1745 0.01 Radians - + -0.1745 +0.1745 0.01 Radians @@ -5078,6 +4952,12 @@ Enabled + + +Disabled +Enabled + + @@ -5172,7 +5052,7 @@ - + No PWMs Two PWMs @@ -5182,7 +5062,7 @@ True - + Disabled Enabled @@ -5190,7 +5070,7 @@ True - + Disabled Enabled @@ -5198,14 +5078,14 @@ True - + Disabled Enabled True - + Disabled 50Hz @@ -5221,73 +5101,74 @@ -32767 32768 - + Disabled Enabled +Dynamic ID/Update - -0:Ch1,1:Ch2,2:Ch3,3:Ch4,4:Ch5,5:Ch6,6:Ch7,7:Ch8 + +0:Ch1,1:Ch2,2:Ch3,3:Ch4,4:Ch5,5:Ch6,6:Ch7,7:Ch8,8:Ch9,9:Ch10,10:Ch11,11:Ch12,12:Ch13,13:Ch14 Disabled Enabled True - -degreesC + -1 80 +degreesC - - - - -Disabled -Enabled + + +AUTO +PX4V1 +Pixhawk +Pixhawk2 +Pixracer +PixhawkMini +Pixhawk2Slim +VRBrain 5.1 +VRBrain 5.2 +VR Micro Brain 5.1 +VR Micro Brain 5.2 +VRBrain Core 1.0 +VRBrain 5.4 - - -0 100 -percentage - - -1000 2000 -ms - - -0 1000 -cm/s - - -0 100 -percentage +True - + True True 1 pascals - + True True 1 degrees celsius - -meters + 0.1 +meters - + FirstBaro 2ndBaro 3rdBaro + + +Disabled +Bus0 + + 1.0:Fresh Water, 1.024:Salt Water @@ -5303,7 +5184,7 @@ - + None AUTO @@ -5317,10 +5198,14 @@ PX4-UAVCAN SBF GSOF +QURT +ERB +MAV +NOVA True - + None AUTO @@ -5337,7 +5222,7 @@ True - + Portable Stationary @@ -5374,7 +5259,7 @@ -100 90 Degrees - + send to first GPS send to 2nd GPS @@ -5388,7 +5273,7 @@ External only - + Disabled log every sample @@ -5439,6 +5324,38 @@ Enable automatic configuration + + +10Hz +8Hz +5Hz + + + + +10Hz +8Hz +5Hz + + + +m + + +m + + +m + + +m + + +m + + +m + @@ -5572,9 +5489,12 @@ +0:StopAtFence,1:UseProximitySensor None StopAtFence +UseProximitySensor +All @@ -5645,6 +5565,69 @@ 0.0 1.5 0.1 + +0 500 +pwm + + +0.25 0.8 + + +0.9:Low, 0.95:Default, 1.0:High + + +6 35 +Volts + + +6 35 +Volts + + +0 200 +Amps + + + +Normal +OneShot +OneShot125 +Brushed16kHz + +True + + +0 2000 + + +0 2000 + + +0.0:Low, 0.15:Default, 0.3:High + + +0.0:Low, 0.1:Default, 0.2:High + + +0 10 +Seconds + + +0.2 0.8 + + + +Disabled +Learn +LearnAndSave + + + + +PWM enabled while disarmed +PWM disabled while disarmed + + @@ -5850,12 +5833,12 @@ Enabled - + GPS 3D Vel and 2D Pos GPS 2D vel and 2D pos GPS 2D pos -No GPS use optical flow +No GPS @@ -5891,11 +5874,12 @@ 10 msec - + Use Baro Use Range Finder Use GPS +Use Range Beacon @@ -6041,68 +6025,49 @@ 0.00001 0.01 gauss/s + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +msec + 0 32766 1 - + Resume Mission Restart Mission - - - -Disabled -AnalogPin -RCChannelPwmValue - - - - -APM2 A0 -APM2 A1 -APM2 A13 -Pixracer -Pixhawk ADC4 -Pixhawk ADC3 - Pixhawk ADC6 -Pixhawk SBUS - - - -0 5.0 -0.01 -Volt - - -0 5.0 -0.01 -Volt - - - - - -0 2000 -Microseconds - - -0 2000 -Microseconds - - None Analog -APM2-MaxbotixI2C -APM2-PulsedLightI2C +MaxbotixI2C +PulsedLightI2C PX4-I2C PX4-PWM BBB-PRU @@ -6110,6 +6075,9 @@ LightWareSerial Bebop MAVLink +uLanding +LeddarOne +MaxbotixSerial @@ -6189,12 +6157,25 @@ 1 centimeters + +0 127 +1 + + +m + + +m + + +m + None Analog -APM2-MaxbotixI2C -APM2-PulsedLightI2C +MaxbotixI2C +PulsedLightI2C PX4-I2C PX4-PWM BBB-PRU @@ -6202,6 +6183,9 @@ LightWareSerial Bebop MAVLink +uLanding +LeddarOne +MaxbotixSerial @@ -6277,15 +6261,20 @@ 1 centimeters - + 0 127 1 - -0 127 -1 + +m - + +m + + +m + + None Analog @@ -6298,9 +6287,12 @@ LightWareSerial Bebop MAVLink +uLanding +LeddarOne +MaxbotixSerial - + Not Used APM2-A0 @@ -6318,30 +6310,30 @@ APM1-airspeed port - -meters/Volt + 0.001 +meters/Volt - -Volts + 0.001 +Volts - + Linear Inverted Hyperbolic - -centimeters + 1 - - centimeters + + 1 +centimeters - + Not Used Pixhawk AUXOUT1 @@ -6358,26 +6350,35 @@ PX4IO ACC2 - -milliseconds + 1 +milliseconds - + No Yes - + 0 127 1 centimeters - + 0 127 1 - + +m + + +m + + +m + + None Analog @@ -6390,9 +6391,12 @@ LightWareSerial Bebop MAVLink +uLanding +LeddarOne +MaxbotixSerial - + Not Used APM2-A0 @@ -6410,30 +6414,30 @@ APM1-airspeed port - -meters/Volt + 0.001 +meters/Volt - -Volts + 0.001 +Volts - + Linear Inverted Hyperbolic - -centimeters + 1 - - centimeters + + 1 +centimeters - + Not Used Pixhawk AUXOUT1 @@ -6450,36 +6454,45 @@ PX4IO ACC2 - -milliseconds + 1 +milliseconds - + No Yes - + 0 127 1 centimeters - + 0 127 1 + +m + + +m + + +m + - + Disable Enable - -meters + 1 +meters @@ -6501,126 +6514,167 @@ -18000 +18000 1 - - - - -Disabled -Enabled Always Land -Enabled Strict - + +m - - -None -CompanionComputer -IRLock - + +m + + +m + + +0 255 - + None PX4-PWM - + 0.001 - + 1 - + 1 - + 0.1 - + None PX4-PWM - + 0.001 - - + + -Disabled -Enabled +Off +Low +Medium +High - + -None -Loiter -LoiterAndDescend +Disable +Enable - -1 100 - - -1 100000 + + +Disable +Enable + - --1 16777215 + + + + +None +LightWareSF40C + - + -NoInfo -Light -Small -Large -HighVortexlarge -Heavy -HighlyManuv -Rotocraft -RESERVED -Glider -LightAir -Parachute -UltraLight -RESERVED -UAV -Space -RESERVED -EmergencySurface -ServiceSurface -PointObstacle +Default +Upside Down - + +-180 180 - + +0 360 - + +0 45 - - - + +0 360 + + +0 45 + + +0 360 + + +0 45 + + +0 360 + + +0 45 + + +0 360 + + +0 45 + + +0 360 + + +0 45 + + -Off -Low -Medium -High +None +LightWareSF40C - + -Disable -Enable +Default +Upside Down - + +-180 180 + + + + -Disable -Enable +Disabled +Enabled + + +None +Servo +EPM + + + +1000 2000 + + +1000 2000 + + +1000 2000 + + +0 255 +seconds + + +0 255 + diff --git a/src/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.5.xml b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.5.xml new file mode 100644 index 0000000000000000000000000000000000000000..2ee76518b7bbc79fda7d63da17c5ddd453a93dca --- /dev/null +++ b/src/FirmwarePlugin/APM/APMParameterFactMetaData.Sub.3.5.xml @@ -0,0 +1,7683 @@ + + + + + + +-100 0 + + +True + + +True + +ArduPlane +AntennaTracker +Copter +Rover +ArduSub + + + +1 255 + + + +Mission Planner and DroidPlanner + AP Planner 2 + + + + +Disabled +Enabled + + + +0 10 +.5 +Hz + + +0:Roll,1:Pitch,2:Yaw + +None +Roll +Pitch +Yaw + + + +0.01 2.0 +0.01 + + + +Disabled + + + +0.1 +Volts + + +50 +mAh + + + +Disabled +Warn only +Disarm +Enter depth hold mode +Enter surface mode + + + + +Disabled +Warn only +Enter surface mode + + + + +Disabled +Warn only + + + + +Disabled +Warn only + + + +Pascal + + +Degrees Centigrade + + + +Disarm +Hold Position +Surface + + + +10 90 + + +100 900 + + + +Disabled +Enabled + + + + +Never change yaw +Face next waypoint +Face next waypoint except RTL +Face along GPS course + + + +50 500 +10 +Centimeters/Second + + +50 500 +10 +cm/s/s + + +0 300 +1 +pwm + + + +Stabilize +DepthHold +Manual + + + + +Stabilize +DepthHold +Manual + + + + +Stabilize +DepthHold +Manual + + + + +Stabilize +DepthHold +Manual + + + + +Stabilize +DepthHold +Manual + + + + +Stabilize +DepthHold +Manual + + + +0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:RCIN,7:IMU,8:CMD,9:CURRENT,10:RCOUT,11:OPTFLOW,12:PID,13:COMPASS,14:INAV,15:CAMERA,17:MOTBATT,18:IMU_FAST,19:IMU_RAW + +Default +Default+RCIN +Default+IMU +Default+Motors +NearlyAll-AC315 +NearlyAll +All+FastATT +All+MotBatt +All+FastIMU +All+FastIMU+PID +All+FullIMU +Disabled + + + + +Normal Start-up +Start-up in ESC Calibration mode if throttle high +Start-up in ESC Calibration mode regardless of throttle +Disabled + + + + +None +Stab Roll/Pitch kP +Rate Roll/Pitch kP +Rate Roll/Pitch kI +Rate Roll/Pitch kD +Stab Yaw kP +Rate Yaw kP +Rate Yaw kD +Altitude Hold kP +Throttle Rate kP +Throttle Accel kP +Throttle Accel kI +Throttle Accel kD +Loiter Speed +Loiter Pos kP +Velocity XY kP +Velocity XY kI +WP Speed +Acro RollPitch kP +Acro Yaw kP +Heli Ext Gyro +OF Loiter kP +OF Loiter kI +OF Loiter kD +Declination +Circle Rate +RangeFinder Gain +Rate Pitch kP +Rate Pitch kI +Rate Pitch kD +Rate Roll kP +Rate Roll kI +Rate Roll kD +Rate Pitch FF +Rate Roll FF +Rate Yaw FF + + + +0 32767 + + +0 32767 + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +ResetToArmedYaw +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost vehicle Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +ResetToArmedYaw +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost vehicle Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +ResetToArmedYaw +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost vehicle Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +ResetToArmedYaw +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost vehicle Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +ResetToArmedYaw +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost vehicle Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw + + + + +Do Nothing +Flip +Simple Mode +RTL +Save Trim +Save WP +Camera Trigger +RangeFinder +Fence +ResetToArmedYaw +Super Simple Mode +Acro Trainer +Auto +AutoTune +Land +Gripper +Parachute Enable +Parachute Release +Parachute 3pos +Auto Mission Reset +AttCon Feed Forward +AttCon Accel Limits +Retract Mount +Relay On/Off +Relay2 On/Off +Relay3 On/Off +Relay4 On/Off +Landing Gear +Lost vehicle Sound +Motor Emergency Stop +Motor Interlock +Brake +Throw + + + +0:All,1:Baro,2:Compass,3:GPS,4:INS,5:Parameters+Rangefinder,6:RC,7:Voltage + +Disabled +Enabled +Skip Baro +Skip Compass +Skip GPS +Skip INS +Skip Params/Rangefinder +Skip RC +Skip Voltage + + + +0 127 +Seconds + + +1000 8000 +Centi-degrees + + +0 100 + +Very Soft +Soft +Medium +Crisp +Very Crisp + +10 + + + +Disabled + + + +0.6:Strict, 0.8:Default, 1.0:Relaxed + + + +Disabled + + + +0.1 1.0 + + +0.2 1.0 + + +0.1 0.8 + + +1 10 + + +30 400 + + +30 400 + + +0.5 4.0 + + +1000 2000 + + + +BlueROV1 +Vectored +Vectored_6DOF +Vectored_6DOF_90 +SimpleROV-3 +SimpleROV-4 +SimpleROV-5 +Custom + +True + + +50 490 +1 +Hz + + +1 10 + + +1 10 + + +0 3 +0.1 + + +0 3 +0.1 + + + +Disabled +Leveling +Leveling and Limited + + + + +Disabled +Very Low +Low +Medium +High +Very High + + + +0.1 6.0 +0.1 + + +0.02 1.00 +0.01 + + +0 4500 +10 +cm/s/s + + +0 4500 +10 +cm/s/s + + +1.000 8.000 + + +0.500 1.500 +0.05 + + +0.000 3.000 + + +0 1000 +Percent*10 + + +0.000 0.400 + + +1.000 100.000 +Hz + + +1.000 3.000 + + +0.500 2.000 + + +0:Roll,1:Pitch,2:Yaw + +All +Roll Only +Pitch Only +Yaw Only +Roll and Pitch +Roll and Yaw +Pitch and Yaw + + + +0.05 0.10 + + +0.001 0.006 + + + +Do Not Use in RTL and Land +Use in RTL and Land + + + +0 5 + + + + +0.0 1.0 +.01 + + + +Disabled +Enabled + + + +0.1 0.4 +.01 + + +0.1 0.4 +.01 + + +0 127 +1 +m/s + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + +-0.1745 +0.1745 +0.01 +Radians + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 + + + +0.001 0.5 +.01 + + +0 10 +1 + + + +Disabled +Enable EKF2 +Enable EKF3 + + + + + +500 18000 +100 +Centi-Degrees/Sec + + +0 72000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + +0 180000 + +Disabled +Slow +Medium +Fast + +1000 +Centi-Degrees/Sec/Sec + + + +Disabled +Enabled + + + +3.000 12.000 + + +3.000 12.000 + + +3.000 6.000 + + +0.5 10.0 + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.08 0.30 +0.005 + + +0.01 0.5 +0.01 + + +0 1 +0.01 +Percent + + +0.0 0.02 +0.001 + + +1 100 +1 +Hz + + +0.10 0.50 +0.005 + + +0.010 0.05 +0.01 + + +0 1 +0.01 +Percent + + +0.000 0.02 +0.001 + + +1 100 +1 +Hz + + +0.1 0.25 + + +0.5 0.9 + + +0.5 0.9 + + + + +0:StopAtFence,1:UseProximitySensor + +None +StopAtFence +UseProximitySensor +All + + + +0 4500 + + +3 30 +meters + + + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +Solo +Bebop +SMBus-Maxell + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Watts + + + +Disabled +Analog Voltage Only +Analog Voltage and Current +Solo +Bebop +SMBus-Maxell + + + + +Disabled +A0 +A1 +Pixhawk +A13 +PX4 + + + + +Disabled +A1 +A2 +Pixhawk +A12 +PX4 + + + + + +Amps/Volt + + +Volts + + +50 +mAh + + +1 +Amps + + + + + +No PWMs +Two PWMs +Four PWMs +Six PWMs +Three PWMs and One Capture + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled +Auto + +True + + + +Disabled +Enabled + +True + + + +Disabled +50Hz +75Hz +100Hz +150Hz +200Hz +250Hz +300Hz + +True + + +-32767 32768 + + + +Disabled +Enabled +Dynamic ID/Update + + + +0:Ch1,1:Ch2,2:Ch3,3:Ch4,4:Ch5,5:Ch6,6:Ch7,7:Ch8,8:Ch9,9:Ch10,10:Ch11,11:Ch12,12:Ch13,13:Ch14 + +Disabled +Enabled + +True + + +-1 80 +degreesC + + + +AUTO +PX4V1 +Pixhawk +Pixhawk2 +Pixracer +PixhawkMini +Pixhawk2Slim +VRBrain 5.1 +VRBrain 5.2 +VR Micro Brain 5.1 +VR Micro Brain 5.2 +VRBrain Core 1.0 +VRBrain 5.4 + +True + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + +Disabled +shift +arm_toggle +arm +disarm +mode_toggle +enter_mode_1 +enter_mode_2 +enter_mode_3 +enter_mode_4 +enter_mode_5 +enter_mode_6 +mount_center +mount_tilt_up +mount_tilt_down +camera_trigger +camera_source_toggle +mount_pan_right +mount_pan_left +lights1_cycle +lights1_brighter +lights1_dimmer +lights2_cycle +lights2_brighter +lights2_dimmer +gain_toggle +gain_inc +gain_dec +trim_roll_inc +trim_roll_dec +trim_pitch_inc +trim_pitch_dec +input_hold_toggle +relay_1_on +relay_1_off +relay_1_toggle +relay_2_on +relay_2_off +relay_2_toggle +custom_1 +custom_2 +custom_3 +custom_4 +custom_5 +custom_6 + + + + + + +Servo +Relay + + + +0 50 +deciseconds + + +1000 2000 +pwm + + +1000 2000 +pwm + + +0 1000 +meters + + + +Low +High + + + +0 10000 +milliseconds + + +0 180 +Degrees + + + +Disabled +PX4 AUX1 +PX4 AUX2 +PX4 AUX3 +PX4 AUX4(fast capture) +PX4 AUX5 +PX4 AUX6 + + + + +TriggerLow +TriggerHigh + + + + + +0 10000 +100 +cm + + +-90 90 +1 +deg/s + + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-3.142 3.142 +0.01 +Radians + + + +Disabled +Internal-Learning +EKF-Learning + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Use Throttle +Use Current + + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + +FirstCompass +SecondCompass +ThirdCompass + + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-400 400 +1 +milligauss + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + +-1000 1000 +1 +Offset per Amp or at Full Throttle + + + + + + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + +Disabled +Enabled + + + + +None +Yaw45 +Yaw90 +Yaw135 +Yaw180 +Yaw225 +Yaw270 +Yaw315 +Roll180 +Roll180Yaw45 +Roll180Yaw90 +Roll180Yaw135 +Pitch180 +Roll180Yaw225 +Roll180Yaw270 +Roll180Yaw315 +Roll90 +Roll90Yaw45 +Roll90Yaw90 +Roll90Yaw135 +Roll270 +Roll270Yaw45 +Roll270Yaw90 +Roll270Yaw136 +Pitch90 +Pitch270 +Pitch180Yaw90 +Pitch180Yaw270 +Roll90Pitch90 +Roll180Pitch90 +Roll270Pitch90 +Roll90Pitch180 +Roll270Pitch180 +Roll90Pitch270 +Roll180Pitch270 +Roll270Pitch270 +Roll90Pitch180Yaw90 +Roll90Yaw270 +Yaw293Pitch68Roll90 + + + + +Internal +External +ForcedExternal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +4 32 + +Very Strict +Strict +Default +Relaxed + +0.1 + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + +0 250 +10 +milliseconds + + + +Use Baro +Use Range Finder +Use GPS +Use Range Beacon + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.000001 0.001 +1/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +50 200 +% + + +0.5 50.0 +m + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +0.05 1.0 +0.05 +rad + + +100 1000 +25 + + +10 50 +5 +cs + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds + + +2.0 6.0 +0.5 +m/s + + +0:FirstEKF,1:SecondEKF,2:ThirdEKF,3:FourthEKF,4:FifthEKF,5:SixthEKF + + + + + +Disabled +Enabled + + + + +GPS 3D Vel and 2D Pos +GPS 2D vel and 2D pos +GPS 2D pos +No GPS + + + +0.05 5.0 +0.05 +m/s + + +0.05 5.0 +0.05 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +10 100 +5 +m + + + +Use Baro +Use Range Finder +Use GPS +Use Range Beacon + + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +0.01 0.5 +0.01 +gauss + + + +When flying +When manoeuvring +Never +After first climb yaw reset +Always + + + +100 1000 +25 + + +0.5 5.0 +0.1 +m/s + + +100 1000 +25 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +1.0 4.0 +0.1 +rad/s + + +0.05 1.0 +0.05 +rad/s + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +0.0001 0.1 +0.0001 +rad/s + + +0.01 1.0 +0.01 +m/s/s + + +0.00001 0.001 +rad/s/s + + +0.00001 0.001 +m/s/s/s + + +0.01 1.0 +0.1 +m/s/s + + +0.0 1.0 +0.1 + + +0:NSats,1:HDoP,2:speed error,3:horiz pos error,4:yaw error,5:pos drift,6:vert speed,7:horiz speed + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +50 200 +% + + +0.5 50.0 +m + + +0:FirstIMU,1:SecondIMU,2:ThirdIMU,3:FourthIMU,4:FifthIMU,5:SixthIMU + + +0.05 1.0 +0.05 +rad + + +100 1000 +25 + + +10 50 +5 +cs + + +0.00001 0.01 +gauss/s + + +0.00001 0.01 +gauss/s + + +-1 70 +1 +% + + +0 0.2 +0.01 + + +0.1 10.0 +0.1 +m + + +100 1000 +25 + + +0 250 +10 +milliseconds +True + + +2.0 6.0 +0.5 +m/s + + +0.5 2.5 +0.1 +m/s/s + + +0:FirstEKF,1:SecondEKF,2:ThirdEKF,3:FourthEKF,4:FifthEKF,5:SixthEKF + + + + + +Disabled +Enabled + + + +0:Altitude,1:Circle,2:Polygon + +None +Altitude +Circle +Altitude and Circle +Polygon +Altitude and Polygon +Circle and Polygon +All + + + + +Report Only +RTL or Land + + + +10 1000 +1 +Meters + + +30 10000 +Meters + + +1 10 +Meters + + +1 20 + + +-100 100 +1 +Meters + + + + + +Disabled +Enabled + + + +-200 +200 +1 + + +-200 +200 +1 + + +-18000 +18000 +1 + + +m + + +m + + +m + + +0 255 + + + + +True +True +1 +pascals + + +True +True +1 +degrees celsius + + +0.1 +meters + + + +FirstBaro +2ndBaro +3rdBaro + + + + +Disabled +Bus0 + + + +1.0:Freshwater,1.024:Saltwater + + +True +True +1 +pascals + + +True +True +1 +degrees celsius + + +True +True +1 +pascals + + +True +True +1 +degrees celsius + + + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF +QURT +ERB +MAV +NOVA + +True + + + +None +AUTO +uBlox +MTK +MTK19 +NMEA +SiRF +HIL +SwiftNav +PX4-UAVCAN +SBF +GSOF +QURT +ERB +MAV +NOVA + +True + + + +Portable +Stationary +Pedestrian +Automotive +Sea +Airborne1G +Airborne2G +Airborne4G + + + + +Disabled +Enabled + + + + +Any +FloatRTK +IntegerRTK + +True + + + +Disabled +Enabled +NoChange + + + +-100 90 +Degrees + + + +send to first GPS +send to 2nd GPS +send to all + + + + +None +All +External only + + + + +Disabled +log every sample +log every 5 samples + +True + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Do not save config +Save config +Save only when needed + + + +0:GPS,1:SBAS,2:Galileo,3:Beidou,4:IMES,5:QZSS,6:GLOSNASS + +Leave as currently configured +GPS-NoSBAS +GPS+SBAS +Galileo-NoSBAS +Galileo+SBAS +Beidou +GPS+IMES+QZSS+SBAS (Japan Only) +GLONASS +GLONASS+SBAS +GPS+GLONASS+SBAS + + + + +Disables automatic configuration +Enable automatic configuration + + + + +10Hz +8Hz +5Hz + +milliseconds + + + +10Hz +8Hz +5Hz + +milliseconds + + +m + + +m + + +m + + +m + + +m + + +m + + +0 250 +milliseconds + + +0 250 +milliseconds + + + + + +Disabled +Enabled + + + + +None +Servo +EPM + + + +1000 2000 +PWM + + +1000 2000 +PWM + + +1000 2000 +PWM + + +0 255 +seconds + + +0 255 + + + + + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +rad/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0.8 1.2 + + +0.8 1.2 + + +0.8 1.2 + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +-3.5 3.5 +m/s/s + + +0 127 +Hz + + +0 127 +Hz + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + +0.05 50 + + + +Never +Start-up only + + + + +Don't adjust the trims +Assume first orientation was level +Assume ACC_BODYFIX is perfectly aligned to the vehicle + + + + +IMU 1 +IMU 2 +IMU 3 + + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +m + + +True + + +True + + +True + + +True + + +True + + +True + + + + + + + +Disabled +Pixhawk Aux1 +Pixhawk Aux2 +Pixhawk Aux3 +Pixhawk Aux4 +Pixhawk Aux5 +Pixhawk Aux6 +Pixhawk 3.3ADC1 +Pixhawk 3.3ADC2 +Pixhawk 6.6ADC + + + + +Low +High + + + + +Disabled +Pixhawk Aux1 +Pixhawk Aux2 +Pixhawk Aux3 +Pixhawk Aux4 +Pixhawk Aux5 +Pixhawk Aux6 +Pixhawk 3.3ADC1 +Pixhawk 3.3ADC2 +Pixhawk 6.6ADC + + + + +Low +High + + + + +Disabled +Pixhawk Aux1 +Pixhawk Aux2 +Pixhawk Aux3 +Pixhawk Aux4 +Pixhawk Aux5 +Pixhawk Aux6 +Pixhawk 3.3ADC1 +Pixhawk 3.3ADC2 +Pixhawk 6.6ADC + + + + +Low +High + + + + + + +None +File +MAVLink +BothFileAndMAVLink + + + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + + +0 32766 +1 + + + +Resume Mission +Restart Mission + + + + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0 100 +1 + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + +True + + + +Retracted +Neutral +MavLink Targeting +RC Targeting +GPS Point + + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + +-180.00 179.99 +1 +Degrees + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +Enabled + + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + + +Disabled +RC5 +RC6 +RC7 +RC8 +RC9 +RC10 +RC11 +RC12 + + + +-18000 17999 +1 +Centi-Degrees + + +-18000 17999 +1 +Centi-Degrees + + +0.0 0.2 +.005 +Seconds + + +0.0 0.2 +.005 +Seconds + + + +None +Servo +3DR Solo +Alexmos Serial +SToRM32 MAVLink +SToRM32 Serial + + + + + + +normal +reverse + + + + +normal +reverse + + + + +normal +reverse + + + + +normal +reverse + + + + +normal +reverse + + + + +normal +reverse + + + + +normal +reverse + + + + +normal +reverse + + + +0.0 1.5 +0.1 + + +0 500 +pwm + + +0.25 0.8 + + +0.9:Low, 0.95:Default, 1.0:High + + +6 35 +Volts + + +6 35 +Volts + + +0 200 +Amps + + + +Normal +OneShot +OneShot125 +Brushed16kHz + +True + + +0 2000 + + +0 2000 + + +0.0:Low, 0.15:Default, 0.3:High + + +0.0:Low, 0.1:Default, 0.2:High + + +0 10 +Seconds + + +0.2 0.8 + + + +Disabled +Learn +LearnAndSave + + + + +PWM enabled while disarmed +PWM disabled while disarmed + + + +5 80 +1 +Degrees + + +0 2 +0.1 +Seconds + + + + + +Off +Low +Medium +High + + + + +Disable +Enable + + + + +Disable +Enable + + + + +Disable +ssd1306 +sh1106 + + + + + + +None +LightWareSF40C +MAVLink +TeraRangerTower + + + + +Default +Upside Down + + + +-180 180 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + +0 360 +degrees + + +0 45 +degrees + + + +None +LightWareSF40C +MAVLink + + + + +Default +Upside Down + + + +-180 180 +degrees + + + + +0.5 5 +0.1 +Hz + + + + + + +0.1 +kilometers + + + +DoNotIncludeHome +IncludeHome + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + +0 200 +pwm + + + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + +1 8 +1 +True + + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Disabled +APM2 A9 pin +APM1 relay +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + + +Off +On +NoChange + + + + + + +None +Analog +MaxbotixI2C +PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial +TrOneI2C + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 32767 +meters + + +5 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +MaxbotixI2C +PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial +TrOneI2C + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + +None +Analog +APM2-MaxbotixI2C +APM2-PulsedLightI2C +PX4-PWM +BBB-PRU +LightWareI2C +LightWareSerial +Bebop +MAVLink +uLanding +LeddarOne +MaxbotixSerial + + + + +Not Used +APM2-A0 +APM2-A1 +APM2-A2 +APM2-A3 +APM2-A4 +APM2-A5 +APM2-A6 +APM2-A7 +APM2-A8 +APM2-A9 +PX4-airspeed port +Pixhawk-airspeed port +APM1-airspeed port + + + +0.001 +meters/Volt + + +0.001 +Volts + + + +Linear +Inverted +Hyperbolic + + + +1 +centimeters + + +1 +centimeters + + + +Not Used +Pixhawk AUXOUT1 +Pixhawk AUXOUT2 +Pixhawk AUXOUT3 +Pixhawk AUXOUT4 +Pixhawk AUXOUT5 +Pixhawk AUXOUT6 +PX4 FMU Relay1 +PX4 FMU Relay2 +PX4IO Relay1 +PX4IO Relay2 +PX4IO ACC1 +PX4IO ACC2 + + + +1 +milliseconds + + + +No +Yes + + + +0 127 +1 +centimeters + + +0 127 +1 + + +m + + +m + + +m + + + + + +None +PX4-PWM + + + +0.001 + + +1 + + +1 + + +0.1 + + + +None +PX4-PWM + + + +0.001 + + + + + +Disabled +ShowSlips +ShowOverruns + + + + +50Hz +100Hz +200Hz +250Hz +300Hz +400Hz + +True + + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +MAVlink1 +MAVLink2 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + +None +MAVLink1 +MAVLink2 +Frsky D +Frsky SPort +GPS +Alexmos Gimbal Serial +SToRM32 Gimbal Serial +Lidar +FrSky SPort Passthrough (OpenTX) +Lidar360 +Aerotenna uLanding +Pozyx Beacon + + + + +1200 +2400 +4800 +9600 +19200 +38400 +57600 +111100 +115200 +500000 +921600 +1500000 + + + + + + +Disable +Enable + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + +800 2200 +1 +pwm + + + +Normal +Reversed + + + + +Disabled +RCPassThru +Flap +Flap_auto +Aileron +mount_pan +mount_tilt +mount_roll +mount_open +camera_trigger +release +mount2_pan +mount2_tilt +mount2_roll +mount2_open +DifferentialSpoiler1 +DifferentialSpoiler2 +AileronWithInput +Elevator +ElevatorWithInput +Rudder +Flaperon1 +Flaperon2 +GroundSteering +Parachute +EPM +LandingGear +EngineRunEnable +HeliRSC +HeliTailRSC +Motor1 +Motor2 +Motor3 +Motor4 +Motor5 +Motor6 +Motor7 +Motor8 +RCIN1 +RCIN2 +RCIN3 +RCIN4 +RCIN5 +RCIN6 +RCIN7 +RCIN8 +RCIN9 +RCIN10 +RCIN11 +RCIN12 +RCIN13 +RCIN14 +RCIN15 +RCIN16 +Ignition +Choke +Starter +Throttle +TrackerYaw +TrackerPitch +ThrottleLeft +ThrottleRight + + + + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + +0 10 +1 +Hz + + + + + +Disable +Enable + + + +1 +meters + + + + +20 2000 +50 +cm/s + + +100 1000 +1 +cm + + +0 1000 +50 +cm/s + + +0 500 +10 +cm/s + + +0 2000 +50 +cm/s + + +50 500 +10 +cm/s/s + + +50 500 +10 +cm/s/s + + +500 5000 +1 +cm/s/s/s + + +100 981 +1 +cm/s/s + + +25 250 +1 +cm/s/s + + + +Disable +Enable + + + + diff --git a/src/FirmwarePlugin/APM/APMParameterMetaData.cc b/src/FirmwarePlugin/APM/APMParameterMetaData.cc index 30032c2f26d8d9204b97cab5d55616a61b9ece0e..ac9a11fda88e0de49edfa2c5a391bd041960d692 100644 --- a/src/FirmwarePlugin/APM/APMParameterMetaData.cc +++ b/src/FirmwarePlugin/APM/APMParameterMetaData.cc @@ -39,22 +39,30 @@ QVariant APMParameterMetaData::_stringToTypedVariant(const QString& string, int convertTo = QVariant::Int; // keep compiler warning happy switch (type) { - case FactMetaData::valueTypeUint8: - case FactMetaData::valueTypeUint16: - case FactMetaData::valueTypeUint32: - convertTo = QVariant::UInt; - break; - case FactMetaData::valueTypeInt8: - case FactMetaData::valueTypeInt16: - case FactMetaData::valueTypeInt32: - convertTo = QVariant::Int; - break; - case FactMetaData::valueTypeFloat: - convertTo = QMetaType::Float; - break; - case FactMetaData::valueTypeDouble: - convertTo = QVariant::Double; - break; + case FactMetaData::valueTypeUint8: + case FactMetaData::valueTypeUint16: + case FactMetaData::valueTypeUint32: + convertTo = QVariant::UInt; + break; + case FactMetaData::valueTypeInt8: + case FactMetaData::valueTypeInt16: + case FactMetaData::valueTypeInt32: + convertTo = QVariant::Int; + break; + case FactMetaData::valueTypeFloat: + convertTo = QMetaType::Float; + break; + case FactMetaData::valueTypeDouble: + convertTo = QVariant::Double; + break; + case FactMetaData::valueTypeString: + qWarning() << "Internal Error: No support for string parameters"; + convertTo = QVariant::String; + break; + case FactMetaData::valueTypeBool: + qWarning() << "Internal Error: No support for string parameters"; + convertTo = QVariant::Bool; + break; } *convertOk = var.convert(convertTo); @@ -568,6 +576,15 @@ void APMParameterMetaData::addMetaDataToFact(Fact* fact, MAV_TYPE vehicleType) } } + // ArduPilot does not yet support decimal places meta data. So for P/I/D parameters we force to 6 places + if ((fact->name().endsWith(QStringLiteral("_P")) || + fact->name().endsWith(QStringLiteral("_I")) || + fact->name().endsWith(QStringLiteral("_D"))) && + (fact->type() == FactMetaData::valueTypeFloat || + fact->type() == FactMetaData::valueTypeDouble)) { + metaData->setDecimalPlaces(6); + } + fact->setMetaData(metaData); } diff --git a/src/FirmwarePlugin/APM/APMRallyPointManager.cc b/src/FirmwarePlugin/APM/APMRallyPointManager.cc index 8061f8e57433ae94f08aa7beb136568537934217..f25aaf3cc0362e7dff4b06c00f2eb6442da4cfdd 100644 --- a/src/FirmwarePlugin/APM/APMRallyPointManager.cc +++ b/src/FirmwarePlugin/APM/APMRallyPointManager.cc @@ -31,7 +31,7 @@ APMRallyPointManager::~APMRallyPointManager() void APMRallyPointManager::sendToVehicle(const QList& rgPoints) { - if (_vehicle->isOfflineEditingVehicle()) { + if (_vehicle->isOfflineEditingVehicle() || !rallyPointsSupported()) { return; } @@ -53,7 +53,7 @@ void APMRallyPointManager::sendToVehicle(const QList& rgPoints) void APMRallyPointManager::loadFromVehicle(void) { - if (_vehicle->isOfflineEditingVehicle() || _readTransactionInProgress) { + if (_vehicle->isOfflineEditingVehicle() || !rallyPointsSupported() || _readTransactionInProgress) { return; } @@ -90,7 +90,7 @@ void APMRallyPointManager::_mavlinkMessageReceived(const mavlink_message_t& mess QGeoCoordinate point((float)rallyPoint.lat / 1e7, (float)rallyPoint.lng / 1e7, rallyPoint.alt); _rgPoints.append(point); - if (rallyPoint.idx < _cReadRallyPoints - 2) { + if (rallyPoint.idx < _cReadRallyPoints - 1) { // Still more points to request _requestRallyPoint(++_currentRallyPoint); } else { @@ -144,3 +144,8 @@ bool APMRallyPointManager::inProgress(void) const { return _readTransactionInProgress || _writeTransactionInProgress; } + +bool APMRallyPointManager::rallyPointsSupported(void) const +{ + return _vehicle->parameterManager()->parameterExists(_vehicle->defaultComponentId(), _rallyTotalParam); +} diff --git a/src/FirmwarePlugin/APM/APMRallyPointManager.h b/src/FirmwarePlugin/APM/APMRallyPointManager.h index 80dc758c487ad8de060950a63d7e683bd4c8149c..4a5ac20672ef02bff5180a817632dbe98d8c5f35 100644 --- a/src/FirmwarePlugin/APM/APMRallyPointManager.h +++ b/src/FirmwarePlugin/APM/APMRallyPointManager.h @@ -25,7 +25,7 @@ public: bool inProgress (void) const final; void loadFromVehicle (void) final; void sendToVehicle (const QList& rgPoints) final; - bool rallyPointsSupported (void) const final { return true; } + bool rallyPointsSupported (void) const final; QString editorQml(void) const final { return QStringLiteral("qrc:/FirmwarePlugin/APM/APMRallyPointEditor.qml"); } diff --git a/src/FirmwarePlugin/APM/APMResources.qrc b/src/FirmwarePlugin/APM/APMResources.qrc new file mode 100644 index 0000000000000000000000000000000000000000..82e2bfc895dd89b42964196ea402bdf9fba608f6 --- /dev/null +++ b/src/FirmwarePlugin/APM/APMResources.qrc @@ -0,0 +1,59 @@ + + + ../../AutoPilotPlugins/APM/APMAirframeComponent.qml + ../../AutoPilotPlugins/APM/APMAirframeComponentSummary.qml + ../../AutoPilotPlugins/APM/APMCameraComponent.qml + ../../AutoPilotPlugins/APM/APMCameraComponentSummary.qml + ../../AutoPilotPlugins/APM/APMFlightModesComponent.qml + ../../AutoPilotPlugins/APM/APMFlightModesComponentSummary.qml + ../../AutoPilotPlugins/APM/APMLightsComponent.qml + ../../AutoPilotPlugins/APM/APMLightsComponentSummary.qml + ../../AutoPilotPlugins/APM/APMSubFrameComponent.qml + ../../AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml + ../../AutoPilotPlugins/APM/APMNotSupported.qml + ../../AutoPilotPlugins/APM/APMPowerComponent.qml + ../../AutoPilotPlugins/APM/APMPowerComponentSummary.qml + ../../AutoPilotPlugins/APM/APMRadioComponentSummary.qml + ../../AutoPilotPlugins/APM/APMSafetyComponentCopter.qml + ../../AutoPilotPlugins/APM/APMSafetyComponentPlane.qml + ../../AutoPilotPlugins/APM/APMSafetyComponentRover.qml + ../../AutoPilotPlugins/APM/APMSafetyComponentSub.qml + ../../AutoPilotPlugins/APM/APMSafetyComponentSummaryCopter.qml + ../../AutoPilotPlugins/APM/APMSafetyComponentSummaryPlane.qml + ../../AutoPilotPlugins/APM/APMSafetyComponentSummaryRover.qml + ../../AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml + ../../AutoPilotPlugins/APM/APMSensorsComponent.qml + ../../AutoPilotPlugins/APM/APMSensorsComponentSummary.qml + ../../AutoPilotPlugins/APM/APMTuningComponentCopter.qml + APMSensorParams.qml + QGroundControl.ArduPilot.qmldir + + + MavCmdInfoCommon.json + MavCmdInfoFixedWing.json + MavCmdInfoMultiRotor.json + MavCmdInfoRover.json + MavCmdInfoSub.json + MavCmdInfoVTOL.json + + + ../../AutoPilotPlugins/APM/APMAirframeFactMetaData.xml + + + APMParameterFactMetaData.Plane.3.3.xml + APMParameterFactMetaData.Plane.3.5.xml + APMParameterFactMetaData.Plane.3.7.xml + APMParameterFactMetaData.Plane.3.8.xml + APMParameterFactMetaData.Copter.3.3.xml + APMParameterFactMetaData.Copter.3.4.xml + APMParameterFactMetaData.Copter.3.5.xml + APMParameterFactMetaData.Rover.3.0.xml + APMParameterFactMetaData.Rover.3.2.xml + APMParameterFactMetaData.Sub.3.4.xml + APMParameterFactMetaData.Sub.3.5.xml + CopterGeoFenceEditor.qml + PlaneGeoFenceEditor.qml + Copter3.4.OfflineEditing.params + Plane3.7.OfflineEditing.params + + diff --git a/src/FirmwarePlugin/APM/APMSensorParams.qml b/src/FirmwarePlugin/APM/APMSensorParams.qml new file mode 100644 index 0000000000000000000000000000000000000000..217ba564dcaca1324ff69a8a9261049bde86d710 --- /dev/null +++ b/src/FirmwarePlugin/APM/APMSensorParams.qml @@ -0,0 +1,87 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.2 + +import QGroundControl.FactSystem 1.0 + +/// This is used to handle the various differences between firmware versions and missing parameters in each in a standard way. +Item { + property var factPanelController ///< Must be specified by consumer of control + + property Fact _noFact: Fact { } + + property Fact compassPrimaryFact: factPanelController.getParameterFact(-1, "COMPASS_PRIMARY") + property bool compass1Primary: compassPrimaryFact.rawValue == 0 + property bool compass2Primary: compassPrimaryFact.rawValue == 1 + property bool compass3Primary: compassPrimaryFact.rawValue == 2 + property var rgCompassPrimary: [ compass1Primary, compass2Primary, compass3Primary ] + + property Fact compass1Id: factPanelController.getParameterFact(-1, "COMPASS_DEV_ID") + property Fact compass2Id: factPanelController.getParameterFact(-1, "COMPASS_DEV_ID2") + property Fact compass3Id: factPanelController.getParameterFact(-1, "COMPASS_DEV_ID3") + + property bool compass1Available: compass1Id.value > 0 + property bool compass2Available: compass2Id.value > 0 + property bool compass3Available: compass3Id.value > 0 + property var rgCompassAvailable: [ compass1Available, compass2Available, compass3Available ] + + property bool compass1RotParamAvailable: factPanelController.parameterExists(-1, "COMPASS_ORIENT") + property bool compass2RotParamAvailable: factPanelController.parameterExists(-1, "COMPASS_ORIENT2") + property bool compass3RotParamAvailable: factPanelController.parameterExists(-1, "COMPASS_ORIENT3") + property var rgCompassRotParamAvailable: [ compass1RotParamAvailable, compass2RotParamAvailable, compass3RotParamAvailable ] + + property Fact compass1RotFact: compass2RotParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_ORIENT") : _noFact + property Fact compass2RotFact: compass2RotParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_ORIENT2") : _noFact + property Fact compass3RotFact: compass3RotParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_ORIENT3") : _noFact + property var rgCompassRotFact: [ compass1RotFact, compass2RotFact, compass3RotFact ] + + property bool compass1UseParamAvailable: factPanelController.parameterExists(-1, "COMPASS_USE") + property bool compass2UseParamAvailable: factPanelController.parameterExists(-1, "COMPASS_USE2") + property bool compass3UseParamAvailable: factPanelController.parameterExists(-1, "COMPASS_USE3") + property var rgCompassUseParamAvailable: [ compass1UseParamAvailable, compass2UseParamAvailable, compass3UseParamAvailable ] + + property Fact compass1UseFact: compass1UseParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_USE") : _noFact + property Fact compass2UseFact: compass2UseParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_USE2") : _noFact + property Fact compass3UseFact: compass3UseParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_USE3") : _noFact + property var rgCompassUseFact: [ compass1UseFact, compass2UseFact, compass3UseFact ] + + property bool compass1Use: compass1UseParamAvailable ? compass1UseFact.value : true + property bool compass2Use: compass2UseParamAvailable ? compass2UseFact.value : true + property bool compass3Use: compass3UseParamAvailable ? compass3UseFact.value : true + + property bool compass1ExternalParamAvailable: factPanelController.parameterExists(-1, "COMPASS_EXTERNAL") + property bool compass2ExternalParamAvailable: factPanelController.parameterExists(-1, "COMPASS_EXTERN2") + property bool compass3ExternalParamAvailable: factPanelController.parameterExists(-1, "COMPASS_EXTERN3") + property var rgCompassExternalParamAvailable: [ compass1ExternalParamAvailable, compass2ExternalParamAvailable, compass3ExternalParamAvailable ] + + property Fact compass1ExternalFact: compass1ExternalParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_EXTERNAL") : _noFact + property Fact compass2ExternalFact: compass2ExternalParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_EXTERN2") : _noFact + property Fact compass3ExternalFact: compass3ExternalParamAvailable ? factPanelController.getParameterFact(-1, "COMPASS_EXTERN3") : _noFact + + property bool compass1External: !!compass1ExternalFact.rawValue + property bool compass2External: !!compass2ExternalFact.rawValue + property bool compass3External: !!compass3ExternalFact.rawValue + property var rgCompassExternal: [ compass1External, compass2External, compass3External ] + + property Fact compass1OfsXFact: factPanelController.getParameterFact(-1, "COMPASS_OFS_X") + property Fact compass1OfsYFact: factPanelController.getParameterFact(-1, "COMPASS_OFS_Y") + property Fact compass1OfsZFact: factPanelController.getParameterFact(-1, "COMPASS_OFS_Z") + property Fact compass2OfsXFact: factPanelController.getParameterFact(-1, "COMPASS_OFS2_X") + property Fact compass2OfsYFact: factPanelController.getParameterFact(-1, "COMPASS_OFS2_Y") + property Fact compass2OfsZFact: factPanelController.getParameterFact(-1, "COMPASS_OFS2_Z") + property Fact compass3OfsXFact: factPanelController.getParameterFact(-1, "COMPASS_OFS3_X") + property Fact compass3OfsYFact: factPanelController.getParameterFact(-1, "COMPASS_OFS3_Y") + property Fact compass3OfsZFact: factPanelController.getParameterFact(-1, "COMPASS_OFS3_Z") + + property bool compass1Calibrated: compass1Available ? compass1OfsXFact.value != 0.0 && compass1OfsYFact.value != 0.0 &&compass1OfsZFact.value != 0.0 : false + property bool compass2Calibrated: compass2Available ? compass2OfsXFact.value != 0.0 && compass2OfsYFact.value != 0.0 &&compass2OfsZFact.value != 0.0 : false + property bool compass3Calibrated: compass3Available ? compass3OfsXFact.value != 0.0 && compass3OfsYFact.value != 0.0 &&compass3OfsZFact.value != 0.0 : false + property var rgCompassCalibrated: [ compass1Calibrated, compass2Calibrated, compass3Calibrated ] +} diff --git a/src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.cc b/src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.cc index d9bc3b4e8b22828a38a4fd53fe12b324ac2c3eab..3c3ef9e5ef05bb093a999ac3a4a0558a77377f01 100644 --- a/src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.cc +++ b/src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.cc @@ -67,36 +67,51 @@ ArduCopterFirmwarePlugin::ArduCopterFirmwarePlugin(void) setSupportedModes(supportedFlightModes); if (!_remapParamNameIntialized) { - FirmwarePlugin::remapParamNameMap_t& remap = _remapParamName[3][4]; - - remap["ATC_ANG_RLL_P"] = QStringLiteral("STB_RLL_P"); - remap["ATC_ANG_PIT_P"] = QStringLiteral("STB_PIT_P"); - remap["ATC_ANG_YAW_P"] = QStringLiteral("STB_YAW_P"); - - remap["ATC_RAT_RLL_P"] = QStringLiteral("RATE_RLL_P"); - remap["ATC_RAT_RLL_I"] = QStringLiteral("RATE_RLL_I"); - remap["ATC_RAT_RLL_IMAX"] = QStringLiteral("RATE_RLL_IMAX"); - remap["ATC_RAT_RLL_D"] = QStringLiteral("RATE_RLL_D"); - remap["ATC_RAT_RLL_FILT"] = QStringLiteral("RATE_RLL_FILT_HZ"); - - remap["ATC_RAT_PIT_P"] = QStringLiteral("RATE_PIT_P"); - remap["ATC_RAT_PIT_I"] = QStringLiteral("RATE_PIT_I"); - remap["ATC_RAT_PIT_IMAX"] = QStringLiteral("RATE_PIT_IMAX"); - remap["ATC_RAT_PIT_D"] = QStringLiteral("RATE_PIT_D"); - remap["ATC_RAT_PIT_FILT"] = QStringLiteral("RATE_PIT_FILT_HZ"); - - remap["ATC_RAT_YAW_P"] = QStringLiteral("RATE_YAW_P"); - remap["ATC_RAT_YAW_I"] = QStringLiteral("RATE_YAW_I"); - remap["ATC_RAT_YAW_IMAX"] = QStringLiteral("RATE_YAW_IMAX"); - remap["ATC_RAT_YAW_D"] = QStringLiteral("RATE_YAW_D"); - remap["ATC_RAT_YAW_FILT"] = QStringLiteral("RATE_YAW_FILT_HZ"); + FirmwarePlugin::remapParamNameMap_t& remapV3_4 = _remapParamName[3][4]; + + remapV3_4["ATC_ANG_RLL_P"] = QStringLiteral("STB_RLL_P"); + remapV3_4["ATC_ANG_PIT_P"] = QStringLiteral("STB_PIT_P"); + remapV3_4["ATC_ANG_YAW_P"] = QStringLiteral("STB_YAW_P"); + + remapV3_4["ATC_RAT_RLL_P"] = QStringLiteral("RATE_RLL_P"); + remapV3_4["ATC_RAT_RLL_I"] = QStringLiteral("RATE_RLL_I"); + remapV3_4["ATC_RAT_RLL_IMAX"] = QStringLiteral("RATE_RLL_IMAX"); + remapV3_4["ATC_RAT_RLL_D"] = QStringLiteral("RATE_RLL_D"); + remapV3_4["ATC_RAT_RLL_FILT"] = QStringLiteral("RATE_RLL_FILT_HZ"); + + remapV3_4["ATC_RAT_PIT_P"] = QStringLiteral("RATE_PIT_P"); + remapV3_4["ATC_RAT_PIT_I"] = QStringLiteral("RATE_PIT_I"); + remapV3_4["ATC_RAT_PIT_IMAX"] = QStringLiteral("RATE_PIT_IMAX"); + remapV3_4["ATC_RAT_PIT_D"] = QStringLiteral("RATE_PIT_D"); + remapV3_4["ATC_RAT_PIT_FILT"] = QStringLiteral("RATE_PIT_FILT_HZ"); + + remapV3_4["ATC_RAT_YAW_P"] = QStringLiteral("RATE_YAW_P"); + remapV3_4["ATC_RAT_YAW_I"] = QStringLiteral("RATE_YAW_I"); + remapV3_4["ATC_RAT_YAW_IMAX"] = QStringLiteral("RATE_YAW_IMAX"); + remapV3_4["ATC_RAT_YAW_D"] = QStringLiteral("RATE_YAW_D"); + remapV3_4["ATC_RAT_YAW_FILT"] = QStringLiteral("RATE_YAW_FILT_HZ"); + + FirmwarePlugin::remapParamNameMap_t& remapV3_5 = _remapParamName[3][5]; + + remapV3_5["SERVO5_FUNCTION"] = QStringLiteral("RC5_FUNCTION"); + remapV3_5["SERVO6_FUNCTION"] = QStringLiteral("RC6_FUNCTION"); + remapV3_5["SERVO7_FUNCTION"] = QStringLiteral("RC7_FUNCTION"); + remapV3_5["SERVO8_FUNCTION"] = QStringLiteral("RC8_FUNCTION"); + remapV3_5["SERVO9_FUNCTION"] = QStringLiteral("RC9_FUNCTION"); + remapV3_5["SERVO10_FUNCTION"] = QStringLiteral("RC10_FUNCTION"); + remapV3_5["SERVO11_FUNCTION"] = QStringLiteral("RC11_FUNCTION"); + remapV3_5["SERVO12_FUNCTION"] = QStringLiteral("RC12_FUNCTION"); + remapV3_5["SERVO13_FUNCTION"] = QStringLiteral("RC13_FUNCTION"); + remapV3_5["SERVO14_FUNCTION"] = QStringLiteral("RC14_FUNCTION"); + + _remapParamNameIntialized = true; } } int ArduCopterFirmwarePlugin::remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const { - // Remapping supports up to 3.4 - return majorVersionNumber == 3 ? 4: Vehicle::versionNotSetValue; + // Remapping supports up to 3.5 + return majorVersionNumber == 3 ? 5 : Vehicle::versionNotSetValue; } bool ArduCopterFirmwarePlugin::isCapable(const Vehicle* vehicle, FirmwareCapabilities capabilities) @@ -120,34 +135,11 @@ void ArduCopterFirmwarePlugin::guidedModeLand(Vehicle* vehicle) void ArduCopterFirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle, double altitudeRel) { - if (qIsNaN(vehicle->altitudeAMSL()->rawValue().toDouble())) { - qgcApp()->showMessage(QStringLiteral("Unable to takeoff, vehicle position not known.")); - return; - } - - mavlink_message_t msg; - mavlink_command_long_t cmd; - - cmd.command = (uint16_t)MAV_CMD_NAV_TAKEOFF; - cmd.confirmation = 0; - cmd.param1 = 0.0f; - cmd.param2 = 0.0f; - cmd.param3 = 0.0f; - cmd.param4 = 0.0f; - cmd.param5 = 0.0f; - cmd.param6 = 0.0f; - cmd.param7 = vehicle->altitudeAMSL()->rawValue().toFloat() + altitudeRel; // AMSL meters - cmd.target_system = vehicle->id(); - cmd.target_component = vehicle->defaultComponentId(); - - MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol(); - mavlink_msg_command_long_encode_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - vehicle->priorityLink()->mavlinkChannel(), - &msg, - &cmd); - - vehicle->sendMessageOnLink(vehicle->priorityLink(), msg); + vehicle->sendMavCommand(vehicle->defaultComponentId(), + MAV_CMD_NAV_TAKEOFF, + true, // show error + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + altitudeRel); } void ArduCopterFirmwarePlugin::guidedModeGotoLocation(Vehicle* vehicle, const QGeoCoordinate& gotoCoord) @@ -227,3 +219,8 @@ QString ArduCopterFirmwarePlugin::geoFenceRadiusParam(Vehicle* vehicle) Q_UNUSED(vehicle); return QStringLiteral("FENCE_RADIUS"); } + +QString ArduCopterFirmwarePlugin::takeControlFlightMode(void) +{ + return QStringLiteral("Stabilize"); +} diff --git a/src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h b/src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h index 3d43481a1494bcf65baf71bed4b42653dc88fa4c..9eb8e0d73a74c989c5c63c066ddfaeedb6627740 100644 --- a/src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h +++ b/src/FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h @@ -68,6 +68,7 @@ public: bool multiRotorXConfig(Vehicle* vehicle) final; QString geoFenceRadiusParam(Vehicle* vehicle) final; QString offlineEditingParamFile(Vehicle* vehicle) final { Q_UNUSED(vehicle); return QStringLiteral(":/FirmwarePlugin/APM/Copter.OfflineEditing.params"); } + QString takeControlFlightMode(void) final; private: static bool _remapParamNameIntialized; diff --git a/src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.cc b/src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.cc index 9fd499eee6ad4c0f47b021e5078d091fa605089f..88a380a1ba39243388e0855fd1dc50ab73faa6fc 100644 --- a/src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.cc +++ b/src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.cc @@ -7,12 +7,11 @@ * ****************************************************************************/ - -/// @file -/// @author Pritam Ghanghas - #include "ArduPlaneFirmwarePlugin.h" +bool ArduPlaneFirmwarePlugin::_remapParamNameIntialized = false; +FirmwarePlugin::remapParamNameMajorVersionMap_t ArduPlaneFirmwarePlugin::_remapParamName; + APMPlaneMode::APMPlaneMode(uint32_t mode, bool settable) : APMCustomMode(mode, settable) { @@ -63,4 +62,32 @@ ArduPlaneFirmwarePlugin::ArduPlaneFirmwarePlugin(void) supportedFlightModes << APMPlaneMode(APMPlaneMode::QLAND ,true); supportedFlightModes << APMPlaneMode(APMPlaneMode::QRTL ,true); setSupportedModes(supportedFlightModes); + + if (!_remapParamNameIntialized) { + FirmwarePlugin::remapParamNameMap_t& remapV3_8 = _remapParamName[3][8]; + + remapV3_8["SERVO5_FUNCTION"] = QStringLiteral("RC5_FUNCTION"); + remapV3_8["SERVO6_FUNCTION"] = QStringLiteral("RC6_FUNCTION"); + remapV3_8["SERVO7_FUNCTION"] = QStringLiteral("RC7_FUNCTION"); + remapV3_8["SERVO8_FUNCTION"] = QStringLiteral("RC8_FUNCTION"); + remapV3_8["SERVO9_FUNCTION"] = QStringLiteral("RC9_FUNCTION"); + remapV3_8["SERVO10_FUNCTION"] = QStringLiteral("RC10_FUNCTION"); + remapV3_8["SERVO11_FUNCTION"] = QStringLiteral("RC11_FUNCTION"); + remapV3_8["SERVO12_FUNCTION"] = QStringLiteral("RC12_FUNCTION"); + remapV3_8["SERVO13_FUNCTION"] = QStringLiteral("RC13_FUNCTION"); + remapV3_8["SERVO14_FUNCTION"] = QStringLiteral("RC14_FUNCTION"); + + _remapParamNameIntialized = true; + } +} + +int ArduPlaneFirmwarePlugin::remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const +{ + // Remapping supports up to 3.8 + return majorVersionNumber == 3 ? 8 : Vehicle::versionNotSetValue; +} + +QString ArduPlaneFirmwarePlugin::takeControlFlightMode(void) +{ + return QStringLiteral("Manual"); } diff --git a/src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.h b/src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.h index 111abf4fac86713a3e2c6b283ac7403c7c93dc03..3ec63a61adccd076e3ef781458c470a6f72383da 100644 --- a/src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.h +++ b/src/FirmwarePlugin/APM/ArduPlaneFirmwarePlugin.h @@ -57,6 +57,13 @@ public: // Overrides from FirmwarePlugin QString offlineEditingParamFile(Vehicle* vehicle) final { Q_UNUSED(vehicle); return QStringLiteral(":/FirmwarePlugin/APM/Plane.OfflineEditing.params"); } + QString takeControlFlightMode(void) final; + const FirmwarePlugin::remapParamNameMajorVersionMap_t& paramNameRemapMajorVersionMap(void) const final { return _remapParamName; } + int remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const final; + +private: + static bool _remapParamNameIntialized; + static FirmwarePlugin::remapParamNameMajorVersionMap_t _remapParamName; }; #endif diff --git a/src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.cc b/src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.cc index 5c4a57599e6e40a7f532cb0964decc0b4a9b72df..bbb7ed961e1155518bd6d6a17c87d2f326a768f2 100644 --- a/src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.cc +++ b/src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.cc @@ -7,12 +7,11 @@ * ****************************************************************************/ - -/// @file -/// @author Pritam Ghanghas - #include "ArduRoverFirmwarePlugin.h" +bool ArduRoverFirmwarePlugin::_remapParamNameIntialized = false; +FirmwarePlugin::remapParamNameMajorVersionMap_t ArduRoverFirmwarePlugin::_remapParamName; + APMRoverMode::APMRoverMode(uint32_t mode, bool settable) : APMCustomMode(mode, settable) { @@ -41,4 +40,28 @@ ArduRoverFirmwarePlugin::ArduRoverFirmwarePlugin(void) supportedFlightModes << APMRoverMode(APMRoverMode::GUIDED ,true); supportedFlightModes << APMRoverMode(APMRoverMode::INITIALIZING ,false); setSupportedModes(supportedFlightModes); + + if (!_remapParamNameIntialized) { + FirmwarePlugin::remapParamNameMap_t& remapV3_2 = _remapParamName[3][2]; + + remapV3_2["SERVO5_FUNCTION"] = QStringLiteral("RC5_FUNCTION"); + remapV3_2["SERVO6_FUNCTION"] = QStringLiteral("RC6_FUNCTION"); + remapV3_2["SERVO7_FUNCTION"] = QStringLiteral("RC7_FUNCTION"); + remapV3_2["SERVO8_FUNCTION"] = QStringLiteral("RC8_FUNCTION"); + remapV3_2["SERVO9_FUNCTION"] = QStringLiteral("RC9_FUNCTION"); + remapV3_2["SERVO10_FUNCTION"] = QStringLiteral("RC10_FUNCTION"); + remapV3_2["SERVO11_FUNCTION"] = QStringLiteral("RC11_FUNCTION"); + remapV3_2["SERVO12_FUNCTION"] = QStringLiteral("RC12_FUNCTION"); + remapV3_2["SERVO13_FUNCTION"] = QStringLiteral("RC13_FUNCTION"); + remapV3_2["SERVO14_FUNCTION"] = QStringLiteral("RC14_FUNCTION"); + + _remapParamNameIntialized = true; + } } + +int ArduRoverFirmwarePlugin::remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const +{ + // Remapping supports up to 3.2 + return majorVersionNumber == 3 ? 2 : Vehicle::versionNotSetValue; +} + diff --git a/src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.h b/src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.h index 78a43877e55ee5ab557dfcaff61b314a5029ec78..88e5e5272560a50678b4c2dd696e09a44e5348f9 100644 --- a/src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.h +++ b/src/FirmwarePlugin/APM/ArduRoverFirmwarePlugin.h @@ -49,6 +49,14 @@ class ArduRoverFirmwarePlugin : public APMFirmwarePlugin public: ArduRoverFirmwarePlugin(void); + + // Overrides from FirmwarePlugin + const FirmwarePlugin::remapParamNameMajorVersionMap_t& paramNameRemapMajorVersionMap(void) const final { return _remapParamName; } + int remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const final; + +private: + static bool _remapParamNameIntialized; + static FirmwarePlugin::remapParamNameMajorVersionMap_t _remapParamName; }; #endif diff --git a/src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc b/src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc index e6dd01b74a9bfe83e11dd580bb8c6a82a8156c36..5b0dd15a049a20feae7cdb1c16f1e73f506e0365 100644 --- a/src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc +++ b/src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc @@ -25,8 +25,9 @@ /// @author Rustom Jehangir #include "ArduSubFirmwarePlugin.h" -#include "QGCApplication.h" -#include "MissionManager.h" + +bool ArduSubFirmwarePlugin::_remapParamNameIntialized = false; +FirmwarePlugin::remapParamNameMajorVersionMap_t ArduSubFirmwarePlugin::_remapParamName; APMSubMode::APMSubMode(uint32_t mode, bool settable) : APMCustomMode(mode, settable) @@ -46,6 +47,29 @@ ArduSubFirmwarePlugin::ArduSubFirmwarePlugin(void) supportedFlightModes << APMSubMode(APMSubMode::STABILIZE ,true); supportedFlightModes << APMSubMode(APMSubMode::ALT_HOLD ,true); setSupportedModes(supportedFlightModes); + + if (!_remapParamNameIntialized) { + FirmwarePlugin::remapParamNameMap_t& remapV3_5 = _remapParamName[3][5]; + + remapV3_5["SERVO5_FUNCTION"] = QStringLiteral("RC5_FUNCTION"); + remapV3_5["SERVO6_FUNCTION"] = QStringLiteral("RC6_FUNCTION"); + remapV3_5["SERVO7_FUNCTION"] = QStringLiteral("RC7_FUNCTION"); + remapV3_5["SERVO8_FUNCTION"] = QStringLiteral("RC8_FUNCTION"); + remapV3_5["SERVO9_FUNCTION"] = QStringLiteral("RC9_FUNCTION"); + remapV3_5["SERVO10_FUNCTION"] = QStringLiteral("RC10_FUNCTION"); + remapV3_5["SERVO11_FUNCTION"] = QStringLiteral("RC11_FUNCTION"); + remapV3_5["SERVO12_FUNCTION"] = QStringLiteral("RC12_FUNCTION"); + remapV3_5["SERVO13_FUNCTION"] = QStringLiteral("RC13_FUNCTION"); + remapV3_5["SERVO14_FUNCTION"] = QStringLiteral("RC14_FUNCTION"); + + _remapParamNameIntialized = true; + } +} + +int ArduSubFirmwarePlugin::remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const +{ + // Remapping supports up to 3.5 + return majorVersionNumber == 3 ? 5 : Vehicle::versionNotSetValue; } int ArduSubFirmwarePlugin::manualControlReservedButtonCount(void) @@ -72,3 +96,13 @@ bool ArduSubFirmwarePlugin::supportsJSButton(void) { return true; } + +bool ArduSubFirmwarePlugin::supportsCalibratePressure(void) +{ + return true; +} + +bool ArduSubFirmwarePlugin::supportsMotorInterference(void) +{ + return false; +} diff --git a/src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.h b/src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.h index c79c2f186c11b93c4d1359c0889b2bf9822d5781..d44bacf43f5bb019047b6714d1e36b9acc7cdb3b 100644 --- a/src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.h +++ b/src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.h @@ -69,6 +69,8 @@ public: // Overrides from FirmwarePlugin int manualControlReservedButtonCount(void); + int defaultJoystickTXMode(void) final { return 3; } + bool supportsThrottleModeCenterZero(void); bool supportsManualControl(void); @@ -77,7 +79,17 @@ public: bool supportsJSButton(void); + bool supportsCalibratePressure(void); + + bool supportsMotorInterference(void); + QString brandImage(const Vehicle* vehicle) const { Q_UNUSED(vehicle); return QStringLiteral("/qmlimages/APM/BrandImageSub"); } + const FirmwarePlugin::remapParamNameMajorVersionMap_t& paramNameRemapMajorVersionMap(void) const final { return _remapParamName; } + int remapParamNameHigestMinorVersionNumber(int majorVersionNumber) const final; + +private: + static bool _remapParamNameIntialized; + static FirmwarePlugin::remapParamNameMajorVersionMap_t _remapParamName; }; #endif diff --git a/src/FirmwarePlugin/APM/CopterGeoFenceEditor.qml b/src/FirmwarePlugin/APM/CopterGeoFenceEditor.qml index f0da718fa250bf75a01a243f8bc267a193faf9c7..480d3213d31c662ad1eabad7fef12d64d04521c9 100644 --- a/src/FirmwarePlugin/APM/CopterGeoFenceEditor.qml +++ b/src/FirmwarePlugin/APM/CopterGeoFenceEditor.qml @@ -43,6 +43,8 @@ Column { width: editorColumn.width height: textField.height + property bool showCombo: modelData.enumStrings.length > 0 + QGCLabel { id: textFieldLabel anchors.baseline: textField.baseline @@ -55,7 +57,7 @@ Column { width: _editFieldWidth showUnits: true fact: modelData - visible: !comboField.visible + visible: !parent.showCombo } FactComboBox { @@ -63,8 +65,8 @@ Column { anchors.right: parent.right width: _editFieldWidth indexModel: false - fact: visible ? modelData : _nullFact - visible: modelData.enumStrings.length + fact: showCombo ? modelData : _nullFact + visible: parent.showCombo property var _nullFact: Fact { } } diff --git a/src/FirmwarePlugin/APM/QGroundControl.ArduPilot.qmldir b/src/FirmwarePlugin/APM/QGroundControl.ArduPilot.qmldir new file mode 100644 index 0000000000000000000000000000000000000000..54a0a5f365607f866b7881cf698f4931814d6b9a --- /dev/null +++ b/src/FirmwarePlugin/APM/QGroundControl.ArduPilot.qmldir @@ -0,0 +1,3 @@ +Module QGroundControl.ArduPilot + +APMSensorParams 1.0 APMSensorParams.qml diff --git a/src/FirmwarePlugin/FirmwarePlugin.cc b/src/FirmwarePlugin/FirmwarePlugin.cc index bbc3309695338b4e97c243046088728ca9ebebc5..5df28367dd5ac895caf761ce4dbd157ee6939649 100644 --- a/src/FirmwarePlugin/FirmwarePlugin.cc +++ b/src/FirmwarePlugin/FirmwarePlugin.cc @@ -7,14 +7,44 @@ * ****************************************************************************/ - #include "FirmwarePlugin.h" #include "QGCApplication.h" +#include "Generic/GenericAutoPilotPlugin.h" #include +static FirmwarePluginFactoryRegister* _instance = NULL; + const char* guided_mode_not_supported_by_vehicle = "Guided mode not supported by Vehicle."; +const char* FirmwarePlugin::px4FollowMeFlightMode = "Follow Me"; + +FirmwarePluginFactory::FirmwarePluginFactory(void) +{ + FirmwarePluginFactoryRegister::instance()->registerPluginFactory(this); +} + +QList FirmwarePluginFactory::supportedVehicleTypes(void) const +{ + QList vehicleTypes; + vehicleTypes << MAV_TYPE_FIXED_WING << MAV_TYPE_QUADROTOR << MAV_TYPE_VTOL_QUADROTOR << MAV_TYPE_GROUND_ROVER << MAV_TYPE_SUBMARINE; + return vehicleTypes; +} + +FirmwarePluginFactoryRegister* FirmwarePluginFactoryRegister::instance(void) +{ + if (!_instance) { + _instance = new FirmwarePluginFactoryRegister; + } + + return _instance; +} + +AutoPilotPlugin* FirmwarePlugin::autopilotPlugin(Vehicle* vehicle) +{ + return new GenericAutoPilotPlugin(vehicle, vehicle); +} + bool FirmwarePlugin::isCapable(const Vehicle *vehicle, FirmwareCapabilities capabilities) { Q_UNUSED(vehicle); @@ -83,6 +113,11 @@ int FirmwarePlugin::manualControlReservedButtonCount(void) return -1; } +int FirmwarePlugin::defaultJoystickTXMode(void) +{ + return 2; +} + bool FirmwarePlugin::supportsThrottleModeCenterZero(void) { // By default, this is supported @@ -99,6 +134,16 @@ bool FirmwarePlugin::supportsRadio(void) return true; } +bool FirmwarePlugin::supportsCalibratePressure(void) +{ + return false; +} + +bool FirmwarePlugin::supportsMotorInterference(void) +{ + return true; +} + bool FirmwarePlugin::supportsJSButton(void) { return false; @@ -259,3 +304,36 @@ int FirmwarePlugin::remapParamNameHigestMinorVersionNumber(int majorVersionNumbe Q_UNUSED(majorVersionNumber); return 0; } + +QString FirmwarePlugin::missionFlightMode(void) +{ + return QString(); +} + +QString FirmwarePlugin::rtlFlightMode(void) +{ + return QString(); +} + +QString FirmwarePlugin::takeControlFlightMode(void) +{ + return QString(); +} + +QString FirmwarePlugin::vehicleImageOpaque(const Vehicle* vehicle) const +{ + Q_UNUSED(vehicle); + return QStringLiteral("/qmlimages/vehicleArrowOpaque.svg"); +} + +QString FirmwarePlugin::vehicleImageOutline(const Vehicle* vehicle) const +{ + Q_UNUSED(vehicle); + return QStringLiteral("/qmlimages/vehicleArrowOutline.svg"); +} + +QString FirmwarePlugin::vehicleImageCompass(const Vehicle* vehicle) const +{ + Q_UNUSED(vehicle); + return QStringLiteral("/qmlimages/compassInstrumentArrow.svg"); +} diff --git a/src/FirmwarePlugin/FirmwarePlugin.h b/src/FirmwarePlugin/FirmwarePlugin.h index 6038748b66010a3523fd0c0338e0a5785bac2862..d9aa618034cfdaf461119d0f4be3d552b630b5b3 100644 --- a/src/FirmwarePlugin/FirmwarePlugin.h +++ b/src/FirmwarePlugin/FirmwarePlugin.h @@ -61,6 +61,9 @@ public: /// value: remapParamNameMinorVersionRemapMap_t entry typedef QMap remapParamNameMajorVersionMap_t; + /// @return The AutoPilotPlugin associated with this firmware plugin. Must be overriden. + virtual AutoPilotPlugin* autopilotPlugin(Vehicle* vehicle); + /// Called when Vehicle is first created to perform any firmware specific setup. virtual void initializeVehicle(Vehicle* vehicle); @@ -122,6 +125,15 @@ public: /// Command vehicle to change to the specified relatice altitude virtual void guidedModeChangeAltitude(Vehicle* vehicle, double altitudeRel); + /// Returns the flight mode for running missions + virtual QString missionFlightMode(void); + + /// Returns the flight mode for RTL + virtual QString rtlFlightMode(void); + + /// Returns the flight mode to use when the operator wants to take back control from autonomouse flight. + virtual QString takeControlFlightMode(void); + /// FIXME: This isn't quite correct being here. All code for Joystick suvehicleTypepport is currently firmware specific /// not just this. I'm going to try to change that. If not, this will need to be removed. /// Returns the number of buttons which are reserved for firmware use in the MANUAL_CONTROL mavlink @@ -130,6 +142,10 @@ public: /// @return -1: reserver all buttons, >0 number of buttons to reserve virtual int manualControlReservedButtonCount(void); + /// Default tx mode to apply to joystick axes + /// TX modes are as outlined here: http://www.rc-airplane-world.com/rc-transmitter-modes.html + virtual int defaultJoystickTXMode(void); + /// Returns true if the vehicle and firmware supports the use of a throttle joystick that /// is zero when centered. Typically not supported on vehicles that have bidirectional /// throttle. @@ -147,6 +163,14 @@ public: /// to be assigned via parameters in firmware. Default is false. virtual bool supportsJSButton(void); + /// Returns true if the firmware supports calibrating the pressure sensor so the altitude will read + /// zero at the current pressure. Default is false. + virtual bool supportsCalibratePressure(void); + + /// Returns true if the firmware supports calibrating motor interference offsets for the compass + /// (CompassMot). Default is true. + virtual bool supportsMotorInterference(void); + /// Called before any mavlink message is processed by Vehicle such that the firmwre plugin /// can adjust any message characteristics. This is handy to adjust or differences in mavlink /// spec implementations such that the base code can remain mavlink generic. @@ -171,9 +195,6 @@ public: /// false: Do not send first item to vehicle, sequence numbers must be adjusted virtual bool sendHomePositionToVehicle(void); - /// Returns the parameter that is used to identify the default component - virtual QString getDefaultComponentIdParam(void) const { return QString(); } - /// Returns the parameter which is used to identify the version number of parameter set virtual QString getVersionParam(void) { return QString(); } @@ -181,7 +202,7 @@ public: virtual void getParameterMetaDataVersionInfo(const QString& metaDataFile, int& majorVersion, int& minorVersion); /// Returns the internal resource parameter meta date file. - virtual QString internalParameterMetaDataFile(void) { return QString(); } + virtual QString internalParameterMetaDataFile(Vehicle* vehicle) { Q_UNUSED(vehicle); return QString(); } /// Loads the specified parameter meta data file. /// @return Opaque parameter meta data information which must be stored with Vehicle. Vehicle is responsible to @@ -225,6 +246,54 @@ public: /// Return the resource file which contains the brand image for the vehicle. virtual QString brandImage(const Vehicle* vehicle) const { Q_UNUSED(vehicle) return QString(); } + + /// Return the resource file which contains the vehicle icon used in the flight view when the view is dark (Satellite for instance) + virtual QString vehicleImageOpaque(const Vehicle* vehicle) const; + + /// Return the resource file which contains the vehicle icon used in the flight view when the view is light (Map for instance) + virtual QString vehicleImageOutline(const Vehicle* vehicle) const; + + /// Return the resource file which contains the vehicle icon used in the compass + virtual QString vehicleImageCompass(const Vehicle* vehicle) const; + + // FIXME: Hack workaround for non pluginize FollowMe support + static const char* px4FollowMeFlightMode; +}; + +class FirmwarePluginFactory : public QObject +{ + Q_OBJECT + +public: + FirmwarePluginFactory(void); + + /// Returns appropriate plugin for autopilot type. + /// @param autopilotType Type of autopilot to return plugin for. + /// @param vehicleType Vehicle type of autopilot to return plugin for. + /// @return Singleton FirmwarePlugin instance for the specified MAV_AUTOPILOT. + virtual FirmwarePlugin* firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType) = 0; + + /// @return List of firmware types this plugin supports. + virtual QList supportedFirmwareTypes(void) const = 0; + + /// @return List of vehicle types this plugin supports. + virtual QList supportedVehicleTypes(void) const; +}; + +class FirmwarePluginFactoryRegister : public QObject +{ + Q_OBJECT + +public: + static FirmwarePluginFactoryRegister* instance(void); + + /// Registers the specified logging category to the system. + void registerPluginFactory(FirmwarePluginFactory* pluginFactory) { _factoryList.append(pluginFactory); } + + QList pluginFactories(void) const { return _factoryList; } + +private: + QList _factoryList; }; #endif diff --git a/src/FirmwarePlugin/FirmwarePluginManager.cc b/src/FirmwarePlugin/FirmwarePluginManager.cc index b7ade237bbcb193c0389c4d4edf88b9beba441ec..6dd4264dc43a8632d71c49d71212471833b6e7fc 100644 --- a/src/FirmwarePlugin/FirmwarePluginManager.cc +++ b/src/FirmwarePlugin/FirmwarePluginManager.cc @@ -12,91 +12,82 @@ /// @author Don Gagne #include "FirmwarePluginManager.h" -#include "APM/ArduCopterFirmwarePlugin.h" -#include "APM/ArduPlaneFirmwarePlugin.h" -#include "APM/ArduRoverFirmwarePlugin.h" -#include "APM/ArduSubFirmwarePlugin.h" -#include "PX4/PX4FirmwarePlugin.h" +#include "FirmwarePlugin.h" FirmwarePluginManager::FirmwarePluginManager(QGCApplication* app) : QGCTool(app) - , _arduCopterFirmwarePlugin(NULL) - , _arduPlaneFirmwarePlugin(NULL) - , _arduRoverFirmwarePlugin(NULL) - , _arduSubFirmwarePlugin(NULL) , _genericFirmwarePlugin(NULL) - , _px4FirmwarePlugin(NULL) { } FirmwarePluginManager::~FirmwarePluginManager() { - delete _arduCopterFirmwarePlugin; - delete _arduPlaneFirmwarePlugin; - delete _arduRoverFirmwarePlugin; - delete _arduSubFirmwarePlugin; delete _genericFirmwarePlugin; - delete _px4FirmwarePlugin; } -QList FirmwarePluginManager::knownFirmwareTypes(void) const +QList FirmwarePluginManager::supportedFirmwareTypes(void) { - QList list; - list << MAV_AUTOPILOT_GENERIC << MAV_AUTOPILOT_PX4 << MAV_AUTOPILOT_ARDUPILOTMEGA; - return list; + if (_supportedFirmwareTypes.isEmpty()) { + QList factoryList = FirmwarePluginFactoryRegister::instance()->pluginFactories(); + for (int i = 0; i < factoryList.count(); i++) { + _supportedFirmwareTypes.append(factoryList[i]->supportedFirmwareTypes()); + } + _supportedFirmwareTypes.append(MAV_AUTOPILOT_GENERIC); + } + return _supportedFirmwareTypes; } -FirmwarePlugin* FirmwarePluginManager::firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType) +QList FirmwarePluginManager::supportedVehicleTypes(MAV_AUTOPILOT firmwareType) { - switch (autopilotType) { - case MAV_AUTOPILOT_ARDUPILOTMEGA: - switch (vehicleType) { - case MAV_TYPE_QUADROTOR: - case MAV_TYPE_HEXAROTOR: - case MAV_TYPE_OCTOROTOR: - case MAV_TYPE_TRICOPTER: - case MAV_TYPE_COAXIAL: - case MAV_TYPE_HELICOPTER: - if (!_arduCopterFirmwarePlugin) { - _arduCopterFirmwarePlugin = new ArduCopterFirmwarePlugin; - } - return _arduCopterFirmwarePlugin; - case MAV_TYPE_FIXED_WING: - if (!_arduPlaneFirmwarePlugin) { - _arduPlaneFirmwarePlugin = new ArduPlaneFirmwarePlugin; - } - return _arduPlaneFirmwarePlugin; - case MAV_TYPE_GROUND_ROVER: - case MAV_TYPE_SURFACE_BOAT: - if (!_arduRoverFirmwarePlugin) { - _arduRoverFirmwarePlugin = new ArduRoverFirmwarePlugin; - } - return _arduRoverFirmwarePlugin; - case MAV_TYPE_SUBMARINE: - if (!_arduSubFirmwarePlugin) { - _arduSubFirmwarePlugin = new ArduSubFirmwarePlugin; - } - return _arduSubFirmwarePlugin; - default: - break; - } - case MAV_AUTOPILOT_PX4: - if (!_px4FirmwarePlugin) { - _px4FirmwarePlugin = new PX4FirmwarePlugin; - } - return _px4FirmwarePlugin; - default: - break; + QList vehicleTypes; + + FirmwarePluginFactory* factory = _findPluginFactory(firmwareType); + + if (factory) { + vehicleTypes = factory->supportedVehicleTypes(); + } else if (firmwareType == MAV_AUTOPILOT_GENERIC) { + vehicleTypes << MAV_TYPE_FIXED_WING << MAV_TYPE_QUADROTOR << MAV_TYPE_VTOL_QUADROTOR << MAV_TYPE_GROUND_ROVER << MAV_TYPE_SUBMARINE; + } else { + qWarning() << "Request for unknown firmware plugin factory" << firmwareType; + } + + return vehicleTypes; +} + +FirmwarePlugin* FirmwarePluginManager::firmwarePluginForAutopilot(MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType) +{ + FirmwarePluginFactory* factory = _findPluginFactory(firmwareType); + FirmwarePlugin* plugin = NULL; + + if (factory) { + plugin = factory->firmwarePluginForAutopilot(firmwareType, vehicleType); + } else if (firmwareType != MAV_AUTOPILOT_GENERIC) { + qWarning() << "Request for unknown firmware plugin factory" << firmwareType; } - if (!_genericFirmwarePlugin) { - _genericFirmwarePlugin = new FirmwarePlugin; + if (!plugin) { + // Default plugin fallback + if (!_genericFirmwarePlugin) { + _genericFirmwarePlugin = new FirmwarePlugin; + } + plugin = _genericFirmwarePlugin; } - return _genericFirmwarePlugin; + + return plugin; } -void FirmwarePluginManager::clearSettings(void) +FirmwarePluginFactory* FirmwarePluginManager::_findPluginFactory(MAV_AUTOPILOT firmwareType) { - // FIXME: NYI + QList factoryList = FirmwarePluginFactoryRegister::instance()->pluginFactories(); + + // Find the plugin which supports this vehicle + for (int i=0; isupportedFirmwareTypes().contains(firmwareType)) { + return factory; + } + } + + return NULL; } diff --git a/src/FirmwarePlugin/FirmwarePluginManager.h b/src/FirmwarePlugin/FirmwarePluginManager.h index efdbb07c54b6acb663f18287ffd7d7bde2c79848..bc1607fe8157f04a4e92e7ecd5a4d7205261b263 100644 --- a/src/FirmwarePlugin/FirmwarePluginManager.h +++ b/src/FirmwarePlugin/FirmwarePluginManager.h @@ -21,11 +21,6 @@ #include "QGCToolbox.h" class QGCApplication; -class ArduCopterFirmwarePlugin; -class ArduPlaneFirmwarePlugin; -class ArduRoverFirmwarePlugin; -class ArduSubFirmwarePlugin; -class PX4FirmwarePlugin; /// FirmwarePluginManager is a singleton which is used to return the correct FirmwarePlugin for a MAV_AUTOPILOT type. @@ -37,24 +32,23 @@ public: FirmwarePluginManager(QGCApplication* app); ~FirmwarePluginManager(); - QList knownFirmwareTypes(void) const; + /// Returns list of firmwares which are supported by the system + QList supportedFirmwareTypes(void); + + /// Returns the list of supported vehicle types for the specified firmware + QList supportedVehicleTypes(MAV_AUTOPILOT firmwareType); /// Returns appropriate plugin for autopilot type. - /// @param autopilotType Type of autopilot to return plugin for. - /// @param vehicleType Vehicle type of autopilot to return plugin for. + /// @param firmwareType Type of firmwware to return plugin for. + /// @param vehicleType Vehicle type to return plugin for. /// @return Singleton FirmwarePlugin instance for the specified MAV_AUTOPILOT. - FirmwarePlugin* firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType); - - /// Clears settings from all firmware plugins. - void clearSettings(void); + FirmwarePlugin* firmwarePluginForAutopilot(MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType); private: - ArduCopterFirmwarePlugin* _arduCopterFirmwarePlugin; - ArduPlaneFirmwarePlugin* _arduPlaneFirmwarePlugin; - ArduRoverFirmwarePlugin* _arduRoverFirmwarePlugin; - ArduSubFirmwarePlugin* _arduSubFirmwarePlugin; - FirmwarePlugin* _genericFirmwarePlugin; - PX4FirmwarePlugin* _px4FirmwarePlugin; + FirmwarePluginFactory* _findPluginFactory(MAV_AUTOPILOT firmwareType); + + FirmwarePlugin* _genericFirmwarePlugin; + QList _supportedFirmwareTypes; }; #endif diff --git a/src/FirmwarePlugin/GeoFenceEditor.qml b/src/FirmwarePlugin/NoGeoFenceEditor.qml similarity index 100% rename from src/FirmwarePlugin/GeoFenceEditor.qml rename to src/FirmwarePlugin/NoGeoFenceEditor.qml diff --git a/src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json b/src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json index b595e720f191e84183988f38c40360eb81de929f..ebbc6516bd2c5efadd6c7ae5ffd4f3e686624b81 100644 --- a/src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json +++ b/src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json @@ -7,7 +7,13 @@ { "id": 21, "comment": "MAV_CMD_NAV_LAND", - "paramRemove": "1,4" + "paramRemove": "1,4", + "param7": { + "label": "Altitude:", + "units": "m", + "default": 0, + "decimalPlaces": 1 + } }, { "id": 22, diff --git a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc index 934774eeffd72502f67127b7096a18faed9c0111..f64b683f81959fa29fa41290701faee3fbe17924 100644 --- a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc +++ b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc @@ -14,65 +14,95 @@ #include "PX4FirmwarePlugin.h" #include "PX4ParameterMetaData.h" #include "QGCApplication.h" -#include "AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h" // FIXME: Hack +#include "PX4AutoPilotPlugin.h" +#include "PX4AdvancedFlightModesController.h" +#include "PX4SimpleFlightModesController.h" +#include "AirframeComponentController.h" +#include "SensorsComponentController.h" +#include "PowerComponentController.h" +#include "RadioComponentController.h" #include #include "px4_custom_mode.h" -struct Modes2Name { - uint8_t main_mode; - uint8_t sub_mode; - const char* name; ///< Name for flight mode - bool canBeSet; ///< true: Vehicle can be set to this flight mode - bool fixedWing; /// fixed wing compatible - bool multiRotor; /// multi rotor compatible -}; - -const char* PX4FirmwarePlugin::manualFlightMode = "Manual"; -const char* PX4FirmwarePlugin::altCtlFlightMode = "Altitude"; -const char* PX4FirmwarePlugin::posCtlFlightMode = "Position"; -const char* PX4FirmwarePlugin::missionFlightMode = "Mission"; -const char* PX4FirmwarePlugin::holdFlightMode = "Hold"; -const char* PX4FirmwarePlugin::takeoffFlightMode = "Takeoff"; -const char* PX4FirmwarePlugin::landingFlightMode = "Land"; -const char* PX4FirmwarePlugin::rtlFlightMode = "Return"; -const char* PX4FirmwarePlugin::acroFlightMode = "Acro"; -const char* PX4FirmwarePlugin::offboardFlightMode = "Offboard"; -const char* PX4FirmwarePlugin::stabilizedFlightMode = "Stabilized"; -const char* PX4FirmwarePlugin::rattitudeFlightMode = "Rattitude"; -const char* PX4FirmwarePlugin::followMeFlightMode = "Follow Me"; - -const char* PX4FirmwarePlugin::rtgsFlightMode = "Return to Groundstation"; - -const char* PX4FirmwarePlugin::readyFlightMode = "Ready"; // unused - -/// Tranlates from PX4 custom modes to flight mode names - -static const struct Modes2Name rgModes2Name[] = { - //main_mode sub_mode name canBeSet FW MC - { PX4_CUSTOM_MAIN_MODE_MANUAL, 0, PX4FirmwarePlugin::manualFlightMode, true, true, true }, - { PX4_CUSTOM_MAIN_MODE_STABILIZED, 0, PX4FirmwarePlugin::stabilizedFlightMode, true, true, true }, - { PX4_CUSTOM_MAIN_MODE_ACRO, 0, PX4FirmwarePlugin::acroFlightMode, true, false, true }, - { PX4_CUSTOM_MAIN_MODE_RATTITUDE, 0, PX4FirmwarePlugin::rattitudeFlightMode, true, false, true }, - { PX4_CUSTOM_MAIN_MODE_ALTCTL, 0, PX4FirmwarePlugin::altCtlFlightMode, true, true, true }, - { PX4_CUSTOM_MAIN_MODE_POSCTL, 0, PX4FirmwarePlugin::posCtlFlightMode, true, true, true }, - { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LOITER, PX4FirmwarePlugin::holdFlightMode, true, true, true }, - { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_MISSION, PX4FirmwarePlugin::missionFlightMode, true, true, true }, - { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTL, PX4FirmwarePlugin::rtlFlightMode, true, true, true }, - { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_FOLLOW_TARGET, PX4FirmwarePlugin::followMeFlightMode, true, true, true }, - { PX4_CUSTOM_MAIN_MODE_OFFBOARD, 0, PX4FirmwarePlugin::offboardFlightMode, true, true, true }, - // modes that can't be directly set by the user - { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LAND, PX4FirmwarePlugin::landingFlightMode, false, true, true }, - { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_READY, PX4FirmwarePlugin::readyFlightMode, false, true, true }, - { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTGS, PX4FirmwarePlugin::rtgsFlightMode, false, true, true }, - { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_TAKEOFF, PX4FirmwarePlugin::takeoffFlightMode, false, true, true }, -}; +const char* PX4FirmwarePlugin::_manualFlightMode = "Manual"; +const char* PX4FirmwarePlugin::_altCtlFlightMode = "Altitude"; +const char* PX4FirmwarePlugin::_posCtlFlightMode = "Position"; +const char* PX4FirmwarePlugin::_missionFlightMode = "Mission"; +const char* PX4FirmwarePlugin::_holdFlightMode = "Hold"; +const char* PX4FirmwarePlugin::_takeoffFlightMode = "Takeoff"; +const char* PX4FirmwarePlugin::_landingFlightMode = "Land"; +const char* PX4FirmwarePlugin::_rtlFlightMode = "Return"; +const char* PX4FirmwarePlugin::_acroFlightMode = "Acro"; +const char* PX4FirmwarePlugin::_offboardFlightMode = "Offboard"; +const char* PX4FirmwarePlugin::_stabilizedFlightMode = "Stabilized"; +const char* PX4FirmwarePlugin::_rattitudeFlightMode = "Rattitude"; +const char* PX4FirmwarePlugin::_followMeFlightMode = "Follow Me"; +const char* PX4FirmwarePlugin::_rtgsFlightMode = "Return to Groundstation"; +const char* PX4FirmwarePlugin::_readyFlightMode = "Ready"; +const char* PX4FirmwarePlugin::_simpleFlightMode = "Simple"; PX4FirmwarePlugin::PX4FirmwarePlugin(void) : _versionNotified(false) { + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "PX4AdvancedFlightModesController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "PX4SimpleFlightModesController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "AirframeComponentController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "SensorsComponentController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "PowerComponentController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "RadioComponentController"); + + struct Modes2Name { + uint8_t main_mode; + uint8_t sub_mode; + const char* name; ///< Name for flight mode + bool canBeSet; ///< true: Vehicle can be set to this flight mode + bool fixedWing; /// fixed wing compatible + bool multiRotor; /// multi rotor compatible + }; + + static const struct Modes2Name rgModes2Name[] = { + //main_mode sub_mode name canBeSet FW MC + { PX4_CUSTOM_MAIN_MODE_MANUAL, 0, PX4FirmwarePlugin::_manualFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_STABILIZED, 0, PX4FirmwarePlugin::_stabilizedFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_ACRO, 0, PX4FirmwarePlugin::_acroFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_RATTITUDE, 0, PX4FirmwarePlugin::_rattitudeFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_ALTCTL, 0, PX4FirmwarePlugin::_altCtlFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_POSCTL, 0, PX4FirmwarePlugin::_posCtlFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_SIMPLE, 0, PX4FirmwarePlugin::_simpleFlightMode, true, false, true }, + { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LOITER, PX4FirmwarePlugin::_holdFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_MISSION, PX4FirmwarePlugin::_missionFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTL, PX4FirmwarePlugin::_rtlFlightMode, true, true, true }, + { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_FOLLOW_TARGET, PX4FirmwarePlugin::_followMeFlightMode, true, false, true }, + { PX4_CUSTOM_MAIN_MODE_OFFBOARD, 0, PX4FirmwarePlugin::_offboardFlightMode, true, false, true }, + // modes that can't be directly set by the user + { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LAND, PX4FirmwarePlugin::_landingFlightMode, false, true, true }, + { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_READY, PX4FirmwarePlugin::_readyFlightMode, false, true, true }, + { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTGS, PX4FirmwarePlugin::_rtgsFlightMode, false, true, true }, + { PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_TAKEOFF, PX4FirmwarePlugin::_takeoffFlightMode, false, true, true }, + }; + + // Convert static information to dynamic list. This allows for plugin override class to manipulate list. + for (size_t i=0; imain_mode; + info.sub_mode = pModes2Name->sub_mode; + info.name = pModes2Name->name; + info.canBeSet = pModes2Name->canBeSet; + info.fixedWing = pModes2Name->fixedWing; + info.multiRotor = pModes2Name->multiRotor; + _flightModeInfoList.append(info); + } +} + +AutoPilotPlugin* PX4FirmwarePlugin::autopilotPlugin(Vehicle* vehicle) +{ + return new PX4AutoPilotPlugin(vehicle, vehicle); } QList PX4FirmwarePlugin::componentsForVehicle(AutoPilotPlugin* vehicle) @@ -86,18 +116,16 @@ QStringList PX4FirmwarePlugin::flightModes(Vehicle* vehicle) { QStringList flightModes; - for (size_t i=0; icanBeSet) { - bool fw = (vehicle->fixedWing() && pModes2Name->fixedWing); - bool mc = (vehicle->multiRotor() && pModes2Name->multiRotor); + foreach (const FlightModeInfo_t& info, _flightModeInfoList) { + if (info.canBeSet) { + bool fw = (vehicle->fixedWing() && info.fixedWing); + bool mc = (vehicle->multiRotor() && info.multiRotor); // show all modes for generic, vtol, etc bool other = !vehicle->fixedWing() && !vehicle->multiRotor(); if (fw || mc || other) { - flightModes += pModes2Name->name; + flightModes += info.name; } } } @@ -114,11 +142,9 @@ QString PX4FirmwarePlugin::flightMode(uint8_t base_mode, uint32_t custom_mode) c px4_mode.data = custom_mode; bool found = false; - for (size_t i=0; imain_mode == px4_mode.main_mode && pModes2Name->sub_mode == px4_mode.sub_mode) { - flightMode = pModes2Name->name; + foreach (const FlightModeInfo_t& info, _flightModeInfoList) { + if (info.main_mode == px4_mode.main_mode && info.sub_mode == px4_mode.sub_mode) { + flightMode = info.name; found = true; break; } @@ -140,15 +166,13 @@ bool PX4FirmwarePlugin::setFlightMode(const QString& flightMode, uint8_t* base_m *custom_mode = 0; bool found = false; - for (size_t i=0; iname, Qt::CaseInsensitive) == 0) { + foreach (const FlightModeInfo_t& info, _flightModeInfoList) { + if (flightMode.compare(info.name, Qt::CaseInsensitive) == 0) { union px4_custom_mode px4_mode; px4_mode.data = 0; - px4_mode.main_mode = pModes2Name->main_mode; - px4_mode.sub_mode = pModes2Name->sub_mode; + px4_mode.main_mode = info.main_mode; + px4_mode.sub_mode = info.sub_mode; *base_mode = MAV_MODE_FLAG_CUSTOM_MODE_ENABLED; *custom_mode = px4_mode.data; @@ -177,10 +201,11 @@ bool PX4FirmwarePlugin::supportsManualControl(void) bool PX4FirmwarePlugin::isCapable(const Vehicle *vehicle, FirmwareCapabilities capabilities) { - if(vehicle->multiRotor()) { + if (vehicle->multiRotor()) { return (capabilities & (MavCmdPreflightStorageCapability | GuidedModeCapability | SetFlightModeCapability | PauseVehicleCapability | OrbitModeCapability)) == capabilities; + } else { + return (capabilities & (MavCmdPreflightStorageCapability | GuidedModeCapability | SetFlightModeCapability | PauseVehicleCapability)) == capabilities; } - return (capabilities & (MavCmdPreflightStorageCapability | GuidedModeCapability | SetFlightModeCapability | PauseVehicleCapability)) == capabilities; } void PX4FirmwarePlugin::initializeVehicle(Vehicle* vehicle) @@ -241,7 +266,7 @@ QString PX4FirmwarePlugin::missionCommandOverrides(MAV_TYPE vehicleType) const return QStringLiteral(":/json/PX4/MavCmdInfoMultiRotor.json"); break; case MAV_TYPE_VTOL_QUADROTOR: - return QStringLiteral(":/json/APM/MavCmdInfoVTOL.json"); + return QStringLiteral(":/json/PX4/MavCmdInfoVTOL.json"); break; case MAV_TYPE_SUBMARINE: return QStringLiteral(":/json/PX4/MavCmdInfoSub.json"); @@ -266,171 +291,112 @@ QObject* PX4FirmwarePlugin::loadParameterMetaData(const QString& metaDataFile) void PX4FirmwarePlugin::pauseVehicle(Vehicle* vehicle) { - // then tell it to loiter at the current position - mavlink_message_t msg; - mavlink_command_long_t cmd; - - cmd.command = (uint16_t)MAV_CMD_DO_REPOSITION; - cmd.confirmation = 0; - cmd.param1 = -1.0f; - cmd.param2 = MAV_DO_REPOSITION_FLAGS_CHANGE_MODE; - cmd.param3 = 0.0f; - cmd.param4 = NAN; - cmd.param5 = NAN; - cmd.param6 = NAN; - cmd.param7 = NAN; - cmd.target_system = vehicle->id(); - cmd.target_component = vehicle->defaultComponentId(); - - MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol(); - mavlink_msg_command_long_encode_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - vehicle->priorityLink()->mavlinkChannel(), - &msg, - &cmd); - - vehicle->sendMessageOnLink(vehicle->priorityLink(), msg); + vehicle->sendMavCommand(vehicle->defaultComponentId(), + MAV_CMD_DO_REPOSITION, + true, // show error if failed + -1.0f, + MAV_DO_REPOSITION_FLAGS_CHANGE_MODE, + 0.0f, + NAN, + NAN, + NAN, + NAN); } void PX4FirmwarePlugin::guidedModeRTL(Vehicle* vehicle) { - vehicle->setFlightMode(rtlFlightMode); + vehicle->setFlightMode(_rtlFlightMode); } void PX4FirmwarePlugin::guidedModeLand(Vehicle* vehicle) { - vehicle->setFlightMode(landingFlightMode); + vehicle->setFlightMode(_landingFlightMode); } void PX4FirmwarePlugin::guidedModeOrbit(Vehicle* vehicle, const QGeoCoordinate& centerCoord, double radius, double velocity, double altitude) { - //-- If not in "guided" mode, make it so. - if(!isGuidedMode(vehicle)) + if (!isGuidedMode(vehicle)) { setGuidedMode(vehicle, true); - MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol(); - mavlink_message_t msg; - mavlink_command_long_t cmd; - cmd.command = (uint16_t)MAV_CMD_SET_GUIDED_SUBMODE_CIRCLE; - cmd.confirmation = 0; - cmd.param1 = radius; - cmd.param2 = velocity; - cmd.param3 = altitude; - cmd.param4 = NAN; - cmd.param5 = centerCoord.isValid() ? centerCoord.latitude() : NAN; - cmd.param6 = centerCoord.isValid() ? centerCoord.longitude() : NAN; - cmd.param7 = centerCoord.isValid() ? centerCoord.altitude() : NAN; - cmd.target_system = vehicle->id(); - cmd.target_component = vehicle->defaultComponentId(); - mavlink_msg_command_long_encode_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - vehicle->priorityLink()->mavlinkChannel(), - &msg, - &cmd); - vehicle->sendMessageOnLink(vehicle->priorityLink(), msg); + } + + vehicle->sendMavCommand(vehicle->defaultComponentId(), + MAV_CMD_SET_GUIDED_SUBMODE_CIRCLE, + true, // show error if fails + radius, + velocity, + altitude, + NAN, + centerCoord.isValid() ? centerCoord.latitude() : NAN, + centerCoord.isValid() ? centerCoord.longitude() : NAN, + centerCoord.isValid() ? centerCoord.altitude() : NAN); } void PX4FirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle, double altitudeRel) { Q_UNUSED(altitudeRel); if (qIsNaN(vehicle->altitudeAMSL()->rawValue().toDouble())) { - qgcApp()->showMessage(QStringLiteral("Unable to takeoff, vehicle position not known.")); + qgcApp()->showMessage(tr("Unable to takeoff, vehicle position not known.")); return; } - MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol(); - - // Set destination altitude - mavlink_message_t msg; - mavlink_command_long_t cmd; - - cmd.command = (uint16_t)MAV_CMD_NAV_TAKEOFF; - cmd.confirmation = 0; - cmd.param1 = -1.0f; - cmd.param2 = 0.0f; - cmd.param3 = 0.0f; - cmd.param4 = NAN; - cmd.param5 = NAN; - cmd.param6 = NAN; - cmd.param7 = vehicle->altitudeAMSL()->rawValue().toDouble() + altitudeRel; - cmd.target_system = vehicle->id(); - cmd.target_component = vehicle->defaultComponentId(); - - mavlink_msg_command_long_encode_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - vehicle->priorityLink()->mavlinkChannel(), - &msg, - &cmd); - vehicle->sendMessageOnLink(vehicle->priorityLink(), msg); + vehicle->sendMavCommand(vehicle->defaultComponentId(), + MAV_CMD_NAV_TAKEOFF, + true, // show error is fails + -1.0f, + 0.0f, + 0.0f, + NAN, + NAN, + NAN, + vehicle->altitudeAMSL()->rawValue().toDouble() + altitudeRel); } void PX4FirmwarePlugin::guidedModeGotoLocation(Vehicle* vehicle, const QGeoCoordinate& gotoCoord) { - if (qIsNaN(vehicle->altitudeRelative()->rawValue().toDouble())) { - qgcApp()->showMessage(QStringLiteral("Unable to go to location, vehicle position not known.")); + if (qIsNaN(vehicle->altitudeAMSL()->rawValue().toDouble())) { + qgcApp()->showMessage(tr("Unable to go to location, vehicle position not known.")); return; } - mavlink_message_t msg; - mavlink_command_long_t cmd; - - cmd.command = (uint16_t)MAV_CMD_DO_REPOSITION; - cmd.confirmation = 0; - cmd.param1 = -1.0f; - cmd.param2 = MAV_DO_REPOSITION_FLAGS_CHANGE_MODE; - cmd.param3 = 0.0f; - cmd.param4 = NAN; - cmd.param5 = gotoCoord.latitude(); - cmd.param6 = gotoCoord.longitude(); - cmd.param7 = vehicle->altitudeAMSL()->rawValue().toDouble(); - cmd.target_system = vehicle->id(); - cmd.target_component = vehicle->defaultComponentId(); - - MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol(); - mavlink_msg_command_long_encode_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - vehicle->priorityLink()->mavlinkChannel(), - &msg, - &cmd); - - vehicle->sendMessageOnLink(vehicle->priorityLink(), msg); + vehicle->sendMavCommand(vehicle->defaultComponentId(), + MAV_CMD_DO_REPOSITION, + true, // show error is fails + -1.0f, + MAV_DO_REPOSITION_FLAGS_CHANGE_MODE, + 0.0f, + NAN, + gotoCoord.latitude(), + gotoCoord.longitude(), + vehicle->altitudeAMSL()->rawValue().toFloat()); } void PX4FirmwarePlugin::guidedModeChangeAltitude(Vehicle* vehicle, double altitudeRel) { - if (qIsNaN(vehicle->altitudeRelative()->rawValue().toDouble())) { - qgcApp()->showMessage(QStringLiteral("Unable to change altitude, vehicle altitude not known.")); + if (!vehicle->homePositionAvailable()) { + qgcApp()->showMessage(tr("Unable to change altitude, home position unknown.")); + return; + } + if (qIsNaN(vehicle->homePosition().altitude())) { + qgcApp()->showMessage(tr("Unable to change altitude, home position altitude unknown.")); return; } - mavlink_message_t msg; - mavlink_command_long_t cmd; - - cmd.command = (uint16_t)MAV_CMD_DO_REPOSITION; - cmd.confirmation = 0; - cmd.param1 = -1.0f; - cmd.param2 = MAV_DO_REPOSITION_FLAGS_CHANGE_MODE; - cmd.param3 = 0.0f; - cmd.param4 = NAN; - cmd.param5 = NAN; - cmd.param6 = NAN; - cmd.param7 = vehicle->altitudeAMSL()->rawValue().toDouble() + altitudeRel; - cmd.target_system = vehicle->id(); - cmd.target_component = vehicle->defaultComponentId(); - - MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol(); - mavlink_msg_command_long_encode_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - vehicle->priorityLink()->mavlinkChannel(), - &msg, - &cmd); - - vehicle->sendMessageOnLink(vehicle->priorityLink(), msg); + vehicle->sendMavCommand(vehicle->defaultComponentId(), + MAV_CMD_DO_REPOSITION, + true, // show error is fails + -1.0f, + MAV_DO_REPOSITION_FLAGS_CHANGE_MODE, + 0.0f, + NAN, + NAN, + NAN, + vehicle->homePosition().altitude() + altitudeRel); } void PX4FirmwarePlugin::setGuidedMode(Vehicle* vehicle, bool guidedMode) { if (guidedMode) { - vehicle->setFlightMode(holdFlightMode); + vehicle->setFlightMode(_holdFlightMode); } else { pauseVehicle(vehicle); } @@ -439,8 +405,8 @@ void PX4FirmwarePlugin::setGuidedMode(Vehicle* vehicle, bool guidedMode) bool PX4FirmwarePlugin::isGuidedMode(const Vehicle* vehicle) const { // Not supported by generic vehicle - return (vehicle->flightMode() == holdFlightMode || vehicle->flightMode() == takeoffFlightMode - || vehicle->flightMode() == landingFlightMode); + return (vehicle->flightMode() == _holdFlightMode || vehicle->flightMode() == _takeoffFlightMode + || vehicle->flightMode() == _landingFlightMode); } bool PX4FirmwarePlugin::adjustIncomingMavlinkMessage(Vehicle* vehicle, mavlink_message_t* message) @@ -498,3 +464,18 @@ void PX4FirmwarePlugin::_handleAutopilotVersion(Vehicle* vehicle, mavlink_messag } } } + +QString PX4FirmwarePlugin::missionFlightMode(void) +{ + return QString(_missionFlightMode); +} + +QString PX4FirmwarePlugin::rtlFlightMode(void) +{ + return QString(_rtlFlightMode); +} + +QString PX4FirmwarePlugin::takeControlFlightMode(void) +{ + return QString(_manualFlightMode); +} diff --git a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h index 47f963e6d51531a191aefb0c1bdd97086040bd72..cdcba598d4c139087e333c9d9de1946f6762ed9e 100644 --- a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h +++ b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h @@ -28,56 +28,72 @@ public: // Overrides from FirmwarePlugin - QList componentsForVehicle(AutoPilotPlugin* vehicle) final; - QList supportedMissionCommands(void) final; + QList componentsForVehicle(AutoPilotPlugin* vehicle) override; + QList supportedMissionCommands(void) override; - bool isCapable (const Vehicle *vehicle, FirmwareCapabilities capabilities) final; - QStringList flightModes (Vehicle* vehicle) final; - QString flightMode (uint8_t base_mode, uint32_t custom_mode) const final; - bool setFlightMode (const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode) final; - void setGuidedMode (Vehicle* vehicle, bool guidedMode) final; - void pauseVehicle (Vehicle* vehicle) final; - void guidedModeRTL (Vehicle* vehicle) final; - void guidedModeLand (Vehicle* vehicle) final; - void guidedModeTakeoff (Vehicle* vehicle, double altitudeRel) final; - void guidedModeOrbit (Vehicle* vehicle, const QGeoCoordinate& centerCoord = QGeoCoordinate(), double radius = NAN, double velocity = NAN, double altitude = NAN) final; - void guidedModeGotoLocation (Vehicle* vehicle, const QGeoCoordinate& gotoCoord) final; - void guidedModeChangeAltitude (Vehicle* vehicle, double altitudeRel) final; - bool isGuidedMode (const Vehicle* vehicle) const; - int manualControlReservedButtonCount(void) final; - bool supportsManualControl (void) final; - void initializeVehicle (Vehicle* vehicle) final; - bool sendHomePositionToVehicle (void) final; - void addMetaDataToFact (QObject* parameterMetaData, Fact* fact, MAV_TYPE vehicleType) final; - QString getDefaultComponentIdParam (void) const final { return QString("SYS_AUTOSTART"); } - QString missionCommandOverrides (MAV_TYPE vehicleType) const final; - QString getVersionParam (void) final { return QString("SYS_PARAM_VER"); } - QString internalParameterMetaDataFile (void) final { return QString(":/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml"); } - void getParameterMetaDataVersionInfo (const QString& metaDataFile, int& majorVersion, int& minorVersion) final { PX4ParameterMetaData::getParameterMetaDataVersionInfo(metaDataFile, majorVersion, minorVersion); } - QObject* loadParameterMetaData (const QString& metaDataFile); - bool adjustIncomingMavlinkMessage (Vehicle* vehicle, mavlink_message_t* message); - GeoFenceManager* newGeoFenceManager (Vehicle* vehicle) { return new PX4GeoFenceManager(vehicle); } - QString offlineEditingParamFile(Vehicle* vehicle) final { Q_UNUSED(vehicle); return QStringLiteral(":/FirmwarePlugin/PX4/PX4.OfflineEditing.params"); } - QString brandImage (const Vehicle* vehicle) const { Q_UNUSED(vehicle); return QStringLiteral("/qmlimages/PX4/BrandImage"); } + AutoPilotPlugin* autopilotPlugin (Vehicle* vehicle) override; + bool isCapable (const Vehicle *vehicle, FirmwareCapabilities capabilities) override; + QStringList flightModes (Vehicle* vehicle) override; + QString flightMode (uint8_t base_mode, uint32_t custom_mode) const override; + bool setFlightMode (const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode) override; + void setGuidedMode (Vehicle* vehicle, bool guidedMode) override; + void pauseVehicle (Vehicle* vehicle) override; + void guidedModeRTL (Vehicle* vehicle) override; + void guidedModeLand (Vehicle* vehicle) override; + void guidedModeTakeoff (Vehicle* vehicle, double altitudeRel) override; + 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; + bool isGuidedMode (const Vehicle* vehicle) const override; + int manualControlReservedButtonCount(void) override; + bool supportsManualControl (void) override; + void initializeVehicle (Vehicle* vehicle) override; + bool sendHomePositionToVehicle (void) override; + void addMetaDataToFact (QObject* parameterMetaData, Fact* fact, 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); } + QObject* loadParameterMetaData (const QString& metaDataFile) final; + bool adjustIncomingMavlinkMessage (Vehicle* vehicle, mavlink_message_t* message) override; + GeoFenceManager* newGeoFenceManager (Vehicle* vehicle) override { return new PX4GeoFenceManager(vehicle); } + QString offlineEditingParamFile(Vehicle* vehicle) override { Q_UNUSED(vehicle); return QStringLiteral(":/FirmwarePlugin/PX4/PX4.OfflineEditing.params"); } + QString brandImage (const Vehicle* vehicle) const override { Q_UNUSED(vehicle); return QStringLiteral("/qmlimages/PX4/BrandImage"); } + QString missionFlightMode (void) override; + QString rtlFlightMode (void) override; + QString takeControlFlightMode (void) override; + // NOTE: For internal use only. Do not use in mainline QGC code. // Use these constants to set flight modes using setFlightMode method. Don't use hardcoded string names since the // names may change. + static const char* _manualFlightMode; + static const char* _acroFlightMode; + static const char* _stabilizedFlightMode; + static const char* _rattitudeFlightMode; + static const char* _altCtlFlightMode; + static const char* _posCtlFlightMode; + static const char* _offboardFlightMode; + static const char* _readyFlightMode; + static const char* _takeoffFlightMode; + static const char* _holdFlightMode; + static const char* _missionFlightMode; + static const char* _rtlFlightMode; + static const char* _landingFlightMode; + static const char* _rtgsFlightMode; + static const char* _followMeFlightMode; + static const char* _simpleFlightMode; - static const char* manualFlightMode; - static const char* acroFlightMode; - static const char* stabilizedFlightMode; - static const char* rattitudeFlightMode; - static const char* altCtlFlightMode; - static const char* posCtlFlightMode; - static const char* offboardFlightMode; - static const char* readyFlightMode; - static const char* takeoffFlightMode; - static const char* holdFlightMode; - static const char* missionFlightMode; - static const char* rtlFlightMode; - static const char* landingFlightMode; - static const char* rtgsFlightMode; - static const char* followMeFlightMode; +protected: + typedef struct { + uint8_t main_mode; + uint8_t sub_mode; + QString name; ///< Name for flight mode + bool canBeSet; ///< true: Vehicle can be set to this flight mode + bool fixedWing; /// fixed wing compatible + bool multiRotor; /// multi rotor compatible + } FlightModeInfo_t; + + QList _flightModeInfoList; private: void _handleAutopilotVersion(Vehicle* vehicle, mavlink_message_t* message); diff --git a/src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.cc b/src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.cc new file mode 100644 index 0000000000000000000000000000000000000000..9b667ee4536d5fde0630bc3ab15fd71a58985381 --- /dev/null +++ b/src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.cc @@ -0,0 +1,44 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +/// @file +/// @author Don Gagne + +#include "PX4FirmwarePluginFactory.h" +#include "PX4/PX4FirmwarePlugin.h" +PX4FirmwarePluginFactory PX4FirmwarePluginFactory; + +PX4FirmwarePluginFactory::PX4FirmwarePluginFactory(void) + : _pluginInstance(NULL) +{ + +} + +QList PX4FirmwarePluginFactory::supportedFirmwareTypes(void) const +{ + QList list; + + list.append(MAV_AUTOPILOT_PX4); + return list; +} + +FirmwarePlugin* PX4FirmwarePluginFactory::firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType) +{ + Q_UNUSED(vehicleType); + + if (autopilotType == MAV_AUTOPILOT_PX4) { + if (!_pluginInstance) { + _pluginInstance = new PX4FirmwarePlugin; + } + return _pluginInstance; + } + + return NULL; +} diff --git a/src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.h b/src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..4edbcef77dc7e761dd36dc565aa9a484679762fd --- /dev/null +++ b/src/FirmwarePlugin/PX4/PX4FirmwarePluginFactory.h @@ -0,0 +1,31 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef PX4FirmwarePluginFactory_H +#define PX4FirmwarePluginFactory_H + +#include "FirmwarePlugin.h" + +class PX4FirmwarePlugin; + +class PX4FirmwarePluginFactory : public FirmwarePluginFactory +{ + Q_OBJECT + +public: + PX4FirmwarePluginFactory(void); + + QList supportedFirmwareTypes (void) const final; + FirmwarePlugin* firmwarePluginForAutopilot (MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType) final; + +private: + PX4FirmwarePlugin* _pluginInstance; +}; + +#endif diff --git a/src/FirmwarePlugin/PX4/PX4GeoFenceManager.cc b/src/FirmwarePlugin/PX4/PX4GeoFenceManager.cc index c7b2251eaf32d8e0f483b67931d2a47690d5f5f5..063b428baaaf33a04d69096cf051923dc123491b 100644 --- a/src/FirmwarePlugin/PX4/PX4GeoFenceManager.cc +++ b/src/FirmwarePlugin/PX4/PX4GeoFenceManager.cc @@ -15,6 +15,7 @@ PX4GeoFenceManager::PX4GeoFenceManager(Vehicle* vehicle) : GeoFenceManager(vehicle) , _firstParamLoadComplete(false) + , _circleEnabled(false) , _circleRadiusFact(NULL) { connect(_vehicle->parameterManager(), &ParameterManager::parametersReadyChanged, this, &PX4GeoFenceManager::_parametersReady); @@ -57,10 +58,11 @@ void PX4GeoFenceManager::_parametersReady(void) emit paramsChanged(_params); emit paramLabelsChanged(_paramLabels); - emit circleSupportedChanged(circleSupported()); + _circleEnabled = true; + emit circleEnabledChanged(true); qCDebug(GeoFenceManagerLog) << "fenceSupported:circleSupported:polygonSupported:breachReturnSupported" << - fenceSupported() << circleSupported() << polygonSupported() << breachReturnSupported(); + _circleEnabled << polygonEnabled() << breachReturnEnabled(); } } @@ -76,14 +78,5 @@ float PX4GeoFenceManager::circleRadius(void) const void PX4GeoFenceManager::_circleRadiusRawValueChanged(QVariant value) { emit circleRadiusChanged(value.toFloat()); - emit circleSupportedChanged(circleSupported()); } -bool PX4GeoFenceManager::circleSupported(void) const -{ - if (_circleRadiusFact) { - return _circleRadiusFact->rawValue().toFloat() >= 0.0; - } - - return false; -} diff --git a/src/FirmwarePlugin/PX4/PX4GeoFenceManager.h b/src/FirmwarePlugin/PX4/PX4GeoFenceManager.h index fbeed77746d9198a7a98faf06182c7bebd9f7eab..b29cf1038f759d7f6aa6b45ba482efae1e2bda5c 100644 --- a/src/FirmwarePlugin/PX4/PX4GeoFenceManager.h +++ b/src/FirmwarePlugin/PX4/PX4GeoFenceManager.h @@ -23,12 +23,11 @@ public: ~PX4GeoFenceManager(); // Overrides from GeoFenceManager - bool fenceSupported (void) const final { return true; } - bool circleSupported (void) const final; - float circleRadius (void) const final; - QVariantList params (void) const final { return _params; } - QStringList paramLabels (void) const final { return _paramLabels; } - QString editorQml (void) const final { return QStringLiteral("qrc:/FirmwarePlugin/PX4/PX4GeoFenceEditor.qml"); } + bool circleEnabled (void) const final { return _circleEnabled; } + float circleRadius (void) const final; + QVariantList params (void) const final { return _params; } + QStringList paramLabels (void) const final { return _paramLabels; } + QString editorQml (void) const final { return QStringLiteral("qrc:/FirmwarePlugin/PX4/PX4GeoFenceEditor.qml"); } private slots: void _circleRadiusRawValueChanged(QVariant value); @@ -39,6 +38,7 @@ private: QVariantList _params; QStringList _paramLabels; + bool _circleEnabled; Fact* _circleRadiusFact; }; diff --git a/src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml b/src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml index 70b016f0768b29a5559fd7f40e4df8706d03d223..782fefd9208fe6268be5837227b358dc4b129f4b 100644 --- a/src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml +++ b/src/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml @@ -2,7 +2,7 @@ 3 1 - 9 + 14 Speed controller bandwidth @@ -137,57 +137,6 @@ 0 - - - Body angular rate process noise - examples/attitude_estimator_ekf - - - Body angular acceleration process noise - examples/attitude_estimator_ekf - - - Acceleration process noise - examples/attitude_estimator_ekf - - - Magnet field vector process noise - examples/attitude_estimator_ekf - - - Gyro measurement noise - examples/attitude_estimator_ekf - - - Accel measurement noise - examples/attitude_estimator_ekf - - - Mag measurement noise - examples/attitude_estimator_ekf - - - Moment of inertia matrix diagonal entry (1, 1) - kg*m^2 - examples/attitude_estimator_ekf - - - Moment of inertia matrix diagonal entry (2, 2) - kg*m^2 - examples/attitude_estimator_ekf - - - Moment of inertia matrix diagonal entry (3, 3) - kg*m^2 - examples/attitude_estimator_ekf - - - Moment of inertia enabled in estimator - If set to != 0 the moment of inertia will be used in the estimator - - examples/attitude_estimator_ekf - - Complimentary filter accelerometer weight @@ -255,13 +204,6 @@ velocity 3 modules/attitude_estimator_q - - Threshold (of RMS) to warn about high vibration levels - 0.01 - 10 - 2 - modules/attitude_estimator_q - @@ -339,7 +281,7 @@ velocity Critical threshold - Sets the threshold when the battery will be reported as critically low. This has to be lower than the low threshold. This threshold commonly will trigger RTL or landing. + Sets the threshold when the battery will be reported as critically low. This has to be lower than the low threshold. This threshold commonly will trigger RTL. 0.05 0.1 norm @@ -347,9 +289,19 @@ velocity 0.01 modules/systemlib + + Emergency threshold + Sets the threshold when the battery will be reported as dangerously low. This has to be lower than the critical threshold. This threshold commonly will trigger landing. + 0.03 + 0.07 + norm + 2 + 0.01 + modules/systemlib + Voltage drop per cell on full throttle - This implicitely defines the internal resistance to maximum current ratio and assumes linearity. A good value to use is the difference between the 5C and 20-25C load. + This implicitely defines the internal resistance to maximum current ratio and assumes linearity. A good value to use is the difference between the 5C and 20-25C load. Not used if BAT_R_INTERNAL is set. 0.07 0.5 V @@ -357,6 +309,14 @@ velocity 0.01 modules/systemlib + + Explicitly defines the per cell internal resistance + If non-negative, then this will be used in place of BAT_V_LOAD_DROP for all calculations. + -1.0 + 0.2 + Ohms + modules/systemlib + Number of cells Defines the number of cells the attached battery consists of. @@ -400,6 +360,7 @@ velocity drivers/camera_trigger GPIO + MAVLink (forward via MAV_CMD_IMAGE_START_CAPTURE) Seagull MAP2 (PWM) @@ -446,9 +407,9 @@ velocity Distance, mission controlled - + Camera trigger pin - Selects which pin is used, ranges from 1 to 6 (AUX1-AUX6 on px4fmu-v2 and the rail pins on px4fmu-v4). The PWM interface takes two pins per camera, while relay triggers on every pin individually. Example: Value 34 would trigger on pins 3 and 4. + Selects which pin is used, ranges from 1 to 6 (AUX1-AUX6 on px4fmu-v2 and the rail pins on px4fmu-v4). The PWM interface takes two pins per camera, while relay triggers on every pin individually. Example: Value 56 would trigger on pins 5 and 6. 1 123456 0 @@ -647,7 +608,7 @@ velocity Time-out for auto disarm after landing - A non-zero, positive value specifies the time-out period in seconds after which the vehicle will be automatically disarmed in case a landing situation has been detected during this period. A value of zero means that automatic disarming is disabled. + A non-zero, positive value specifies the time-out period in seconds after which the vehicle will be automatically disarmed in case a landing situation has been detected during this period. The vehicle will also auto-disarm right after arming if it has not even flown, however the time will be longer by a factor of 5. A value of zero means that automatic disarming is disabled. 0 20 s @@ -666,6 +627,17 @@ velocity Don't allow arming without GPS + + Arm switch is only a button + The default uses the arm switch as real switch. If parameter set button gets handled like stick arming. + 0 + 1 + modules/commander + + Arm switch is a button that only triggers arming and disarming + Arm switch is a switch that stays on when armed + + Battery failsafe mode Action the system takes on low battery. Defaults to off @@ -673,8 +645,9 @@ velocity 1 modules/commander - Return to Land + Return to land Warning + Return to land at critically low level, land at current position if reaching dangerously low levels Land at current position @@ -687,6 +660,78 @@ See COM_OBL_ACT and COM_OBL_RC_ACT to configure action 1 modules/commander + + Maximum EKF position innovation test ratio that will allow arming + 0.1 + 1.0 + m + 2 + 0.05 + modules/commander + + + Maximum EKF velocity innovation test ratio that will allow arming + 0.1 + 1.0 + m/s + 2 + 0.05 + modules/commander + + + Maximum EKF height innovation test ratio that will allow arming + 0.1 + 1.0 + m + 2 + 0.05 + modules/commander + + + Maximum EKF yaw innovation test ratio that will allow arming + 0.1 + 1.0 + rad + 2 + 0.05 + modules/commander + + + Maximum value of EKF accelerometer delta velocity bias estimate that will allow arming + 0.001 + 0.01 + m/s + 4 + 0.0005 + modules/commander + + + Maximum value of EKF gyro delta angle bias estimate that will allow arming + 0.0001 + 0.0017 + rad + 5 + 0.0001 + modules/commander + + + Maximum accelerometer inconsistency between IMU units that will allow arming + 0.1 + 1.0 + m/s/s + 2 + 0.05 + modules/commander + + + Maximum rate gyro inconsistency between IMU units that will allow arming + 0.02 + 0.2 + rad/s + 3 + 0.01 + modules/commander + @@ -775,6 +820,14 @@ See COM_OBL_ACT and COM_OBL_RC_ACT to configure action + + Minimum time of arrival delta between non-IMU observations before data is downsampled. +Baro and Magnetometer data will be averaged before downsampling, other data will be point sampled resulting in loss of information + 10 + 50 + ms + modules/ekf2 + Magnetometer measurement delay relative to IMU measurements 0 @@ -1015,6 +1068,14 @@ Assumes measurement is timestamped at trailing edge of integration period1 modules/ekf2 + + Noise for synthetic sideslip fusion + 0.1 + 1.0 + m/s + 2 + modules/ekf2 + Magnetic declination deg @@ -1313,7 +1374,13 @@ value will determine the minimum airspeed which will still be fused 1 modules/ekf2 - + + Boolean determining if synthetic sideslip measurements should fused + A value of 1 indicates that fusion is active + + modules/ekf2 + + Time constant of the velocity output prediction and smoothing filter 1.0 s @@ -1352,6 +1419,14 @@ value will determine the minimum airspeed which will still be fused 3 modules/ekf2 + + Range sensor pitch offset + -0.75 + 0.75 + rad + 3 + modules/ekf2 + @@ -1501,6 +1576,14 @@ value will determine the minimum airspeed which will still be fused 0.5 modules/fw_att_control + + Roll control to yaw control feedforward gain + This gain can be used to counteract the "adverse yaw" effect for fixed wings. When the plane enters a roll it will tend to yaw the nose out of the turn. This gain enables the use of a yaw actuator (rudder, airbrakes, ...) to counteract this effect. + 0.0 + 1 + 0.01 + modules/fw_att_control + Wheel steering rate proportional gain This defines how much the wheel steering input will be commanded depending on the current body angular rate error. @@ -1699,6 +1782,45 @@ value will determine the minimum airspeed which will still be fused 0.01 modules/fw_att_control + + Whether to scale throttle by battery power level + This compensates for voltage drop of the battery over time by attempting to normalize performance across the operating range of the battery. The fixed wing should constantly behave as if it was fully charged with reduced max thrust at lower battery percentages. i.e. if cruise speed is at 0.5 throttle at 100% battery, it will still be 0.5 at 60% battery. + + modules/fw_att_control + + + Acro body x max rate + This is the rate the controller is trying to achieve if the user applies full roll stick input in acro mode. + 45 + 720 + degrees + modules/fw_att_control + + + Acro body y max rate + This is the body y rate the controller is trying to achieve if the user applies full pitch stick input in acro mode. + 45 + 720 + degrees + modules/fw_att_control + + + Acro body z max rate + This is the body z rate the controller is trying to achieve if the user applies full yaw stick input in acro mode. + 10 + 180 + degrees + modules/fw_att_control + + + Threshold for Rattitude mode + Manual input needed in order to override attitude control rate setpoints and instead pass manual stick inputs as rate setpoints + 0.0 + 1.0 + 2 + 0.01 + modules/fw_att_control + @@ -1900,6 +2022,16 @@ value will determine the minimum airspeed which will still be fused + + Cruise Airspeed + The fixed wing controller tries to fly at this airspeed. + 0.0 + 40 + m/s + 1 + 0.5 + modules/navigator + Minimum Airspeed If the airspeed falls below this value, the TECS controller will try to increase airspeed more aggressively. @@ -2069,16 +2201,6 @@ value will determine the minimum airspeed which will still be fused 0.01 modules/fw_pos_control_l1 - - Cruise Airspeed - The fixed wing controller tries to fly at this airspeed. - 0.0 - 40 - m/s - 1 - 0.5 - modules/navigator - @@ -2181,6 +2303,7 @@ but also ignore less noise None Return to Land Loiter + Flight terminate @@ -2213,43 +2336,32 @@ but also ignore less noise 1 modules/navigator - + Max horizontal distance in meters - Set to > 0 to activate a geofence action if horizontal distance to home exceeds this value. - -1 - 5000 + Maximum horizontal distance in meters the vehicle can be from home before triggering a geofence action. Disabled if 0. + 0 + 10000 m 1 modules/navigator - + Max vertical distance in meters - Set to > 0 to activate a geofence action if vertical distance to home exceeds this value. - -1 + Maximum vertical distance in meters the vehicle can be from home before triggering a geofence action. Disabled if 0. + 0 + 10000 m 1 modules/navigator - - - Consider mount operation mode - If set to 1, mount mode will be enforced. - - drivers/gimbal - - - Auxiliary switch to set mount operation mode - Set to 0 to disable manual mode control. If set to an auxiliary switch: Switch off means the gimbal is put into safe/locked position. Switch on means the gimbal can move freely, and landing gear will be retracted if applicable. + + + Satellite radio read interval 0 - 3 - drivers/gimbal - - AUX1 - Disable - AUX3 - AUX2 - + 300 + s + drivers/iridiumsbd @@ -2283,6 +2395,14 @@ but also ignore less noise 2 modules/land_detector + + Multicopter sub-hover throttle scaling + The range between throttle_min and throttle_hover is scaled by this parameter to define how close to minimum throttle the current throttle value needs to be in order to get accepted as landed. + 0.05 + 0.5 + 2 + modules/land_detector + Multicopter free-fall trigger time Seconds (decimal) that freefall conditions have to met before triggering a freefall. Minimal value is limited by LAND_DETECTOR_UPDATE_RATE=50Hz in landDetector.h @@ -2292,6 +2412,14 @@ but also ignore less noise 2 modules/land_detector + + Manual flight stick down threshold for landing + When controlling manually the throttle stick value (0 to 1) has to be bellow this threshold in order to pass the check for landing. So if set to 1 it's allowed to land with any stick position. + 0 + 1 + 2 + modules/land_detector + Fixedwing max horizontal velocity Maximum horizontal velocity allowed in the landed state (m/s) @@ -2328,6 +2456,18 @@ but also ignore less noise 1 modules/land_detector + + Total flight time in microseconds + Total flight time of this autopilot. Higher 32 bits of the value. Flight time in microseconds = (LND_FLIGHT_T_HI << 32) | LND_FLIGHT_T_LO. + 0 + modules/land_detector + + + Total flight time in microseconds + Total flight time of this autopilot. Lower 32 bits of the value. Flight time in microseconds = (LND_FLIGHT_T_HI << 32) | LND_FLIGHT_T_LO. + 0 + modules/land_detector + @@ -2384,15 +2524,31 @@ but also ignore less noise 3 modules/local_position_estimator - - Optical flow xy standard deviation - 0.01 - 1 + + Optical flow scale + 0.1 + 10.0 m 3 modules/local_position_estimator - + + Optical flow rotation (roll/pitch) noise gain + 0.1 + 10.0 + m/s / (rad) + 3 + modules/local_position_estimator + + + Optical flow angular velocity noise gain + 0.0 + 10.0 + m/s / (rad/s) + 3 + modules/local_position_estimator + + Optical flow minimum quality threshold 0 255 @@ -2431,7 +2587,7 @@ but also ignore less noise 3 modules/local_position_estimator - + Accelerometer xy noise density Data sheet noise density = 150ug/sqrt(Hz) = 0.0015 m/s^2/sqrt(Hz) Larger than data sheet to account for tilt error. 0.00001 @@ -2440,7 +2596,7 @@ but also ignore less noise 4 modules/local_position_estimator - + Accelerometer z noise density Data sheet noise density = 150ug/sqrt(Hz) = 0.0015 m/s^2/sqrt(Hz) 0.00001 @@ -2452,16 +2608,11 @@ but also ignore less noise Barometric presssure altitude z standard deviation 0.01 - 3 + 100 m 2 modules/local_position_estimator - - Enables GPS data, also forces alt init with GPS - - modules/local_position_estimator - GPS delay compensaton 0 @@ -2519,7 +2670,16 @@ EPV used if greater than this value 3 modules/local_position_estimator - + + Vision delay compensaton + Set to zero to enable automatic compensation from measurement timestamps + 0 + 0.1 + sec + 2 + modules/local_position_estimator + + Vision xy standard deviation 0.01 1 @@ -2530,22 +2690,17 @@ EPV used if greater than this value Vision z standard deviation 0.01 - 2 + 100 m 3 modules/local_position_estimator - - Vision correction - - modules/local_position_estimator - - + Vicon position standard deviation - 0.01 + 0.0001 1 m - 3 + 4 modules/local_position_estimator @@ -2574,15 +2729,24 @@ EPV used if greater than this value 8 modules/local_position_estimator + + Terrain random walk noise density, hilly/outdoor (0.1), flat/Indoor (0.001) + 0 + 1 + (m/s)/(sqrt(hz)) + 3 + modules/local_position_estimator + - Terrain maximum percent grade, hilly/outdoor (100 = 45 deg), flat/Indoor (0 = 0 deg) + Terrain maximum percent grade, hilly/outdoor (100 = 45 deg), flat/Indoor (0 = 0 deg) +Used to calculate increased terrain random walk nosie due to movement 0 100 % 3 modules/local_position_estimator - + Flow gyro high pass filter cut off frequency 0 2 @@ -2590,7 +2754,14 @@ EPV used if greater than this value 3 modules/local_position_estimator - + + Enable publishing of a fake global position (e.g for AUTO missions using Optical Flow) +by initializing the estimator to the LPE_LAT/LON parameters when global information is unavailable + 0 + 1 + modules/local_position_estimator + + Local origin latitude for nav w/o GPS -90 90 @@ -2598,7 +2769,7 @@ EPV used if greater than this value 8 modules/local_position_estimator - + Local origin longitude for nav w/o GPS -180 180 @@ -2614,12 +2785,12 @@ EPV used if greater than this value 0 modules/local_position_estimator - - Required xy standard deviation to publish position - 0.3 - 5.0 - m - 1 + + Required velocity xy standard deviation to publish position + 0.01 + 1.0 + m/s + 3 modules/local_position_estimator @@ -2630,6 +2801,39 @@ EPV used if greater than this value 1 modules/local_position_estimator + + Land detector z standard deviation + 0.001 + 10.0 + m + 3 + modules/local_position_estimator + + + Land detector xy velocity standard deviation + 0.01 + 10.0 + m/s + 3 + modules/local_position_estimator + + + Integer bitmask controlling data fusion + Set bits in the following positions to enable: 0 : Set to true to fuse GPS data if available, also requires GPS for altitude init 1 : Set to true to fuse optical flow data if available 2 : Set to true to fuse vision position 3 : Set to true to fuse vision yaw 4 : Set to true to fuse land detector 5 : Set to true to publish AGL as local position down component 6 : Set to true to enable flow gyro compensation 7 : Set to true to enable baro fusion default (247, no vision yaw) + 0 + 255 + modules/local_position_estimator + + fuse GPS, requires GPS for alt. init + fuse optical flow + fuse vision position + fuse vision yaw + fuse land detector + pub agl as lpos down + flow gyro compensation + fuse baro + + @@ -2644,7 +2848,7 @@ EPV used if greater than this value 250 modules/mavlink - + MAVLink protocol version modules/mavlink @@ -2701,46 +2905,6 @@ EPV used if greater than this value drivers/mkblctrl - - - Low pass filter frequency for Gyro - platforms/qurt/fc_addon/mpu_spi - - MPU9X50_GYRO_LPF_184HZ - MPU9X50_GYRO_LPF_250HZ - MPU9X50_GYRO_LPF_41HZ - MPU9X50_GYRO_LPF_92HZ - MPU9X50_GYRO_LPF_10HZ - MPU9X50_GYRO_LPF_20HZ - MPU9X50_GYRO_LPF_3600HZ_NOLPF - MPU9X50_GYRO_LPF_5HZ - - - - Low pass filter frequency for Accelerometer - platforms/qurt/fc_addon/mpu_spi - - MPU9X50_ACC_LPF_184HZ - MPU9X50_ACC_LPF_460HZ - MPU9X50_ACC_LPF_41HZ - MPU9X50_ACC_LPF_92HZ - MPU9X50_ACC_LPF_10HZ - MPU9X50_ACC_LPF_20HZ - MPU9X50_ACC_LPF_460HZ_NOLPF - MPU9X50_ACC_LPF_5HZ - - - - Sample rate in Hz - platforms/qurt/fc_addon/mpu_spi - - MPU9x50_SAMPLE_RATE_200HZ - MPU9x50_SAMPLE_RATE_100HZ - MPU9x50_SAMPLE_RATE_1000HZ - MPU9x50_SAMPLE_RATE_500HZ - - - Set offboard loss failsafe mode @@ -2764,7 +2928,7 @@ EPV used if greater than this value Land at current position - + Take-off altitude This is the minimum altitude the system will take off to. 0 @@ -2848,8 +3012,13 @@ EPV used if greater than this value modules/navigator + + Enable weather-vane mode takeoff for missions + + modules/navigator + - Weather-vane mode for loiter mode + Weather-vane mode for loiter modules/navigator @@ -2902,6 +3071,9 @@ EPV used if greater than this value Disabled Land at current position Return to Land + Terminate + Data Link Auto Recovery (CASA Outback Challenge rules) + Lockdown @@ -2913,139 +3085,120 @@ EPV used if greater than this value Disabled Land at current position Return to Land + Terminate + RC Auto Recovery (CASA Outback Challenge rules) + Lockdown - - - - Roll P gain - Roll proportional gain, i.e. desired angular speed in rad/s for error 1 rad. - 0.0 - examples/mc_att_control_multiplatform - - - Roll rate P gain - Roll rate proportional gain, i.e. control output for angular speed error 1 rad/s. - 0.0 - examples/mc_att_control_multiplatform - - - Roll rate I gain - Roll rate integral gain. Can be set to compensate static thrust difference or gravity center offset. - 0.0 - examples/mc_att_control_multiplatform - - - Roll rate D gain - Roll rate differential gain. Small values help reduce fast oscillations. If value is too big oscillations will appear again. - 0.0 - examples/mc_att_control_multiplatform - - - Pitch P gain - Pitch proportional gain, i.e. desired angular speed in rad/s for error 1 rad. - 0.0 - 1/s - examples/mc_att_control_multiplatform - - - Pitch rate P gain - Pitch rate proportional gain, i.e. control output for angular speed error 1 rad/s. - 0.0 - examples/mc_att_control_multiplatform - - - Pitch rate I gain - Pitch rate integral gain. Can be set to compensate static thrust difference or gravity center offset. - 0.0 - examples/mc_att_control_multiplatform - - - Pitch rate D gain - Pitch rate differential gain. Small values help reduce fast oscillations. If value is too big oscillations will appear again. - 0.0 - examples/mc_att_control_multiplatform + + Force VTOL mode takeoff and land + + modules/navigator - - Yaw P gain - Yaw proportional gain, i.e. desired angular speed in rad/s for error 1 rad. - 0.0 - 1/s - examples/mc_att_control_multiplatform + + + + Mount input mode +RC uses the AUX input channels (see MNT_MAN_* parameters), +MAVLINK_ROI uses the MAV_CMD_DO_SET_ROI Mavlink message, and MAVLINK_DO_MOUNT the +MAV_CMD_DO_MOUNT_CONFIGURE and MAV_CMD_DO_MOUNT_CONTROL messages to control a mount + 0 + 3 + drivers/vmount + + RC + DISABLE + MAVLINK_DO_MOUNT + MAVLINK_ROI + - - Yaw rate P gain - Yaw rate proportional gain, i.e. control output for angular speed error 1 rad/s. - 0.0 - examples/mc_att_control_multiplatform + + Mount output mode +AUX uses the mixer output Control Group #2. +MAVLINK uses the MAV_CMD_DO_MOUNT_CONFIGURE and MAV_CMD_DO_MOUNT_CONTROL MavLink messages +to control a mount (set MNT_MAV_SYSID & MNT_MAV_COMPID) + 0 + 1 + drivers/vmount + + MAVLINK + AUX + - - Yaw rate I gain - Yaw rate integral gain. Can be set to compensate static thrust difference or gravity center offset. - 0.0 - examples/mc_att_control_multiplatform + + Mavlink System ID (if MNT_MODE_OUT is MAVLINK) + drivers/vmount - - Yaw rate D gain - Yaw rate differential gain. Small values help reduce fast oscillations. If value is too big oscillations will appear again. - 0.0 - examples/mc_att_control_multiplatform + + Mavlink Component ID (if MNT_MODE_OUT is MAVLINK) + drivers/vmount - - Yaw feed forward - Feed forward weight for manual yaw control. 0 will give slow responce and no overshot, 1 - fast responce and big overshot. - 0.0 + + Mixer value for selecting normal mode +if required by the gimbal (only in AUX output mode) + -1.0 1.0 - examples/mc_att_control_multiplatform - - - Max yaw rate - Limit for yaw rate, has effect for large rotations in autonomous mode, to avoid large control output and mixer saturation. - 0.0 - 360.0 - deg/s - examples/mc_att_control_multiplatform - - - Max acro roll rate - 0.0 - 360.0 - deg/s - examples/mc_att_control_multiplatform + 3 + drivers/vmount - - Max acro pitch rate - 0.0 - 360.0 - deg/s - examples/mc_att_control_multiplatform + + Mixer value for selecting a locking mode +if required for the gimbal (only in AUX output mode) + -1.0 + 1.0 + 3 + drivers/vmount - - Max acro yaw rate - 0.0 - deg/s - examples/mc_att_control_multiplatform + + This enables the mount to be manually controlled when no ROI is set + If set to 1, the mount will be controlled by the AUX channels below when no ROI is set. + + drivers/vmount - - Max manual roll - 0.0 - 90.0 - deg - examples/mc_pos_control_multiplatform + + Auxiliary channel to control roll (in AUX input or manual mode) + 0 + 5 + drivers/vmount + + AUX1 + Disable + AUX3 + AUX2 + AUX5 + AUX4 + - - Max manual pitch - 0.0 - 90.0 - deg - examples/mc_pos_control_multiplatform + + Auxiliary channel to control pitch (in AUX input or manual mode) + 0 + 5 + drivers/vmount + + AUX1 + Disable + AUX3 + AUX2 + AUX5 + AUX4 + - - Max manual yaw rate - 0.0 - deg/s - examples/mc_pos_control_multiplatform + + Auxiliary channel to control yaw (in AUX input or manual mode) + 0 + 5 + drivers/vmount + + AUX1 + Disable + AUX3 + AUX2 + AUX5 + AUX4 + + + Roll time constant Reduce if the system is too twitchy, increase if the response is too slow and sluggish. @@ -3071,6 +3224,7 @@ EPV used if greater than this value Roll proportional gain, i.e. desired angular speed in rad/s for error 1 rad. 0.0 8 + 1/s 2 0.1 modules/mc_att_control @@ -3092,6 +3246,14 @@ EPV used if greater than this value 0.01 modules/mc_att_control + + Roll rate integrator limit + Roll rate integrator limit. Can be set to increase the amount of integrator available to counteract disturbances or reduced to improve settling time after large roll moment trim changes. + 0.0 + 2 + 0.01 + modules/mc_att_control + Roll rate D gain Roll rate differential gain. Small values help reduce fast oscillations. If value is too big oscillations will appear again. @@ -3115,7 +3277,7 @@ EPV used if greater than this value 10 1/s 2 - 0.0005 + 0.1 modules/mc_att_control @@ -3135,6 +3297,14 @@ EPV used if greater than this value 0.01 modules/mc_att_control + + Pitch rate integrator limit + Pitch rate integrator limit. Can be set to increase the amount of integrator available to counteract disturbances or reduced to improve settling time after large pitch moment trim changes. + 0.0 + 2 + 0.01 + modules/mc_att_control + Pitch rate D gain Pitch rate differential gain. Small values help reduce fast oscillations. If value is too big oscillations will appear again. @@ -3177,6 +3347,14 @@ EPV used if greater than this value 0.01 modules/mc_att_control + + Yaw rate integrator limit + Yaw rate integrator limit. Can be set to increase the amount of integrator available to counteract disturbances or reduced to improve settling time after large yaw moment trim changes. + 0.0 + 2 + 0.01 + modules/mc_att_control + Yaw rate D gain Yaw rate differential gain. Small values help reduce fast oscillations. If value is too big oscillations will appear again. @@ -3269,7 +3447,7 @@ EPV used if greater than this value 5 modules/mc_att_control - + Threshold for Rattitude mode Manual input needed in order to override attitude control rate setpoints and instead pass manual stick inputs as rate setpoints 0.0 @@ -3278,114 +3456,68 @@ EPV used if greater than this value 0.01 modules/mc_att_control - - - - Minimum thrust - Minimum vertical thrust. It's recommended to set it > 0 to avoid free fall with zero thrust. - 0.0 - 1.0 - examples/mc_pos_control_multiplatform + + Battery power level scaler + This compensates for voltage drop of the battery over time by attempting to normalize performance across the operating range of the battery. The copter should constantly behave as if it was fully charged with reduced max acceleration at lower battery percentages. i.e. if hover is at 0.5 throttle at 100% battery, it will still be 0.5 at 60% battery. + + modules/mc_att_control - - Maximum thrust - Limit max allowed thrust. + + TPA P Breakpoint + Throttle PID Attenuation (TPA) Magnitude of throttle setpoint at which to begin attenuating roll/pitch P gain 0.0 1.0 - examples/mc_pos_control_multiplatform - - - Proportional gain for vertical position error - 0.0 - examples/mc_pos_control_multiplatform - - - Proportional gain for vertical velocity error - 0.0 - examples/mc_pos_control_multiplatform - - - Integral gain for vertical velocity error - Non zero value allows hovering thrust estimation on stabilized or autonomous takeoff. - 0.0 - examples/mc_pos_control_multiplatform - - - Differential gain for vertical velocity error - 0.0 - examples/mc_pos_control_multiplatform - - - Maximum vertical velocity - Maximum vertical velocity in AUTO mode and endpoint for stabilized modes (ALTCTRL). - 0.0 - m/s - examples/mc_pos_control_multiplatform + 2 + 0.1 + modules/mc_att_control - - Vertical velocity feed forward - Feed forward weight for altitude control in stabilized modes (ALTCTRL). 0 will give slow responce and no overshot, 1 - fast responce and big overshot. + + TPA I Breakpoint + Throttle PID Attenuation (TPA) Magnitude of throttle setpoint at which to begin attenuating roll/pitch I gain 0.0 1.0 - examples/mc_pos_control_multiplatform - - - Proportional gain for horizontal position error - 0.0 - examples/mc_pos_control_multiplatform - - - Proportional gain for horizontal velocity error - 0.0 - examples/mc_pos_control_multiplatform - - - Integral gain for horizontal velocity error - Non-zero value allows to resist wind. - 0.0 - examples/mc_pos_control_multiplatform - - - Differential gain for horizontal velocity error. Small values help reduce fast oscillations. If value is too big oscillations will appear again - 0.0 - examples/mc_pos_control_multiplatform - - - Maximum horizontal velocity - Maximum horizontal velocity in AUTO mode and endpoint for position stabilized mode (POSCTRL). - 0.0 - m/s - examples/mc_pos_control_multiplatform + 2 + 0.1 + modules/mc_att_control - - Horizontal velocity feed forward - Feed forward weight for position control in position control mode (POSCTRL). 0 will give slow responce and no overshot, 1 - fast responce and big overshot. + + TPA D Breakpoint + Throttle PID Attenuation (TPA) Magnitude of throttle setpoint at which to begin attenuating roll/pitch D gain 0.0 1.0 - examples/mc_pos_control_multiplatform + 2 + 0.1 + modules/mc_att_control - - Maximum tilt angle in air - Limits maximum tilt in AUTO and POSCTRL modes during flight. + + TPA Rate P + Throttle PID Attenuation (TPA) Rate at which to attenuate roll/pitch P gain Attenuation factor is 1.0 when throttle magnitude is below the setpoint Above the setpoint, the attenuation factor is (1 - rate * (throttle - breakpoint) / (1.0 - breakpoint)) 0.0 - 90.0 - deg - examples/mc_pos_control_multiplatform + 1.0 + 2 + 0.05 + modules/mc_att_control - - Maximum tilt during landing - Limits maximum tilt angle on landing. + + TPA Rate I + Throttle PID Attenuation (TPA) Rate at which to attenuate roll/pitch I gain Attenuation factor is 1.0 when throttle magnitude is below the setpoint Above the setpoint, the attenuation factor is (1 - rate * (throttle - breakpoint) / (1.0 - breakpoint)) 0.0 - 90.0 - deg - examples/mc_pos_control_multiplatform + 1.0 + 2 + 0.05 + modules/mc_att_control - - Landing descend rate + + TPA Rate D + Throttle PID Attenuation (TPA) Rate at which to attenuate roll/pitch D gain Attenuation factor is 1.0 when throttle magnitude is below the setpoint Above the setpoint, the attenuation factor is (1 - rate * (throttle - breakpoint) / (1.0 - breakpoint)) 0.0 - m/s - examples/mc_pos_control_multiplatform + 1.0 + 2 + 0.05 + modules/mc_att_control + + Minimum thrust in auto thrust control It's recommended to set it > 0 to avoid free fall with zero thrust. @@ -3636,6 +3768,13 @@ EPV used if greater than this value 2 modules/mc_pos_control + + Deadzone of Z stick where altitude hold is enabled + 0.0 + 1.0 + 2 + modules/mc_pos_control + Maximum horizontal velocity for which position hold is enabled (use 0 to disable check) 0.0 @@ -3669,6 +3808,24 @@ EPV used if greater than this value 1 modules/mc_pos_control + + Maximum vertical acceleration in velocity controlled modes upward + 2.0 + 15.0 + m/s/s + 2 + 1 + modules/mc_pos_control + + + Maximum vertical acceleration in velocity controlled modes down + 2.0 + 15.0 + m/s/s + 2 + 1 + modules/mc_pos_control + Altitude control mode, note mode 1 only tested with LPE 0 @@ -3679,6 +3836,18 @@ EPV used if greater than this value Altitude following + + Manual control stick exponential curve sensitivity attenuation with small velocity setpoints + The higher the value the less sensitivity the stick has around zero while still reaching the maximum value with full stick deflection. + 0 + 1 + 2 + modules/mc_pos_control + + Purely cubic input curve + Purely linear input curve (default) + + @@ -3723,71 +3892,66 @@ EPV used if greater than this value true drivers/px4fmu - - Invert direction of main output channel 1 - Set to 1 to invert the channel, 0 for default direction. - - true - drivers/px4io + + Trim value for FMU PWM output channel 1 + Set to normalized offset + -0.2 + 0.2 + 2 + drivers/px4fmu - - Invert direction of main output channel 2 - Set to 1 to invert the channel, 0 for default direction. - - true - drivers/px4io + + Trim value for FMU PWM output channel 2 + Set to normalized offset + -0.2 + 0.2 + 2 + drivers/px4fmu - - Invert direction of main output channel 3 - Set to 1 to invert the channel, 0 for default direction. - - true - drivers/px4io - - - Invert direction of main output channel 4 - Set to 1 to invert the channel, 0 for default direction. - - true - drivers/px4io + + Trim value for FMU PWM output channel 3 + Set to normalized offset + -0.2 + 0.2 + 2 + drivers/px4fmu - - Invert direction of main output channel 5 - Set to 1 to invert the channel, 0 for default direction. - - true - drivers/px4io + + Trim value for FMU PWM output channel 4 + Set to normalized offset + -0.2 + 0.2 + 2 + drivers/px4fmu - - Invert direction of main output channel 6 - Set to 1 to invert the channel, 0 for default direction. - - true - drivers/px4io + + Trim value for FMU PWM output channel 5 + Set to normalized offset + -0.2 + 0.2 + 2 + drivers/px4fmu - - Invert direction of main output channel 7 - Set to 1 to invert the channel, 0 for default direction. - - true - drivers/px4io + + Trim value for FMU PWM output channel 6 + Set to normalized offset + -0.2 + 0.2 + 2 + drivers/px4fmu - - Invert direction of main output channel 8 - Set to 1 to invert the channel, 0 for default direction. - + + Set the PWM output frequency for the main outputs + IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. Set to 400 for industry default or 1000 for high frequency ESCs. + -1 + 2000 + Hz true - drivers/px4io - - - S.BUS out - Set to 1 to enable S.BUS version 1 output instead of RSSI. - - drivers/px4io + modules/sensors - Set the minimum PWM for the MAIN outputs - IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. COMPLETELY POWER-CYCLE THE SYSTEM TO PUT CHANGES INTO EFFECT. Set to 1000 for industry default or 900 to increase servo travel. + Set the minimum PWM for the main outputs + IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. Set to 1000 for industry default or 900 to increase servo travel. 800 1400 us @@ -3795,17 +3959,17 @@ EPV used if greater than this value modules/sensors - Set the maximum PWM for the MAIN outputs - IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. COMPLETELY POWER-CYCLE THE SYSTEM TO PUT CHANGES INTO EFFECT. Set to 2000 for industry default or 2100 to increase servo travel. + Set the maximum PWM for the main outputs + IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. Set to 2000 for industry default or 2100 to increase servo travel. 1600 2200 us true modules/sensors - - Set the disarmed PWM for MAIN outputs - IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. COMPLETELY POWER-CYCLE THE SYSTEM TO PUT CHANGES INTO EFFECT. This is the PWM pulse the autopilot is outputting if not armed. The main use of this parameter is to silence ESCs when they are disarmed. + + Set the disarmed PWM for the main outputs + IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. This is the PWM pulse the autopilot is outputting if not armed. The main use of this parameter is to silence ESCs when they are disarmed. 0 2200 us @@ -3813,8 +3977,8 @@ EPV used if greater than this value modules/sensors - Set the minimum PWM for the MAIN outputs - IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. COMPLETELY POWER-CYCLE THE SYSTEM TO PUT CHANGES INTO EFFECT. Set to 1000 for default or 900 to increase servo travel + Set the minimum PWM for the auxiliary outputs + IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. Set to 1000 for default or 900 to increase servo travel 800 1400 us @@ -3822,23 +3986,37 @@ EPV used if greater than this value modules/sensors - Set the maximum PWM for the MAIN outputs - IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. COMPLETELY POWER-CYCLE THE SYSTEM TO PUT CHANGES INTO EFFECT. Set to 2000 for default or 2100 to increase servo travel + Set the maximum PWM for the auxiliary outputs + IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. Set to 2000 for default or 2100 to increase servo travel 1600 2200 us true modules/sensors - - Set the disarmed PWM for AUX outputs - IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. COMPLETELY POWER-CYCLE THE SYSTEM TO PUT CHANGES INTO EFFECT. This is the PWM pulse the autopilot is outputting if not armed. The main use of this parameter is to silence ESCs when they are disarmed. + + Set the disarmed PWM for auxiliary outputs + IMPORTANT: CHANGING THIS PARAMETER REQUIRES A COMPLETE SYSTEM REBOOT IN ORDER TO APPLY THE CHANGES. This is the PWM pulse the autopilot is outputting if not armed. The main use of this parameter is to silence ESCs when they are disarmed. 0 2200 us true modules/sensors + + Thrust to PWM model parameter + Parameter used to model the relationship between static thrust and motor input PWM. Model is: thrust = (1-factor)*PWM + factor * PWM^2 + 0.0 + 1.0 + modules/sensors + + + Minimum motor rise time (slew rate limit) + Minimum time allowed for the motor input signal to pass through a range of 1000 PWM units. A value x means that the motor signal can only go from 1000 to 2000 PWM in maximum x seconds. Zero means that slew rate limiting is disabled. + 0.0 + s/(1000*PWM) + modules/sensors + @@ -4248,41 +4426,7 @@ EPV used if greater than this value modules/position_estimator_inav - - - RC receiver type - Acceptable values: - RC_RECEIVER_SPEKTRUM = 1, - RC_RECEIVER_LEMONRX = 2, - platforms/qurt/fc_addon/rc_receiver - - - - Roll trim - The trim value is the actuator control value the system needs for straight and level flight. It can be calibrated by flying manually straight and level using the RC trims and copying them using the GCS. - -0.25 - 0.25 - 2 - 0.01 - modules/commander - - - Pitch trim - The trim value is the actuator control value the system needs for straight and level flight. It can be calibrated by flying manually straight and level using the RC trims and copying them using the GCS. - -0.25 - 0.25 - 2 - 0.01 - modules/commander - - - Yaw trim - The trim value is the actuator control value the system needs for straight and level flight. It can be calibrated by flying manually straight and level using the RC trims and copying them using the GCS. - -0.25 - 0.25 - 2 - 0.01 - modules/commander - RC Channel 1 Minimum Minimum value for RC channel 1 @@ -5389,6 +5533,47 @@ EPV used if greater than this value 2000 modules/sensors + + Sample rate of the remote control values for the low pass filter on roll,pitch, yaw and throttle + Has an influence on the cutoff frequency precision. + 1.0 + Hz + modules/sensors + + + Cutoff frequency for the low pass filter on roll,pitch, yaw and throttle + Does not get set unless below RC_FLT_SMP_RATE/2 because of filter instability characteristics. + 0.1 + Hz + modules/sensors + + + Roll trim + The trim value is the actuator control value the system needs for straight and level flight. It can be calibrated by flying manually straight and level using the RC trims and copying them using the GCS. + -0.25 + 0.25 + 2 + 0.01 + modules/commander + + + Pitch trim + The trim value is the actuator control value the system needs for straight and level flight. It can be calibrated by flying manually straight and level using the RC trims and copying them using the GCS. + -0.25 + 0.25 + 2 + 0.01 + modules/commander + + + Yaw trim + The trim value is the actuator control value the system needs for straight and level flight. It can be calibrated by flying manually straight and level using the RC trims and copying them using the GCS. + -0.25 + 0.25 + 2 + 0.01 + modules/commander + @@ -5647,6 +5832,33 @@ EPV used if greater than this value Channel 8 + + Arm switch channel + 0 + 18 + modules/sensors + + Channel 11 + Channel 10 + Channel 13 + Channel 12 + Channel 15 + Channel 14 + Channel 17 + Channel 16 + Channel 18 + Channel 1 + Unassigned + Channel 3 + Channel 2 + Channel 5 + Channel 4 + Channel 7 + Channel 6 + Channel 9 + Channel 8 + + Flaps channel 0 @@ -5701,6 +5913,87 @@ EPV used if greater than this value Channel 8 + + Landing gear switch channel + 0 + 18 + modules/sensors + + Channel 11 + Channel 10 + Channel 13 + Channel 12 + Channel 15 + Channel 14 + Channel 17 + Channel 16 + Channel 18 + Channel 1 + Unassigned + Channel 3 + Channel 2 + Channel 5 + Channel 4 + Channel 7 + Channel 6 + Channel 9 + Channel 8 + + + + Stabilize switch channel mapping + 0 + 18 + modules/sensors + + Channel 11 + Channel 10 + Channel 13 + Channel 12 + Channel 15 + Channel 14 + Channel 17 + Channel 16 + Channel 18 + Channel 1 + Unassigned + Channel 3 + Channel 2 + Channel 5 + Channel 4 + Channel 7 + Channel 6 + Channel 9 + Channel 8 + + + + Manual switch channel mapping + 0 + 18 + modules/sensors + + Channel 11 + Channel 10 + Channel 13 + Channel 12 + Channel 15 + Channel 14 + Channel 17 + Channel 16 + Channel 18 + Channel 1 + Unassigned + Channel 3 + Channel 2 + Channel 5 + Channel 4 + Channel 7 + Channel 6 + Channel 9 + Channel 8 + + Threshold for selecting assist mode 0-1 indicate where in the full channel range the threshold sits 0 : min 1 : max sign indicates polarity of comparison positive : true when channel>th negative : true when channel<th @@ -5764,6 +6057,13 @@ EPV used if greater than this value 1 modules/sensors + + Threshold for the arm switch + 0-1 indicate where in the full channel range the threshold sits 0 : min 1 : max sign indicates polarity of comparison positive : true when channel>th negative : true when channel<th + -1 + 1 + modules/sensors + Threshold for the VTOL transition switch 0-1 indicate where in the full channel range the threshold sits 0 : min 1 : max sign indicates polarity of comparison positive : true when channel>th negative : true when channel<th @@ -5771,6 +6071,27 @@ EPV used if greater than this value 1 modules/sensors + + Threshold for the landing gear switch + 0-1 indicate where in the full channel range the threshold sits 0 : min 1 : max sign indicates polarity of comparison positive : true when channel>th negative : true when channel<th + -1 + 1 + modules/sensors + + + Threshold for the stabilize switch + 0-1 indicate where in the full channel range the threshold sits 0 : min 1 : max sign indicates polarity of comparison positive : true when channel>th negative : true when channel<th + -1 + 1 + modules/sensors + + + Threshold for the manual switch + 0-1 indicate where in the full channel range the threshold sits 0 : min 1 : max sign indicates polarity of comparison positive : true when channel>th negative : true when channel<th + -1 + 1 + modules/sensors + @@ -5900,14 +6221,6 @@ FW_AIRSPD_MIN * RWTO_AIRSPD_SCL - - UTC offset (unit: min) - the difference in hours and minutes from Coordinated Universal Time (UTC) for a your place and date. for example, In case of South Korea(UTC+09:00), UTC offset is 540 min (9*60) refer to https://en.wikipedia.org/wiki/List_of_UTC_time_offsets - -1000 - 1000 - min - modules/logger - Logging rate A value of -1 indicates the commandline argument should be obeyed. A value of 0 sets the minimum rate, any other value is interpreted as rate in Hertz. This parameter is only read out before logging starts (which commonly is before arming). @@ -5948,6 +6261,34 @@ This is used for gathering replay logs for the ekf2 module Medium priority + + UTC offset (unit: min) + the difference in hours and minutes from Coordinated Universal Time (UTC) for a your place and date. for example, In case of South Korea(UTC+09:00), UTC offset is 540 min (9*60) refer to https://en.wikipedia.org/wiki/List_of_UTC_time_offsets + -1000 + 1000 + min + modules/logger + + + Logging Mode + Determines when to start and stop logging. By default, logging is started when arming the system, and stopped when disarming. This parameter is only for the new logger (SYS_LOGGER=1). + 0 + 3 + true + modules/logger + + from boot until disarm + when armed until disarm (default) + from boot until shutdown - IMU and Baro data only (used for thermal calibration) + from boot until shutdown + + + + Log UUID + If set to 1, add an ID to the log, which uniquely identifies the vehicle + + modules/logger + @@ -6446,160 +6787,754 @@ This is used for gathering replay logs for the ekf2 module Roll 90°, Yaw 90° - - PX4Flow board rotation - This parameter defines the rotation of the PX4FLOW board relative to the platform. Zero rotation is defined as Y on flow board pointing towards front of vehicle - true + + PX4Flow board rotation + This parameter defines the yaw rotation of the PX4FLOW board relative to the vehicle body frame. Zero rotation is defined as X on flow board pointing towards front of vehicle. The recommneded installation default for the PX4FLOW board is with the Y axis forward (270 deg yaw). + true + modules/sensors + + Yaw 45° + No rotation + Yaw 135° + Yaw 90° + Yaw 225° + Yaw 180° + Yaw 315° + Yaw 270° + + + + Board rotation Y (Pitch) offset + This parameter defines a rotational offset in degrees around the Y (Pitch) axis. It allows the user to fine tune the board offset in the event of misalignment. + deg + modules/sensors + + + Board rotation X (Roll) offset + This parameter defines a rotational offset in degrees around the X (Roll) axis It allows the user to fine tune the board offset in the event of misalignment. + deg + modules/sensors + + + Board rotation Z (YAW) offset + This parameter defines a rotational offset in degrees around the Z (Yaw) axis. It allows the user to fine tune the board offset in the event of misalignment. + deg + modules/sensors + + + External magnetometer rotation + modules/sensors + + Pitch 90° + Pitch 270° + Roll 270° + Roll 270°, Yaw 45° + Roll 270°, Yaw 90° + Roll 270°, Yaw 135° + Yaw 45° + No rotation + Yaw 135° + Yaw 90° + Yaw 225° + Yaw 180° + Yaw 315° + Yaw 270° + Roll 180°, Yaw 45° + Roll 180° + Roll 180°, Yaw 135° + Roll 180°, Yaw 90° + Roll 180°, Yaw 225° + Pitch 180° + Roll 180°, Yaw 315° + Roll 180°, Yaw 270° + Roll 90°, Yaw 45° + Roll 90° + Roll 90°, Yaw 135° + Roll 90°, Yaw 90° + + + + Select primary magnetometer + 0 + 2 + modules/sensors + + External is primary Mag + Auto-select Mag + Internal is primary Mag + + + + Threshold (of RMS) to warn about high vibration levels + 0.01 + 10 + 2 + modules/sensors + + + + + Lidar-Lite (LL40LS) PWM + + true + modules/sensors + + + Lightware laser rangefinder (serial) + 0 + 4 + true + modules/sensors + + SF02 + Disabled + SF10/b + SF10/a + SF11/c + SF10/c + + + + Maxbotix Soanr (mb12xx) + + true + modules/sensors + + + TeraRanger One (trone) + + true + modules/sensors + + + Lightware SF1xx laser rangefinder (i2c) + 0 + 4 + true + modules/sensors + + SF10/a + Disabled + SF10/c + SF10/b + SF11/c + + + + Thermal control of sensor temperature + modules/sensors + + Thermal control off + Thermal control unavailable + + + + + + Set to 1 to enable thermal compensation for accelerometer sensors. Set to 0 to disable + 0 + 1 + modules/sensors + + + ID of Accelerometer that the calibration is for + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer scale factor - X axis + modules/sensors + + + Accelerometer scale factor - Y axis + modules/sensors + + + Accelerometer scale factor - Z axis + modules/sensors + + + Accelerometer calibration reference temperature + modules/sensors + + + Accelerometer calibration minimum temperature + modules/sensors + + + Accelerometer calibration maximum temperature + modules/sensors + + + ID of Accelerometer that the calibration is for + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer scale factor - X axis + modules/sensors + + + Accelerometer scale factor - Y axis + modules/sensors + + + Accelerometer scale factor - Z axis + modules/sensors + + + Accelerometer calibration reference temperature + modules/sensors + + + Accelerometer calibration minimum temperature + modules/sensors + + + Accelerometer calibration maximum temperature + modules/sensors + + + ID of Accelerometer that the calibration is for + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^3 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^2 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^1 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - X axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - Y axis + modules/sensors + + + Accelerometer offset temperature ^0 polynomial coefficient - Z axis + modules/sensors + + + Accelerometer scale factor - X axis + modules/sensors + + + Accelerometer scale factor - Y axis + modules/sensors + + + Accelerometer scale factor - Z axis + modules/sensors + + + Accelerometer calibration reference temperature + modules/sensors + + + Accelerometer calibration minimum temperature + modules/sensors + + + Accelerometer calibration maximum temperature + modules/sensors + + + Set to 1 to enable thermal compensation for barometric pressure sensors. Set to 0 to disable + 0 + 1 + modules/sensors + + + ID of Barometer that the calibration is for + modules/sensors + + + Barometer offset temperature ^5 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^4 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^3 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^2 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^1 polynomial coefficients + modules/sensors + + + Barometer offset temperature ^0 polynomial coefficient + modules/sensors + + + Barometer scale factor - X axis + modules/sensors + + + Barometer calibration reference temperature + modules/sensors + + + Barometer calibration minimum temperature + modules/sensors + + + Barometer calibration maximum temperature + modules/sensors + + + ID of Barometer that the calibration is for + modules/sensors + + + Barometer offset temperature ^5 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^4 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^3 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^2 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^1 polynomial coefficients + modules/sensors + + + Barometer offset temperature ^0 polynomial coefficient + modules/sensors + + + Barometer scale factor - X axis + modules/sensors + + + Barometer calibration reference temperature + modules/sensors + + + Barometer calibration minimum temperature + modules/sensors + + + Barometer calibration maximum temperature + modules/sensors + + + ID of Barometer that the calibration is for + modules/sensors + + + Barometer offset temperature ^5 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^4 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^3 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^2 polynomial coefficient + modules/sensors + + + Barometer offset temperature ^1 polynomial coefficients + modules/sensors + + + Barometer offset temperature ^0 polynomial coefficient + modules/sensors + + + Barometer scale factor - X axis + modules/sensors + + + Barometer calibration reference temperature + modules/sensors + + + Barometer calibration minimum temperature + modules/sensors + + + Barometer calibration maximum temperature + modules/sensors + + + Set to 1 to enable thermal compensation for rate gyro sensors. Set to 0 to disable + 0 + 1 + modules/sensors + + + ID of Gyro that the calibration is for + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - Z axis + modules/sensors + + + Gyro rate offset temperature ^2 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^2 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^2 polynomial coefficient - Z axis + modules/sensors + + + Gyro rate offset temperature ^1 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^1 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^1 polynomial coefficient - Z axis + modules/sensors + + + Gyro rate offset temperature ^0 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^0 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^0 polynomial coefficient - Z axis + modules/sensors + + + Gyro scale factor - X axis + modules/sensors + + + Gyro scale factor - Y axis + modules/sensors + + + Gyro scale factor - Z axis + modules/sensors + + + Gyro calibration reference temperature + modules/sensors + + + Gyro calibration minimum temperature + modules/sensors + + + Gyro calibration maximum temperature + modules/sensors + + + ID of Gyro that the calibration is for + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - Z axis + modules/sensors + + + Gyro rate offset temperature ^2 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^2 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^2 polynomial coefficient - Z axis + modules/sensors + + + Gyro rate offset temperature ^1 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^1 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^1 polynomial coefficient - Z axis modules/sensors - - Yaw 45° - No rotation - Yaw 135° - Yaw 90° - Yaw 225° - Yaw 180° - Yaw 315° - Yaw 270° - - - Board rotation Y (Pitch) offset - This parameter defines a rotational offset in degrees around the Y (Pitch) axis. It allows the user to fine tune the board offset in the event of misalignment. - deg + + Gyro rate offset temperature ^0 polynomial coefficient - X axis modules/sensors - - Board rotation X (Roll) offset - This parameter defines a rotational offset in degrees around the X (Roll) axis It allows the user to fine tune the board offset in the event of misalignment. - deg + + Gyro rate offset temperature ^0 polynomial coefficient - Y axis modules/sensors - - Board rotation Z (YAW) offset - This parameter defines a rotational offset in degrees around the Z (Yaw) axis. It allows the user to fine tune the board offset in the event of misalignment. - deg + + Gyro rate offset temperature ^0 polynomial coefficient - Z axis modules/sensors - - External magnetometer rotation + + Gyro scale factor - X axis modules/sensors - - Pitch 90° - Pitch 270° - Roll 270° - Roll 270°, Yaw 45° - Roll 270°, Yaw 90° - Roll 270°, Yaw 135° - Yaw 45° - No rotation - Yaw 135° - Yaw 90° - Yaw 225° - Yaw 180° - Yaw 315° - Yaw 270° - Roll 180°, Yaw 45° - Roll 180° - Roll 180°, Yaw 135° - Roll 180°, Yaw 90° - Roll 180°, Yaw 225° - Pitch 180° - Roll 180°, Yaw 315° - Roll 180°, Yaw 270° - Roll 90°, Yaw 45° - Roll 90° - Roll 90°, Yaw 135° - Roll 90°, Yaw 90° - - - Select primary magnetometer - 0 - 2 + + Gyro scale factor - Y axis modules/sensors - - External is primary Mag - Auto-select Mag - Internal is primary Mag - - - - - Lidar-Lite (LL40LS) PWM - - true + + Gyro scale factor - Z axis modules/sensors - - Lightware SF0x laser rangefinder - - true + + Gyro calibration reference temperature modules/sensors - - Maxbotix Soanr (mb12xx) - - true + + Gyro calibration minimum temperature modules/sensors - - Lightware SF1xx laser rangefinder - 0 - 4 - true + + Gyro calibration maximum temperature modules/sensors - - SF10/a - Disabled - SF10/c - SF10/b - SF11/c - - - - - ESC model - See esc_model_t enum definition in uart_esc_dev.h for all supported ESC model enum values. - platforms/qurt/fc_addon/uart_esc - - ESC_350QX - ESC_200QX - ESC_210QC - + + ID of Gyro that the calibration is for + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^3 polynomial coefficient - Z axis + modules/sensors - - ESC UART baud rate - Default rate is 250Kbps, whic is used in off-the-shelf QRP ESC products. - platforms/qurt/fc_addon/uart_esc + + Gyro rate offset temperature ^2 polynomial coefficient - X axis + modules/sensors - - Motor 1 Mapping - platforms/qurt/fc_addon/uart_esc + + Gyro rate offset temperature ^2 polynomial coefficient - Y axis + modules/sensors - - Motor 2 Mapping - platforms/qurt/fc_addon/uart_esc + + Gyro rate offset temperature ^2 polynomial coefficient - Z axis + modules/sensors - - Motor 3 Mapping - platforms/qurt/fc_addon/uart_esc + + Gyro rate offset temperature ^1 polynomial coefficient - X axis + modules/sensors - - Motor 4 Mapping - platforms/qurt/fc_addon/uart_esc + + Gyro rate offset temperature ^1 polynomial coefficient - Y axis + modules/sensors - - - - Interval of one subscriber in the example in ms - ms - examples/subscriber + + Gyro rate offset temperature ^1 polynomial coefficient - Z axis + modules/sensors + + + Gyro rate offset temperature ^0 polynomial coefficient - X axis + modules/sensors + + + Gyro rate offset temperature ^0 polynomial coefficient - Y axis + modules/sensors + + + Gyro rate offset temperature ^0 polynomial coefficient - Z axis + modules/sensors + + + Gyro scale factor - X axis + modules/sensors + + + Gyro scale factor - Y axis + modules/sensors + + + Gyro scale factor - Z axis + modules/sensors + + + Gyro calibration reference temperature + modules/sensors + + + Gyro calibration minimum temperature + modules/sensors - - Float Demonstration Parameter in the Example - examples/subscriber + + Gyro calibration maximum temperature + modules/sensors @@ -6649,16 +7584,15 @@ This is used for gathering replay logs for the ekf2 module Data does not survive reset - + Set multicopter estimator group - Set the group of estimators used for multicopters and vtols - 0 + Set the group of estimators used for multicopters and VTOLs + 1 2 true modules/systemlib local_position_estimator, attitude_estimator_q - position_estimator_inav, attitude_estimator_q ekf2 @@ -6671,15 +7605,18 @@ This is used for gathering replay logs for the ekf2 module modules/systemlib FrSky Telemetry - Normal Telemetry (19200 baud, 8N1) - Normal Telemetry (38400 baud, 8N1) + Crazyflie (Syslink) Normal Telemetry (57600 baud, 8N1) Command Receiver (57600 baud, 8N1) OSD (57600 baud, 8N1) + Iridium Telemetry (19200 baud, 8N1) + Normal Telemetry (38400 baud, 8N1) Disabled + Normal Telemetry (19200 baud, 8N1) ESP8266 (921600 baud, 8N1) Companion Link (57600 baud, 8N1) Companion Link (921600 baud, 8N1) + Normal Telemetry (115200 baud, 8N1) @@ -6699,6 +7636,51 @@ This is used for gathering replay logs for the ekf2 module sdlog2 (default) + + Enable stack checking + + modules/systemlib + + + Enable auto start of rate gyro thermal calibration at the next power up + 0 : Set to 0 to do nothing 1 : Set to 1 to start a calibration at next boot This parameter is reset to zero when the the temperature calibration starts. default (0, no calibration) + 0 + 1 + modules/systemlib + + + Enable auto start of accelerometer thermal calibration at the next power up + 0 : Set to 0 to do nothing 1 : Set to 1 to start a calibration at next boot This parameter is reset to zero when the the temperature calibration starts. default (0, no calibration) + 0 + 1 + modules/systemlib + + + Enable auto start of barometer thermal calibration at the next power up + 0 : Set to 0 to do nothing 1 : Set to 1 to start a calibration at next boot This parameter is reset to zero when the the temperature calibration starts. default (0, no calibration) + 0 + 1 + modules/systemlib + + + Required temperature rise during thermal calibration + A temperature increase greater than this value is required during calibration. Calibration will complete for each sensor when the temperature increase above the starting temeprature exceeds the value set by SYS_CAL_TDEL. If the temperature rise is insufficient, the calibration will continue indefinitely and the board will need to be repowered to exit. + 10 + deg C + modules/systemlib + + + Minimum starting temperature for thermal calibration + Temperature calibration for each sensor will ignore data if the temperature is lower than the value set by SYS_CAL_TMIN. + deg C + modules/systemlib + + + Maximum starting temperature for thermal calibration + Temperature calibration will not start if the temperature of any sensor is higher than the value set by SYS_CAL_TMAX. + deg C + modules/systemlib + @@ -6757,15 +7739,14 @@ This is used for gathering replay logs for the ekf2 module UAVCAN mode - 0 - UAVCAN disabled. 1 - Enabled support for UAVCAN actuators and sensors. 2 - Enabled support for dynamic node ID allocation and firmware update. 3 - Sets the motor control outputs to UAVCAN and enables support for dynamic node ID allocation and firmware update. + 0 - UAVCAN disabled. 1 - Basic support for UAVCAN actuators and sensors. 2 - Full support for dynamic node ID allocation and firmware update. 3 - Sets the motor control outputs to UAVCAN and enables support for dynamic node ID allocation and firmware update. 0 3 modules/uavcan - Enabled Disabled - Motors/Update - Dynamic ID/Update + Sensors and Motors + Sensors Enabled @@ -6782,6 +7763,12 @@ This is used for gathering replay logs for the ekf2 module bit/s modules/uavcan + + UAVCAN ESC will spin at idle throttle when armed, even if the mixer outputs zero setpoints + + true + modules/uavcan + @@ -6849,6 +7836,23 @@ to accelerate forward if necessary 1 modules/vtol_att_control + + Differential thrust in forwards flight + Set to 1 to enable differential thrust in fixed-wing flight. + 0 + 1 + 0 + modules/vtol_att_control + + + Differential thrust scaling factor + This factor specifies how the yaw input gets mapped to differential thrust in forwards flight. + 0.0 + 1.0 + 2 + 0.1 + modules/vtol_att_control + VTOL number of engines 0 @@ -7029,12 +8033,6 @@ to accelerate forward if necessary s modules/vtol_att_control - - Force VTOL mode takeoff and land - 0 - 1 - modules/vtol_att_control - QuadChute Minimum altitude for fixed wing flight, when in fixed wing the altitude drops below this altitude the vehicle will transition back to MC mode and enter failsafe RTL @@ -7042,6 +8040,14 @@ to accelerate forward if necessary 200.0 modules/vtol_att_control + + Airspeed less front transition time (open loop) + The duration of the front transition when there is no airspeed feedback available. + 1.0 + 30.0 + seconds + modules/vtol_att_control + @@ -7299,21 +8305,37 @@ Maps the change of airspeed error to the acceleration setpoint - - EXFW_HDNG_P - examples/fixedwing_control - - - EXFW_ROLL_P - examples/fixedwing_control - - - EXFW_PITCH_P - examples/fixedwing_control + + Failsafe channel mapping + The RC mapping index indicates which channel is used for failsafe If 0, whichever channel is mapped to throttle is used otherwise the value indicates the specific rc channel to use + 0 + 18 + modules/sensors + + Channel 11 + Channel 10 + Channel 13 + Channel 12 + Channel 15 + Channel 14 + Channel 17 + Channel 16 + Channel 18 + Channel 1 + Unassigned + Channel 3 + Channel 2 + Channel 5 + Channel 4 + Channel 7 + Channel 6 + Channel 9 + Channel 8 + - - RV_YAW_P - examples/rover_steering_control + + COM_RC_STICK_OV + modules/commander First flightmode slot (1000-1160) @@ -7441,49 +8463,21 @@ Maps the change of airspeed error to the acceleration setpoint Stabilized - - SEG_TH2V_P - modules/segway - - - SEG_TH2V_I - modules/segway + + RV_YAW_P + examples/rover_steering_control - - SEG_TH2V_I_MAX - modules/segway + + EXFW_HDNG_P + examples/fixedwing_control - - SEG_Q2V - modules/segway + + EXFW_ROLL_P + examples/fixedwing_control - - Failsafe channel mapping - The RC mapping index indicates which channel is used for failsafe If 0, whichever channel is mapped to throttle is used otherwise the value indicates the specific rc channel to use - 0 - 18 - modules/sensors - - Channel 11 - Channel 10 - Channel 13 - Channel 12 - Channel 15 - Channel 14 - Channel 17 - Channel 16 - Channel 18 - Channel 1 - Unassigned - Channel 3 - Channel 2 - Channel 5 - Channel 4 - Channel 7 - Channel 6 - Channel 9 - Channel 8 - + + EXFW_PITCH_P + examples/fixedwing_control diff --git a/src/FirmwarePlugin/PX4/PX4ParameterMetaData.cc b/src/FirmwarePlugin/PX4/PX4ParameterMetaData.cc index 7fcfaeb7b2fb150c9a2d7f550b27941d372a0df6..a3c9e1e20a094da692504cdb6a17e980e817bc22 100644 --- a/src/FirmwarePlugin/PX4/PX4ParameterMetaData.cc +++ b/src/FirmwarePlugin/PX4/PX4ParameterMetaData.cc @@ -39,22 +39,30 @@ QVariant PX4ParameterMetaData::_stringToTypedVariant(const QString& string, Fact int convertTo = QVariant::Int; // keep compiler warning happy switch (type) { - case FactMetaData::valueTypeUint8: - case FactMetaData::valueTypeUint16: - case FactMetaData::valueTypeUint32: - convertTo = QVariant::UInt; - break; - case FactMetaData::valueTypeInt8: - case FactMetaData::valueTypeInt16: - case FactMetaData::valueTypeInt32: - convertTo = QVariant::Int; - break; - case FactMetaData::valueTypeFloat: - convertTo = QMetaType::Float; - break; - case FactMetaData::valueTypeDouble: - convertTo = QVariant::Double; - break; + case FactMetaData::valueTypeUint8: + case FactMetaData::valueTypeUint16: + case FactMetaData::valueTypeUint32: + convertTo = QVariant::UInt; + break; + case FactMetaData::valueTypeInt8: + case FactMetaData::valueTypeInt16: + case FactMetaData::valueTypeInt32: + convertTo = QVariant::Int; + break; + case FactMetaData::valueTypeFloat: + convertTo = QMetaType::Float; + break; + case FactMetaData::valueTypeDouble: + convertTo = QVariant::Double; + break; + case FactMetaData::valueTypeString: + qWarning() << "Internal Error: No support for string parameters"; + convertTo = QVariant::String; + break; + case FactMetaData::valueTypeBool: + qWarning() << "Internal Error: No support for string parameters"; + convertTo = QVariant::Bool; + break; } *convertOk = var.convert(convertTo); diff --git a/src/FirmwarePlugin/PX4/PX4Resources.qrc b/src/FirmwarePlugin/PX4/PX4Resources.qrc new file mode 100644 index 0000000000000000000000000000000000000000..de0775e1c697981ff1af8fe535732869a0aefacd --- /dev/null +++ b/src/FirmwarePlugin/PX4/PX4Resources.qrc @@ -0,0 +1,27 @@ + + + ../../AutoPilotPlugins/PX4/PX4AdvancedFlightModes.qml + ../../AutoPilotPlugins/PX4/PX4FlightModes.qml + ../../AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml + ../../AutoPilotPlugins/PX4/PX4SimpleFlightModes.qml + ../../AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml + ../../AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml + ../../AutoPilotPlugins/PX4/PX4TuningComponentVTOL.qml + + + MavCmdInfoCommon.json + MavCmdInfoFixedWing.json + MavCmdInfoMultiRotor.json + MavCmdInfoRover.json + MavCmdInfoSub.json + MavCmdInfoVTOL.json + + + ../../AutoPilotPlugins/PX4/AirframeFactMetaData.xml + + + PX4ParameterFactMetaData.xml + PX4GeoFenceEditor.qml + V1.4.OfflineEditing.params + + diff --git a/src/FirmwarePlugin/PX4/px4_custom_mode.h b/src/FirmwarePlugin/PX4/px4_custom_mode.h index b3e9de3aba25d001d04a95c0983480a600ea9a48..6569ce6e0b092f6fb98b1804b77d9e98759ee4fc 100644 --- a/src/FirmwarePlugin/PX4/px4_custom_mode.h +++ b/src/FirmwarePlugin/PX4/px4_custom_mode.h @@ -50,7 +50,8 @@ enum PX4_CUSTOM_MAIN_MODE { PX4_CUSTOM_MAIN_MODE_ACRO, PX4_CUSTOM_MAIN_MODE_OFFBOARD, PX4_CUSTOM_MAIN_MODE_STABILIZED, - PX4_CUSTOM_MAIN_MODE_RATTITUDE + PX4_CUSTOM_MAIN_MODE_RATTITUDE, + PX4_CUSTOM_MAIN_MODE_SIMPLE }; enum PX4_CUSTOM_SUB_MODE_AUTO { diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml index 85faa00b0efe911bef2aa2ba47cc38282b615ba9..07f4c68327bb9515c4cba56019f363a21fa46b4f 100644 --- a/src/FlightDisplay/FlightDisplayView.qml +++ b/src/FlightDisplay/FlightDisplayView.qml @@ -33,24 +33,14 @@ QGCView { QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + property bool activeVehicleJoystickEnabled: _activeVehicle ? _activeVehicle.joystickEnabled : false + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property bool _mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false - - property real _roll: _activeVehicle ? _activeVehicle.roll.value : _defaultRoll - property real _pitch: _activeVehicle ? _activeVehicle.pitch.value : _defaultPitch - property real _heading: _activeVehicle ? _activeVehicle.heading.value : _defaultHeading - - - property Fact _emptyFact: Fact { } - property Fact _groundSpeedFact: _activeVehicle ? _activeVehicle.groundSpeed : _emptyFact - property Fact _airSpeedFact: _activeVehicle ? _activeVehicle.airSpeed : _emptyFact - - property bool activeVehicleJoystickEnabled: _activeVehicle ? _activeVehicle.joystickEnabled : false - property real _savedZoomLevel: 0 - - property real pipSize: mainWindow.width * 0.2 + property real _margins: ScreenTools.defaultFontPixelWidth / 2 + property real _pipSize: mainWindow.width * 0.2 readonly property bool isBackgroundDark: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true readonly property real _defaultRoll: 0 @@ -91,7 +81,7 @@ QGCView { } function px4JoystickCheck() { - if ( _activeVehicle && !_activeVehicle.supportsManualControl && (QGroundControl.virtualTabletJoystick || _activeVehicle.joystickEnabled)) { + if ( _activeVehicle && !_activeVehicle.supportsManualControl && (QGroundControl.settingsManager.appSettings.virtualJoystick.value || _activeVehicle.joystickEnabled)) { px4JoystickSupport.open() } } @@ -109,18 +99,19 @@ QGCView { } Connections { - target: QGroundControl - onVirtualTabletJoystickChanged: px4JoystickCheck() + target: QGroundControl.settingsManager.appSettings.virtualJoystick + onValueChanged: px4JoystickCheck() } onActiveVehicleJoystickEnabledChanged: px4JoystickCheck() Component.onCompleted: { - widgetsLoader.source = "FlightDisplayViewWidgets.qml" setStates() px4JoystickCheck() } + QGCMapPalette { id: mapPal; lightColors: _mainIsMap ? _flightMap.isSatelliteMap : true } + QGCViewPanel { id: _panel anchors.fill: parent @@ -134,8 +125,8 @@ QGCView { anchors.left: _panel.left anchors.bottom: _panel.bottom visible: _mainIsMap || _isPipVisible - width: _mainIsMap ? _panel.width : pipSize - height: _mainIsMap ? _panel.height : pipSize * (9/16) + width: _mainIsMap ? _panel.width : _pipSize + height: _mainIsMap ? _panel.height : _pipSize * (9/16) states: [ State { name: "pipMode" @@ -153,9 +144,10 @@ QGCView { } ] FlightDisplayViewMap { - id: _flightMap - anchors.fill: parent - flightWidgets: widgetsLoader.item + id: _flightMap + anchors.fill: parent + flightWidgets: flightDisplayViewWidgets + rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9 } } @@ -163,8 +155,8 @@ QGCView { Item { id: _flightVideo z: _mainIsMap ? _panel.z + 2 : _panel.z + 1 - width: !_mainIsMap ? _panel.width : pipSize - height: !_mainIsMap ? _panel.height : pipSize * (9/16) + width: !_mainIsMap ? _panel.width : _pipSize + height: !_mainIsMap ? _panel.height : _pipSize * (9/16) anchors.left: _panel.left anchors.bottom: _panel.bottom visible: QGroundControl.videoManager.hasVideo && (!_mainIsMap || _isPipVisible) @@ -201,8 +193,8 @@ QGCView { QGCPipable { id: _flightVideoPipControl z: _flightVideo.z + 3 - width: pipSize - height: pipSize * (9/16) + width: _pipSize + height: _pipSize * (9/16) anchors.left: _panel.left anchors.bottom: _panel.bottom anchors.margins: ScreenTools.defaultFontPixelHeight @@ -218,35 +210,108 @@ QGCView { } } - //-- Widgets - Loader { - id: widgetsLoader - z: _panel.z + 4 - height: ScreenTools.availableHeight - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - asynchronous: true - visible: status == Loader.Ready - - property bool isBackgroundDark: root.isBackgroundDark - property var qgcView: root + Row { + id: singleMultiSelector + anchors.topMargin: ScreenTools.toolbarHeight + _margins + anchors.rightMargin: _margins + anchors.right: parent.right + anchors.top: parent.top + spacing: ScreenTools.defaultFontPixelWidth + z: _panel.z + 4 + visible: QGroundControl.multiVehicleManager.vehicles.count > 1 + + ExclusiveGroup { id: multiVehicleSelectorGroup } + + QGCRadioButton { + id: singleVehicleView + exclusiveGroup: multiVehicleSelectorGroup + text: qsTr("Single") + checked: true + color: mapPal.text + } + + QGCRadioButton { + exclusiveGroup: multiVehicleSelectorGroup + text: qsTr("Multi-Vehicle (WIP)") + color: mapPal.text + } } + FlightDisplayViewWidgets { + id: flightDisplayViewWidgets + z: _panel.z + 4 + height: ScreenTools.availableHeight + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + qgcView: root + isBackgroundDark: root.isBackgroundDark + visible: singleVehicleView.checked + } + + // 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: QGroundControl.videoManager.videoRunning && QGroundControl.videoManager.recordingEnabled + opacity: 0.75 + + Rectangle { + anchors.top: parent.top + anchors.bottom: parent.bottom + width: height + radius: QGroundControl.videoManager && QGroundControl.videoManager.videoReceiver && QGroundControl.videoManager.videoReceiver.recording ? 0 : height + color: "red" + } + + QGCColoredImage { + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + width: height * 0.625 + sourceSize.width: width + source: "/qmlimages/CameraIcon.svg" + fillMode: Image.PreserveAspectFit + color: "white" + } + + MouseArea { + anchors.fill: parent + onClicked: QGroundControl.videoManager.videoReceiver && QGroundControl.videoManager.videoReceiver.recording ? QGroundControl.videoManager.videoReceiver.stopRecording() : QGroundControl.videoManager.videoReceiver.startRecording() + } + } + + MultiVehicleList { + anchors.margins: _margins + anchors.top: singleMultiSelector.bottom + anchors.right: parent.right + anchors.bottom: parent.bottom + width: ScreenTools.defaultFontPixelWidth * 30 + visible: !singleVehicleView.checked + z: _panel.z + 4 + } + + //-- Virtual Joystick Loader { id: virtualJoystickMultiTouch z: _panel.z + 5 width: parent.width - (_flightVideoPipControl.width / 2) height: Math.min(ScreenTools.availableHeight * 0.25, ScreenTools.defaultFontPixelWidth * 16) - visible: QGroundControl.virtualTabletJoystick + visible: _virtualJoystick.value anchors.bottom: _flightVideoPipControl.top anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 2 - anchors.horizontalCenter: widgetsLoader.horizontalCenter + anchors.horizontalCenter: flightDisplayViewWidgets.horizontalCenter source: "qrc:/qml/VirtualJoystick.qml" - active: QGroundControl.virtualTabletJoystick + active: _virtualJoystick.value property bool useLightColors: root.isBackgroundDark + + property Fact _virtualJoystick: QGroundControl.settingsManager.appSettings.virtualJoystick } } } diff --git a/src/FlightDisplay/FlightDisplayViewMap.qml b/src/FlightDisplay/FlightDisplayViewMap.qml index decd6d79cdced6db8df482d42705ee64c832dab5..12c7b7fdc83272a14a8ccefb07d7d9cf6b248e61 100644 --- a/src/FlightDisplay/FlightDisplayViewMap.qml +++ b/src/FlightDisplay/FlightDisplayViewMap.qml @@ -29,6 +29,7 @@ FlightMap { property alias missionController: missionController property var flightWidgets + property var rightPanelWidth property bool _followVehicle: true property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle @@ -36,6 +37,7 @@ FlightMap { property var activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate() property var _gotoHereCoordinate: QtPositioning.coordinate() property int _retaskSequence: 0 + property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2) Component.onCompleted: { QGroundControl.flightMapPosition = center @@ -52,6 +54,7 @@ FlightMap { } QGCPalette { id: qgcPal; colorGroupEnabled: true } + QGCMapPalette { id: mapPal; lightColors: isSatelliteMap } MissionController { id: missionController @@ -68,6 +71,111 @@ FlightMap { Component.onCompleted: start(false /* editMode */) } + ExclusiveGroup { + id: _mapTypeButtonsExclusiveGroup + } + + ToolStrip { + id: toolStrip + anchors.leftMargin: ScreenTools.defaultFontPixelWidth + anchors.left: parent.left + anchors.topMargin: _toolButtonTopMargin + anchors.top: parent.top + color: qgcPal.window + title: qsTr("Fly") + z: QGroundControl.zOrderWidgets + buttonVisible: [ true, true, _showZoom, _showZoom ] + maxHeight: (_flightVideo.visible ? _flightVideo.y : parent.height) - toolStrip.y // Massive reach across hack + + property bool _showZoom: !ScreenTools.isShortScreen + + model: [ + { + name: "Center", + iconSource: "/qmlimages/MapCenter.svg", + dropPanelComponent: centerMapDropPanel + }, + { + name: "Map", + iconSource: "/qmlimages/MapType.svg", + dropPanelComponent: mapTypeDropPanel + }, + { + name: "In", + iconSource: "/qmlimages/ZoomPlus.svg" + }, + { + name: "Out", + iconSource: "/qmlimages/ZoomMinus.svg" + } + ] + + onClicked: { + switch (index) { + case 2: + _flightMap.zoomLevel += 0.5 + break + case 3: + _flightMap.zoomLevel -= 0.5 + break + } + } + } + + // Toolstrip drop panel compomnents + + MapFitFunctions { + id: mapFitFunctions + map: _flightMap + mapFitViewport: Qt.rect(leftToolWidth, _toolButtonTopMargin, flightMap.width - leftToolWidth - rightPanelWidth, flightMap.height - _toolButtonTopMargin) + usePlannedHomePosition: false + mapMissionController: missionController + mapGeoFenceController: geoFenceController + mapRallyPointController: rallyPointController + + property real leftToolWidth: toolStrip.x + toolStrip.width + } + + Component { + id: centerMapDropPanel + + CenterMapDropPanel { + map: _flightMap + fitFunctions: mapFitFunctions + showFollowVehicle: true + followVehicle: _followVehicle + + onFollowVehicleChanged: _followVehicle = followVehicle + } + } + + Component { + id: mapTypeDropPanel + + Column { + spacing: ScreenTools.defaultFontPixelHeight / 2 + + QGCLabel { text: qsTr("Map type:") } + Row { + spacing: ScreenTools.defaultFontPixelWidth + Repeater { + model: QGroundControl.flightMapSettings.mapTypes + + QGCButton { + checkable: true + checked: QGroundControl.flightMapSettings.mapType === text + text: modelData + exclusiveGroup: _mapTypeButtonsExclusiveGroup + onClicked: { + QGroundControl.flightMapSettings.mapType = text + dropPanel.hide() + } + } + } + } + } + } + // Add trajectory points to the map MapItemView { model: _mainIsMap ? _activeVehicle ? _activeVehicle.trajectoryPoints : 0 : 0 @@ -110,7 +218,8 @@ FlightMap { MapPolygon { border.color: "#80FF0000" border.width: 3 - path: geoFenceController.polygonSupported ? geoFenceController.polygon.path : undefined + path: geoFenceController.polygon.path + visible: geoFenceController.polygonEnabled } // GeoFence circle @@ -118,15 +227,17 @@ FlightMap { border.color: "#80FF0000" border.width: 3 center: missionController.plannedHomePosition - radius: geoFenceController.circleSupported ? geoFenceController.circleRadius : 0 + radius: geoFenceController.circleRadius z: QGroundControl.zOrderMapItems + visible: geoFenceController.circleEnabled } // GeoFence breach return point MapQuickItem { - anchorPoint: Qt.point(sourceItem.width / 2, sourceItem.height / 2) + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY coordinate: geoFenceController.breachReturnPoint - visible: geoFenceController.breachReturnSupported + visible: geoFenceController.breachReturnEnabled sourceItem: MissionItemIndexLabel { label: "F" } z: QGroundControl.zOrderMapItems } @@ -137,7 +248,8 @@ FlightMap { delegate: MapQuickItem { id: itemIndicator - anchorPoint: Qt.point(sourceItem.width / 2, sourceItem.height / 2) + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY coordinate: object.coordinate z: QGroundControl.zOrderMapItems @@ -153,8 +265,8 @@ FlightMap { coordinate: _gotoHereCoordinate visible: _activeVehicle && _activeVehicle.guidedMode && _gotoHereCoordinate.isValid z: QGroundControl.zOrderMapItems - anchorPoint.x: sourceItem.width / 2 - anchorPoint.y: sourceItem.height / 2 + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY sourceItem: MissionItemIndexLabel { checked: true @@ -167,7 +279,6 @@ FlightMap { anchors.rightMargin: ScreenTools.defaultFontPixelHeight * (0.33) anchors.bottom: parent.bottom anchors.right: parent.right - z: QGroundControl.zOrderWidgets mapControl: flightMap visible: !ScreenTools.isTinyScreen } diff --git a/src/FlightDisplay/FlightDisplayViewVideo.qml b/src/FlightDisplay/FlightDisplayViewVideo.qml index 2b82520948f95229ad601ed5dd3d44af33c716e5..b3ea10af40682e98d964bf164169bb1b1894b5f3 100644 --- a/src/FlightDisplay/FlightDisplayViewVideo.qml +++ b/src/FlightDisplay/FlightDisplayViewVideo.qml @@ -23,35 +23,61 @@ import QGroundControl.Controllers 1.0 Item { id: root + property double _ar: QGroundControl.settingsManager.videoSettings.aspectRatio.rawValue + property bool _showGrid: QGroundControl.settingsManager.videoSettings.gridLines.rawValue > 0 + Rectangle { id: noVideo anchors.fill: parent color: Qt.rgba(0,0,0,0.75) visible: !QGroundControl.videoManager.videoRunning QGCLabel { - text: qsTr("NO VIDEO") + text: qsTr("WAITING FOR VIDEO") font.family: ScreenTools.demiboldFontFamily color: "white" font.pointSize: _mainIsMap ? ScreenTools.smallFontPointSize : ScreenTools.largeFontPointSize anchors.centerIn: parent } } - QGCVideoBackground { + Rectangle { anchors.fill: parent - display: QGroundControl.videoManager.videoSurface - receiver: QGroundControl.videoManager.videoReceiver + color: "black" visible: QGroundControl.videoManager.videoRunning - /* TODO: Come up with a way to make this an option - QGCAttitudeHUD { - id: attitudeHUD - visible: !_mainIsMap - rollAngle: _roll - pitchAngle: _pitch - width: ScreenTools.defaultFontPixelHeight * (30) - height: ScreenTools.defaultFontPixelHeight * (30) - active: QGroundControl.multiVehicleManager.activeVehicleAvailable - z: QGroundControl.zOrderWidgets + QGCVideoBackground { + height: parent.height + width: _ar != 0.0 ? height * _ar : parent.width + anchors.centerIn: parent + display: QGroundControl.videoManager.videoSurface + receiver: QGroundControl.videoManager.videoReceiver + visible: QGroundControl.videoManager.videoRunning + Rectangle { + color: Qt.rgba(1,1,1,0.5) + height: parent.height + width: 1 + x: parent.width * 0.33 + visible: _showGrid + } + Rectangle { + color: Qt.rgba(1,1,1,0.5) + height: parent.height + width: 1 + x: parent.width * 0.66 + visible: _showGrid + } + Rectangle { + color: Qt.rgba(1,1,1,0.5) + width: parent.width + height: 1 + y: parent.height * 0.33 + visible: _showGrid + } + Rectangle { + color: Qt.rgba(1,1,1,0.5) + width: parent.width + height: 1 + y: parent.height * 0.66 + visible: _showGrid + } } - */ } } diff --git a/src/FlightDisplay/FlightDisplayViewWidgets.qml b/src/FlightDisplay/FlightDisplayViewWidgets.qml index dd054d326038bad8457cf08c85cc85601fcba3f8..fd553fde2ffc1e8b3ead0d974c1e4062646db6f2 100644 --- a/src/FlightDisplay/FlightDisplayViewWidgets.qml +++ b/src/FlightDisplay/FlightDisplayViewWidgets.qml @@ -15,31 +15,31 @@ import QtQuick.Dialogs 1.2 import QtLocation 5.3 import QtPositioning 5.2 -import QGroundControl 1.0 -import QGroundControl.ScreenTools 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.Palette 1.0 -import QGroundControl.Vehicle 1.0 -import QGroundControl.FlightMap 1.0 +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Vehicle 1.0 +import QGroundControl.FlightMap 1.0 Item { id: _root - property alias guidedModeBar: _guidedModeBar - property bool gotoEnabled: _activeVehicle && _activeVehicle.guidedMode && _activeVehicle.flying + property alias guidedModeBar: _guidedModeBar + property bool gotoEnabled: _activeVehicle && _activeVehicle.guidedMode && _activeVehicle.flying + property var qgcView + property bool isBackgroundDark - property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle - property bool _isSatellite: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true - property bool _lightWidgetBorders: _isSatellite - property bool _useAlternateInstruments: QGroundControl.virtualTabletJoystick || ScreenTools.isTinyScreen + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property bool _isSatellite: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true + property bool _lightWidgetBorders: _isSatellite - readonly property real _margins: ScreenTools.defaultFontPixelHeight / 2 - readonly property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2) + readonly property real _margins: ScreenTools.defaultFontPixelHeight * 0.5 QGCMapPalette { id: mapPal; lightColors: isBackgroundDark } - QGCPalette { id: qgcPal } + QGCPalette { id: qgcPal } - function getGadgetWidth() { + function getPreferredInstrumentWidth() { if(ScreenTools.isMobile) { return ScreenTools.isTinyScreen ? mainWindow.width * 0.2 : mainWindow.width * 0.15 } @@ -47,12 +47,40 @@ Item { return Math.min(w, 200) } - ExclusiveGroup { - id: _dropButtonsExclusiveGroup + function _setInstrumentWidget() { + if(QGroundControl.corePlugin.options.instrumentWidget.source.toString().length) { + instrumentsLoader.source = QGroundControl.corePlugin.options.instrumentWidget.source + switch(QGroundControl.corePlugin.options.instrumentWidget.widgetPosition) { + case CustomInstrumentWidget.POS_TOP_RIGHT: + instrumentsLoader.state = "topMode" + break; + case CustomInstrumentWidget.POS_BOTTOM_RIGHT: + instrumentsLoader.state = "bottomMode" + break; + case CustomInstrumentWidget.POS_CENTER_RIGHT: + default: + instrumentsLoader.state = "centerMode" + break; + } + } else { + var useAlternateInstruments = QGroundControl.settingsManager.appSettings.virtualJoystick.value || ScreenTools.isTinyScreen + if(useAlternateInstruments) { + instrumentsLoader.source = "qrc:/qml/QGCInstrumentWidgetAlternate.qml" + instrumentsLoader.state = "topMode" + } else { + instrumentsLoader.source = "qrc:/qml/QGCInstrumentWidget.qml" + instrumentsLoader.state = "centerMode" + } + } } - ExclusiveGroup { - id: _mapTypeButtonsExclusiveGroup + Connections { + target: QGroundControl.settingsManager.appSettings.virtualJoystick + onValueChanged: _setInstrumentWidget() + } + + Component.onCompleted: { + _setInstrumentWidget() } //-- Map warnings @@ -80,206 +108,43 @@ Item { } } - //-- Dismiss Drop Down (if any) - MouseArea { - anchors.fill: parent - enabled: _dropButtonsExclusiveGroup.current != null - onClicked: { - if(_dropButtonsExclusiveGroup.current) - _dropButtonsExclusiveGroup.current.checked = false - _dropButtonsExclusiveGroup.current = null - } - } - //-- Instrument Panel - QGCInstrumentWidget { - id: instrumentGadget + Loader { + id: instrumentsLoader anchors.margins: ScreenTools.defaultFontPixelHeight / 2 anchors.right: altitudeSlider.visible ? altitudeSlider.left : parent.right - anchors.verticalCenter: parent.verticalCenter - visible: !_useAlternateInstruments - size: getGadgetWidth() - active: _activeVehicle != null - heading: _heading - rollAngle: _roll - pitchAngle: _pitch - groundSpeedFact: _groundSpeedFact - airSpeedFact: _airSpeedFact - lightBorders: _lightWidgetBorders z: QGroundControl.zOrderWidgets - qgcView: parent.parent.qgcView - maxHeight: parent.height - (anchors.margins * 2) - } - - QGCInstrumentWidgetAlternate { - id: instrumentGadgetAlternate - anchors.margins: ScreenTools.defaultFontPixelHeight / 2 - anchors.top: parent.top - anchors.right: altitudeSlider.visible ? altitudeSlider.left : parent.right - visible: _useAlternateInstruments - width: ScreenTools.isTinyScreen ? getGadgetWidth() * 1.5 : getGadgetWidth() - active: _activeVehicle != null - heading: _heading - rollAngle: _roll - pitchAngle: _pitch - groundSpeedFact: _groundSpeedFact - airSpeedFact: _airSpeedFact - isSatellite: _isSatellite - z: QGroundControl.zOrderWidgets - } - - ValuesWidget { - anchors.topMargin: ScreenTools.defaultFontPixelHeight - anchors.top: instrumentGadgetAlternate.bottom - anchors.horizontalCenter: instrumentGadgetAlternate.horizontalCenter - width: getGadgetWidth() - qgcView: parent.parent.qgcView - textColor: _isSatellite ? "white" : "black" - visible: _useAlternateInstruments - maxHeight: virtualJoystickMultiTouch.visible ? virtualJoystickMultiTouch.y - y : parent.height - anchors.margins - y - } - - QGCLabel { - id: flyLabel - text: qsTr("Fly") - color: mapPal.text - visible: !ScreenTools.isShortScreen - anchors.topMargin: _toolButtonTopMargin - anchors.horizontalCenter: toolColumn.horizontalCenter - anchors.top: parent.top - } - - //-- Vertical Tool Buttons - Column { - id: toolColumn - anchors.topMargin: ScreenTools.isShortScreen ? _toolButtonTopMargin : ScreenTools.defaultFontPixelHeight / 2 - anchors.leftMargin: ScreenTools.defaultFontPixelHeight - anchors.left: parent.left - anchors.top: ScreenTools.isShortScreen ? parent.top : flyLabel.bottom - spacing: ScreenTools.defaultFontPixelHeight - visible: _mainIsMap - - //-- Map Center Control - DropButton { - id: centerMapDropButton - dropDirection: dropRight - buttonImage: "/qmlimages/MapCenter.svg" - viewportMargins: ScreenTools.defaultFontPixelWidth / 2 - exclusiveGroup: _dropButtonsExclusiveGroup - z: QGroundControl.zOrderWidgets - lightBorders: _lightWidgetBorders - - dropDownComponent: Component { - Row { - spacing: ScreenTools.defaultFontPixelWidth - - QGCCheckBox { - id: followVehicleCheckBox - text: qsTr("Follow Vehicle") - checked: _flightMap ? _flightMap._followVehicle : false - anchors.verticalCenter: parent.verticalCenter - //anchors.baseline: centerMapButton.baseline - This doesn't work correctly on mobile for some strange reason, so we center instead - - onClicked: { - _dropButtonsExclusiveGroup.current = null - _flightMap._followVehicle = !_flightMap._followVehicle - } - } - - QGCButton { - id: centerMapButton - text: qsTr("Center map on Vehicle") - enabled: _activeVehicle && !followVehicleCheckBox.checked - - property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle - - onClicked: { - _dropButtonsExclusiveGroup.current = null - _flightMap.center = activeVehicle.coordinate - } - } + property var qgcView: _root.qgcView + property real maxHeight:parent.height - (anchors.margins * 2) + states: [ + State { + name: "topMode" + AnchorChanges { + target: instrumentsLoader + anchors.verticalCenter: undefined + anchors.bottom: undefined + anchors.top: _root ? _root.top : undefined } - } - } - - //-- Map Type Control - DropButton { - id: mapTypeButton - dropDirection: dropRight - buttonImage: "/qmlimages/MapType.svg" - viewportMargins: ScreenTools.defaultFontPixelWidth / 2 - exclusiveGroup: _dropButtonsExclusiveGroup - z: QGroundControl.zOrderWidgets - lightBorders: _lightWidgetBorders - - dropDownComponent: Component { - Column { - spacing: ScreenTools.defaultFontPixelWidth - - Row { - spacing: ScreenTools.defaultFontPixelWidth - - Repeater { - model: QGroundControl.flightMapSettings.mapTypes - - QGCButton { - checkable: true - checked: QGroundControl.flightMapSettings.mapType === text - text: modelData - width: clearButton.width - exclusiveGroup: _mapTypeButtonsExclusiveGroup - - onClicked: { - QGroundControl.flightMapSettings.mapType = text - checked = true - _dropButtonsExclusiveGroup.current = null - } - } - } - } - - QGCButton { - id: clearButton - text: qsTr("Clear Flight Trails") - enabled: QGroundControl.multiVehicleManager.activeVehicle - onClicked: { - QGroundControl.multiVehicleManager.activeVehicle.clearTrajectoryPoints() - _dropButtonsExclusiveGroup.current = null - } - } + }, + State { + name: "centerMode" + AnchorChanges { + target: instrumentsLoader + anchors.top: undefined + anchors.bottom: undefined + anchors.verticalCenter: _root ? _root.verticalCenter : undefined + } + }, + State { + name: "bottomMode" + AnchorChanges { + target: instrumentsLoader + anchors.top: undefined + anchors.verticalCenter: undefined + anchors.bottom: _root ? _root.bottom : undefined } } - } - - //-- Zoom Map In - RoundButton { - id: mapZoomPlus - visible: !ScreenTools.isTinyScreen && _mainIsMap - buttonImage: "/qmlimages/ZoomPlus.svg" - exclusiveGroup: _dropButtonsExclusiveGroup - z: QGroundControl.zOrderWidgets - lightBorders: _lightWidgetBorders - onClicked: { - if(_flightMap) - _flightMap.zoomLevel += 0.5 - checked = false - } - } - - //-- Zoom Map Out - RoundButton { - id: mapZoomMinus - visible: !ScreenTools.isTinyScreen && _mainIsMap - buttonImage: "/qmlimages/ZoomMinus.svg" - exclusiveGroup: _dropButtonsExclusiveGroup - z: QGroundControl.zOrderWidgets - lightBorders: _lightWidgetBorders - onClicked: { - if(_flightMap) - _flightMap.zoomLevel -= 0.5 - checked = false - } - } + ] } //-- Guided mode buttons @@ -291,7 +156,7 @@ Item { width: guidedModeColumn.width + (_margins * 2) height: guidedModeColumn.height + (_margins * 2) radius: ScreenTools.defaultFontPixelHeight * 0.25 - color: _lightWidgetBorders ? Qt.rgba(qgcPal.mapWidgetBorderLight.r, qgcPal.mapWidgetBorderLight.g, qgcPal.mapWidgetBorderLight.b, 0.8) : Qt.rgba(qgcPal.mapWidgetBorderDark.r, qgcPal.mapWidgetBorderDark.g, qgcPal.mapWidgetBorderDark.b, 0.75) + color: _isSatellite ? Qt.rgba(qgcPal.mapWidgetBorderLight.r, qgcPal.mapWidgetBorderLight.g, qgcPal.mapWidgetBorderLight.b, 0.8) : Qt.rgba(qgcPal.mapWidgetBorderDark.r, qgcPal.mapWidgetBorderDark.g, qgcPal.mapWidgetBorderDark.b, 0.75) visible: _activeVehicle z: QGroundControl.zOrderWidgets state: "Shown" @@ -335,7 +200,7 @@ Item { interval: 7000 running: true onTriggered: { - if (ScreenTools.isShortScreen) { + if (ScreenTools.isTinyScreen) { _guidedModeBar.state = "Hidden" } } @@ -351,6 +216,7 @@ Item { readonly property int confirmGoTo: 8 readonly property int confirmRetask: 9 readonly property int confirmOrbit: 10 + readonly property int confirmAbort: 11 property int confirmActionCode property real _showMargin: _margins @@ -398,6 +264,9 @@ Item { //-- Center on current flight map position and orbit with a 50m radius (velocity/direction controlled by the RC) //_activeVehicle.guidedModeOrbit(QGroundControl.flightMapPosition, 50.0) break; + case confirmAbort: + _activeVehicle.abortLanding(50) // hardcoded value for climbOutAltitude that is currently ignored + break; default: console.warn(qsTr("Internal error: unknown confirmActionCode"), confirmActionCode) } @@ -426,7 +295,7 @@ Item { break; case confirmTakeoff: altitudeSlider.visible = true - altitudeSlider.setInitialValueMeters(2) + altitudeSlider.setInitialValueMeters(3) guidedModeConfirm.confirmText = qsTr("takeoff") break; case confirmLand: @@ -437,7 +306,7 @@ Item { break; case confirmChangeAlt: altitudeSlider.visible = true - altitudeSlider.setInitialValueAppSettingsDistanceUnits(_activeVehicle.altitudeAMSL.value) + altitudeSlider.setInitialValueAppSettingsDistanceUnits(_activeVehicle.altitudeRelative.value) guidedModeConfirm.confirmText = qsTr("change altitude") break; case confirmGoTo: @@ -449,6 +318,9 @@ Item { case confirmOrbit: guidedModeConfirm.confirmText = qsTr("enter orbit mode") break; + case confirmAbort: + guidedModeConfirm.confirmText = qsTr("abort landing") + break; } _guidedModeBar.visible = false guidedModeConfirm.visible = true @@ -463,7 +335,7 @@ Item { QGCLabel { anchors.horizontalCenter: parent.horizontalCenter - color: _lightWidgetBorders ? qgcPal.mapWidgetBorderDark : qgcPal.mapWidgetBorderLight + color: _isSatellite ? qgcPal.mapWidgetBorderDark : qgcPal.mapWidgetBorderLight text: "Click in map to move vehicle" visible: gotoEnabled } @@ -516,6 +388,13 @@ Item { onClicked: _guidedModeBar.confirmAction(_guidedModeBar.confirmOrbit) } + QGCButton { + pointSize: _guidedModeBar._fontPointSize + text: qsTr("Abort") + visible: _activeVehicle && _activeVehicle.flying && _activeVehicle.fixedWing + onClicked: _guidedModeBar.confirmAction(_guidedModeBar.confirmAbort) + } + } // Row } // Column } // Rectangle - Guided mode buttons @@ -610,8 +489,8 @@ Item { anchors.left: parent.left anchors.right: parent.right orientation: Qt.Vertical - minimumValue: QGroundControl.metersToAppSettingsDistanceUnits(2) - maximumValue: QGroundControl.metersToAppSettingsDistanceUnits((_activeVehicle && _activeVehicle.flying) ? 100 : 10) + minimumValue: QGroundControl.metersToAppSettingsDistanceUnits(0) + maximumValue: QGroundControl.metersToAppSettingsDistanceUnits((_activeVehicle && _activeVehicle.flying) ? Math.round((_activeVehicle.altitudeRelative.value + 100) / 100) * 100 : 10) } } } diff --git a/src/FlightDisplay/MultiVehicleList.qml b/src/FlightDisplay/MultiVehicleList.qml new file mode 100644 index 0000000000000000000000000000000000000000..a266bf0b6dd13f9a79f990f63ff70395bec336d0 --- /dev/null +++ b/src/FlightDisplay/MultiVehicleList.qml @@ -0,0 +1,135 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Controls 1.3 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Vehicle 1.0 +import QGroundControl.FlightMap 1.0 + +QGCListView { + id: missionItemEditorListView + spacing: ScreenTools.defaultFontPixelHeight / 2 + orientation: ListView.Vertical + model: QGroundControl.multiVehicleManager.vehicles + cacheBuffer: _cacheBuffer < 0 ? 0 : _cacheBuffer + clip: true + + property real _margin: ScreenTools.defaultFontPixelWidth / 2 + property real _cacheBuffer: height * 2 + property real _widgetHeight: ScreenTools.defaultFontPixelHeight * 3 + + delegate: Rectangle { + width: parent.width + height: innerColumn.y + innerColumn.height + _margin + color: qgcPal.buttonHighlight + opacity: 0.8 + radius: _margin + + property var _vehicle: object + property color _textColor: "black" + + QGCPalette { id: qgcPal } + + Row { + id: widgetLayout + anchors.margins: _margin + anchors.top: parent.top + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelWidth / 2 + layoutDirection: Qt.RightToLeft + + QGCCompassWidget { + size: _widgetHeight + vehicle: _vehicle + } + + QGCAttitudeWidget { + size: _widgetHeight + vehicle: _vehicle + } + } + + RowLayout { + anchors.top: widgetLayout.top + anchors.bottom: widgetLayout.bottom + anchors.left: parent.left + anchors.right: widgetLayout.left + spacing: ScreenTools.defaultFontPixelWidth / 2 + + QGCLabel { + Layout.alignment: Qt.AlignTop + text: _vehicle.id + color: _textColor + } + + FlightModeMenu { + font.pointSize: ScreenTools.largeFontPointSize + color: _textColor + activeVehicle: _vehicle + } + } + + Column { + id: innerColumn + anchors.margins: _margin + anchors.left: parent.left + anchors.right: parent.right + anchors.top: widgetLayout.bottom + spacing: _margin + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 5 + color: "green" + } + + Row { + spacing: ScreenTools.defaultFontPixelWidth + + QGCButton { + text: "Arm" + visible: !_vehicle.armed + onClicked: _vehicle.armed = true + } + + QGCButton { + text: "Start" + visible: _vehicle.armed && _vehicle.flightMode != _vehicle.missionFlightMode + onClicked: _vehicle.flightMode = _vehicle.missionFlightMode + } + + QGCButton { + text: "Stop" + visible: _vehicle.armed && _vehicle.pauseVehicleSupported + onClicked: _vehicle.pauseVehicle() + } + + QGCButton { + text: "RTL" + visible: _vehicle.armed && _vehicle.flightMode != _vehicle.rtlFlightMode + onClicked: _vehicle.flightMode = _vehicle.rtlFlightMode + } + + QGCButton { + text: "Take control" + visible: _vehicle.armed && _vehicle.flightMode != _vehicle.takeControlFlightMode + onClicked: _vehicle.flightMode = _vehicle.takeControlFlightMode + } + + } + } + } +} // QGCListView diff --git a/src/FlightDisplay/VideoManager.cc b/src/FlightDisplay/VideoManager.cc index 02c325fabffee80638ec6f20bef41ae3002bf4e9..c5c858b593b70ce591dc2f21ccb21d4b39b2b94a 100644 --- a/src/FlightDisplay/VideoManager.cc +++ b/src/FlightDisplay/VideoManager.cc @@ -11,6 +11,8 @@ #include #include #include +#include +#include #ifndef QGC_DISABLE_UVC #include @@ -20,15 +22,10 @@ #include "ScreenToolsController.h" #include "VideoManager.h" - -static const char* kVideoSourceKey = "VideoSource"; -static const char* kVideoUDPPortKey = "VideoUDPPort"; -static const char* kVideoRTSPUrlKey = "VideoRTSPUrl"; -static const char* kUDPStream = "UDP Video Stream"; -#if defined(QGC_GST_STREAMING) -static const char* kRTSPStream = "RTSP Video Stream"; -#endif -static const char* kNoVideo = "No Video Available"; +#include "QGCToolbox.h" +#include "QGCCorePlugin.h" +#include "QGCOptions.h" +#include "Settings/SettingsManager.h" QGC_LOGGING_CATEGORY(VideoManagerLog, "VideoManagerLog") @@ -38,20 +35,9 @@ VideoManager::VideoManager(QGCApplication* app) , _videoSurface(NULL) , _videoReceiver(NULL) , _videoRunning(false) - , _udpPort(5600) //-- Defalut Port 5600 == Solo UDP Port , _init(false) + , _videoSettings(NULL) { - //-- Get saved settings - QSettings settings; - setVideoSource(settings.value(kVideoSourceKey, kUDPStream).toString()); - setUdpPort(settings.value(kVideoUDPPortKey, 5600).toUInt()); - setRtspURL(settings.value(kVideoRTSPUrlKey, "rtsp://192.168.42.1:554/live").toString()); //-- Example RTSP URL - _init = true; -#if defined(QGC_GST_STREAMING) - _updateVideo(); - connect(&_frameTimer, &QTimer::timeout, this, &VideoManager::_updateTimer); - _frameTimer.start(1000); -#endif } //----------------------------------------------------------------------------- @@ -67,66 +53,28 @@ VideoManager::setToolbox(QGCToolbox *toolbox) QGCTool::setToolbox(toolbox); QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); qmlRegisterUncreatableType("QGroundControl.VideoManager", 1, 0, "VideoManager", "Reference only"); -} -//----------------------------------------------------------------------------- -bool -VideoManager::hasVideo() -{ -#if defined(QGC_GST_STREAMING) - return true; -#endif - return !_videoSource.isEmpty(); -} + _videoSettings = toolbox->settingsManager()->videoSettings(); + QString videoSource = _videoSettings->videoSource()->rawValue().toString(); + connect(_videoSettings->videoSource(), &Fact::rawValueChanged, this, &VideoManager::_videoSourceChanged); -//----------------------------------------------------------------------------- -bool -VideoManager::isGStreamer() -{ #if defined(QGC_GST_STREAMING) - return _videoSource == kUDPStream || _videoSource == kRTSPStream; -#else - return false; -#endif -} - -//----------------------------------------------------------------------------- -#ifndef QGC_DISABLE_UVC -bool -VideoManager::uvcEnabled() -{ - return QCameraInfo::availableCameras().count() > 0; -} -#endif - -//----------------------------------------------------------------------------- -void -VideoManager::setVideoSource(QString vSource) -{ - if(vSource == kNoVideo) - return; - _videoSource = vSource; - QSettings settings; - settings.setValue(kVideoSourceKey, vSource); - emit videoSourceChanged(); #ifndef QGC_DISABLE_UVC + // If we are using a UVC camera setup the device name QList cameras = QCameraInfo::availableCameras(); foreach (const QCameraInfo &cameraInfo, cameras) { - if(cameraInfo.description() == vSource) { + if(cameraInfo.description() == videoSource) { _videoSourceID = cameraInfo.deviceName(); emit videoSourceIDChanged(); - qCDebug(VideoManagerLog) << "Found USB source:" << _videoSourceID << " Name:" << _videoSource; + qCDebug(VideoManagerLog) << "Found USB source:" << _videoSourceID << " Name:" << videoSource; break; } } #endif + emit isGStreamerChanged(); - qCDebug(VideoManagerLog) << "New Video Source:" << vSource; - /* - * Not working. Requires restart for now. (Undef KRTSP/kUDP above when enabling this) - if(isGStreamer()) - _updateVideo(); - */ + qCDebug(VideoManagerLog) << "New Video Source:" << videoSource; + if(_videoReceiver) { if(isGStreamer()) { _videoReceiver->start(); @@ -134,85 +82,89 @@ VideoManager::setVideoSource(QString vSource) _videoReceiver->stop(); } } +#endif + + _init = true; +#if defined(QGC_GST_STREAMING) + _updateVideo(); + connect(&_frameTimer, &QTimer::timeout, this, &VideoManager::_updateTimer); + _frameTimer.start(1000); +#endif } -//----------------------------------------------------------------------------- -void -VideoManager::setUdpPort(quint16 port) +void VideoManager::_videoSourceChanged(void) { - _udpPort = port; - QSettings settings; - settings.setValue(kVideoUDPPortKey, port); - emit udpPortChanged(); - /* - * Not working. Requires restart for now. (Undef KRTSP/kUDP above when enabling this) - if(_videoSource == kUDPStream) - _updateVideo(); - */ + emit hasVideoChanged(); + emit isGStreamerChanged(); } //----------------------------------------------------------------------------- -void -VideoManager::setRtspURL(QString url) +bool +VideoManager::hasVideo() { - _rtspURL = url; - QSettings settings; - settings.setValue(kVideoRTSPUrlKey, url); - emit rtspURLChanged(); - /* - * Not working. Requires restart for now. (Undef KRTSP/kUDP above when enabling this) - if(_videoSource == kRTSPStream) - _updateVideo(); - */ +#if defined(QGC_GST_STREAMING) + return true; +#endif + QString videoSource = _videoSettings->videoSource()->rawValue().toString(); + return !videoSource.isEmpty() && videoSource != VideoSettings::videoSourceNoVideo; } //----------------------------------------------------------------------------- -QStringList -VideoManager::videoSourceList() +bool +VideoManager::isGStreamer() { - _videoSourceList.clear(); #if defined(QGC_GST_STREAMING) - _videoSourceList.append(kUDPStream); - _videoSourceList.append(kRTSPStream); + QString videoSource = _videoSettings->videoSource()->rawValue().toString(); + return videoSource == VideoSettings::videoSourceUDP || videoSource == VideoSettings::videoSourceRTSP; +#else + return false; #endif +} + +//----------------------------------------------------------------------------- #ifndef QGC_DISABLE_UVC - QList cameras = QCameraInfo::availableCameras(); - foreach (const QCameraInfo &cameraInfo, cameras) { - qCDebug(VideoManagerLog) << "UVC Video source ID:" << cameraInfo.deviceName() << " Name:" << cameraInfo.description(); - _videoSourceList.append(cameraInfo.description()); - } -#endif - if(_videoSourceList.count() == 0) - _videoSourceList.append(kNoVideo); - return _videoSourceList; +bool +VideoManager::uvcEnabled() +{ + return QCameraInfo::availableCameras().count() > 0; } +#endif //----------------------------------------------------------------------------- void VideoManager::_updateTimer() { #if defined(QGC_GST_STREAMING) - if(_videoRunning) - { - time_t elapsed = 0; - if(_videoSurface) - { - elapsed = time(0) - _videoSurface->lastFrame(); - } - if(elapsed > 2 && _videoSurface) - { - _videoRunning = false; - _videoSurface->setLastFrame(0); - emit videoRunningChanged(); + if(_videoReceiver && _videoSurface) { + if(_videoReceiver->stopping() || _videoReceiver->starting()) { + return; } - } - else - { - if(_videoSurface && _videoSurface->lastFrame()) { - if(!_videoRunning) - { + + if(_videoReceiver->streaming()) { + if(!_videoRunning) { + _videoSurface->setLastFrame(0); _videoRunning = true; emit videoRunningChanged(); } + } else { + if(_videoRunning) { + _videoRunning = false; + emit videoRunningChanged(); + } + } + + if(_videoRunning) { + time_t elapsed = 0; + time_t lastFrame = _videoSurface->lastFrame(); + if(lastFrame != 0) { + elapsed = time(0) - _videoSurface->lastFrame(); + } + if(elapsed > 2 && _videoSurface) { + _videoReceiver->stop(); + } + } else { + if(!_videoReceiver->running()) { + _videoReceiver->start(); + } } } #endif @@ -228,13 +180,14 @@ void VideoManager::_updateVideo() delete _videoSurface; _videoSurface = new VideoSurface; _videoReceiver = new VideoReceiver(this); - #if defined(QGC_GST_STREAMING) +#if defined(QGC_GST_STREAMING) _videoReceiver->setVideoSink(_videoSurface->videoSink()); - if(_videoSource == kUDPStream) - _videoReceiver->setUri(QStringLiteral("udp://0.0.0.0:%1").arg(_udpPort)); + QString videoSource = _videoSettings->videoSource()->rawValue().toString(); + if (_videoSettings->videoSource()->rawValue().toString() == VideoSettings::videoSourceUDP) + _videoReceiver->setUri(QStringLiteral("udp://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt())); else - _videoReceiver->setUri(_rtspURL); - #endif + _videoReceiver->setUri(_videoSettings->rtspUrl()->rawValue().toString()); +#endif _videoReceiver->start(); } } diff --git a/src/FlightDisplay/VideoManager.h b/src/FlightDisplay/VideoManager.h index 2ff5cfac6e476c9eea7b5c16c2c5fa9408bc2406..aaffec22e3c3cb52ad18d5fefc512273cd103c2a 100644 --- a/src/FlightDisplay/VideoManager.h +++ b/src/FlightDisplay/VideoManager.h @@ -13,6 +13,7 @@ #include #include +#include #include "QGCLoggingCategory.h" #include "VideoSurface.h" @@ -21,6 +22,8 @@ Q_DECLARE_LOGGING_CATEGORY(VideoManagerLog) +class VideoSettings; + class VideoManager : public QGCTool { Q_OBJECT @@ -29,26 +32,19 @@ public: VideoManager (QGCApplication* app); ~VideoManager (); - Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged) - Q_PROPERTY(bool isGStreamer READ isGStreamer NOTIFY isGStreamerChanged) - Q_PROPERTY(QString videoSourceID READ videoSourceID NOTIFY videoSourceIDChanged) - Q_PROPERTY(QString videoSource READ videoSource WRITE setVideoSource NOTIFY videoSourceChanged) - Q_PROPERTY(QStringList videoSourceList READ videoSourceList NOTIFY videoSourceListChanged) - Q_PROPERTY(bool videoRunning READ videoRunning NOTIFY videoRunningChanged) - Q_PROPERTY(quint16 udpPort READ udpPort WRITE setUdpPort NOTIFY udpPortChanged) - Q_PROPERTY(QString rtspURL READ rtspURL WRITE setRtspURL NOTIFY rtspURLChanged) - Q_PROPERTY(bool uvcEnabled READ uvcEnabled CONSTANT) - Q_PROPERTY(VideoSurface* videoSurface MEMBER _videoSurface CONSTANT) - Q_PROPERTY(VideoReceiver* videoReceiver MEMBER _videoReceiver CONSTANT) + Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged) + Q_PROPERTY(bool isGStreamer READ isGStreamer NOTIFY isGStreamerChanged) + Q_PROPERTY(QString videoSourceID READ videoSourceID NOTIFY videoSourceIDChanged) + Q_PROPERTY(bool videoRunning READ videoRunning NOTIFY videoRunningChanged) + Q_PROPERTY(bool uvcEnabled READ uvcEnabled CONSTANT) + Q_PROPERTY(VideoSurface* videoSurface MEMBER _videoSurface CONSTANT) + Q_PROPERTY(VideoReceiver* videoReceiver MEMBER _videoReceiver CONSTANT) + Q_PROPERTY(bool recordingEnabled READ recordingEnabled CONSTANT) bool hasVideo (); bool isGStreamer (); bool videoRunning () { return _videoRunning; } QString videoSourceID () { return _videoSourceID; } - QString videoSource () { return _videoSource; } - QStringList videoSourceList (); - quint16 udpPort () { return _udpPort; } - QString rtspURL () { return _rtspURL; } #if defined(QGC_DISABLE_UVC) bool uvcEnabled () { return false; } @@ -56,9 +52,11 @@ public: bool uvcEnabled (); #endif - void setVideoSource (QString vSource); - void setUdpPort (quint16 port); - void setRtspURL (QString url); +#if defined(QGC_GST_STREAMING) && defined(QGC_ENABLE_VIDEORECORDING) + bool recordingEnabled () { return true; } +#else + bool recordingEnabled () { return false; } +#endif // Override from QGCTool void setToolbox (QGCToolbox *toolbox); @@ -66,30 +64,25 @@ public: signals: void hasVideoChanged (); void videoRunningChanged (); - void videoSourceChanged (); - void videoSourceListChanged (); void isGStreamerChanged (); void videoSourceIDChanged (); - void udpPortChanged (); - void rtspURLChanged (); + +private slots: + void _videoSourceChanged(void); private: void _updateTimer (); void _updateVideo (); -private: - VideoSurface* _videoSurface; - VideoReceiver* _videoReceiver; - bool _videoRunning; + VideoSurface* _videoSurface; + VideoReceiver* _videoReceiver; + bool _videoRunning; #if defined(QGC_GST_STREAMING) - QTimer _frameTimer; + QTimer _frameTimer; #endif - QString _videoSource; - QString _videoSourceID; - QStringList _videoSourceList; - quint16 _udpPort; - QString _rtspURL; - bool _init; + QString _videoSourceID; + bool _init; + VideoSettings* _videoSettings; }; #endif diff --git a/src/FlightDisplay/VirtualJoystick.qml b/src/FlightDisplay/VirtualJoystick.qml index 07248d6df162d007ab36bc99a29a79df586ebca9..f10d4e2d25e74641bcad74a40a398217fc9c9b83 100644 --- a/src/FlightDisplay/VirtualJoystick.qml +++ b/src/FlightDisplay/VirtualJoystick.qml @@ -21,7 +21,7 @@ Item { Timer { interval: 40 // 25Hz, same as real joystick rate - running: QGroundControl.virtualTabletJoystick && _activeVehicle + running: QGroundControl.settingsManager.appSettings.virtualJoystick.value && _activeVehicle repeat: true onTriggered: { if (_activeVehicle) { diff --git a/src/FlightDisplay/qmldir b/src/FlightDisplay/qmldir index 68ea784d7ebd8050175949dc10d5a1b62d48b962..bdcc8b713ff35bf132244fbcdb4e358a00f38d3f 100644 --- a/src/FlightDisplay/qmldir +++ b/src/FlightDisplay/qmldir @@ -2,4 +2,7 @@ Module QGroundControl.FlightDisplay FlightDisplayView 1.0 FlightDisplayView.qml FlightDisplayViewMap 1.0 FlightDisplayViewMap.qml +FlightDisplayViewVideo 1.0 FlightDisplayViewVideo.qml +FlightDisplayViewWidgets 1.0 FlightDisplayViewWidgets.qml +MultiVehicleList 1.0 MultiVehicleList.qml diff --git a/src/FlightMap/FlightMap.qml b/src/FlightMap/FlightMap.qml index 2d3b7f2df94df111cea747b4e3a7cdc9701fd063..076641a91b8d06422e034eb9fc71bfcb68f9d0f5 100644 --- a/src/FlightMap/FlightMap.qml +++ b/src/FlightMap/FlightMap.qml @@ -82,6 +82,14 @@ Map { scaleText.text = text } + function setVisibleRegion(region) { + // This works around a bug on Qt where if you set a visibleRegion and then the user moves or zooms the map + // and then you set the same visibleRegion the map will not move/scale appropriately since it thinks there + // is nothing to do. + _map.visibleRegion = QtPositioning.rectangle(QtPositioning.coordinate(0, 0), QtPositioning.coordinate(0, 0)) + _map.visibleRegion = region + } + zoomLevel: 18 center: QGroundControl.lastKnownHomePosition gesture.flickDeceleration: 3000 @@ -121,8 +129,8 @@ Map { /// Ground Station location MapQuickItem { - anchorPoint.x: sourceItem.width / 2 - anchorPoint.y: sourceItem.height / 2 + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY visible: mainWindow.gcsPosition.isValid coordinate: mainWindow.gcsPosition sourceItem: MissionItemIndexLabel { @@ -153,13 +161,14 @@ Map { // Not sure why this is needed, but trying to reference polygonDrawer directly from other code doesn't work property alias polygonDraw: polygonDrawer - QGCLabel { - id: polygonHelp + QGCMapLabel { + id: polygonHelp anchors.topMargin: parent.height - ScreenTools.availableHeight anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right horizontalAlignment: Text.AlignHCenter + map: _map text: qsTr("Click to add point %1").arg(ScreenTools.isMobile || !polygonDrawer.polygonReady ? "" : qsTr("- Right Click to end polygon")) visible: polygonDrawer.drawingPolygon @@ -349,8 +358,17 @@ Map { // Add first coordinate polygonPath.push(clickCoordinate) } else { - // Update finalized coordinate - polygonPath[polygonDrawerPolygon.path.length - 1] = clickCoordinate + // Add subsequent coordinate + if (ScreenTools.isMobile) { + // Since mobile has no mouse, the onPositionChangedHandler will not fire. We have to add the coordinate + // here instead. + polygonDrawer.justClicked = false + polygonPath.push(clickCoordinate) + } else { + // The onPositionChanged handler for mouse movement will have already added the coordinate to the array. + // Just update it to the final position + polygonPath[polygonDrawerPolygon.path.length - 1] = clickCoordinate + } } polygonDrawerPolygonSet.path = polygonPath polygonDrawerPolygon.path = polygonPath @@ -360,10 +378,15 @@ Map { } onPositionChanged: { + if (ScreenTools.isMobile) { + // We don't track mouse drag on mobile + return + } if (polygonDrawerPolygon.path.length) { var dragCoordinate = _map.toCoordinate(Qt.point(mouse.x, mouse.y)) var polygonPath = polygonDrawerPolygon.path if (polygonDrawer.justClicked){ + // Add new drag coordinate polygonPath.push(dragCoordinate) polygonDrawer.justClicked = false } diff --git a/src/FlightMap/Images/ArrowHead.svg b/src/FlightMap/Images/ArrowHead.svg deleted file mode 100644 index fd70dad199cbd16661d51f6c2a441012b0db042f..0000000000000000000000000000000000000000 --- a/src/FlightMap/Images/ArrowHead.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - diff --git a/src/FlightMap/Images/airplaneOpaque.svg b/src/FlightMap/Images/airplaneOpaque.svg deleted file mode 100644 index c9ac663f140ed7f870cc015218fc953cc3bf8afc..0000000000000000000000000000000000000000 --- a/src/FlightMap/Images/airplaneOpaque.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - -Layer 1 - - diff --git a/src/FlightMap/Images/airplaneOutline.svg b/src/FlightMap/Images/airplaneOutline.svg deleted file mode 100644 index 686381d439e6339491df6d4ffb66d0031fab1b4e..0000000000000000000000000000000000000000 --- a/src/FlightMap/Images/airplaneOutline.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - -Layer 1 - - diff --git a/src/FlightMap/Images/buttonHome.svg b/src/FlightMap/Images/buttonHome.svg deleted file mode 100644 index 22012e566112b73bc1895eb2985218aba83fa233..0000000000000000000000000000000000000000 --- a/src/FlightMap/Images/buttonHome.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/src/FlightMap/Images/buttonMore.svg b/src/FlightMap/Images/buttonMore.svg deleted file mode 100644 index f19e27ff1d2055cffd7b421e68aff96ebec46aae..0000000000000000000000000000000000000000 --- a/src/FlightMap/Images/buttonMore.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/FlightMap/Images/compassInstrumentAirplane.svg b/src/FlightMap/Images/compassInstrumentAirplane.svg deleted file mode 100644 index 5fdc728643a4717abace682c31d7d4c61d97bfdf..0000000000000000000000000000000000000000 --- a/src/FlightMap/Images/compassInstrumentAirplane.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - diff --git a/src/FlightMap/Images/compassInstrumentArrow.svg b/src/FlightMap/Images/compassInstrumentArrow.svg new file mode 100644 index 0000000000000000000000000000000000000000..433119885f8a8fc7e7df186d9602685adb935759 --- /dev/null +++ b/src/FlightMap/Images/compassInstrumentArrow.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/FlightMap/Images/vehicleArrowOpaque.svg b/src/FlightMap/Images/vehicleArrowOpaque.svg new file mode 100644 index 0000000000000000000000000000000000000000..3f71ec00d60818b67803c725bfe8da709d52662c --- /dev/null +++ b/src/FlightMap/Images/vehicleArrowOpaque.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/FlightMap/Images/vehicleArrowOutline.svg b/src/FlightMap/Images/vehicleArrowOutline.svg new file mode 100644 index 0000000000000000000000000000000000000000..991d6185e2720ff7d68a32ba02ddfebd279402dd --- /dev/null +++ b/src/FlightMap/Images/vehicleArrowOutline.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/FlightMap/MapItems/MissionItemIndicator.qml b/src/FlightMap/MapItems/MissionItemIndicator.qml index ec325c1ec81ad5b3b1f81c7f42cb560c1cd7230f..58ad845430ee9c7460a3d7e61a9830e319d8c7b1 100644 --- a/src/FlightMap/MapItems/MissionItemIndicator.qml +++ b/src/FlightMap/MapItems/MissionItemIndicator.qml @@ -24,8 +24,8 @@ MapQuickItem { signal clicked - anchorPoint.x: sourceItem.width / 2 - anchorPoint.y: sourceItem.height / 2 + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY sourceItem: MissionItemIndexLabel { diff --git a/src/FlightMap/MapItems/VehicleMapItem.qml b/src/FlightMap/MapItems/VehicleMapItem.qml index 4bc9a3a49837cc4628bdf887a3cc987340149a8a..fa1988a2e70bcf5beb6af25012af3ada1a8c99a1 100644 --- a/src/FlightMap/MapItems/VehicleMapItem.qml +++ b/src/FlightMap/MapItems/VehicleMapItem.qml @@ -30,7 +30,7 @@ MapQuickItem { sourceItem: Image { id: vehicleIcon - source: isSatellite ? "/qmlimages/airplaneOpaque.svg" : "/qmlimages/airplaneOutline.svg" + source: isSatellite ? vehicle.vehicleImageOpaque : vehicle.vehicleImageOutline mipmap: true width: size sourceSize.width: size diff --git a/src/FlightMap/MapScale.qml b/src/FlightMap/MapScale.qml index 7c0d878bebd1ca4ee2ab53ba1263619158be0f66..8a265d86398904f128e0779636ec5e18d3fb6830 100644 --- a/src/FlightMap/MapScale.qml +++ b/src/FlightMap/MapScale.qml @@ -10,9 +10,10 @@ import QtQuick 2.4 import QtQuick.Controls 1.3 -import QGroundControl 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.ScreenTools 1.0 +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.SettingsManager 1.0 /// Map scale control Item { @@ -114,7 +115,7 @@ Item { var rightCoord = mapControl.toCoordinate(Qt.point(scaleLinePixelLength, scale.y)) var scaleLineMeters = Math.round(leftCoord.distanceTo(rightCoord)) - if (QGroundControl.distanceUnits.value == QGroundControl.DistanceUnitsFeet) { + if (QGroundControl.settingsManager.unitsSettings.distanceUnits.value == UnitsSettings.DistanceUnitsFeet) { calculateFeetRatio(scaleLineMeters, scaleLinePixelLength) } else { calculateMetersRatio(scaleLineMeters, scaleLinePixelLength) @@ -138,9 +139,9 @@ Item { onTriggered: calculateScale() } - QGCLabel { + QGCMapLabel { id: scaleText - color: _color + map: mapControl font.family: ScreenTools.demiboldFontFamily anchors.left: parent.left anchors.right: parent.right diff --git a/src/FlightMap/Widgets/CameraWidget.qml b/src/FlightMap/Widgets/CameraWidget.qml new file mode 100644 index 0000000000000000000000000000000000000000..8e0ec95ce15a6ef7cfff29826b81e17cb4341eed --- /dev/null +++ b/src/FlightMap/Widgets/CameraWidget.qml @@ -0,0 +1,54 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 + +/// Camera controls used in InstrumentSwipeView +QGCFlickable { + id: _root + height: Math.min(maxHeight, column.height) + contentHeight: column.height + flickableDirection: Flickable.VerticalFlick + clip: true + + property var qgcView + property color textColor + property var maxHeight + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + + MouseArea { + anchors.fill: parent + onClicked: showNextPage() + } + + Column { + id: column + width: parent.width + spacing: ScreenTools.defaultFontPixelHeight + + QGCLabel { + anchors.horizontalCenter: parent.horizontalCenter + color: textColor + text: qsTr("Camera Controls") + } + + QGCButton { + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Trigger Camera") + onClicked: _activeVehicle.triggerCamera() + enabled: _activeVehicle + } + } +} diff --git a/src/FlightMap/Widgets/CenterMapDropButton.qml b/src/FlightMap/Widgets/CenterMapDropButton.qml new file mode 100644 index 0000000000000000000000000000000000000000..9fb58839e6a5e88e991b3aa2e0c362f414af44cc --- /dev/null +++ b/src/FlightMap/Widgets/CenterMapDropButton.qml @@ -0,0 +1,235 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Controls 1.3 +import QtQuick.Layouts 1.2 +import QtPositioning 5.3 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 + +DropButton { + id: dropButton + dropDirection: dropRight + buttonImage: "/qmlimages/MapCenter.svg" + viewportMargins: ScreenTools.defaultFontPixelWidth / 2 + lightBorders: map.isSatelliteMap + + property var map + property rect mapFitViewport + property bool usePlannedHomePosition ///< true: planned home position used for calculations, false: vehicle home position use for calculations + property var geoFenceController + property var missionController + property var rallyPointController + property bool showMission: true + property bool showAllItems: true + property bool showFollowVehicle: false + property bool followVehicle: false + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + + function fitHomePosition() { + var homePosition = QtPositioning.coordinate() + var activeVehicle = QGroundControl.multiVehicleManager.activeVehicle + if (usePlannedHomePosition) { + homePosition = missionController.visualItems.get(0).coordinate + } else if (activeVehicle) { + homePosition = activeVehicle.homePosition + } + return homePosition + } + + /// Normalize latitude to range: 0 to 180, S to N + function normalizeLat(lat) { + return lat + 90.0 + } + + /// Normalize longitude to range: 0 to 360, W to E + function normalizeLon(lon) { + return lon + 180.0 + } + + /// Fits the visible region of the map to inclues all of the specified coordinates. If no coordinates + /// are specified the map will center to fitHomePosition() + function fitMapViewportToAllCoordinates(coordList) { + if (coordList.length == 0) { + map.center = fitHomePosition() + return + } + + // Create the normalized lat/lon corners for the coordinate bounding rect from the list of coordinates + var north = normalizeLat(coordList[0].latitude) + var south = north + var east = normalizeLon(coordList[0].longitude) + var west = east + for (var i=1; i 2) { + for (var i=0; i + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Controls 1.3 +import QtQuick.Layouts 1.2 +import QtPositioning 5.3 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 + +ColumnLayout { + id: root + spacing: ScreenTools.defaultFontPixelWidth * 0.5 + + property var map + property var fitFunctions + property bool showMission: true + property bool showAllItems: true + property bool showFollowVehicle: false + property bool followVehicle: false + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + + QGCLabel { text: qsTr("Center map on:") } + + QGCButton { + text: qsTr("Mission") + Layout.fillWidth: true + visible: showMission + enabled: !followVehicleCheckBox.checked + + onClicked: { + dropPanel.hide() + fitFunctions.fitMapViewportToMissionItems() + } + } + + QGCButton { + text: qsTr("All items") + Layout.fillWidth: true + visible: showAllItems + enabled: !followVehicleCheckBox.checked + + onClicked: { + dropPanel.hide() + fitFunctions.fitMapViewportToAllItems() + } + } + + QGCButton { + text: qsTr("Home") + Layout.fillWidth: true + enabled: !followVehicleCheckBox.checked + + onClicked: { + dropPanel.hide() + map.center = fitFunctions.fitHomePosition() + } + } + + QGCButton { + text: qsTr("Current Location") + Layout.fillWidth: true + enabled: mainWindow.gcsPosition.isValid && !followVehicleCheckBox.checked + + onClicked: { + dropPanel.hide() + map.center = mainWindow.gcsPosition + } + } + + QGCButton { + text: qsTr("Vehicle") + Layout.fillWidth: true + enabled: _activeVehicle && _activeVehicle.latitude != 0 && _activeVehicle.longitude != 0 && !followVehicleCheckBox.checked + + onClicked: { + dropPanel.hide() + map.center = activeVehicle.coordinate + } + } + + QGCCheckBox { + id: followVehicleCheckBox + text: qsTr("Follow Vehicle") + checked: followVehicle + visible: showFollowVehicle + + onClicked: { + dropPanel.hide() + root.followVehicle = checked + } + } +} // Column diff --git a/src/FlightMap/Widgets/InstrumentSwipeView.qml b/src/FlightMap/Widgets/InstrumentSwipeView.qml index 7e5128d4e739fc0eb47da0586d9e02b17aac7d74..22ec90583a3cf666723ca9ef51b12a0fc6b266f9 100644 --- a/src/FlightMap/Widgets/InstrumentSwipeView.qml +++ b/src/FlightMap/Widgets/InstrumentSwipeView.qml @@ -1,106 +1,99 @@ import QtQuick 2.5 -import QtQuick.Controls 1.4 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 import QGroundControl.Palette 1.0 import QGroundControl.ScreenTools 1.0 import QGroundControl.FlightMap 1.0 Item { - id: _root - clip: true - height: valuesPage.height + pageIndicatorRow.anchors.topMargin + pageIndicatorRow.height + id: _root + clip: true + height: column.height - property var qgcView ///< QGCView to use for showing dialogs + property var qgcView ///< QGCView to use for showing dialogs property color textColor property color backgroundColor - property var maxHeight ///< Maximum height that should be taken, smaller than this is ok + property var maxHeight ///< Maximum height that should be taken, smaller than this is ok - property real _margins: ScreenTools.defaultFontPixelWidth / 2 + property real _margins: ScreenTools.defaultFontPixelWidth / 2 + property real _pageWidth: _root.width + property int _currentPage: 0 + property int _maxPage: 3 + + onWidthChanged: showPage(_currentPage) function showPicker() { valuesPage.showPicker() } - ValuesWidget { - id: valuesPage - width: _root.width - qgcView: _root.qgcView - textColor: _root.textColor - maxHeight: _root.maxHeight - } - - VibrationWidget { - id: vibrationPage - anchors.left: valuesPage.right - width: _root.width - textColor: _root.textColor - backgroundColor: _root.backgroundColor - maxHeight: _root.maxHeight + function showPage(pageIndex) { + pageRow.x = -(pageIndex * _pageWidth) } - Row { - id: pageIndicatorRow - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - spacing: _margins - - Rectangle { - id: valuesPageIndicator - height: radius * 2 - width: radius * 2 - radius: 2.5 - border.color: textColor - border.width: 1 - color: textColor - } - - Rectangle { - id: vibrationPageIndicator - height: radius * 2 - width: radius * 2 - radius: 2.5 - border.color: textColor - border.width: 1 - color: "transparent" + function showNextPage() { + if (_currentPage == _maxPage) { + _currentPage = 0 + } else { + _currentPage++ } + showPage(_currentPage) } MouseArea { - anchors.fill: parent + anchors.fill: parent + onClicked: showNextPage() + } - property real xDragStart - property real xValuesPageSave + Column { + id: column + anchors.left: parent.left + anchors.right: parent.right - onPressed: { - if (mouse.button == Qt.LeftButton) { - mouse.accepted = true - xDragStart = mouse.x - xValuesPageSave = valuesPage.x + Row { + id: pageRow + + ValuesWidget { + id: valuesPage + width: _pageWidth + qgcView: _root.qgcView + textColor: _root.textColor + maxHeight: _root.maxHeight + } + CameraWidget { + width: _pageWidth + qgcView: _root.qgcView + textColor: _root.textColor + maxHeight: _root.maxHeight + } + VehicleHealthWidget { + width: _pageWidth + qgcView: _root.qgcView + textColor: _root.textColor + maxHeight: _root.maxHeight + } + VibrationWidget { + width: _pageWidth + textColor: _root.textColor + backgroundColor: _root.backgroundColor + maxHeight: _root.maxHeight } } - onPositionChanged: { - valuesPage.x = xValuesPageSave + mouse.x - xDragStart - } + Row { + anchors.horizontalCenter: parent.horizontalCenter + spacing: _margins - onReleased: { - if (mouse.x < xDragStart) { - if (xValuesPageSave == 0) { - valuesPage.x = -valuesPage.width - _root.height = Qt.binding(function() { return vibrationPage.height + pageIndicatorRow.anchors.topMargin + pageIndicatorRow.height } ) - valuesPageIndicator.color = "transparent" - vibrationPageIndicator.color = textColor - } else { - valuesPage.x = xValuesPageSave - } - } else { - if (xValuesPageSave != 0) { - valuesPage.x = 0 - _root.height = Qt.binding(function() { return valuesPage.height + pageIndicatorRow.anchors.topMargin + pageIndicatorRow.height } ) - valuesPageIndicator.color = textColor - vibrationPageIndicator.color = "transparent" - } else { - valuesPage.x = xValuesPageSave + Repeater { + model: _maxPage + 1 + + Rectangle { + height: radius * 2 + width: radius * 2 + radius: ScreenTools.defaultFontPixelWidth / 3 + border.color: textColor + border.width: 1 + color: _currentPage == index ? textColor : "transparent" } } } diff --git a/src/FlightMap/Widgets/MapFitFunctions.qml b/src/FlightMap/Widgets/MapFitFunctions.qml new file mode 100644 index 0000000000000000000000000000000000000000..dc76a54fe0672d6da042774b93f868d470297972 --- /dev/null +++ b/src/FlightMap/Widgets/MapFitFunctions.qml @@ -0,0 +1,144 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtPositioning 5.3 + +import QGroundControl 1.0 + +/// Set of functions for fitting the map viewpoer to a specific constraint +Item { + property var map + property rect mapFitViewport + property bool usePlannedHomePosition ///< true: planned home position used for calculations, false: vehicle home position use for calculations + property var mapGeoFenceController + property var mapMissionController + property var mapRallyPointController + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + + function fitHomePosition() { + var homePosition = QtPositioning.coordinate() + var activeVehicle = QGroundControl.multiVehicleManager.activeVehicle + if (usePlannedHomePosition) { + homePosition = mapMissionController.visualItems.get(0).coordinate + } else if (activeVehicle) { + homePosition = activeVehicle.homePosition + } + return homePosition + } + + /// Normalize latitude to range: 0 to 180, S to N + function normalizeLat(lat) { + return lat + 90.0 + } + + /// Normalize longitude to range: 0 to 360, W to E + function normalizeLon(lon) { + return lon + 180.0 + } + + /// Fits the visible region of the map to inclues all of the specified coordinates. If no coordinates + /// are specified the map will center to fitHomePosition() + function fitMapViewportToAllCoordinates(coordList) { + if (coordList.length == 0) { + map.center = fitHomePosition() + return + } + + // Create the normalized lat/lon corners for the coordinate bounding rect from the list of coordinates + var north = normalizeLat(coordList[0].latitude) + var south = north + var east = normalizeLon(coordList[0].longitude) + var west = east + for (var i=1; i 2) { + for (var i=0; i + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 + +QGCFlickable { + id: _root + height: Math.min(maxHeight, healthColumn.y + healthColumn.height) + contentHeight: healthColumn.y + healthColumn.height + flickableDirection: Flickable.VerticalFlick + clip: true + + property var qgcView + property color textColor + property var maxHeight + + property var unhealthySensors: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle.unhealthySensors : [ ] + + // Any time the unhealthy sensors list changes, switch to the health page + onUnhealthySensorsChanged: { + if (unhealthySensors.length != 0) { + showPage(1) + } + } + + MouseArea { + anchors.fill: parent + onClicked: showNextPage() + } + + Column { + id: healthColumn + width: parent.width + + QGCLabel { + width: parent.width + horizontalAlignment: Text.AlignHCenter + color: textColor + text: qsTr("Vehicle Health") + } + + QGCLabel { + width: parent.width + horizontalAlignment: Text.AlignHCenter + color: textColor + text: qsTr("All systems healthy") + visible: healthRepeater.count == 0 + } + + Repeater { + id: healthRepeater + model: unhealthySensors + + Row { + Image { + source: "/qmlimages/Yield.svg" + height: ScreenTools.defaultFontPixelHeight + sourceSize.height: height + fillMode: Image.PreserveAspectFit + } + + QGCLabel { + color: textColor + text: modelData + } + } + } + } +} diff --git a/src/FlightMap/Widgets/VibrationWidget.qml b/src/FlightMap/Widgets/VibrationWidget.qml index 96cba71db22ee1715b4952d607b075cb038e0ac7..0a7cb00875a909956d2c693b1c98b797a1a242ce 100644 --- a/src/FlightMap/Widgets/VibrationWidget.qml +++ b/src/FlightMap/Widgets/VibrationWidget.qml @@ -39,6 +39,11 @@ QGCFlickable { QGCPalette { id:qgcPal; colorGroupEnabled: true } + MouseArea { + anchors.fill: parent + onClicked: showNextPage() + } + Item { id: innerItem width: parent.width @@ -157,7 +162,7 @@ QGCFlickable { Rectangle { anchors.fill: parent color: backgroundColor - opacity: 0.95 + opacity: 0.75 visible: _activeVehicle ? isNaN(_activeVehicle.vibration.xAxis.value) : false QGCLabel { diff --git a/src/FlightMap/qmldir b/src/FlightMap/qmldir index 8bc71ce14b0132e5ce75c29fee8559879241589f..8d6f8ededb2ef4047b93d5ec908e6b1f06bb2673 100644 --- a/src/FlightMap/qmldir +++ b/src/FlightMap/qmldir @@ -1,22 +1,25 @@ Module QGroundControl.FlightMap # Main view controls -FlightMap 1.0 FlightMap.qml -QGCVideoBackground 1.0 QGCVideoBackground.qml +FlightMap 1.0 FlightMap.qml +QGCVideoBackground 1.0 QGCVideoBackground.qml # Widgets -InstrumentSwipeView 1.0 InstrumentSwipeView.qml -MapScale 1.0 MapScale.qml -QGCArtificialHorizon 1.0 QGCArtificialHorizon.qml -QGCAttitudeHUD 1.0 QGCAttitudeHUD.qml -QGCAttitudeWidget 1.0 QGCAttitudeWidget.qml -QGCCompassWidget 1.0 QGCCompassWidget.qml -QGCInstrumentWidget 1.0 QGCInstrumentWidget.qml -QGCInstrumentWidgetAlternate 1.0 QGCInstrumentWidgetAlternate.qml -QGCPitchIndicator 1.0 QGCPitchIndicator.qml -QGCSlider 1.0 QGCSlider.qml -ValuesWidget 1.0 ValuesWidget.qml -VibrationWidget 1.0 VibrationWidget.qml +CameraWidget 1.0 CameraWidget.qml +CenterMapDropButton 1.0 CenterMapDropButton.qml +CenterMapDropPanel 1.0 CenterMapDropPanel.qml +InstrumentSwipeView 1.0 InstrumentSwipeView.qml +MapFitFunctions 1.0 MapFitFunctions.qml +MapScale 1.0 MapScale.qml +QGCArtificialHorizon 1.0 QGCArtificialHorizon.qml +QGCAttitudeHUD 1.0 QGCAttitudeHUD.qml +QGCAttitudeWidget 1.0 QGCAttitudeWidget.qml +QGCCompassWidget 1.0 QGCCompassWidget.qml +QGCPitchIndicator 1.0 QGCPitchIndicator.qml +QGCSlider 1.0 QGCSlider.qml +ValuesWidget 1.0 ValuesWidget.qml +VehicleHealthWidget 1.0 VehicleHealthWidget.qml +VibrationWidget 1.0 VibrationWidget.qml # Map items MissionItemIndicator 1.0 MissionItemIndicator.qml diff --git a/src/FollowMe/FollowMe.cc b/src/FollowMe/FollowMe.cc index 196e3223e7d35460f1f7810567308459c260def4..1bb1e188076dc0f455c6df44ac4107ca15267f91 100644 --- a/src/FollowMe/FollowMe.cc +++ b/src/FollowMe/FollowMe.cc @@ -11,7 +11,7 @@ #include #include "MultiVehicleManager.h" -#include "PX4FirmwarePlugin.h" +#include "FirmwarePlugin.h" #include "MAVLinkProtocol.h" #include "FollowMe.h" #include "Vehicle.h" @@ -38,7 +38,7 @@ void FollowMe::followMeHandleManager(const QString&) for (int i=0; i< vehicles.count(); i++) { Vehicle* vehicle = qobject_cast(vehicles[i]); - if (vehicle->px4Firmware() && vehicle->flightMode().compare(PX4FirmwarePlugin::followMeFlightMode, Qt::CaseInsensitive) == 0) { + if (vehicle->px4Firmware() && vehicle->flightMode().compare(FirmwarePlugin::px4FollowMeFlightMode, Qt::CaseInsensitive) == 0) { _enable(); return; } @@ -138,7 +138,7 @@ void FollowMe::_sendGCSMotionReport(void) for (int i=0; i< vehicles.count(); i++) { Vehicle* vehicle = qobject_cast(vehicles[i]); - if(vehicle->flightMode().compare(PX4FirmwarePlugin::followMeFlightMode, Qt::CaseInsensitive) == 0) { + if(vehicle->flightMode().compare(FirmwarePlugin::px4FollowMeFlightMode, Qt::CaseInsensitive) == 0) { mavlink_message_t message; mavlink_msg_follow_target_encode_chan(mavlinkProtocol->getSystemId(), mavlinkProtocol->getComponentId(), diff --git a/src/GAudioOutput.cc b/src/GAudioOutput.cc index 584b5ac5c29e2f9b3bb83590e2ccd619ecb52f4c..480e04dedf38c963409ffa025b2f6aefe336c0a7 100644 --- a/src/GAudioOutput.cc +++ b/src/GAudioOutput.cc @@ -18,31 +18,25 @@ */ #include -#include #include #include "GAudioOutput.h" #include "QGCApplication.h" #include "QGC.h" +#include "SettingsManager.h" #if defined __android__ #include #include #endif -const char* GAudioOutput::_mutedKey = "AudioMuted"; - GAudioOutput::GAudioOutput(QGCApplication* app) : QGCTool(app) - , muted(false) #ifndef __android__ , thread(new QThread()) , worker(new QGCAudioWorker()) #endif { - QSettings settings; - muted = settings.value(_mutedKey, false).toBool(); - muted |= app->runningUnitTests(); #ifndef __android__ worker->moveToThread(thread); connect(this, &GAudioOutput::textToSpeak, worker, &QGCAudioWorker::say); @@ -60,23 +54,10 @@ GAudioOutput::~GAudioOutput() } -void GAudioOutput::mute(bool mute) -{ - QSettings settings; - muted = mute; - settings.setValue(_mutedKey, mute); -#ifndef __android__ - emit mutedChanged(mute); -#endif -} - -bool GAudioOutput::isMuted() -{ - return muted; -} - bool GAudioOutput::say(const QString& inText) { + bool muted = qgcApp()->toolbox()->settingsManager()->appSettings()->audioMuted()->rawValue().toBool(); + muted |= qgcApp()->runningUnitTests(); if (!muted && !qgcApp()->runningUnitTests()) { #if defined __android__ #if defined QGC_SPEECH_ENABLED diff --git a/src/GAudioOutput.h b/src/GAudioOutput.h index 4827e4bb3cf952af1a7cfa6aea71e1f5e4fb4d3e..9a1e40f9df0c032b2a87ae7356e74449001c4868 100644 --- a/src/GAudioOutput.h +++ b/src/GAudioOutput.h @@ -62,30 +62,19 @@ public: AUDIO_SEVERITY_DEBUG = 7 }; - /** @brief Get the mute state */ - bool isMuted(); - public slots: /** @brief Say this text */ bool say(const QString& text); - /** @brief Mute/unmute sound */ - void mute(bool mute); signals: - void mutedChanged(bool); bool textToSpeak(QString text); void beepOnce(); protected: - bool muted; - #if !defined __android__ QThread* thread; QGCAudioWorker* worker; #endif - -private: - static const char* _mutedKey; }; #endif // AUDIOOUTPUT_H diff --git a/src/GPS/definitions.h b/src/GPS/definitions.h index ca655d0b79ea621a8698952941a53e32ce4887be..63fd2c2b100a1ae34a43f1eceb1dd25a30d23468 100644 --- a/src/GPS/definitions.h +++ b/src/GPS/definitions.h @@ -80,10 +80,14 @@ static inline gps_abstime gps_absolute_time() { //timespec is UNIX-specific #ifdef _WIN32 +#if _MSC_VER < 1900 struct timespec { time_t tv_sec; long tv_nsec; }; +#else +#include +#endif #endif diff --git a/src/HomePositionManager.cc b/src/HomePositionManager.cc deleted file mode 100644 index 7d5ef9527e825ed2dbfcfdd2866a4d745fb06c1f..0000000000000000000000000000000000000000 --- a/src/HomePositionManager.cc +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -#include -#include -#include -#include -#include - -#include "UAS.h" -#include "UASInterface.h" -#include "HomePositionManager.h" -#include "QGC.h" -#include "QGCApplication.h" -#include "MultiVehicleManager.h" - -#define PI 3.1415926535897932384626433832795 -#define MEAN_EARTH_DIAMETER 12756274.0 -#define UMR 0.017453292519943295769236907684886 - -const char* HomePositionManager::_settingsGroup = "HomePositionManager"; -const char* HomePositionManager::_latitudeKey = "Latitude"; -const char* HomePositionManager::_longitudeKey = "Longitude"; -const char* HomePositionManager::_altitudeKey = "Altitude"; - -HomePositionManager::HomePositionManager(QGCApplication* app) - : QGCTool(app) - , homeLat(47.3769) - , homeLon(8.549444) - , homeAlt(470.0) -{ - qmlRegisterUncreatableType ("QGroundControl", 1, 0, "HomePositionManager", "Reference only"); -} - -void HomePositionManager::setToolbox(QGCToolbox *toolbox) -{ - QGCTool::setToolbox(toolbox); - - - _loadSettings(); -} - -void HomePositionManager::_storeSettings(void) -{ - QSettings settings; - - settings.remove(_settingsGroup); - settings.beginGroup(_settingsGroup); - - for (int i=0; i<_homePositions.count(); i++) { - HomePosition* homePos = qobject_cast(_homePositions[i]); - - qDebug() << "Saving" << homePos->name(); - - settings.beginGroup(homePos->name()); - settings.setValue(_latitudeKey, homePos->coordinate().latitude()); - settings.setValue(_longitudeKey, homePos->coordinate().longitude()); - settings.setValue(_altitudeKey, homePos->coordinate().altitude()); - settings.endGroup(); - } - - settings.endGroup(); - - // Deprecated settings for old editor - settings.beginGroup("QGC_UASMANAGER"); - settings.setValue("HOMELAT", homeLat); - settings.setValue("HOMELON", homeLon); - settings.setValue("HOMEALT", homeAlt); - settings.endGroup(); -} - -void HomePositionManager::_loadSettings(void) -{ - QSettings settings; - - _homePositions.clear(); - - settings.beginGroup(_settingsGroup); - - foreach(const QString &name, settings.childGroups()) { - QGeoCoordinate coordinate; - - qDebug() << "Load setting" << name; - - settings.beginGroup(name); - coordinate.setLatitude(settings.value(_latitudeKey).toDouble()); - coordinate.setLongitude(settings.value(_longitudeKey).toDouble()); - coordinate.setAltitude(settings.value(_altitudeKey).toDouble()); - settings.endGroup(); - - _homePositions.append(new HomePosition(name, coordinate, this)); - } - - settings.endGroup(); - - if (_homePositions.count() == 0) { - _homePositions.append(new HomePosition("ETH Campus", QGeoCoordinate(47.3769, 8.549444, 470.0), this)); - } -} - -void HomePositionManager::updateHomePosition(const QString& name, const QGeoCoordinate& coordinate) -{ - HomePosition * homePos = NULL; - - for (int i=0; i<_homePositions.count(); i++) { - homePos = qobject_cast(_homePositions[i]); - if (homePos->name() == name) { - break; - } - homePos = NULL; - } - - if (homePos == NULL) { - HomePosition* homePos = new HomePosition(name, coordinate, this); - _homePositions.append(homePos); - } else { - homePos->setName(name); - homePos->setCoordinate(coordinate); - } - - _storeSettings(); -} - -void HomePositionManager::deleteHomePosition(const QString& name) -{ - // Don't allow delete of last position - if (_homePositions.count() == 1) { - return; - } - - qDebug() << "Attempting delete" << name; - - for (int i=0; i<_homePositions.count(); i++) { - if (qobject_cast(_homePositions[i])->name() == name) { - qDebug() << "Deleting" << name; - _homePositions.removeAt(i); - break; - } - } - - _storeSettings(); -} - -HomePosition::HomePosition(const QString& name, const QGeoCoordinate& coordinate, HomePositionManager* homePositionManager, QObject* parent) - : QObject(parent) - , _coordinate(coordinate) - , _homePositionManager(homePositionManager) -{ - setObjectName(name); -} - -HomePosition::~HomePosition() -{ - -} - -QString HomePosition::name(void) -{ - return objectName(); -} - -void HomePosition::setName(const QString& name) -{ - setObjectName(name); - _homePositionManager->_storeSettings(); - emit nameChanged(name); -} - -QGeoCoordinate HomePosition::coordinate(void) -{ - return _coordinate; -} - -void HomePosition::setCoordinate(const QGeoCoordinate& coordinate) -{ - _coordinate = coordinate; - _homePositionManager->_storeSettings(); - emit coordinateChanged(coordinate); -} diff --git a/src/HomePositionManager.h b/src/HomePositionManager.h deleted file mode 100644 index 049b818a79ae3a58ba8c6e6cc7e5bc243b5e56df..0000000000000000000000000000000000000000 --- a/src/HomePositionManager.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -#ifndef HomePositionManager_H -#define HomePositionManager_H - -#include "QmlObjectListModel.h" -#include "QGCToolbox.h" - -#include - -class HomePositionManager; - -class HomePosition : public QObject -{ - Q_OBJECT - -public: - HomePosition(const QString& name, const QGeoCoordinate& coordinate, HomePositionManager* homePositionManager, QObject* parent = NULL); - ~HomePosition(); - - Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) - Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) - - // Property accessors - - QString name(void); - void setName(const QString& name); - - QGeoCoordinate coordinate(void); - void setCoordinate(const QGeoCoordinate& coordinate); - -signals: - void nameChanged(const QString& name); - void coordinateChanged(const QGeoCoordinate& coordinate); - -private: - QGeoCoordinate _coordinate; - HomePositionManager* _homePositionManager; -}; - -class HomePositionManager : public QGCTool -{ - Q_OBJECT - -public: - HomePositionManager(QGCApplication* app); - - Q_PROPERTY(QmlObjectListModel* homePositions READ homePositions CONSTANT) - - /// If name is not already a home position a new one will be added, otherwise the existing - /// home position will be updated - Q_INVOKABLE void updateHomePosition(const QString& name, const QGeoCoordinate& coordinate); - - Q_INVOKABLE void deleteHomePosition(const QString& name); - - // Property accesors - - QmlObjectListModel* homePositions(void) { return &_homePositions; } - - // Should only be called by HomePosition - void _storeSettings(void); - - // Override from QGCTool - virtual void setToolbox(QGCToolbox *toolbox); - -private: - void _loadSettings(void); - - QmlObjectListModel _homePositions; - - static const char* _settingsGroup; - static const char* _latitudeKey; - static const char* _longitudeKey; - static const char* _altitudeKey; - -// Everything below is deprecated and will be removed once old Map code is removed -public: - - // Deprecated methods - - /** @brief Get home position latitude */ - double getHomeLatitude() const { - return homeLat; - } - /** @brief Get home position longitude */ - double getHomeLongitude() const { - return homeLon; - } - /** @brief Get home position altitude */ - double getHomeAltitude() const { - return homeAlt; - } - -protected: - double homeLat; - double homeLon; - double homeAlt; -}; - -#endif diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index 17ce67b478e49a66e087359aeef9597b0df59c3f..36d85721bcc0daa4a9672e44137b36d34c12686d 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -18,13 +18,19 @@ QGC_LOGGING_CATEGORY(JoystickLog, "JoystickLog") QGC_LOGGING_CATEGORY(JoystickValuesLog, "JoystickValuesLog") -const char* Joystick::_settingsGroup = "Joysticks"; -const char* Joystick::_calibratedSettingsKey = "Calibrated1"; // Increment number to force recalibration -const char* Joystick::_buttonActionSettingsKey = "ButtonActionName%1"; -const char* Joystick::_throttleModeSettingsKey = "ThrottleMode"; -const char* Joystick::_exponentialSettingsKey = "Exponential"; -const char* Joystick::_accumulatorSettingsKey = "Accumulator"; -const char* Joystick::_deadbandSettingsKey = "Deadband"; +const char* Joystick::_settingsGroup = "Joysticks"; +const char* Joystick::_calibratedSettingsKey = "Calibrated2"; // Increment number to force recalibration +const char* Joystick::_buttonActionSettingsKey = "ButtonActionName%1"; +const char* Joystick::_throttleModeSettingsKey = "ThrottleMode"; +const char* Joystick::_exponentialSettingsKey = "Exponential"; +const char* Joystick::_accumulatorSettingsKey = "Accumulator"; +const char* Joystick::_deadbandSettingsKey = "Deadband"; +const char* Joystick::_txModeSettingsKey = NULL; +const char* Joystick::_fixedWingTXModeSettingsKey = "TXMode_FixedWing"; +const char* Joystick::_multiRotorTXModeSettingsKey = "TXMode_MultiRotor"; +const char* Joystick::_roverTXModeSettingsKey = "TXMode_Rover"; +const char* Joystick::_vtolTXModeSettingsKey = "TXMode_VTOL"; +const char* Joystick::_submarineTXModeSettingsKey = "TXMode_Submarine"; const char* Joystick::_rgFunctionSettingsKey[Joystick::maxFunction] = { "RollAxis", @@ -33,6 +39,8 @@ const char* Joystick::_rgFunctionSettingsKey[Joystick::maxFunction] = { "ThrottleAxis" }; +int Joystick::_transmitterMode = 2; + Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatCount, MultiVehicleManager* multiVehicleManager) : _exitThread(false) , _name(name) @@ -67,13 +75,74 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatC } _loadSettings(); + + connect(_multiVehicleManager, &MultiVehicleManager::activeVehicleChanged, this, &Joystick::_activeVehicleChanged); } Joystick::~Joystick() { - delete _rgAxisValues; - delete _rgCalibration; - delete _rgButtonValues; + delete[] _rgAxisValues; + delete[] _rgCalibration; + delete[] _rgButtonValues; +} + +void Joystick::_setDefaultCalibration(void) { + QSettings settings; + settings.beginGroup(_settingsGroup); + settings.beginGroup(_name); + _calibrated = settings.value(_calibratedSettingsKey, false).toBool(); + + // Only set default calibrations if we do not have a calibration for this gamecontroller + if(_calibrated) return; + + for(int axis = 0; axis < _axisCount; axis++) { + Joystick::Calibration_t calibration; + _rgCalibration[axis] = calibration; + } + + _rgCalibration[1].reversed = true; + _rgCalibration[3].reversed = true; + + // Default TX Mode 2 axis assignments for gamecontrollers + _rgFunctionAxis[rollFunction] = 2; + _rgFunctionAxis[pitchFunction] = 3; + _rgFunctionAxis[yawFunction] = 0; + _rgFunctionAxis[throttleFunction] = 1; + + _exponential = false; + _accumulator = false; + _deadband = false; + _throttleMode = ThrottleModeCenterZero; + _calibrated = true; + + _saveSettings(); +} + +void Joystick::_activeVehicleChanged(Vehicle *activeVehicle) +{ + if(activeVehicle) { + if(activeVehicle->fixedWing()) { + _txModeSettingsKey = _fixedWingTXModeSettingsKey; + } else if(activeVehicle->multiRotor()) { + _txModeSettingsKey = _multiRotorTXModeSettingsKey; + } else if(activeVehicle->rover()) { + _txModeSettingsKey = _roverTXModeSettingsKey; + } else if(activeVehicle->vtol()) { + _txModeSettingsKey = _vtolTXModeSettingsKey; + } else if(activeVehicle->sub()) { + _txModeSettingsKey = _submarineTXModeSettingsKey; + } else { + _txModeSettingsKey = NULL; + qWarning() << "No valid joystick TXmode settings key for selected vehicle"; + return; + } + + QSettings settings; + settings.beginGroup(_settingsGroup); + int mode = settings.value(_txModeSettingsKey, activeVehicle->firmwarePlugin()->defaultJoystickTXMode()).toInt(); + + setTXMode(mode); + } } void Joystick::_loadSettings(void) @@ -81,6 +150,10 @@ void Joystick::_loadSettings(void) QSettings settings; settings.beginGroup(_settingsGroup); + + if(_txModeSettingsKey) + _transmitterMode = settings.value(_txModeSettingsKey, 2).toInt(); + settings.beginGroup(_name); bool badSettings = false; @@ -96,7 +169,7 @@ void Joystick::_loadSettings(void) _throttleMode = (ThrottleMode_t)settings.value(_throttleModeSettingsKey, ThrottleModeCenterZero).toInt(&convertOk); badSettings |= !convertOk; - qCDebug(JoystickLog) << "_loadSettings calibrated:throttlemode:exponential:deadband:badsettings" << _calibrated << _throttleMode << _exponential << _deadband << badSettings; + qCDebug(JoystickLog) << "_loadSettings calibrated:txmode:throttlemode:exponential:deadband:badsettings" << _calibrated << _transmitterMode << _throttleMode << _exponential << _deadband << badSettings; QString minTpl ("Axis%1Min"); QString maxTpl ("Axis%1Max"); @@ -136,6 +209,10 @@ void Joystick::_loadSettings(void) qCDebug(JoystickLog) << "_loadSettings function:axis:badsettings" << function << functionAxis << badSettings; } + // FunctionAxis mappings are always stored in TX mode 2 + // Remap to stored TX mode in settings + _remapAxes(2, _transmitterMode, _rgFunctionAxis); + for (int button=0; button<_totalButtonCount; button++) { _rgButtonActions << settings.value(QString(_buttonActionSettingsKey).arg(button), QString()).toString(); qCDebug(JoystickLog) << "_loadSettings button:action" << button << _rgButtonActions[button]; @@ -152,6 +229,12 @@ void Joystick::_saveSettings(void) QSettings settings; settings.beginGroup(_settingsGroup); + + // Transmitter mode is static + // Save the mode we are using + if(_txModeSettingsKey) + settings.setValue(_txModeSettingsKey, _transmitterMode); + settings.beginGroup(_name); settings.setValue(_calibratedSettingsKey, _calibrated); @@ -160,7 +243,7 @@ void Joystick::_saveSettings(void) settings.setValue(_deadbandSettingsKey, _deadband); settings.setValue(_throttleModeSettingsKey, _throttleMode); - qCDebug(JoystickLog) << "_saveSettings calibrated:throttlemode:deadband" << _calibrated << _throttleMode << _deadband; + qCDebug(JoystickLog) << "_saveSettings calibrated:throttlemode:deadband:txmode" << _calibrated << _throttleMode << _deadband << _transmitterMode; QString minTpl ("Axis%1Min"); QString maxTpl ("Axis%1Max"); @@ -187,8 +270,13 @@ void Joystick::_saveSettings(void) << calibration->deadband; } + // Always save function Axis mappings in TX Mode 2 + // Write mode 2 mappings without changing mapping currently in use + int temp[maxFunction]; + _remapAxes(_transmitterMode, 2, temp); + for (int function=0; function 0 && mode <= 4) { + _remapAxes(_transmitterMode, mode, _rgFunctionAxis); + _transmitterMode = mode; + _saveSettings(); + } else { + qCWarning(JoystickLog) << "Invalid mode:" << mode; + } +} + /// Adjust the raw axis value to the -1:1 range given calibration information float Joystick::_adjustRange(int value, Calibration_t calibration, bool withDeadbands) { @@ -286,7 +410,7 @@ void Joystick::run(void) } } - if (_calibrationMode != CalibrationModeCalibrating) { + if (_calibrationMode != CalibrationModeCalibrating && _calibrated) { int axis = _rgFunctionAxis[rollFunction]; float roll = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis], _deadband); @@ -406,6 +530,9 @@ void Joystick::startPolling(Vehicle* vehicle) vehicle->setJoystickEnabled(false); } + // Update qml in case of joystick transition + emit calibratedChanged(_calibrated); + // Only connect the new vehicle if it wants joystick data if (vehicle->joystickEnabled()) { _pollingStartedForCalibration = false; @@ -430,14 +557,15 @@ void Joystick::stopPolling(void) if (_activeVehicle && _activeVehicle->joystickEnabled()) { UAS* uas = _activeVehicle->uas(); - + // Neutral attitude controls + // emit manualControl(0, 0, 0, 0.5, 0, _activeVehicle->joystickMode()); disconnect(this, &Joystick::manualControl, uas, &UAS::setExternalControlSetpoint); } // FIXME: **** //disconnect(this, &Joystick::buttonActionTriggered, uas, &UAS::triggerAction); _exitThread = true; - } + } } void Joystick::setCalibration(int axis, Calibration_t& calibration) @@ -471,6 +599,7 @@ void Joystick::setFunctionAxis(AxisFunction_t function, int axis) _calibrated = true; _rgFunctionAxis[function] = axis; + _saveSettings(); emit calibratedChanged(_calibrated); } diff --git a/src/Joystick/Joystick.h b/src/Joystick/Joystick.h index c9915eae20d1c7d6d29600948e7e4493cbc7bbc7..10d65fbfbee2fa0958faee9070027723585357d3 100644 --- a/src/Joystick/Joystick.h +++ b/src/Joystick/Joystick.h @@ -30,12 +30,18 @@ public: ~Joystick(); - typedef struct { + typedef struct Calibration_t { int min; int max; int center; int deadband; bool reversed; + Calibration_t() + : min(-32767) + , max(32767) + , center(0) + , deadband(0) + , reversed(false) {} } Calibration_t; typedef enum { @@ -68,7 +74,8 @@ public: Q_PROPERTY(int throttleMode READ throttleMode WRITE setThrottleMode NOTIFY throttleModeChanged) Q_PROPERTY(bool exponential READ exponential WRITE setExponential NOTIFY exponentialChanged) Q_PROPERTY(bool accumulator READ accumulator WRITE setAccumulator NOTIFY accumulatorChanged) - + Q_PROPERTY(bool requiresCalibration READ requiresCalibration CONSTANT) + // Property accessors int axisCount(void) { return _axisCount; } @@ -88,6 +95,13 @@ public: QVariantList buttonActions(void); QString name(void) { return _name; } + + // Joystick index used by sdl library + // Settable because sdl library remaps indicies after certain events + virtual int index(void) = 0; + virtual void setIndex(int index) = 0; + + virtual bool requiresCalibration(void) { return true; } int throttleMode(void); void setThrottleMode(int mode); @@ -101,6 +115,9 @@ public: bool deadband(void); void setDeadband(bool accu); + void setTXMode(int mode); + int getTXMode(void) { return _transmitterMode; } + typedef enum { CalibrationModeOff, // Not calibrating CalibrationModeMonitor, // Monitors are active, continue to send to vehicle if already polling @@ -141,12 +158,13 @@ signals: void buttonActionTriggered(int action); protected: - void _saveSettings(void); - void _loadSettings(void); - float _adjustRange(int value, Calibration_t calibration, bool withDeadbands); - void _buttonAction(const QString& action); - bool _validAxis(int axis); - bool _validButton(int button); + void _setDefaultCalibration(void); + void _saveSettings(void); + void _loadSettings(void); + float _adjustRange(int value, Calibration_t calibration, bool withDeadbands); + void _buttonAction(const QString& action); + bool _validAxis(int axis); + bool _validButton(int button); private: virtual bool _open() = 0; @@ -157,6 +175,9 @@ private: virtual int _getAxis(int i) = 0; virtual uint8_t _getHat(int hat,int i) = 0; + int _mapFunctionMode(int mode, int function); + void _remapAxes(int currentMode, int newMode, int (&newMapping)[maxFunction]); + // Override from QThread virtual void run(void); @@ -172,6 +193,7 @@ protected: int _hatButtonCount; int _totalButtonCount; + static int _transmitterMode; CalibrationMode_t _calibrationMode; int* _rgAxisValues; @@ -203,6 +225,15 @@ private: static const char* _exponentialSettingsKey; static const char* _accumulatorSettingsKey; static const char* _deadbandSettingsKey; + static const char* _txModeSettingsKey; + static const char* _fixedWingTXModeSettingsKey; + static const char* _multiRotorTXModeSettingsKey; + static const char* _roverTXModeSettingsKey; + static const char* _vtolTXModeSettingsKey; + static const char* _submarineTXModeSettingsKey; + +private slots: + void _activeVehicleChanged(Vehicle* activeVehicle); }; #endif diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 1ef0fc607b73b83326bf5724f84f91958aa2214a..a36f4a64839e38af4e249d6e0e0ba05fc49ed1bf 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -48,14 +48,35 @@ JoystickManager::~JoystickManager() { void JoystickManager::setToolbox(QGCToolbox *toolbox) { - QGCTool::setToolbox(toolbox); + QGCTool::setToolbox(toolbox); _multiVehicleManager = _toolbox->multiVehicleManager(); QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); +} + +void JoystickManager::init() +{ +#ifdef __sdljoystick__ + if (JoystickSDL::init()) { + _setActiveJoystickFromSettings(); + connect(&_joystickCheckTimer, &QTimer::timeout, this, &JoystickManager::_updateAvailableJoysticks); + _joystickCheckTimer.start(250); + } +#elif defined(__android__) + /* + * Android Joystick not yet supported + */ +#endif +} + +void JoystickManager::_setActiveJoystickFromSettings(void) +{ + QMap newMap; #ifdef __sdljoystick__ - _name2JoystickMap = JoystickSDL::discover(_multiVehicleManager); + // Get the latest joystick mapping + newMap = JoystickSDL::discover(_multiVehicleManager); #elif defined(__android__) /* * Android Joystick not yet supported @@ -63,16 +84,31 @@ void JoystickManager::setToolbox(QGCToolbox *toolbox) */ #endif + if (_activeJoystick && !newMap.contains(_activeJoystick->name())) { + qCDebug(JoystickManagerLog) << "Active joystick removed"; + setActiveJoystick(NULL); + } + + // Check to see if our current mapping contains any joysticks that are not in the new mapping + // If so, those joysticks have been unplugged, and need to be cleaned up + QMap::iterator i; + for (i = _name2JoystickMap.begin(); i != _name2JoystickMap.end(); ++i) { + if (!newMap.contains(i.key())) { + qCDebug(JoystickManagerLog) << "Releasing joystick:" << i.key(); + i.value()->stopPolling(); + i.value()->wait(1000); + i.value()->deleteLater(); + } + } + + _name2JoystickMap = newMap; + emit availableJoysticksChanged(); + if (!_name2JoystickMap.count()) { - qCDebug(JoystickManagerLog) << "\tnone found"; + setActiveJoystick(NULL); return; } - _setActiveJoystickFromSettings(); -} - -void JoystickManager::_setActiveJoystickFromSettings(void) -{ QSettings settings; settings.beginGroup(_settingsGroup); @@ -94,23 +130,31 @@ Joystick* JoystickManager::activeJoystick(void) void JoystickManager::setActiveJoystick(Joystick* joystick) { QSettings settings; - - if (!_name2JoystickMap.contains(joystick->name())) { + + if (joystick != NULL && !_name2JoystickMap.contains(joystick->name())) { qCWarning(JoystickManagerLog) << "Set active not in map" << joystick->name(); return; } - + + if (_activeJoystick == joystick) { + return; + } + if (_activeJoystick) { _activeJoystick->stopPolling(); } _activeJoystick = joystick; - settings.beginGroup(_settingsGroup); - settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name()); - + if (_activeJoystick != NULL) { + qCDebug(JoystickManagerLog) << "Set active:" << _activeJoystick->name(); + + settings.beginGroup(_settingsGroup); + settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name()); + } + emit activeJoystickChanged(_activeJoystick); - emit activeJoystickNameChanged(_activeJoystick->name()); + emit activeJoystickNameChanged(_activeJoystick?_activeJoystick->name():""); } QVariantList JoystickManager::joysticks(void) @@ -143,3 +187,31 @@ void JoystickManager::setActiveJoystickName(const QString& name) setActiveJoystick(_name2JoystickMap[name]); } + +void JoystickManager::_updateAvailableJoysticks(void) +{ +#ifdef __sdljoystick__ + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_QUIT: + qCDebug(JoystickManagerLog) << "SDL ERROR:" << SDL_GetError(); + break; + case SDL_JOYDEVICEADDED: + qCDebug(JoystickManagerLog) << "Joystick added:" << event.jdevice.which; + _setActiveJoystickFromSettings(); + break; + case SDL_JOYDEVICEREMOVED: + qCDebug(JoystickManagerLog) << "Joystick removed:" << event.jdevice.which; + _setActiveJoystickFromSettings(); + break; + default: + break; + } + } +#elif defined(__android__) + /* + * Android Joystick not yet supported + */ +#endif +} diff --git a/src/Joystick/JoystickManager.h b/src/Joystick/JoystickManager.h index 26cf0093f986256206b80296044a3846f40e8072..98a3d09ee2c0f58d3101e5dadd55a77291296b3e 100644 --- a/src/Joystick/JoystickManager.h +++ b/src/Joystick/JoystickManager.h @@ -29,8 +29,8 @@ public: ~JoystickManager(); /// List of available joysticks - Q_PROPERTY(QVariantList joysticks READ joysticks CONSTANT) - Q_PROPERTY(QStringList joystickNames READ joystickNames CONSTANT) + Q_PROPERTY(QVariantList joysticks READ joysticks NOTIFY availableJoysticksChanged) + Q_PROPERTY(QStringList joystickNames READ joystickNames NOTIFY availableJoysticksChanged) /// Active joystick Q_PROPERTY(Joystick* activeJoystick READ activeJoystick WRITE setActiveJoystick NOTIFY activeJoystickChanged) @@ -48,11 +48,16 @@ public: // Override from QGCTool virtual void setToolbox(QGCToolbox *toolbox); +public slots: + void init(); + signals: void activeJoystickChanged(Joystick* joystick); void activeJoystickNameChanged(const QString& name); + void availableJoysticksChanged(void); private slots: + void _updateAvailableJoysticks(void); private: void _setActiveJoystickFromSettings(void); @@ -64,6 +69,8 @@ private: static const char * _settingsGroup; static const char * _settingsKeyActiveJoystick; + + QTimer _joystickCheckTimer; }; #endif diff --git a/src/Joystick/JoystickSDL.cc b/src/Joystick/JoystickSDL.cc index c23448026535b13dd9eab5f8d35a2e8986f04f0d..cf7f105b93f069bfa7d9994db019e8f83e7bfc3e 100644 --- a/src/Joystick/JoystickSDL.cc +++ b/src/Joystick/JoystickSDL.cc @@ -10,17 +10,24 @@ JoystickSDL::JoystickSDL(const QString& name, int axisCount, int buttonCount, in , _isGameController(isGameController) , _index(index) { + if(_isGameController) _setDefaultCalibration(); } -QMap JoystickSDL::discover(MultiVehicleManager* _multiVehicleManager) { - static QMap ret; - - if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0) { +bool JoystickSDL::init(void) { + if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) { + SDL_JoystickEventState(SDL_ENABLE); qWarning() << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError(); - return ret; + return false; } _loadGameControllerMappings(); + return true; +} + +QMap JoystickSDL::discover(MultiVehicleManager* _multiVehicleManager) { + static QMap ret; + + QMap newRet; // Load available joysticks @@ -29,11 +36,12 @@ QMap JoystickSDL::discover(MultiVehicleManager* _multiVehicl for (int i=0; i JoystickSDL::discover(MultiVehicleManager* _multiVehicl hatCount = 0; } else { isGameController = false; - axisCount = SDL_JoystickNumAxes(sdlJoystick); - buttonCount = SDL_JoystickNumButtons(sdlJoystick); - hatCount = SDL_JoystickNumHats(sdlJoystick); + if (SDL_Joystick* sdlJoystick = SDL_JoystickOpen(i)) { + SDL_ClearError(); + axisCount = SDL_JoystickNumAxes(sdlJoystick); + buttonCount = SDL_JoystickNumButtons(sdlJoystick); + hatCount = SDL_JoystickNumHats(sdlJoystick); + if (axisCount < 0 || buttonCount < 0 || hatCount < 0) { + qCWarning(JoystickLog) << "\t libsdl error parsing joystick features:" << SDL_GetError(); + } + SDL_JoystickClose(sdlJoystick); + } else { + qCWarning(JoystickLog) << "\t libsdl failed opening joystick" << qPrintable(name) << "error:" << SDL_GetError(); + continue; + } } - SDL_JoystickClose(sdlJoystick); - qCDebug(JoystickLog) << "\t" << name << "axes:" << axisCount << "buttons:" << buttonCount << "hats:" << hatCount << "isGC:" << isGameController; - ret[name] = new JoystickSDL(name, axisCount, buttonCount, hatCount, i, isGameController, _multiVehicleManager); + newRet[name] = new JoystickSDL(name, qMax(0,axisCount), qMax(0,buttonCount), qMax(0,hatCount), i, isGameController, _multiVehicleManager); } else { + newRet[name] = ret[name]; + if (newRet[name]->index() != i) { + newRet[name]->setIndex(i); // This joystick index has been remapped by SDL + } + // Anything left in ret after we exit the loop has been removed (unplugged) and needs to be cleaned up. + // We will handle that in JoystickManager in case the removed joystick was in use. + ret.remove(name); qCDebug(JoystickLog) << "\tSkipping duplicate" << name; } } + + if (!newRet.count()) { + qCDebug(JoystickLog) << "\tnone found"; + } + + ret = newRet; return ret; } @@ -85,11 +114,32 @@ bool JoystickSDL::_open(void) { return false; } + qCDebug(JoystickLog) << "Opened joystick at" << sdlJoystick; + return true; } void JoystickSDL::_close(void) { - SDL_JoystickClose(sdlJoystick); + if (sdlJoystick == NULL) { + qCDebug(JoystickLog) << "Attempt to close null joystick!"; + return; + } + + qCDebug(JoystickLog) << "Closing" << SDL_JoystickName(sdlJoystick) << "at" << sdlJoystick; + + // We get a segfault if we try to close a joystick that has been detached + if (SDL_JoystickGetAttached(sdlJoystick) == SDL_FALSE) { + qCDebug(JoystickLog) << "\tJoystick is not attached!"; + } else { + + if (SDL_JoystickInstanceID(sdlJoystick) != -1) { + qCDebug(JoystickLog) << "\tID:" << SDL_JoystickInstanceID(sdlJoystick); + SDL_JoystickClose(sdlJoystick); + } + } + + sdlJoystick = NULL; + sdlController = NULL; } bool JoystickSDL::_update(void) @@ -123,4 +173,3 @@ uint8_t JoystickSDL::_getHat(int hat,int i) { } return 0; } - diff --git a/src/Joystick/JoystickSDL.h b/src/Joystick/JoystickSDL.h index 2c4a9ca6aeb93fae1880f4f8b3e266604c181eb3..ba74e0a328f68569ee96ec40bfb0b7b7fa32e279 100644 --- a/src/Joystick/JoystickSDL.h +++ b/src/Joystick/JoystickSDL.h @@ -13,6 +13,13 @@ public: JoystickSDL(const QString& name, int axisCount, int buttonCount, int hatCount, int index, bool isGameController, MultiVehicleManager* multiVehicleManager); static QMap discover(MultiVehicleManager* _multiVehicleManager); + static bool init(void); + + int index(void) { return _index; } + void setIndex(int index) { _index = index; } + + // This can be uncommented to hide the calibration buttons for gamecontrollers in the future + // bool requiresCalibration(void) final { return !_isGameController; } private: static void _loadGameControllerMappings(); diff --git a/src/JsonHelper.cc b/src/JsonHelper.cc index b15220ca90f5b7b840c006f54b449ef9e0859ac1..e29a94a899abf5701786b42964519e5006690f43 100644 --- a/src/JsonHelper.cc +++ b/src/JsonHelper.cc @@ -97,10 +97,12 @@ void JsonHelper::saveGeoCoordinate(const QGeoCoordinate& coordinate, bool JsonHelper::validateKeyTypes(const QJsonObject& jsonObject, const QStringList& keys, const QList& types, QString& errorString) { - for (int i=0; i supportedMajorVersion || (fileMajorVersion == supportedMajorVersion && fileMinorVersion > supportedMinorVersion)) { - errorString = QObject::tr("File version (%1.%2) is larger than current supported version (%3.%4)").arg(fileMajorVersion).arg(fileMinorVersion).arg(supportedMajorVersion).arg(supportedMinorVersion); + if (version > maxSupportedVersion) { + errorString = QObject::tr("File version %1 is newer than current supported version %2").arg(version).arg(maxSupportedVersion); return false; } @@ -284,3 +284,27 @@ bool JsonHelper::validateKeys(const QJsonObject& jsonObject, const QList + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtLocation 5.3 +import QtPositioning 5.2 + +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 + + +/// Mission item edit control +Item { + id: _root + + property var map ///< Map control to place item in + + property var _complexItem + + Component.onCompleted: { + if (object.mapVisualQML) { + var component = Qt.createComponent(object.mapVisualQML) + if (component.status === Component.Error) { + console.log("Error loading Qml: ", object.mapVisualQML, component.errorString()) + } + _complexItem = component.createObject(map, { "map": _root.map }) + } + } + + Component.onDestruction: { + if (_complexItem) { + _complexItem.destroy() + } + } +} diff --git a/src/MissionEditor/FWLandingPatternEditor.qml b/src/MissionEditor/FWLandingPatternEditor.qml new file mode 100644 index 0000000000000000000000000000000000000000..8d26b50b1ea97f492dc74e58402eced177f465ab --- /dev/null +++ b/src/MissionEditor/FWLandingPatternEditor.qml @@ -0,0 +1,142 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Vehicle 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 + +// Editor for Fixed Wing Landing Pattern complex mission item +Rectangle { + id: _root + height: visible ? ((editorColumn.visible ? editorColumn.height : editorColumnNeedLandingPoint.height) + (_margin * 2)) : 0 + width: availableWidth + color: qgcPal.windowShadeDark + radius: _radius + + // The following properties must be available up the hierarchy chain + //property real availableWidth ///< Width for control + //property var missionItem ///< Mission Item for editor + + property real _margin: ScreenTools.defaultFontPixelWidth / 4 + property real _spacer: ScreenTools.defaultFontPixelWidth / 2 + + Column { + id: editorColumn + anchors.margins: _margin + anchors.left: parent.left + anchors.right: parent.right + visible: missionItem.landingCoordSet + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + font.pointSize: ScreenTools.smallFontPointSize + text: qsTr("WIP (NOT FOR REAL FLIGHT!)") + } + + Item { width: 1; height: _margin } + + QGCLabel { text: qsTr("Loiter point") } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: qgcPal.text + } + + Item { width: 1; height: _spacer } + + FactTextFieldGrid { + anchors.left: parent.left + anchors.right: parent.right + factList: [ missionItem.loiterAltitude, missionItem.loiterRadius ] + } + + Item { width: 1; height: _spacer } + + QGCCheckBox { + id: loiterAltRelative + anchors.right: parent.right + text: qsTr("Altitude relative to home") + checked: missionItem.loiterAltitudeRelative + onClicked: missionItem.loiterAltitudeRelative = checked + } + + Item { width: 1; height: _spacer } + + QGCCheckBox { + anchors.left: loiterAltRelative.left + text: qsTr("Loiter clockwise") + checked: missionItem.loiterClockwise + onClicked: missionItem.loiterClockwise = checked + } + + Item { width: 1; height: ScreenTools.defaultFontPixelHeight / 2 } + + QGCLabel { text: qsTr("Landing point") } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: qgcPal.text + } + + Item { width: 1; height: _spacer } + + FactTextFieldGrid { + anchors.left: parent.left + anchors.right: parent.right + factList: [ missionItem.landingAltitude, missionItem.landingDistance, missionItem.landingHeading ] + } + + Item { width: 1; height: _spacer } + + QGCCheckBox { + anchors.right: parent.right + text: qsTr("Altitude relative to home") + checked: missionItem.landingAltitudeRelative + onClicked: missionItem.landingAltitudeRelative = checked + } + } + + Column { + id: editorColumnNeedLandingPoint + anchors.margins: _margin + anchors.left: parent.left + anchors.right: parent.right + visible: !missionItem.landingCoordSet + spacing: ScreenTools.defaultFontPixelHeight + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + font.pointSize: ScreenTools.smallFontPointSize + text: qsTr("WIP (NOT FOR REAL FLIGHT!)") + } + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: qsTr("Click in map to set landing point.") + } + } +} diff --git a/src/MissionEditor/FWLandingPatternMapVisual.qml b/src/MissionEditor/FWLandingPatternMapVisual.qml new file mode 100644 index 0000000000000000000000000000000000000000..ec4af323614af5746bebbf157a8bb6221023af7d --- /dev/null +++ b/src/MissionEditor/FWLandingPatternMapVisual.qml @@ -0,0 +1,265 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtLocation 5.3 +import QtPositioning 5.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 + +/// Fixed Wing Landing Pattern map visuals +Item { + property var map ///< Map control to place item in + + property var _missionItem: object + property var _itemVisuals: [ ] + property var _mouseArea + property var _dragAreas: [ ] + + readonly property int _flightPathIndex: 0 + readonly property int _loiterPointIndex: 1 + readonly property int _loiterRadiusIndex: 2 + readonly property int _landPointIndex: 3 + + function hideItemVisuals() { + for (var i=0; i<_itemVisuals.length; i++) { + _itemVisuals[i].destroy() + } + _itemVisuals = [ ] + } + + function showItemVisuals() { + if (_itemVisuals.length === 0) { + var itemVisual = flightPathComponent.createObject(map) + map.addMapItem(itemVisual) + _itemVisuals[_flightPathIndex] =itemVisual + itemVisual = loiterPointComponent.createObject(map) + map.addMapItem(itemVisual) + _itemVisuals[_loiterPointIndex] = itemVisual + itemVisual = loiterRadiusComponent.createObject(map) + map.addMapItem(itemVisual) + _itemVisuals[_loiterRadiusIndex] = itemVisual + itemVisual = landPointComponent.createObject(map) + map.addMapItem(itemVisual) + _itemVisuals[_landPointIndex] = itemVisual + } + } + + function hideMouseArea() { + if (_mouseArea) { + _mouseArea.destroy() + _mouseArea = undefined + } + } + + function showMouseArea() { + if (!_mouseArea) { + _mouseArea = mouseAreaComponent.createObject(map) + map.addMapItem(_mouseArea) + } + } + + function hideDragAreas() { + for (var i=0; i<_dragAreas.length; i++) { + _dragAreas[i].destroy() + } + _dragAreas = [ ] + } + + function showDragAreas() { + if (_dragAreas.length === 0) { + _dragAreas.push(dragAreaComponent.createObject(map, { "dragLoiter": true })) + _dragAreas.push(dragAreaComponent.createObject(map, { "dragLoiter": false })) + } + } + + Component.onCompleted: { + if (_missionItem.landingCoordSet) { + showItemVisuals() + if (_missionItem.isCurrentItem) { + showDragAreas() + } + } else if (_missionItem.isCurrentItem) { + showMouseArea() + } + } + + Component.onDestruction: { + hideDragAreas() + hideMouseArea() + hideItemVisuals() + } + + Connections { + target: _missionItem + + onIsCurrentItemChanged: { + if (_missionItem.isCurrentItem) { + if (_missionItem.landingCoordSet) { + showDragAreas() + } else { + showMouseArea() + } + } else { + hideMouseArea() + hideDragAreas() + } + } + + onLandingCoordSetChanged: { + if (_missionItem.landingCoordSet) { + hideMouseArea() + showItemVisuals() + showDragAreas() + } else if (_missionItem.isCurrentItem) { + hideDragAreas() + showMouseArea() + } + } + } + + // Mouse area to capture landing point coordindate + Component { + id: mouseAreaComponent + + MouseArea { + anchors.fill: map + + onClicked: { + var coordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y)) + coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) + coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) + coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) + _missionItem.landingCoordinate = coordinate + } + } + } + + // Control which is used to drag items + Component { + id: dragAreaComponent + + Rectangle { + id: itemDragger + x: mapQuickItem ? (mapQuickItem.x + mapQuickItem.anchorPoint.x - (itemDragger.width / 2)) : 100 + y: mapQuickItem ? (mapQuickItem.y + mapQuickItem.anchorPoint.y - (itemDragger.height / 2)) : 100 + width: ScreenTools.defaultFontPixelHeight * 2 + height: ScreenTools.defaultFontPixelHeight * 2 + color: "transparent" + z: QGroundControl.zOrderMapItems + 1 // Above item icons + + property bool dragLoiter + property var mapQuickItem: dragLoiter ? _itemVisuals[_loiterPointIndex] : _itemVisuals[_landPointIndex] + property bool _preventCoordinateBindingLoop: false + + onXChanged: liveDrag() + onYChanged: liveDrag() + + function liveDrag() { + if (!itemDragger._preventCoordinateBindingLoop && Drag.active) { + var point = Qt.point(itemDragger.x + (itemDragger.width / 2), itemDragger.y + (itemDragger.height / 2)) + var coordinate = map.toCoordinate(point) + itemDragger._preventCoordinateBindingLoop = true + if (dragLoiter) { + coordinate.altitude = _missionItem.loiterCoordinate.altitude + _missionItem.loiterCoordinate = coordinate + } else { + coordinate.altitude = _missionItem.landingCoordinate.altitude + _missionItem.landingCoordinate = coordinate + } + itemDragger._preventCoordinateBindingLoop = false + } + } + + Drag.active: itemDrag.drag.active + Drag.hotSpot.x: width / 2 + Drag.hotSpot.y: height / 2 + + MouseArea { + id: itemDrag + anchors.fill: parent + drag.target: parent + drag.minimumX: 0 + drag.minimumY: 0 + drag.maximumX: itemDragger.parent.width - parent.width + drag.maximumY: itemDragger.parent.height - parent.height + } + } + } + + // Flight path + Component { + id: flightPathComponent + + MapPolyline { + z: QGroundControl.zOrderMapItems - 1 // Under item indicators + line.color: "#be781c" + line.width: 2 + path: _missionItem.landingCoordSet ? [ _missionItem.loiterCoordinate, _missionItem.landingCoordinate ] : undefined + } + } + + // Loiter point + Component { + id: loiterPointComponent + + MapQuickItem { + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY + z: QGroundControl.zOrderMapItems + coordinate: _missionItem.loiterCoordinate + + sourceItem: + MissionItemIndexLabel { + label: "Loiter" + checked: _missionItem.isCurrentItem + + onClicked: setCurrentItem(_missionItem.sequenceNumber) + } + } + } + + // Loiter radius visual + Component { + id: loiterRadiusComponent + + MapCircle { + z: QGroundControl.zOrderMapItems + center: _missionItem.loiterCoordinate + radius: _missionItem.loiterRadius.value + border.width: 2 + border.color: "green" + color: "transparent" + } + } + + // Land point + Component { + id: landPointComponent + + MapQuickItem { + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY + z: QGroundControl.zOrderMapItems + coordinate: _missionItem.landingCoordinate + + sourceItem: + MissionItemIndexLabel { + label: "Land" + checked: _missionItem.isCurrentItem + + onClicked: setCurrentItem(_missionItem.sequenceNumber) + } + } + } +} diff --git a/src/MissionEditor/MissionEditor.qml b/src/MissionEditor/MissionEditor.qml index 34dea1a2fb5116657a4e02dd4fedb6b359b502ba..49e863200ed7a3ee1fdc338eca45ced12f662eb2 100644 --- a/src/MissionEditor/MissionEditor.qml +++ b/src/MissionEditor/MissionEditor.qml @@ -37,7 +37,7 @@ QGCView { readonly property real _margin: ScreenTools.defaultFontPixelHeight * 0.5 readonly property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle readonly property real _rightPanelWidth: Math.min(parent.width / 3, ScreenTools.defaultFontPixelWidth * 30) - readonly property real _rightPanelOpacity: 0.8 + readonly property real _rightPanelOpacity: 1 readonly property int _toolButtonCount: 6 readonly property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2) readonly property var _defaultVehicleCoordinate: QtPositioning.coordinate(37.803784, -122.462276) @@ -48,6 +48,7 @@ QGCView { property bool _firstVehiclePosition: true property var activeVehiclePosition: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate() property bool _lightWidgetBorders: editorMap.isSatelliteMap + property bool _addWaypointOnClick: false /// The controller which should be called for load/save, send to/from vehicle calls property var _syncDropDownController: missionController @@ -76,42 +77,30 @@ QGCView { } } - function normalizeLat(lat) { - // Normalize latitude to range: 0 to 180, S to N - return lat + 90.0 - } + property bool _firstMissionLoadComplete: false + property bool _firstFenceLoadComplete: false + property bool _firstRallyLoadComplete: false + property bool _firstLoadComplete: false - function normalizeLon(lon) { - // Normalize longitude to range: 0 to 360, W to E - return lon + 180.0 + function checkFirstLoadComplete() { + if (!_firstLoadComplete && _firstMissionLoadComplete && _firstRallyLoadComplete && _firstFenceLoadComplete) { + _firstLoadComplete = true + mapFitFunctions.fitMapViewportToAllItems() + } } - /// Fix the map viewport to the current mission items. - function fitViewportToMissionItems() { - if (_visualItems.count == 1) { - editorMap.center = _visualItems.get(0).coordinate - } else { - var missionItem = _visualItems.get(0) - var north = normalizeLat(missionItem.coordinate.latitude) - var south = north - var east = normalizeLon(missionItem.coordinate.longitude) - var west = east - - for (var i=1; i<_visualItems.count; i++) { - missionItem = _visualItems.get(i) - - if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) { - var lat = normalizeLat(missionItem.coordinate.latitude) - var lon = normalizeLon(missionItem.coordinate.longitude) - - north = Math.max(north, lat) - south = Math.min(south, lat) - east = Math.max(east, lon) - west = Math.min(west, lon) - } - } - editorMap.visibleRegion = QtPositioning.rectangle(QtPositioning.coordinate(north - 90.0, west - 180.0), QtPositioning.coordinate(south - 90.0, east - 180.0)) - } + MapFitFunctions { + id: mapFitFunctions + map: editorMap + mapFitViewport: Qt.rect(leftToolWidth, toolbarHeight, editorMap.width - leftToolWidth - rightPanelWidth, editorMap.height - toolbarHeight) + usePlannedHomePosition: true + mapGeoFenceController: geoFenceController + mapMissionController: missionController + mapRallyPointController: rallyPointController + + property real toolbarHeight: qgcView.height - ScreenTools.availableHeight + property real rightPanelWidth: _rightPanelWidth + property real leftToolWidth: toolStrip.x + toolStrip.width } MissionController { @@ -124,10 +113,10 @@ QGCView { function loadFromSelectedFile() { if (ScreenTools.isMobile) { - qgcView.showDialog(mobileFilePicker, qsTr("Select Mission File"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) + qgcView.showDialog(mobileFilePicker, qsTr("Select Mission File"), qgcView.showDialogDefaultWidth, StandardButton.Cancel) } else { missionController.loadFromFilePicker() - fitViewportToMissionItems() + mapFitFunctions.fitMapViewportToMissionItems() _currentMissionItem = _visualItems.get(0) } } @@ -140,13 +129,19 @@ QGCView { } } + function fitViewportToItems() { + mapFitFunctions.fitMapViewportToMissionItems() + } + onVisualItemsChanged: { itemDragger.clearItem() } onNewItemsFromVehicle: { - fitViewportToMissionItems() + mapFitFunctions.fitMapViewportToMissionItems() setCurrentItem(0) + _firstMissionLoadComplete = true + checkFirstLoadComplete() } } @@ -168,6 +163,7 @@ QGCView { qgcView.showDialog(mobileFilePicker, qsTr("Select Fence File"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) } else { geoFenceController.loadFromFilePicker() + mapFitFunctions.fitMapViewportToFenceItems() } } @@ -181,6 +177,22 @@ QGCView { } } } + + function fitViewportToItems() { + mapFitFunctions.fitMapViewportToFenceItems() + } + + onLoadComplete: { + _firstFenceLoadComplete = true + switch (_syncDropDownController) { + case geoFenceController: + mapFitFunctions.fitMapViewportToFenceItems() + break + case missionController: + checkFirstLoadComplete() + break + } + } } RallyPointController { @@ -209,6 +221,23 @@ QGCView { qgcView.showDialog(mobileFilePicker, qsTr("Select Rally Point File"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) } else { rallyPointController.loadFromFilePicker() + mapFitFunctions.fitMapViewportToRallyItems() + } + } + + function fitViewportToItems() { + mapFitFunctions.fitMapViewportToRallyItems() + } + + onLoadComplete: { + _firstRallyLoadComplete = true + switch (_syncDropDownController) { + case rallyPointController: + mapFitFunctions.fitMapViewportToRallyItems() + break + case missionController: + checkFirstLoadComplete() + break } } } @@ -224,16 +253,19 @@ QGCView { } function setCurrentItem(sequenceNumber) { - editorMap.polygonDraw.cancelPolygonEdit() - _currentMissionItem = undefined - for (var i=0; i<_visualItems.count; i++) { - var visualItem = _visualItems.get(i) - if (visualItem.sequenceNumber == sequenceNumber) { - _currentMissionItem = visualItem - _currentMissionItem.isCurrentItem = true - _currentMissionIndex = i - } else { - visualItem.isCurrentItem = false + if (sequenceNumber !== _currentMissionIndex) { + editorMap.polygonDraw.cancelPolygonEdit() + _currentMissionItem = undefined + _currentMissionIndex = -1 + for (var i=0; i<_visualItems.count; i++) { + var visualItem = _visualItems.get(i) + if (visualItem.sequenceNumber == sequenceNumber) { + _currentMissionItem = visualItem + _currentMissionItem.isCurrentItem = true + _currentMissionIndex = i + } else { + visualItem.isCurrentItem = false + } } } } @@ -243,18 +275,19 @@ QGCView { Component { id: mobileFilePicker - QGCMobileFileDialog { - openDialog: true - fileExtension: _syncDropDownController.fileExtension - onFilenameReturned: _syncDropDownController.loadFromFile(filename) + QGCMobileFileOpenDialog { + fileExtension: _syncDropDownController.fileExtension + onFilenameReturned: { + _syncDropDownController.loadFromFile(filename) + _syncDropDownController.fitViewportToItems() + } } } Component { id: mobileFileSaver - QGCMobileFileDialog { - openDialog: false + QGCMobileFileSaveDialog { fileExtension: _syncDropDownController.fileExtension onFilenameReturned: _syncDropDownController.saveToFile(filename) } @@ -345,13 +378,13 @@ QGCView { switch (_editingLayer) { case _layerMission: - if (addMissionItemsButton.checked) { + if (_addWaypointOnClick) { var sequenceNumber = missionController.insertSimpleMissionItem(coordinate, missionController.visualItems.count) setCurrentItem(sequenceNumber) } break case _layerGeoFence: - if (geoFenceController.breachReturnSupported) { + if (geoFenceController.breachReturnEnabled) { geoFenceController.breachReturnPoint = coordinate geoFenceController.validateBreachReturn() } @@ -370,8 +403,8 @@ QGCView { id: itemDragger x: mapCoordinateIndicator ? (mapCoordinateIndicator.x + mapCoordinateIndicator.anchorPoint.x - (itemDragger.width / 2)) : 100 y: mapCoordinateIndicator ? (mapCoordinateIndicator.y + mapCoordinateIndicator.anchorPoint.y - (itemDragger.height / 2)) : 100 - width: ScreenTools.defaultFontPixelHeight * 2 - height: ScreenTools.defaultFontPixelHeight * 2 + width: ScreenTools.defaultFontPixelHeight * 3 + height: ScreenTools.defaultFontPixelHeight * 3 color: "transparent" visible: false z: QGroundControl.zOrderMapItems + 1 // Above item icons @@ -415,43 +448,12 @@ QGCView { } } - // Add the complex mission item polygon to the map - MapItemView { - model: missionController.complexVisualItems - - delegate: MapPolygon { - color: 'green' - path: object.polygonPath - opacity: 0.5 - } - } - - // Add the complex mission item grid to the map - MapItemView { + // Add the complex mission item to the map + Repeater { model: missionController.complexVisualItems - delegate: MapPolyline { - line.color: "white" - line.width: 2 - path: object.gridPoints - } - } - - // Add the complex mission item exit coordinates - MapItemView { - model: missionController.complexVisualItems - delegate: exitCoordinateComponent - } - - Component { - id: exitCoordinateComponent - - MissionItemIndicator { - coordinate: object.exitCoordinate - z: QGroundControl.zOrderMapItems - missionItem: object - sequenceNumber: object.lastSequenceNumber - visible: object.specifiesCoordinate + delegate: ComplexMissionItem { + map: editorMap } } @@ -467,7 +469,7 @@ QGCView { MissionItemIndicator { id: itemIndicator coordinate: object.coordinate - visible: object.specifiesCoordinate + visible: object.isSimpleItem && object.specifiesCoordinate z: QGroundControl.zOrderMapItems missionItem: object sequenceNumber: object.sequenceNumber @@ -499,12 +501,13 @@ QGCView { anchors.left: parent.right Repeater { - model: object.childItems + model: object.isSimpleItem ? object.childItems : 0 delegate: MissionItemIndexLabel { - label: object.abbreviation - checked: object.isCurrentItem - z: 2 + label: object.abbreviation + checked: object.isCurrentItem + z: 2 + specifiesCoordinate: false onClicked: setCurrentItem(object.sequenceNumber) } @@ -539,6 +542,7 @@ QGCView { anchors.leftMargin: parent.width - _rightPanelWidth anchors.left: parent.left spacing: _horizontalMargin + visible: QGroundControl.corePlugin.options.enablePlanViewSelector readonly property real _buttonRadius: ScreenTools.defaultFontPixelHeight * 0.75 @@ -559,69 +563,40 @@ QGCView { _syncDropDownController = rallyPointController break } + _syncDropDownController.fitViewportToItems() } } - RoundButton { + QGCRadioButton { id: planElementMission - radius: parent._buttonRadius - buttonImage: "/qmlimages/Plan.svg" - lightBorders: _lightWidgetBorders exclusiveGroup: planElementSelectorGroup + text: qsTr("Mission") checked: true - } - - QGCLabel { - text: qsTr("Mission") - color: mapPal.text - anchors.verticalCenter: parent.verticalCenter - - MouseArea { - anchors.fill: parent - onClicked: planElementMission.checked = true - } + color: mapPal.text + textStyle: Text.Outline + textStyleColor: mapPal.textOutline } Item { height: 1; width: 1 } - RoundButton { + QGCRadioButton { id: planElementGeoFence - radius: parent._buttonRadius - buttonImage: "/qmlimages/Plan.svg" - lightBorders: _lightWidgetBorders exclusiveGroup: planElementSelectorGroup - } - - QGCLabel { - text: qsTr("Fence") - color: mapPal.text - anchors.verticalCenter: parent.verticalCenter - - MouseArea { - anchors.fill: parent - onClicked: planElementGeoFence.checked = true - } + text: qsTr("Fence") + color: mapPal.text + textStyle: Text.Outline + textStyleColor: mapPal.textOutline } Item { height: 1; width: 1 } - RoundButton { + QGCRadioButton { id: planElementRallyPoints - radius: parent._buttonRadius - buttonImage: "/qmlimages/Plan.svg" - lightBorders: _lightWidgetBorders exclusiveGroup: planElementSelectorGroup - } - - QGCLabel { - text: qsTr("Rally") - color: mapPal.text - anchors.verticalCenter: parent.verticalCenter - - MouseArea { - anchors.fill: parent - onClicked: planElementRallyPoints.checked = true - } + text: qsTr("Rally") + color: mapPal.text + textStyle: Text.Outline + textStyleColor: mapPal.textOutline } } // Row - Plan Element Selector @@ -629,7 +604,7 @@ QGCView { Item { id: missionItemEditor anchors.topMargin: _margin - anchors.top: planElementSelectorRow.bottom + anchors.top: planElementSelectorRow.visible ? planElementSelectorRow.bottom : planElementSelectorRow.top anchors.bottom: parent.bottom anchors.right: parent.right width: _rightPanelWidth @@ -644,7 +619,7 @@ QGCView { onWheel: wheel.accepted = true } - ListView { + QGCListView { id: missionItemEditorListView anchors.left: parent.left anchors.right: parent.right @@ -678,7 +653,7 @@ QGCView { onMoveHomeToMapCenter: _visualItems.get(0).coordinate = editorMap.center } - } // ListView + } // QGCListView } // Item - Mission Item editor // GeoFence Editor @@ -698,8 +673,9 @@ QGCView { MapPolygon { border.color: "#80FF0000" border.width: 3 - path: geoFenceController.polygonSupported ? geoFenceController.polygon.path : undefined + path: geoFenceController.polygon.path z: QGroundControl.zOrderMapItems + visible: geoFenceController.polygonEnabled } // GeoFence circle @@ -707,15 +683,17 @@ QGCView { border.color: "#80FF0000" border.width: 3 center: missionController.plannedHomePosition - radius: geoFenceController.circleSupported ? geoFenceController.circleRadius : 0 + radius: geoFenceController.circleRadius z: QGroundControl.zOrderMapItems + visible: geoFenceController.circleEnabled } // GeoFence breach return point MapQuickItem { - anchorPoint: Qt.point(sourceItem.width / 2, sourceItem.height / 2) + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY coordinate: geoFenceController.breachReturnPoint - visible: geoFenceController.breachReturnSupported + visible: geoFenceController.breachReturnEnabled sourceItem: MissionItemIndexLabel { label: "F" } z: QGroundControl.zOrderMapItems } @@ -754,7 +732,8 @@ QGCView { delegate: MapQuickItem { id: itemIndicator - anchorPoint: Qt.point(sourceItem.width / 2, sourceItem.height / 2) + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY coordinate: object.coordinate z: QGroundControl.zOrderMapItems @@ -788,175 +767,86 @@ QGCView { } } - QGCLabel { - id: planLabel - text: qsTr("Plan") - color: mapPal.text - visible: !ScreenTools.isShortScreen - anchors.topMargin: _toolButtonTopMargin - anchors.horizontalCenter: toolColumn.horizontalCenter - anchors.top: parent.top - } - - //-- Vertical Tool Buttons - Column { - id: toolColumn - anchors.topMargin: ScreenTools.isShortScreen ? _toolButtonTopMargin : ScreenTools.defaultFontPixelHeight / 2 - anchors.leftMargin: ScreenTools.defaultFontPixelHeight + ToolStrip { + id: toolStrip + anchors.leftMargin: ScreenTools.defaultFontPixelWidth anchors.left: parent.left - anchors.top: ScreenTools.isShortScreen ? parent.top : planLabel.bottom - spacing: ScreenTools.defaultFontPixelHeight + anchors.topMargin: _toolButtonTopMargin + anchors.top: parent.top + color: qgcPal.window + title: qsTr("Plan") z: QGroundControl.zOrderWidgets - - RoundButton { - id: addMissionItemsButton - buttonImage: "/qmlimages/MapAddMission.svg" - lightBorders: _lightWidgetBorders - visible: _editingLayer == _layerMission - } - - RoundButton { - id: addShapeButton - buttonImage: "/qmlimages/MapDrawShape.svg" - lightBorders: _lightWidgetBorders - visible: _editingLayer == _layerMission - - onClicked: { - var coordinate = editorMap.center - coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) - coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) - coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) - var sequenceNumber = missionController.insertComplexMissionItem(coordinate, missionController.visualItems.count) - setCurrentItem(sequenceNumber) - checked = false - addMissionItemsButton.checked = false + showAlternateIcon: [ false, false, _syncDropDownController.dirty, false, false, false, false ] + rotateImage: [ false, false, _syncDropDownController.syncInProgress, false, false, false, false ] + buttonEnabled: [ true, true, !_syncDropDownController.syncInProgress, true, true, true, true ] + buttonVisible: [ true, true, true, true, true, _showZoom, _showZoom ] + maxHeight: mapScale.y - toolStrip.y + + property bool _showZoom: !ScreenTools.isShortScreen + + model: [ + { + name: "Waypoint", + iconSource: "/qmlimages/MapAddMission.svg", + toggle: true + }, + { + name: "Pattern", + iconSource: "/qmlimages/MapDrawShape.svg", + dropPanelComponent: patternDropPanel + }, + { + name: "Sync", + iconSource: "/qmlimages/MapSync.svg", + alternateIconSource: "/qmlimages/MapSyncChanged.svg", + dropPanelComponent: syncDropPanel + }, + { + name: "Center", + iconSource: "/qmlimages/MapCenter.svg", + dropPanelComponent: centerMapDropPanel + }, + { + name: "Map", + iconSource: "/qmlimages/MapType.svg", + dropPanelComponent: mapTypeDropPanel + }, + { + name: "In", + iconSource: "/qmlimages/ZoomPlus.svg" + }, + { + name: "Out", + iconSource: "/qmlimages/ZoomMinus.svg" } - } + ] - DropButton { - id: syncButton - dropDirection: dropRight - buttonImage: _syncDropDownController.dirty ? "/qmlimages/MapSyncChanged.svg" : "/qmlimages/MapSync.svg" - viewportMargins: ScreenTools.defaultFontPixelWidth / 2 - exclusiveGroup: _dropButtonsExclusiveGroup - dropDownComponent: syncDropDownComponent - enabled: !_syncDropDownController.syncInProgress - rotateImage: _syncDropDownController.syncInProgress - lightBorders: _lightWidgetBorders - } - - DropButton { - id: centerMapButton - dropDirection: dropRight - buttonImage: "/qmlimages/MapCenter.svg" - viewportMargins: ScreenTools.defaultFontPixelWidth / 2 - exclusiveGroup: _dropButtonsExclusiveGroup - lightBorders: _lightWidgetBorders - - dropDownComponent: Component { - Column { - spacing: ScreenTools.defaultFontPixelWidth * 0.5 - QGCLabel { text: qsTr("Center map:") } - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCButton { - text: qsTr("Home") - width: ScreenTools.defaultFontPixelWidth * 10 - onClicked: { - centerMapButton.hideDropDown() - editorMap.center = missionController.visualItems.get(0).coordinate - } - } - QGCButton { - text: qsTr("Mission") - width: ScreenTools.defaultFontPixelWidth * 10 - onClicked: { - centerMapButton.hideDropDown() - fitViewportToMissionItems() - } - } - QGCButton { - text: qsTr("Vehicle") - width: ScreenTools.defaultFontPixelWidth * 10 - enabled: activeVehicle && activeVehicle.latitude != 0 && activeVehicle.longitude != 0 - property var activeVehicle: _activeVehicle - onClicked: { - centerMapButton.hideDropDown() - editorMap.center = activeVehicle.coordinate - } - } - } - } - } - } - - DropButton { - id: mapTypeButton - dropDirection: dropRight - buttonImage: "/qmlimages/MapType.svg" - viewportMargins: ScreenTools.defaultFontPixelWidth / 2 - exclusiveGroup: _dropButtonsExclusiveGroup - lightBorders: _lightWidgetBorders - - dropDownComponent: Component { - Column { - spacing: _margin - QGCLabel { text: qsTr("Map type:") } - Row { - spacing: ScreenTools.defaultFontPixelWidth - Repeater { - model: QGroundControl.flightMapSettings.mapTypes - - QGCButton { - checkable: true - checked: QGroundControl.flightMapSettings.mapType === text - text: modelData - exclusiveGroup: _mapTypeButtonsExclusiveGroup - onClicked: { - QGroundControl.flightMapSettings.mapType = text - checked = true - mapTypeButton.hideDropDown() - } - } - } - } - } - } - } - - //-- Zoom Map In - RoundButton { - id: mapZoomPlus - visible: !ScreenTools.isTinyScreen && !ScreenTools.isShortScreen - buttonImage: "/qmlimages/ZoomPlus.svg" - lightBorders: _lightWidgetBorders - - onClicked: { - if(editorMap) - editorMap.zoomLevel += 0.5 - checked = false - } - } - - //-- Zoom Map Out - RoundButton { - id: mapZoomMinus - visible: !ScreenTools.isTinyScreen && !ScreenTools.isShortScreen - buttonImage: "/qmlimages/ZoomMinus.svg" - lightBorders: _lightWidgetBorders - onClicked: { - if(editorMap) - editorMap.zoomLevel -= 0.5 - checked = false + onClicked: { + switch (index) { + case 0: + _addWaypointOnClick = checked + break + case 5: + editorMap.zoomLevel += 0.5 + break + case 6: + editorMap.zoomLevel -= 0.5 + break + case 5: + editorMap.zoomLevel += 0.5 + break + case 6: + editorMap.zoomLevel -= 0.5 + break } } } MapScale { + id: mapScale anchors.margins: ScreenTools.defaultFontPixelHeight * (0.66) anchors.bottom: waypointValuesDisplay.visible ? waypointValuesDisplay.top : parent.bottom anchors.left: parent.left - z: QGroundControl.zOrderWidgets mapControl: editorMap visible: !ScreenTools.isTinyScreen } @@ -971,9 +861,8 @@ QGCView { missionItems: missionController.visualItems expandedWidth: missionItemEditor.x - (ScreenTools.defaultFontPixelWidth * 2) missionDistance: missionController.missionDistance + missionTime: missionController.missionTime missionMaxTelemetry: missionController.missionMaxTelemetry - cruiseDistance: missionController.cruiseDistance - hoverDistance: missionController.hoverDistance visible: _editingLayer == _layerMission && !ScreenTools.isShortScreen } } // FlightMap @@ -1016,8 +905,10 @@ QGCView { } } + //- ToolStrip DropPanel Components + Component { - id: syncDropDownComponent + id: syncDropPanel Column { id: columnHolder @@ -1045,7 +936,7 @@ QGCView { Layout.fillWidth: true enabled: _activeVehicle && !_syncDropDownController.syncInProgress onClicked: { - syncButton.hideDropDown() + dropPanel.hide() _syncDropDownController.sendToVehicle() } } @@ -1055,7 +946,7 @@ QGCView { Layout.fillWidth: true enabled: _activeVehicle && !_syncDropDownController.syncInProgress onClicked: { - syncButton.hideDropDown() + dropPanel.hide() if (_syncDropDownController.dirty) { qgcView.showDialog(syncLoadFromVehicleOverwrite, columnHolder._overwriteText, qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) } else { @@ -1069,7 +960,7 @@ QGCView { Layout.fillWidth: true enabled: !_syncDropDownController.syncInProgress onClicked: { - syncButton.hideDropDown() + dropPanel.hide() _syncDropDownController.saveToSelectedFile() } } @@ -1079,7 +970,7 @@ QGCView { Layout.fillWidth: true enabled: !_syncDropDownController.syncInProgress onClicked: { - syncButton.hideDropDown() + dropPanel.hide() if (_syncDropDownController.dirty) { qgcView.showDialog(syncLoadFromFileOverwrite, columnHolder._overwriteText, qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) } else { @@ -1092,12 +983,77 @@ QGCView { text: qsTr("Remove All") Layout.fillWidth: true onClicked: { - syncButton.hideDropDown() - _syncDropDownController.removeAll() + dropPanel.hide() qgcView.showDialog(removeAllPromptDialog, qsTr("Remove all"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.No) } } } } } + + Component { + id: centerMapDropPanel + + CenterMapDropPanel { + map: editorMap + fitFunctions: mapFitFunctions + } + } + + Component { + id: mapTypeDropPanel + + Column { + spacing: _margin + + QGCLabel { text: qsTr("Map type:") } + Row { + spacing: ScreenTools.defaultFontPixelWidth + Repeater { + model: QGroundControl.flightMapSettings.mapTypes + + QGCButton { + checkable: true + checked: QGroundControl.flightMapSettings.mapType === text + text: modelData + exclusiveGroup: _mapTypeButtonsExclusiveGroup + + onClicked: { + QGroundControl.flightMapSettings.mapType = text + dropPanel.hide() + } + } + } + } + } + } + + Component { + id: patternDropPanel + + ColumnLayout { + spacing: ScreenTools.defaultFontPixelWidth * 0.5 + + QGCLabel { text: qsTr("Create complex pattern:") } + + Repeater { + model: missionController.complexMissionItemNames + + QGCButton { + text: modelData + Layout.fillWidth: true + + onClicked: { + var coordinate = editorMap.center + coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces) + coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces) + coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces) + var sequenceNumber = missionController.insertComplexMissionItem(modelData, coordinate, missionController.visualItems.count) + setCurrentItem(sequenceNumber) + dropPanel.hide() + } + } + } + } // Column + } } // QGCVIew diff --git a/src/MissionEditor/MissionItemEditor.qml b/src/MissionEditor/MissionItemEditor.qml index d7be22e884dafc792d58d977b15c9cdd90ecefc0..156345685abacd2cd2ff97222ad9dc85a347f674 100644 --- a/src/MissionEditor/MissionItemEditor.qml +++ b/src/MissionEditor/MissionItemEditor.qml @@ -18,30 +18,30 @@ Rectangle { color: _currentItem ? qgcPal.buttonHighlight : qgcPal.windowShade radius: _radius - property var missionItem ///< MissionItem associated with this editor - property bool readOnly ///< true: read only view, false: full editing view + property var missionItem ///< MissionItem associated with this editor + property bool readOnly ///< true: read only view, false: full editing view signal clicked signal remove signal insert signal moveHomeToMapCenter - property bool _currentItem: missionItem.isCurrentItem - property color _outerTextColor: _currentItem ? "black" : qgcPal.text + property bool _currentItem: missionItem.isCurrentItem + property color _outerTextColor: _currentItem ? "black" : qgcPal.text + property bool _noMissionItemsAdded: ListView.view.model.count == 1 readonly property real _editFieldWidth: Math.min(width - _margin * 2, ScreenTools.defaultFontPixelWidth * 12) readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2 readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2 + readonly property real _hamburgerSize: commandPicker.height * 0.75 QGCPalette { id: qgcPal colorGroupEnabled: enabled } - MouseArea { anchors.fill: parent - visible: !missionItem.isCurrentItem onClicked: _root.clicked() } @@ -54,61 +54,69 @@ Rectangle { color: _outerTextColor } - Image { + QGCColoredImage { id: hamburger anchors.rightMargin: ScreenTools.defaultFontPixelWidth anchors.right: parent.right anchors.verticalCenter: commandPicker.verticalCenter - width: commandPicker.height - height: commandPicker.height - sourceSize.height: height + width: _hamburgerSize + height: _hamburgerSize + sourceSize.height: _hamburgerSize source: "qrc:/qmlimages/Hamburger.svg" visible: missionItem.isCurrentItem && missionItem.sequenceNumber != 0 + color: qgcPal.windowShade - MouseArea { - anchors.fill: parent - onClicked: hamburgerMenu.popup() + } - Menu { - id: hamburgerMenu + MouseArea { + // The MouseArea for the hamburger is larger than the hamburger image itself in order to provide a larger + // touch area on mobile + anchors.top: parent.top + anchors.bottom: editorLoader.top + anchors.leftMargin: -hamburger.anchors.rightMargin + anchors.left: hamburger.left + anchors.right: parent.right + onClicked: hamburgerMenu.popup() + + Menu { + id: hamburgerMenu + + MenuItem { + text: qsTr("Insert") + onTriggered: insert() + } - MenuItem { - text: qsTr("Insert") - onTriggered: insert() - } + MenuItem { + text: qsTr("Delete") + onTriggered: remove() + } - MenuItem { - text: qsTr("Delete") - onTriggered: remove() - } + MenuItem { + text: "Change command..." + onTriggered: commandPicker.clicked() + } - MenuItem { - text: "Change command..." - onTriggered: commandPicker.clicked() - } + MenuSeparator { + visible: missionItem.isSimpleItem + } - MenuSeparator { - visible: missionItem.isSimpleItem - } + MenuItem { + text: qsTr("Show all values") + checkable: true + checked: missionItem.isSimpleItem ? missionItem.rawEdit : false + visible: missionItem.isSimpleItem - MenuItem { - text: qsTr("Show all values") - checkable: true - checked: missionItem.isSimpleItem ? missionItem.rawEdit : false - visible: missionItem.isSimpleItem - - onTriggered: { - if (missionItem.rawEdit) { - if (missionItem.friendlyEditAllowed) { - missionItem.rawEdit = false - } else { - qgcView.showMessage(qsTr("Mission Edit"), qsTr("You have made changes to the mission item which cannot be shown in Simple Mode"), StandardButton.Ok) - } + onTriggered: { + if (missionItem.rawEdit) { + if (missionItem.friendlyEditAllowed) { + missionItem.rawEdit = false } else { - missionItem.rawEdit = true + qgcView.showMessage(qsTr("Mission Edit"), qsTr("You have made changes to the mission item which cannot be shown in Simple Mode"), StandardButton.Ok) } - checked = missionItem.rawEdit + } else { + missionItem.rawEdit = true } + checked = missionItem.rawEdit } } } @@ -121,7 +129,6 @@ Rectangle { anchors.rightMargin: ScreenTools.defaultFontPixelWidth anchors.left: label.right anchors.top: parent.top - //anchors.right: hamburger.left visible: missionItem.sequenceNumber != 0 && missionItem.isCurrentItem && !missionItem.rawEdit && missionItem.isSimpleItem text: missionItem.commandName @@ -133,16 +140,14 @@ Rectangle { } } - onClicked: qgcView.showDialog(commandDialog, qsTr("Select Mission Command"), qgcView.showDialogDefaultWidth, StandardButton.Cancel) + onClicked: qgcView.showDialog(commandDialog, qsTr("Select Mission Command"), qgcView.showDialogDefaultWidth, StandardButton.Cancel) } QGCLabel { anchors.fill: commandPicker visible: missionItem.sequenceNumber == 0 || !missionItem.isCurrentItem || !missionItem.isSimpleItem verticalAlignment: Text.AlignVCenter - text: missionItem.sequenceNumber == 0 ? - qsTr("Planned Home Position") : - (missionItem.isSimpleItem ? missionItem.commandName : qsTr("Survey")) + text: missionItem.sequenceNumber == 0 ? qsTr("Mission Settings") : missionItem.commandName color: _outerTextColor } @@ -153,8 +158,12 @@ Rectangle { anchors.left: parent.left anchors.top: commandPicker.bottom height: item ? item.height : 0 - source: missionItem.isSimpleItem ? "qrc:/qml/SimpleItemEditor.qml" : "qrc:/qml/SurveyItemEditor.qml" - onLoaded: { item.visible = Qt.binding(function() { return _currentItem; }) } + source: missionItem.sequenceNumber == 0 ? "qrc:/qml/MissionSettingsEditor.qml" : missionItem.editorQml + + onLoaded: { + item.visible = Qt.binding(function() { return _currentItem; }) + } + property real availableWidth: _root.width - (_margin * 2) ///< How wide the editor should be property var editorRoot: _root } diff --git a/src/MissionEditor/MissionItemStatus.qml b/src/MissionEditor/MissionItemStatus.qml index fcedf7fd412341bfe772d433d496ba9c03dd6878..2aad79b34b699c69c86626ed4142f4995fa3468b 100644 --- a/src/MissionEditor/MissionItemStatus.qml +++ b/src/MissionEditor/MissionItemStatus.qml @@ -10,6 +10,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.3 +import QtQuick.Layouts 1.2 import QGroundControl.ScreenTools 1.0 import QGroundControl.Controls 1.0 @@ -19,20 +20,6 @@ import QGroundControl.FactSystem 1.0 import QGroundControl.FactControls 1.0 Rectangle { - readonly property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle - - property Fact _offlineEditingVehicleType: QGroundControl.offlineEditingVehicleType - property Fact _offlineEditingCruiseSpeed: QGroundControl.offlineEditingCruiseSpeed - property Fact _offlineEditingHoverSpeed: QGroundControl.offlineEditingHoverSpeed - - property var currentMissionItem ///< Mission item to display status for - property var missionItems ///< List of all available mission items - property real expandedWidth ///< Width of control when expanded - property real missionDistance - property real missionMaxTelemetry - property real cruiseDistance - property real hoverDistance - width: _expanded ? expandedWidth : _collapsedWidth height: Math.max(valueGrid.height, valueMissionGrid.height) + (_margins * 2) radius: ScreenTools.defaultFontPixelWidth * 0.5 @@ -40,42 +27,35 @@ Rectangle { opacity: 0.80 clip: true - readonly property real margins: ScreenTools.defaultFontPixelWidth - - property real _collapsedWidth: valueGrid.width + (margins * 2) - property bool _expanded: true - - property real _distance: _statusValid ? _currentMissionItem.distance : 0 - property real _altDifference: _statusValid ? _currentMissionItem.altDifference : 0 - property real _gradient: _statusValid && _currentMissionItem.distance > 0 ? Math.atan(_currentMissionItem.altDifference / _currentMissionItem.distance) : 0 - property real _gradientPercent: isNaN(_gradient) ? 0 : _gradient * 100 - property real _azimuth: _statusValid ? _currentMissionItem.azimuth : -1 - property real _missionDistance: _missionValid ? missionDistance : 0 - property real _missionMaxTelemetry: _missionValid ? missionMaxTelemetry : 0 - property real _missionTime: _missionValid && _missionSpeed > 0 ? (_isVTOL ? _hoverTime + _cruiseTime : _missionDistance / _missionSpeed) : 0 - property real _hoverDistance: _missionValid ? hoverDistance : 0 - property real _cruiseDistance: _missionValid ? cruiseDistance : 0 - property real _hoverTime: _missionValid && _offlineEditingHoverSpeed.value > 0 ? _hoverDistance / _offlineEditingHoverSpeed.value : 0 - property real _cruiseTime: _missionValid && _offlineEditingCruiseSpeed.value > 0 ? _cruiseDistance / _offlineEditingCruiseSpeed.value : 0 - - property bool _statusValid: currentMissionItem != undefined - property bool _vehicleValid: _activeVehicle != undefined - property bool _missionValid: missionItems != undefined - property bool _currentSurvey: _statusValid ? _currentMissionItem.commandName == "Survey" : false - property bool _isVTOL: _vehicleValid ? _activeVehicle.vtol : _offlineEditingVehicleType.enumStringValue == "VTOL" //hardcoded - property real _missionSpeed: _offlineEditingVehicleType.enumStringValue == "Fixedwing" ? _offlineEditingCruiseSpeed.value : _offlineEditingHoverSpeed.value - - property string _distanceText: _statusValid ? QGroundControl.metersToAppSettingsDistanceUnits(_distance).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString : " " - property string _altText: _statusValid ? QGroundControl.metersToAppSettingsDistanceUnits(_altDifference).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString : " " - property string _gradientText: _statusValid ? _gradientPercent.toFixed(0) + "%" : " " - property string _azimuthText: _statusValid ? Math.round(_azimuth) : " " - property string _missionDistanceText: _missionValid ? QGroundControl.metersToAppSettingsDistanceUnits(_missionDistance).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString : " " - property string _missionTimeText: _missionValid ? _missionTime.toFixed(0) + "s" : " " - property string _missionMaxTelemetryText: _missionValid ? QGroundControl.metersToAppSettingsDistanceUnits(_missionMaxTelemetry).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString : " " - property string _hoverDistanceText: _missionValid ? QGroundControl.metersToAppSettingsDistanceUnits(_hoverDistance).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString : " " - property string _cruiseDistanceText: _missionValid ? QGroundControl.metersToAppSettingsDistanceUnits(_cruiseDistance).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString : " " - property string _hoverTimeText: _missionValid ? _hoverTime.toFixed(0) + "s" : " " - property string _cruiseTimeText: _missionValid ? _cruiseTime.toFixed(0) + "s" : " " + property var currentMissionItem ///< Mission item to display status for + property var missionItems ///< List of all available mission items + property real expandedWidth ///< Width of control when expanded + property real missionDistance ///< Total mission distance + property real missionTime ///< Total mission time + property real missionMaxTelemetry + + property real _collapsedWidth: valueGrid.width + (_margins * 2) + property bool _expanded: true + + property bool _statusValid: currentMissionItem != undefined + property bool _missionValid: missionItems != undefined + + property real _distance: _statusValid ? _currentMissionItem.distance : NaN + property real _altDifference: _statusValid ? _currentMissionItem.altDifference : NaN + property real _gradient: _statusValid && _currentMissionItem.distance > 0 ? Math.atan(_currentMissionItem.altDifference / _currentMissionItem.distance) : NaN + property real _gradientPercent: isNaN(_gradient) ? NaN : _gradient * 100 + property real _azimuth: _statusValid ? _currentMissionItem.azimuth : NaN + property real _missionDistance: _missionValid ? missionDistance : NaN + property real _missionMaxTelemetry: _missionValid ? missionMaxTelemetry : NaN + property real _missionTime: _missionValid ? missionTime : NaN + + property string _distanceText: isNaN(_distance) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_distance).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString + property string _altDifferenceText: isNaN(_altDifference) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_altDifference).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString + property string _gradientText: isNaN(_gradient) ? "-.-" : _gradientPercent.toFixed(0) + "%" + property string _azimuthText: isNaN(_azimuth) ? "-.-" : Math.round(_azimuth) + property string _missionDistanceText: isNaN(_missionDistance) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_missionDistance).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString + property string _missionTimeText: isNaN(_missionTime) ? "-.-" : Number(_missionTime / 60).toFixed(1) + " min" + property string _missionMaxTelemetryText: isNaN(_missionMaxTelemetry) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_missionMaxTelemetry).toFixed(2) + " " + QGroundControl.appSettingsDistanceUnitsString readonly property real _margins: ScreenTools.defaultFontPixelWidth @@ -89,20 +69,20 @@ Rectangle { anchors.margins: _margins spacing: _margins - Grid { - id: valueGrid - columns: 2 - columnSpacing: _margins + GridLayout { + id: valueGrid + columns: 2 + rowSpacing: 0 + columnSpacing: _margins anchors.verticalCenter: parent.verticalCenter - QGCLabel { text: qsTr("Selected waypoint") } - QGCLabel { text: qsTr(" ") } + QGCLabel { text: qsTr("Selected waypoint"); Layout.columnSpan: 2 } QGCLabel { text: qsTr("Distance:") } QGCLabel { text: _distanceText } QGCLabel { text: qsTr("Alt diff:") } - QGCLabel { text: _altText } + QGCLabel { text: _altDifferenceText } QGCLabel { text: qsTr("Gradient:") } QGCLabel { text: _gradientText } @@ -111,7 +91,7 @@ Rectangle { QGCLabel { text: _azimuthText } } - ListView { + QGCListView { id: statusListView model: missionItems highlightMoveDuration: 250 @@ -165,42 +145,6 @@ Rectangle { QGCLabel { text: qsTr("Max telem dist:") } QGCLabel { text: _missionMaxTelemetryText } - - QGCLabel { - text: qsTr("Hover distance:") - visible: _isVTOL - } - QGCLabel { - text: _hoverDistanceText - visible: _isVTOL - } - - QGCLabel { - text: qsTr("Cruise distance:") - visible: _isVTOL - } - QGCLabel { - text: _cruiseDistanceText - visible: _isVTOL - } - - QGCLabel { - text: qsTr("Hover time:") - visible: _isVTOL - } - QGCLabel { - text: _hoverTimeText - visible: _isVTOL - } - - QGCLabel { - text: qsTr("Cruise time:") - visible: _isVTOL - } - QGCLabel { - text: _cruiseTimeText - visible: _isVTOL - } } } } diff --git a/src/MissionEditor/MissionSettingsEditor.qml b/src/MissionEditor/MissionSettingsEditor.qml new file mode 100644 index 0000000000000000000000000000000000000000..b209b6e113f13d30339a7112bea2b3bbfea00c22 --- /dev/null +++ b/src/MissionEditor/MissionSettingsEditor.qml @@ -0,0 +1,225 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Vehicle 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.SettingsManager 1.0 + +// Editor for Mission Settings +Rectangle { + id: valuesRect + width: availableWidth + height: deferedload.status == Loader.Ready ? (visible ? deferedload.item.height : 0) : 0 + color: qgcPal.windowShadeDark + visible: missionItem.isCurrentItem + radius: _radius + + Loader { + id: deferedload + active: valuesRect.visible + asynchronous: true + anchors.margins: _margin + anchors.left: valuesRect.left + anchors.right: valuesRect.right + anchors.top: valuesRect.top + + sourceComponent: Component { + Item { + id: valuesItem + height: valuesColumn.height + (_margin * 2) + + property var _missionVehicle: missionController.vehicle + property bool _offlineEditing: _missionVehicle.isOfflineEditingVehicle + property bool _showOfflineEditingCombos: _offlineEditing && _noMissionItemsAdded + property bool _showCruiseSpeed: !_missionVehicle.multiRotor + property bool _showHoverSpeed: _missionVehicle.multiRotor || missionController.vehicle.vtol + property bool _multipleFirmware: QGroundControl.supportedFirmwareCount > 2 + property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 16 + + readonly property string _firmwareLabel: qsTr("Firmware:") + readonly property string _vehicleLabel: qsTr("Vehicle:") + + QGCPalette { id: qgcPal } + + Column { + id: valuesColumn + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + spacing: _margin + + QGCLabel { text: qsTr("Planned Home Position") } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: qgcPal.text + } + + Repeater { + model: missionItem.textFieldFacts + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + QGCLabel { text: object.name; Layout.fillWidth: true } + FactTextField { + Layout.preferredWidth: _fieldWidth + showUnits: true + fact: object + visible: !_root.readOnly + } + FactLabel { + Layout.preferredWidth: _fieldWidth + fact: object + visible: _root.readOnly + } + } + } + + QGCLabel { + width: parent.width + wrapMode: Text.WordWrap + font.pointSize: ScreenTools.smallFontPointSize + text: qsTr("Actual position set by vehicle at flight time.") + horizontalAlignment: Text.AlignHCenter + } + + QGCLabel { + text: qsTr("Vehicle Info") + visible: _multipleFirmware + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: qgcPal.text + visible: _multipleFirmware + } + + GridLayout { + anchors.left: parent.left + anchors.right: parent.right + columnSpacing: ScreenTools.defaultFontPixelWidth + rowSpacing: columnSpacing + columns: 2 + visible: _multipleFirmware + + QGCLabel { + text: _firmwareLabel + visible: _showOfflineEditingCombos + Layout.fillWidth: true + } + FactComboBox { + fact: QGroundControl.settingsManager.appSettings.offlineEditingFirmwareType + indexModel: false + visible: _showOfflineEditingCombos + Layout.preferredWidth: _fieldWidth + } + + QGCLabel { + text: _firmwareLabel + visible: !_showOfflineEditingCombos + Layout.fillWidth: true + } + QGCLabel { + text: _missionVehicle.firmwareTypeString + visible: !_showOfflineEditingCombos + Layout.preferredWidth: _fieldWidth + } + + QGCLabel { + text: _vehicleLabel + visible: _showOfflineEditingCombos + Layout.fillWidth: true + } + FactComboBox { + id: offlineVehicleCombo + fact: QGroundControl.settingsManager.appSettings.offlineEditingVehicleType + indexModel: false + visible: _showOfflineEditingCombos + Layout.preferredWidth: _fieldWidth + } + + QGCLabel { + text: _vehicleLabel + visible: !_showOfflineEditingCombos + Layout.fillWidth: true + } + QGCLabel { + text: _missionVehicle.vehicleTypeString + visible: !_showOfflineEditingCombos + Layout.preferredWidth: _fieldWidth + } + + QGCLabel { + Layout.row: 2 + text: qsTr("Cruise speed:") + visible: _showCruiseSpeed + Layout.fillWidth: true + } + FactTextField { + fact: QGroundControl.settingsManager.appSettings.offlineEditingCruiseSpeed + visible: _showCruiseSpeed + Layout.preferredWidth: _fieldWidth + } + + QGCLabel { + Layout.row: 3 + text: qsTr("Hover speed:") + visible: _showHoverSpeed + Layout.fillWidth: true + } + FactTextField { + fact: QGroundControl.settingsManager.appSettings.offlineEditingHoverSpeed + visible: _showHoverSpeed + Layout.preferredWidth: _fieldWidth + } + } // GridLayout + + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + visible: !_multipleFirmware + QGCLabel { text: qsTr("Hover speed:"); Layout.fillWidth: true } + FactTextField { + Layout.preferredWidth: _fieldWidth + fact: QGroundControl.settingsManager.appSettings.offlineEditingHoverSpeed + } + } + + QGCLabel { + width: parent.width + wrapMode: Text.WordWrap + font.pointSize: ScreenTools.smallFontPointSize + text: qsTr("Speeds are only used for time calculations. Actual vehicle speed will not be affected.") + horizontalAlignment: Text.AlignHCenter + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: qgcPal.text + } + + QGCButton { + width: parent.width * 0.9 + text: qsTr("Set Home To Map Center") + onClicked: editorRoot.moveHomeToMapCenter() + anchors.horizontalCenter: parent.horizontalCenter + } + + } // Column + } // Item + } // Component + } // Loader +} // Rectangle diff --git a/src/MissionEditor/RallyPointEditorHeader.qml b/src/MissionEditor/RallyPointEditorHeader.qml index 8a3828a6f2e8925a5c9590b97eda7c4cda32f0f2..ada44fc27b9b98a53c2bf1a98c07cb6f3f33c322 100644 --- a/src/MissionEditor/RallyPointEditorHeader.qml +++ b/src/MissionEditor/RallyPointEditorHeader.qml @@ -37,7 +37,7 @@ QGCFlickable { anchors.left: parent.left anchors.right: parent.right anchors.top: editorLabel.bottom - height: helpLabel.y + helpLabel.height + (_margin * 2) + height: infoLabel.height + helpLabel.height + (_margin * 2) color: qgcPal.windowShadeDark radius: _radius diff --git a/src/MissionEditor/SimpleItemEditor.qml b/src/MissionEditor/SimpleItemEditor.qml index 3e7b1e56a27c8feb4ec8e8655ebc8dfe62b95742..677656d768784c8f8288638f6e5e205dc68e8285 100644 --- a/src/MissionEditor/SimpleItemEditor.qml +++ b/src/MissionEditor/SimpleItemEditor.qml @@ -2,6 +2,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2 import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.2 import QGroundControl.ScreenTools 1.0 import QGroundControl.Vehicle 1.0 @@ -42,65 +43,65 @@ Rectangle { width: parent.width wrapMode: Text.WordWrap font.pointSize: ScreenTools.smallFontPointSize - text: missionItem.sequenceNumber == 0 ? - qsTr("Planned home position. Actual home position set by Vehicle.") : - (missionItem.rawEdit ? - qsTr("Provides advanced access to all commands/parameters. Be very careful!") : - missionItem.commandDescription) + text: missionItem.rawEdit ? + qsTr("Provides advanced access to all commands/parameters. Be very careful!") : + missionItem.commandDescription } - Repeater { - model: missionItem.comboboxFacts + GridLayout { + anchors.left: parent.left + anchors.right: parent.right + columns: 2 - Item { - width: valuesColumn.width - height: comboBoxFact.height + Repeater { + model: missionItem.comboboxFacts QGCLabel { - id: comboBoxLabel - anchors.baseline: comboBoxFact.baseline - text: object.name - visible: object.name != "" + text: object.name + visible: object.name != "" + Layout.column: 0 + Layout.row: index } + } + + Repeater { + model: missionItem.comboboxFacts FactComboBox { - id: comboBoxFact - anchors.right: parent.right - width: comboBoxLabel.visible ? _editFieldWidth : parent.width - indexModel: false - model: object.enumStrings - fact: object + indexModel: false + model: object.enumStrings + fact: object + Layout.column: 1 + Layout.row: index + Layout.fillWidth: true } } } - Repeater { - model: missionItem.textFieldFacts + GridLayout { + anchors.left: parent.left + anchors.right: parent.right + columns: 2 - Item { - width: valuesColumn.width - height: textField.height + Repeater { + model: missionItem.textFieldFacts QGCLabel { - id: textFieldLabel - anchors.baseline: textField.baseline - text: object.name + text: object.name + Layout.column: 0 + Layout.row: index } + } - FactTextField { - id: textField - anchors.right: parent.right - width: _editFieldWidth - showUnits: true - fact: object - visible: !_root.readOnly - } + Repeater { + model: missionItem.textFieldFacts - FactLabel { - anchors.baseline: textFieldLabel.baseline - anchors.right: parent.right + FactTextField { + showUnits: true fact: object - visible: _root.readOnly + Layout.column: 1 + Layout.row: index + Layout.fillWidth: true } } } @@ -113,13 +114,6 @@ Rectangle { fact: object } } - - QGCButton { - text: qsTr("Move Home to map center") - visible: missionItem.homePosition - onClicked: editorRoot.moveHomeToMapCenter() - anchors.horizontalCenter: parent.horizontalCenter - } } // Column } // Item } // Component diff --git a/src/MissionEditor/SurveyComplexItem.qml b/src/MissionEditor/SurveyComplexItem.qml new file mode 100644 index 0000000000000000000000000000000000000000..a438fb7077895fa7b5aaac001601529468539a16 --- /dev/null +++ b/src/MissionEditor/SurveyComplexItem.qml @@ -0,0 +1,109 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtLocation 5.3 +import QtPositioning 5.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 + +/// Survey Complex Mission Item visuals +Item { + property var map ///< Map control to place item in + + property var _missionItem: object + property var _polygon + property var _grid + property var _entryCoordinate + property var _exitCoordinate + + Component.onCompleted: { + _polygon = polygonComponent.createObject(map) + _grid = gridComponent.createObject(map) + _entryCoordinate = entryPointComponent.createObject(map) + _exitCoordinate = exitPointComponent.createObject(map) + map.addMapItem(_polygon) + map.addMapItem(_grid) + map.addMapItem(_entryCoordinate) + map.addMapItem(_exitCoordinate) + } + + Component.onDestruction: { + _polygon.destroy() + _grid.destroy() + _entryCoordinate.destroy() + _exitCoordinate.destroy() + } + + // Survey area polygon + Component { + id: polygonComponent + + MapPolygon { + color: "green" + opacity: 0.5 + path: _missionItem.polygonPath + } + } + + // Survey grid lines + Component { + id: gridComponent + + MapPolyline { + line.color: "white" + line.width: 2 + path: _missionItem.gridPoints + } + } + + // Entry point + Component { + id: entryPointComponent + + MapQuickItem { + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY + z: QGroundControl.zOrderMapItems + coordinate: _missionItem.coordinate + + sourceItem: + MissionItemIndexLabel { + label: "Entry" + checked: _missionItem.isCurrentItem + + onClicked: setCurrentItem(_missionItem.sequenceNumber) + } + } + } + + // Exit point + Component { + id: exitPointComponent + + MapQuickItem { + anchorPoint.x: sourceItem.anchorPointX + anchorPoint.y: sourceItem.anchorPointY + z: QGroundControl.zOrderMapItems + coordinate: _missionItem.exitCoordinate + + sourceItem: + MissionItemIndexLabel { + label: "Exit" + checked: _missionItem.isCurrentItem + + onClicked: setCurrentItem(_missionItem.sequenceNumber) + } + } + } +} diff --git a/src/MissionEditor/SurveyItemEditor.qml b/src/MissionEditor/SurveyItemEditor.qml index 0192ed38c2d735a2bc923ba81d63ff983e786f98..75f952acac609ad749d4e1c41a34d52e6d40a2d6 100644 --- a/src/MissionEditor/SurveyItemEditor.qml +++ b/src/MissionEditor/SurveyItemEditor.qml @@ -22,44 +22,23 @@ Rectangle { //property real availableWidth ///< Width for control //property var missionItem ///< Mission Item for editor - property real _margin: ScreenTools.defaultFontPixelWidth / 2 + property real _margin: ScreenTools.defaultFontPixelWidth * 0.25 property int _cameraIndex: 1 + property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10.5 readonly property int _gridTypeManual: 0 readonly property int _gridTypeCustomCamera: 1 readonly property int _gridTypeCamera: 2 - Component.onCompleted: { - console.log("gridAltitude", missionItem.gridAltitude.value) - console.log("gridAltitudeRelative", missionItem.gridAltitudeRelative) - console.log("gridAngle", missionItem.gridAngle.value) - console.log("gridSpacing", missionItem.gridSpacing.value) - console.log("turnaroundDist", missionItem.turnaroundDist.value) - console.log("cameraTrigger", missionItem.cameraTrigger) - console.log("cameraTriggerDistance", missionItem.cameraTriggerDistance.value) - console.log("groundResolution", missionItem.groundResolution.value) - console.log("frontalOverlap", missionItem.frontalOverlap.value) - console.log("sideOverlap", missionItem.sideOverlap.value) - console.log("cameraSensorWidth", missionItem.cameraSensorWidth.value) - console.log("cameraSensorHeight", missionItem.cameraSensorHeight.value) - console.log("cameraResolutionWidth", missionItem.cameraResolutionWidth.value) - console.log("cameraResolutionHeight", missionItem.cameraResolutionHeight.value) - console.log("cameraFocalLength", missionItem.cameraFocalLength.value) - console.log("fixedValueIsAltitude", missionItem.fixedValueIsAltitude) - console.log("cameraOrientationLandscape", missionItem.cameraOrientationLandscape) - console.log("manualGrid", missionItem.manualGrid) - console.log("camera", missionItem.camera) - } - ListModel { id: cameraModelList Component.onCompleted: { - cameraModelList.setProperty(_gridTypeCustomCamera, "sensorWidth", missionItem.cameraSensorWidth.rawValue) - cameraModelList.setProperty(_gridTypeCustomCamera, "sensorHeight", missionItem.cameraSensorHeight.rawValue) - cameraModelList.setProperty(_gridTypeCustomCamera, "imageWidth", missionItem.cameraResolutionWidth.rawValue) - cameraModelList.setProperty(_gridTypeCustomCamera, "imageHeight", missionItem.cameraResolutionHeight.rawValue) - cameraModelList.setProperty(_gridTypeCustomCamera, "focalLength", missionItem.cameraFocalLength.rawValue) + cameraModelList.setProperty(_gridTypeCustomCamera, "sensorWidth", missionItem.cameraSensorWidth.rawValue) + cameraModelList.setProperty(_gridTypeCustomCamera, "sensorHeight", missionItem.cameraSensorHeight.rawValue) + cameraModelList.setProperty(_gridTypeCustomCamera, "imageWidth", missionItem.cameraResolutionWidth.rawValue) + cameraModelList.setProperty(_gridTypeCustomCamera, "imageHeight", missionItem.cameraResolutionHeight.rawValue) + cameraModelList.setProperty(_gridTypeCustomCamera, "focalLength", missionItem.cameraFocalLength.rawValue) } ListElement { @@ -68,6 +47,14 @@ Rectangle { ListElement { text: qsTr("Custom Camera Grid") } + ListElement { + text: qsTr("Typhoon H CGO3+") + sensorWidth: 6.264 + sensorHeight: 4.698 + imageWidth: 4000 + imageHeight: 3000 + focalLength: 14 + } ListElement { text: qsTr("Sony ILCE-QX1") //http://www.sony.co.uk/electronics/interchangeable-lens-cameras/ilce-qx1-body-kit/specifications sensorWidth: 23.2 //http://www.sony.com/electronics/camera-lenses/sel16f28/specifications @@ -111,16 +98,16 @@ Rectangle { } function recalcFromCameraValues() { - var focalLength = missionItem.cameraFocalLength.rawValue - var sensorWidth = missionItem.cameraSensorWidth.rawValue - var sensorHeight = missionItem.cameraSensorHeight.rawValue - var imageWidth = missionItem.cameraResolutionWidth.rawValue - var imageHeight = missionItem.cameraResolutionHeight.rawValue + var focalLength = missionItem.cameraFocalLength.rawValue + var sensorWidth = missionItem.cameraSensorWidth.rawValue + var sensorHeight = missionItem.cameraSensorHeight.rawValue + var imageWidth = missionItem.cameraResolutionWidth.rawValue + var imageHeight = missionItem.cameraResolutionHeight.rawValue - var altitude = missionItem.gridAltitude.rawValue - var groundResolution = missionItem.groundResolution.rawValue - var frontalOverlap = missionItem.frontalOverlap.rawValue - var sideOverlap = missionItem.sideOverlap.rawValue + var altitude = missionItem.gridAltitude.rawValue + var groundResolution= missionItem.groundResolution.rawValue + var frontalOverlap = missionItem.frontalOverlap.rawValue + var sideOverlap = missionItem.sideOverlap.rawValue if (focalLength <= 0 || sensorWidth <= 0 || sensorHeight <= 0 || imageWidth <= 0 || imageHeight <= 0 || groundResolution <= 0) { return @@ -132,17 +119,17 @@ Rectangle { var cameraTriggerDistance if (missionItem.fixedValueIsAltitude) { - groundResolution = (altitude * sensorWidth * 100) / (imageWidth * focalLength) + groundResolution = (altitude * sensorWidth * 100) / (imageWidth * focalLength) } else { altitude = (imageWidth * groundResolution * focalLength) / (sensorWidth * 100) } if (cameraOrientationLandscape.checked) { - imageSizeSideGround = (imageWidth * groundResolution) / 100 + imageSizeSideGround = (imageWidth * groundResolution) / 100 imageSizeFrontGround = (imageHeight * groundResolution) / 100 } else { - imageSizeSideGround = (imageHeight * groundResolution) / 100 - imageSizeFrontGround = (imageWidth * groundResolution) / 100 + imageSizeSideGround = (imageHeight * groundResolution) / 100 + imageSizeFrontGround = (imageWidth * groundResolution) / 100 } gridSpacing = imageSizeSideGround * ( (100-sideOverlap) / 100 ) @@ -260,25 +247,6 @@ Rectangle { anchors.right: parent.right spacing: _margin - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - font.pointSize: ScreenTools.smallFontPointSize - text: gridTypeCombo.currentIndex == 0 ? - qsTr("Create a flight path which covers a polygonal area by specifying all grid parameters.") : - qsTr("Create a flight path which fully covers a polygonal area using camera specifications.") - } - - QGCLabel { text: qsTr("Camera:") } - - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - height: 1 - color: qgcPal.text - } - QGCComboBox { id: gridTypeCombo anchors.left: parent.left @@ -307,17 +275,27 @@ Rectangle { missionItem.manualGrid = false missionItem.camera = gridTypeCombo.textAt(index) _noCameraValueRecalc = true - missionItem.cameraSensorWidth.rawValue = cameraModelList.get(index).sensorWidth - missionItem.cameraSensorHeight.rawValue = cameraModelList.get(index).sensorHeight - missionItem.cameraResolutionWidth.rawValue = cameraModelList.get(index).imageWidth + missionItem.cameraSensorWidth.rawValue = cameraModelList.get(index).sensorWidth + missionItem.cameraSensorHeight.rawValue = cameraModelList.get(index).sensorHeight + missionItem.cameraResolutionWidth.rawValue = cameraModelList.get(index).imageWidth missionItem.cameraResolutionHeight.rawValue = cameraModelList.get(index).imageHeight - missionItem.cameraFocalLength.rawValue = cameraModelList.get(index).focalLength + missionItem.cameraFocalLength.rawValue = cameraModelList.get(index).focalLength _noCameraValueRecalc = false recalcFromCameraValues() } } } + QGCLabel { text: qsTr("Camera"); visible: gridTypeCombo.currentIndex !== _gridTypeManual} + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + color: qgcPal.text + visible: gridTypeCombo.currentIndex !== _gridTypeManual + } + // Camera based grid ui Column { anchors.left: parent.left @@ -327,6 +305,7 @@ Rectangle { Row { spacing: _margin + anchors.horizontalCenter: parent.horizontalCenter QGCRadioButton { id: cameraOrientationLandscape @@ -344,82 +323,104 @@ Rectangle { } Column { + id: custCameraCol anchors.left: parent.left anchors.right: parent.right spacing: _margin - visible: gridTypeCombo.currentIndex == _gridTypeCustomCamera - - GridLayout { - columns: 3 - columnSpacing: _margin - rowSpacing: _margin - - property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10 - - QGCLabel { } - QGCLabel { text: qsTr("Width") } - QGCLabel { text: qsTr("Height") } + visible: gridTypeCombo.currentIndex === _gridTypeCustomCamera + + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + Item { Layout.fillWidth: true } + QGCLabel { + Layout.preferredWidth: _root._fieldWidth + text: qsTr("Width") + } + QGCLabel { + Layout.preferredWidth: _root._fieldWidth + text: qsTr("Height") + } + } - QGCLabel { text: qsTr("Sensor:") } + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + QGCLabel { text: qsTr("Sensor:"); Layout.fillWidth: true } FactTextField { - Layout.preferredWidth: parent._fieldWidth + Layout.preferredWidth: _root._fieldWidth fact: missionItem.cameraSensorWidth } FactTextField { - Layout.preferredWidth: parent._fieldWidth + Layout.preferredWidth: _root._fieldWidth fact: missionItem.cameraSensorHeight } + } - QGCLabel { text: qsTr("Image:") } + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + QGCLabel { text: qsTr("Image:"); Layout.fillWidth: true } FactTextField { - Layout.preferredWidth: parent._fieldWidth + Layout.preferredWidth: _root._fieldWidth fact: missionItem.cameraResolutionWidth } FactTextField { - Layout.preferredWidth: parent._fieldWidth + Layout.preferredWidth: _root._fieldWidth fact: missionItem.cameraResolutionHeight } } - FactTextFieldRow { - spacing: _margin - fact: missionItem.cameraFocalLength + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + QGCLabel { + text: missionItem.cameraFocalLength.name + ":" + Layout.fillWidth: true + } + FactTextField { + Layout.preferredWidth: _root._fieldWidth + fact: missionItem.cameraFocalLength + } } - } // Column - custom camera - QGCLabel { text: qsTr("Image Overlap") } + } // Column - custom camera - Row { + RowLayout { + anchors.left: parent.left + anchors.right: parent.right spacing: _margin - - Item { - width: ScreenTools.defaultFontPixelWidth * 2 - height: 1 + Item { Layout.fillWidth: true } + QGCLabel { + Layout.preferredWidth: _root._fieldWidth + text: qsTr("Frontal") } - QGCLabel { - anchors.baseline: frontalOverlapField.baseline - text: qsTr("Frontal:") + Layout.preferredWidth: _root._fieldWidth + text: qsTr("Side") } + } + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + QGCLabel { text: qsTr("Overlap:"); Layout.fillWidth: true } FactTextField { - id: frontalOverlapField - width: ScreenTools.defaultFontPixelWidth * 7 - fact: missionItem.frontalOverlap - } - - QGCLabel { - anchors.baseline: frontalOverlapField.baseline - text: qsTr("Side:") + Layout.preferredWidth: _root._fieldWidth + fact: missionItem.frontalOverlap } - FactTextField { - width: frontalOverlapField.width - fact: missionItem.sideOverlap + Layout.preferredWidth: _root._fieldWidth + fact: missionItem.sideOverlap } } - QGCLabel { text: qsTr("Grid:") } + QGCLabel { text: qsTr("Grid") } Rectangle { anchors.left: parent.left @@ -428,12 +429,36 @@ Rectangle { color: qgcPal.text } - FactTextFieldGrid { + RowLayout { anchors.left: parent.left anchors.right: parent.right - columnSpacing: _margin - rowSpacing: _margin - factList: [ missionItem.gridAngle, missionItem.turnaroundDist ] + spacing: _margin + QGCLabel { + text: missionItem.gridAngle.name + ":" + Layout.fillWidth: true + anchors.verticalCenter: parent.verticalCenter + } + FactTextField { + fact: missionItem.gridAngle + anchors.verticalCenter: parent.verticalCenter + Layout.preferredWidth: _root._fieldWidth + } + } + + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + QGCLabel { + text: missionItem.turnaroundDist.name + ":" + Layout.fillWidth: true + anchors.verticalCenter: parent.verticalCenter + } + FactTextField { + fact: missionItem.turnaroundDist + anchors.verticalCenter: parent.verticalCenter + Layout.preferredWidth: _root._fieldWidth + } } QGCLabel { @@ -450,19 +475,20 @@ Rectangle { spacing: _margin QGCRadioButton { - id: fixedAltitudeRadio - anchors.baseline: gridAltitudeField.baseline - text: qsTr("Altitude:") - checked: missionItem.fixedValueIsAltitude - exclusiveGroup: fixedValueGroup - onClicked: missionItem.fixedValueIsAltitude = true + id: fixedAltitudeRadio + text: qsTr("Altitude:") + checked: missionItem.fixedValueIsAltitude + exclusiveGroup: fixedValueGroup + onClicked: missionItem.fixedValueIsAltitude = true + Layout.fillWidth: true + anchors.verticalCenter: parent.verticalCenter } FactTextField { - id: gridAltitudeField - Layout.fillWidth: true - fact: missionItem.gridAltitude - enabled: fixedAltitudeRadio.checked + fact: missionItem.gridAltitude + enabled: fixedAltitudeRadio.checked + Layout.preferredWidth: _root._fieldWidth + anchors.verticalCenter: parent.verticalCenter } } @@ -472,19 +498,20 @@ Rectangle { spacing: _margin QGCRadioButton { - id: fixedGroundResolutionRadio - anchors.baseline: groundResolutionField.baseline - text: qsTr("Ground res:") - checked: !missionItem.fixedValueIsAltitude - exclusiveGroup: fixedValueGroup - onClicked: missionItem.fixedValueIsAltitude = false + id: fixedGroundResolutionRadio + text: qsTr("Ground res:") + checked: !missionItem.fixedValueIsAltitude + exclusiveGroup: fixedValueGroup + onClicked: missionItem.fixedValueIsAltitude = false + Layout.fillWidth: true + anchors.verticalCenter: parent.verticalCenter } FactTextField { - id: groundResolutionField - Layout.fillWidth: true - fact: missionItem.groundResolution - enabled: fixedGroundResolutionRadio.checked + fact: missionItem.groundResolution + enabled: fixedGroundResolutionRadio.checked + Layout.preferredWidth: _root._fieldWidth + anchors.verticalCenter: parent.verticalCenter } } } @@ -496,7 +523,7 @@ Rectangle { spacing: _margin visible: gridTypeCombo.currentIndex == _gridTypeManual - QGCLabel { text: qsTr("Grid:") } + QGCLabel { text: qsTr("Grid") } Rectangle { anchors.left: parent.left @@ -508,7 +535,7 @@ Rectangle { FactTextFieldGrid { anchors.left: parent.left anchors.right: parent.right - columnSpacing: _margin + columnSpacing: _margin * 10 rowSpacing: _margin factList: [ missionItem.gridAngle, missionItem.gridSpacing, missionItem.gridAltitude, missionItem.turnaroundDist ] } @@ -520,7 +547,7 @@ Rectangle { onClicked: missionItem.gridAltitudeRelative = checked } - QGCLabel { text: qsTr("Camera:") } + QGCLabel { text: qsTr("Camera") } Rectangle { anchors.left: parent.left @@ -551,7 +578,7 @@ Rectangle { } } - QGCLabel { text: qsTr("Polygon:") } + QGCLabel { text: qsTr("Polygon") } Rectangle { anchors.left: parent.left @@ -562,8 +589,10 @@ Rectangle { Row { spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter QGCButton { + width: _root.width * 0.45 text: editorMap.polygonDraw.drawingPolygon ? qsTr("Finish Draw") : qsTr("Draw") visible: !editorMap.polygonDraw.adjustingPolygon enabled: ((editorMap.polygonDraw.drawingPolygon && editorMap.polygonDraw.polygonReady) || !editorMap.polygonDraw.drawingPolygon) @@ -578,6 +607,7 @@ Rectangle { } QGCButton { + width: _root.width * 0.4 text: editorMap.polygonDraw.adjustingPolygon ? qsTr("Finish Adjust") : qsTr("Adjust") visible: missionItem.polygonPath.length > 0 && !editorMap.polygonDraw.drawingPolygon @@ -591,7 +621,7 @@ Rectangle { } } - QGCLabel { text: qsTr("Statistics:") } + QGCLabel { text: qsTr("Statistics") } Rectangle { anchors.left: parent.left @@ -601,14 +631,25 @@ Rectangle { } Grid { - columns: 2 - spacing: ScreenTools.defaultFontPixelWidth + columns: 2 + columnSpacing: ScreenTools.defaultFontPixelWidth QGCLabel { text: qsTr("Survey area:") } QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(missionItem.coveredArea).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString } - QGCLabel { text: qsTr("# shots:") } + QGCLabel { text: qsTr("Photo count:") } QGCLabel { text: missionItem.cameraShots } + + QGCLabel { text: qsTr("Photo interval:") } + QGCLabel { + text: { + var timeVal = missionItem.timeBetweenShots + if(!isFinite(timeVal) || missionItem.cameraShots === 0) { + return qsTr("N/A") + } + return timeVal.toFixed(1) + " " + qsTr("secs") + } + } } } } diff --git a/src/MissionManager/ComplexMissionItem.cc b/src/MissionManager/ComplexMissionItem.cc index 04f76ecc5dbd67c55051aeb12ffeda9b5d66829c..43075c1ee119556264c8c6f4189bdac7ce330e64 100644 --- a/src/MissionManager/ComplexMissionItem.cc +++ b/src/MissionManager/ComplexMissionItem.cc @@ -7,9 +7,10 @@ * ****************************************************************************/ - #include "ComplexMissionItem.h" +const char* ComplexMissionItem::jsonComplexItemTypeKey = "complexItemType"; + ComplexMissionItem::ComplexMissionItem(Vehicle* vehicle, QObject* parent) : VisualMissionItem(vehicle, parent) { diff --git a/src/MissionManager/ComplexMissionItem.h b/src/MissionManager/ComplexMissionItem.h index d3e7e327c6e2fa5bac609b57e4a344353df1d086..5aa8b072da6c258c252ff5b3c485130f973c42eb 100644 --- a/src/MissionManager/ComplexMissionItem.h +++ b/src/MissionManager/ComplexMissionItem.h @@ -21,6 +21,7 @@ public: const ComplexMissionItem& operator=(const ComplexMissionItem& other); + Q_PROPERTY(QString mapVisualQML READ mapVisualQML CONSTANT) Q_PROPERTY(int lastSequenceNumber READ lastSequenceNumber NOTIFY lastSequenceNumberChanged) Q_PROPERTY(double complexDistance READ complexDistance NOTIFY complexDistanceChanged) @@ -36,15 +37,25 @@ public: /// Load the complex mission item from Json /// @param complexObject Complex mission item json object + /// @param sequenceNumber Sequence number for first MISSION_ITEM in survey /// @param[out] errorString Error if load fails /// @return true: load success, false: load failed, errorString set - virtual bool load(const QJsonObject& complexObject, QString& errorString) = 0; + virtual bool load(const QJsonObject& complexObject, int sequenceNumber, QString& errorString) = 0; /// Get the point of complex mission item furthest away from a coordinate /// @param other QGeoCoordinate to which distance is calculated /// @return the greatest distance from any point of the complex item to some coordinate virtual double greatestDistanceTo(const QGeoCoordinate &other) const = 0; + /// Informs the complex item of the cruise speed it will fly at + virtual void setCruiseSpeed(double cruiseSpeed) = 0; + + /// This mission item attribute specifies the type of the complex item. + static const char* jsonComplexItemTypeKey; + + /// @return The QML resource file which contains the control which visualizes the item on the map. + virtual QString mapVisualQML(void) const = 0; + signals: void lastSequenceNumberChanged (int lastSequenceNumber); void complexDistanceChanged (double complexDistance); diff --git a/src/MissionManager/ComplexMissionItemTest.cc b/src/MissionManager/ComplexMissionItemTest.cc index 6d446ded7083c177170f6778d52f06c76a9bac9b..a91e37dda22d1c7c6b6703f6e67f837fa720c502 100644 --- a/src/MissionManager/ComplexMissionItemTest.cc +++ b/src/MissionManager/ComplexMissionItemTest.cc @@ -180,26 +180,6 @@ void ComplexMissionItemTest::_testCameraTrigger(void) { QCOMPARE(_complexItem->property("cameraTrigger").toBool(), true); - // Turning on/off camera triggering while there is no grid should trigger: - // cameraTriggerChanged - // dirtyChanged - // lastSequenceNumber should not change - - int lastSeq = _complexItem->lastSequenceNumber(); - - _complexItem->setProperty("cameraTrigger", false); - QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask | cameraTriggerChangedMask)); - QVERIFY(!_multiSpy->pullBoolFromSignalIndex(cameraTriggerChangedIndex)); - QCOMPARE(_complexItem->lastSequenceNumber(), lastSeq); - - _complexItem->setDirty(false); - _multiSpy->clearAllSignals(); - - _complexItem->setProperty("cameraTrigger", true); - QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask | cameraTriggerChangedMask)); - QVERIFY(_multiSpy->pullBoolFromSignalIndex(cameraTriggerChangedIndex)); - QCOMPARE(_complexItem->lastSequenceNumber(), lastSeq); - // Set up a grid for (int i=0; i<3; i++) { @@ -209,7 +189,7 @@ void ComplexMissionItemTest::_testCameraTrigger(void) _complexItem->setDirty(false); _multiSpy->clearAllSignals(); - lastSeq = _complexItem->lastSequenceNumber(); + int lastSeq = _complexItem->lastSequenceNumber(); QVERIFY(lastSeq > 0); // Turning off camera triggering should remove two camera trigger mission items, this should trigger: diff --git a/src/MissionManager/FWLandingPattern.FactMetaData.json b/src/MissionManager/FWLandingPattern.FactMetaData.json new file mode 100644 index 0000000000000000000000000000000000000000..0efffaee46689d4dc33fa590b4e1ba17026f9df0 --- /dev/null +++ b/src/MissionManager/FWLandingPattern.FactMetaData.json @@ -0,0 +1,45 @@ +[ +{ + "name": "Landing distance", + "shortDescription": "Distance between landing and loiter points.", + "type": "double", + "units": "m", + "decimalPlaces": 1, + "defaultValue": 100.0 +}, +{ + "name": "Landing heading", + "shortDescription": "Heading from land point to loiter point.", + "type": "double", + "units": "deg", + "min": 0.0, + "max": 360.0, + "decimalPlaces": 0, + "defaultValue": 270.0 +}, +{ + "name": "Loiter altitude", + "shortDescription": "Aircraft will proceed to the loiter point and loiter until it reaches this altitude. Once altitude is reached the aircraft will proceed to land.", + "type": "double", + "units": "m", + "decimalPlaces": 1, + "defaultValue": 40.0 +}, +{ + "name": "Loiter radius", + "shortDescription": "Loiter radius.", + "type": "double", + "decimalPlaces": 1, + "min": 0.1, + "units": "m", + "defaultValue": 75.0 +}, +{ + "name": "Landing altitude", + "shortDescription": "Altitude for landing point.", + "type": "double", + "units": "m", + "decimalPlaces": 1, + "defaultValue": 0.0 +} +] diff --git a/src/MissionManager/FixedWingLandingComplexItem.cc b/src/MissionManager/FixedWingLandingComplexItem.cc new file mode 100644 index 0000000000000000000000000000000000000000..3ec84230b7ca675195eb587c7d82b696df149044 --- /dev/null +++ b/src/MissionManager/FixedWingLandingComplexItem.cc @@ -0,0 +1,293 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "FixedWingLandingComplexItem.h" +#include "JsonHelper.h" +#include "MissionController.h" +#include "QGCGeo.h" +#include "QGroundControlQmlGlobal.h" + +#include + +QGC_LOGGING_CATEGORY(FixedWingLandingComplexItemLog, "FixedWingLandingComplexItemLog") + +const char* FixedWingLandingComplexItem::jsonComplexItemTypeValue = "fwLandingPattern"; + +const char* FixedWingLandingComplexItem::_loiterToLandDistanceName = "Landing distance"; +const char* FixedWingLandingComplexItem::_landingHeadingName = "Landing heading"; +const char* FixedWingLandingComplexItem::_loiterAltitudeName = "Loiter altitude"; +const char* FixedWingLandingComplexItem::_loiterRadiusName = "Loiter radius"; +const char* FixedWingLandingComplexItem::_landingAltitudeName = "Landing altitude"; + +QMap FixedWingLandingComplexItem::_metaDataMap; + +FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, QObject* parent) + : ComplexMissionItem(vehicle, parent) + , _sequenceNumber(0) + , _dirty(false) + , _landingCoordSet(false) + , _ignoreRecalcSignals(false) + , _loiterToLandDistanceFact (0, _loiterToLandDistanceName, FactMetaData::valueTypeDouble) + , _loiterAltitudeFact (0, _loiterAltitudeName, FactMetaData::valueTypeDouble) + , _loiterRadiusFact (0, _loiterRadiusName, FactMetaData::valueTypeDouble) + , _landingHeadingFact (0, _landingHeadingName, FactMetaData::valueTypeDouble) + , _landingAltitudeFact (0, _landingAltitudeName, FactMetaData::valueTypeDouble) + , _loiterClockwise(true) + , _loiterAltitudeRelative(true) + , _landingAltitudeRelative(true) +{ + _editorQml = "qrc:/qml/FWLandingPatternEditor.qml"; + + if (_metaDataMap.isEmpty()) { + _metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/FWLandingPattern.FactMetaData.json"), NULL /* metaDataParent */); + } + + _loiterToLandDistanceFact.setMetaData (_metaDataMap[_loiterToLandDistanceName]); + _loiterAltitudeFact.setMetaData (_metaDataMap[_loiterAltitudeName]); + _loiterRadiusFact.setMetaData (_metaDataMap[_loiterRadiusName]); + _landingHeadingFact.setMetaData (_metaDataMap[_landingHeadingName]); + _landingAltitudeFact.setMetaData (_metaDataMap[_landingAltitudeName]); + + _loiterToLandDistanceFact.setRawValue (_loiterToLandDistanceFact.rawDefaultValue()); + _loiterAltitudeFact.setRawValue (_loiterAltitudeFact.rawDefaultValue()); + _loiterRadiusFact.setRawValue (_loiterRadiusFact.rawDefaultValue()); + _landingHeadingFact.setRawValue (_landingHeadingFact.rawDefaultValue()); + _landingAltitudeFact.setRawValue (_landingAltitudeFact.rawDefaultValue()); + + connect(&_loiterToLandDistanceFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_recalcLoiterCoordFromFacts); + connect(&_landingHeadingFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_recalcLoiterCoordFromFacts); + connect(this, &FixedWingLandingComplexItem::loiterCoordinateChanged, this, &FixedWingLandingComplexItem::_recalcFactsFromCoords); + connect(this, &FixedWingLandingComplexItem::landingCoordinateChanged, this, &FixedWingLandingComplexItem::_recalcFactsFromCoords); +} + +int FixedWingLandingComplexItem::lastSequenceNumber(void) const +{ + // land start, loiter, land + return _sequenceNumber + 2; +} + +void FixedWingLandingComplexItem::setDirty(bool dirty) +{ + if (_dirty != dirty) { + _dirty = dirty; + emit dirtyChanged(_dirty); + } +} + +void FixedWingLandingComplexItem::save(QJsonObject& saveObject) const +{ + saveObject[JsonHelper::jsonVersionKey] = 1; + saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; + saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; + + // FIXME: Need real implementation +} + +void FixedWingLandingComplexItem::setSequenceNumber(int sequenceNumber) +{ + if (_sequenceNumber != sequenceNumber) { + _sequenceNumber = sequenceNumber; + emit sequenceNumberChanged(sequenceNumber); + emit lastSequenceNumberChanged(lastSequenceNumber()); + } +} + +bool FixedWingLandingComplexItem::load(const QJsonObject& complexObject, int sequenceNumber, QString& errorString) +{ + // FIXME: Need real implementation + Q_UNUSED(complexObject); + Q_UNUSED(sequenceNumber); + + errorString = "NYI"; + return false; +} + +double FixedWingLandingComplexItem::greatestDistanceTo(const QGeoCoordinate &other) const +{ + // FIXME: Need real implementation + Q_UNUSED(other); + + double greatestDistance = 0.0; + +#if 0 + for (int i=0; i<_gridPoints.count(); i++) { + QGeoCoordinate currentCoord = _gridPoints[i].value(); + double distance = currentCoord.distanceTo(other); + if (distance > greatestDistance) { + greatestDistance = distance; + } + } +#endif + + return greatestDistance; +} + +bool FixedWingLandingComplexItem::specifiesCoordinate(void) const +{ + return true; +} + +QmlObjectListModel* FixedWingLandingComplexItem::getMissionItems(void) const +{ + QmlObjectListModel* pMissionItems = new QmlObjectListModel; + + int seqNum = _sequenceNumber; + + MissionItem* item = new MissionItem(seqNum++, // sequence number + MAV_CMD_DO_LAND_START, // MAV_CMD + MAV_FRAME_MISSION, // MAV_FRAME + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, // param 1-7 + true, // autoContinue + false, // isCurrentItem + pMissionItems); // parent - allow delete on pMissionItems to delete everthing + pMissionItems->append(item); + + float loiterRadius = _loiterRadiusFact.rawValue().toDouble() * (_loiterClockwise ? 1.0 : -1.0); + item = new MissionItem(seqNum++, + MAV_CMD_NAV_LOITER_TO_ALT, + _loiterAltitudeRelative ? MAV_FRAME_GLOBAL_RELATIVE_ALT : MAV_FRAME_GLOBAL, + 1.0, // Heading required = true + loiterRadius, // Loiter radius + 0.0, // param 3 - unused + 0.0, // Exit crosstrack - center of waypoint + _loiterCoordinate.latitude(), + _loiterCoordinate.longitude(), + _loiterCoordinate.altitude(), + true, // autoContinue + false, // isCurrentItem + pMissionItems); // parent - allow delete on pMissionItems to delete everthing + pMissionItems->append(item); + + item = new MissionItem(seqNum++, + MAV_CMD_NAV_LAND, + _landingAltitudeRelative ? MAV_FRAME_GLOBAL_RELATIVE_ALT : MAV_FRAME_GLOBAL, + 0.0, 0.0, 0.0, 0.0, // param 1-4 + _landingCoordinate.latitude(), + _landingCoordinate.longitude(), + 0.0, // altitude + true, // autoContinue + false, // isCurrentItem + pMissionItems); // parent - allow delete on pMissionItems to delete everthing + pMissionItems->append(item); + + return pMissionItems; +} + +double FixedWingLandingComplexItem::complexDistance(void) const +{ + // FIXME: Need real implementation + return 0; +} + +void FixedWingLandingComplexItem::setCruiseSpeed(double cruiseSpeed) +{ + // FIXME: Need real implementation + Q_UNUSED(cruiseSpeed); +} + +void FixedWingLandingComplexItem::setLandingCoordinate(const QGeoCoordinate& coordinate) +{ + if (coordinate != _landingCoordinate) { + _landingCoordinate = coordinate; + if (_landingCoordSet) { + emit exitCoordinateChanged(coordinate); + emit landingCoordinateChanged(coordinate); + } else { + _ignoreRecalcSignals = true; + emit exitCoordinateChanged(coordinate); + emit landingCoordinateChanged(coordinate); + _ignoreRecalcSignals = false; + _landingCoordSet = true; + _recalcLoiterCoordFromFacts(); + emit landingCoordSetChanged(true); + } + } +} + +void FixedWingLandingComplexItem::setLoiterCoordinate(const QGeoCoordinate& coordinate) +{ + if (coordinate != _loiterCoordinate) { + _loiterCoordinate = coordinate; + emit coordinateChanged(coordinate); + emit loiterCoordinateChanged(coordinate); + } +} + +void FixedWingLandingComplexItem::_recalcLoiterCoordFromFacts(void) +{ + if (!_ignoreRecalcSignals && _landingCoordSet) { + double north, east, down; + QGeoCoordinate tangentOrigin = _landingCoordinate; + + convertGeoToNed(_landingCoordinate, tangentOrigin, &north, &east, &down); + + QPointF originPoint(east, north); + north += _loiterToLandDistanceFact.rawValue().toDouble(); + QPointF loiterPoint(east, north); + QPointF rotatedLoiterPoint = _rotatePoint(loiterPoint, originPoint, -_landingHeadingFact.rawValue().toDouble()); + + convertNedToGeo(rotatedLoiterPoint.y(), rotatedLoiterPoint.x(), down, tangentOrigin, &_loiterCoordinate); + + _ignoreRecalcSignals = true; + emit loiterCoordinateChanged(_loiterCoordinate); + emit coordinateChanged(_loiterCoordinate); + _ignoreRecalcSignals = false; + } +} + +QPointF FixedWingLandingComplexItem::_rotatePoint(const QPointF& point, const QPointF& origin, double angle) +{ + QPointF rotated; + double radians = (M_PI / 180.0) * angle; + + rotated.setX(((point.x() - origin.x()) * cos(radians)) - ((point.y() - origin.y()) * sin(radians)) + origin.x()); + rotated.setY(((point.x() - origin.x()) * sin(radians)) + ((point.y() - origin.y()) * cos(radians)) + origin.y()); + + return rotated; +} + +void FixedWingLandingComplexItem::_recalcFactsFromCoords(void) +{ + if (!_ignoreRecalcSignals && _landingCoordSet) { + + // Prevent signal recursion + _ignoreRecalcSignals = true; + + // Calc new distance + + double northLand, eastLand, down; + double northLoiter, eastLoiter; + QGeoCoordinate tangentOrigin = _landingCoordinate; + + convertGeoToNed(_landingCoordinate, tangentOrigin, &northLand, &eastLand, &down); + convertGeoToNed(_loiterCoordinate, tangentOrigin, &northLoiter, &eastLoiter, &down); + + double newDistance = sqrt(pow(eastLoiter - eastLand, 2.0) + pow(northLoiter - northLand, 2.0)); + _loiterToLandDistanceFact.setRawValue(newDistance); + + // Calc new heading + + QPointF vector(eastLoiter - eastLand, northLoiter - northLand); + double radians = atan2(vector.y(), vector.x()); + double degrees = qRadiansToDegrees(radians); + // Change angle to north up = 0 degrees + degrees -= 90; + // Reverse the angle direction to go from mathematic angle (counter-clockwise) to compass heading (clockwise) + degrees *= -1.0; + // Bring with 0-360 range + if (degrees < 0.0) { + degrees += 360.0; + } else if (degrees > 360.0) { + degrees -= 360.0; + } + _landingHeadingFact.setRawValue(degrees); + + _ignoreRecalcSignals = false; + } +} diff --git a/src/MissionManager/FixedWingLandingComplexItem.h b/src/MissionManager/FixedWingLandingComplexItem.h new file mode 100644 index 0000000000000000000000000000000000000000..a9be9ccfce92a62f0c5e56c853039324dff3ff47 --- /dev/null +++ b/src/MissionManager/FixedWingLandingComplexItem.h @@ -0,0 +1,126 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef FixedWingLandingComplexItem_H +#define FixedWingLandingComplexItem_H + +#include "ComplexMissionItem.h" +#include "MissionItem.h" +#include "Fact.h" +#include "QGCLoggingCategory.h" + +Q_DECLARE_LOGGING_CATEGORY(FixedWingLandingComplexItemLog) + +class FixedWingLandingComplexItem : public ComplexMissionItem +{ + Q_OBJECT + +public: + FixedWingLandingComplexItem(Vehicle* vehicle, QObject* parent = NULL); + + Q_PROPERTY(Fact* loiterAltitude READ loiterAltitude CONSTANT) + Q_PROPERTY(Fact* loiterRadius READ loiterRadius CONSTANT) + Q_PROPERTY(Fact* landingAltitude READ landingAltitude CONSTANT) + Q_PROPERTY(Fact* landingDistance READ landingDistance CONSTANT) + Q_PROPERTY(Fact* landingHeading READ landingHeading CONSTANT) + Q_PROPERTY(bool loiterClockwise MEMBER _loiterClockwise NOTIFY loiterClockwiseChanged) + Q_PROPERTY(bool loiterAltitudeRelative MEMBER _loiterAltitudeRelative NOTIFY loiterAltitudeRelativeChanged) + Q_PROPERTY(bool landingAltitudeRelative MEMBER _landingAltitudeRelative NOTIFY landingAltitudeRelativeChanged) + Q_PROPERTY(QGeoCoordinate loiterCoordinate READ loiterCoordinate WRITE setLoiterCoordinate NOTIFY loiterCoordinateChanged) + Q_PROPERTY(QGeoCoordinate landingCoordinate READ landingCoordinate WRITE setLandingCoordinate NOTIFY landingCoordinateChanged) + Q_PROPERTY(bool landingCoordSet MEMBER _landingCoordSet NOTIFY landingCoordSetChanged) + + Fact* loiterAltitude (void) { return &_loiterAltitudeFact; } + Fact* loiterRadius (void) { return &_loiterRadiusFact; } + Fact* landingAltitude (void) { return &_landingAltitudeFact; } + Fact* landingDistance (void) { return &_loiterToLandDistanceFact; } + Fact* landingHeading (void) { return &_landingHeadingFact; } + QGeoCoordinate landingCoordinate (void) const { return _landingCoordinate; } + QGeoCoordinate loiterCoordinate (void) const { return _loiterCoordinate; } + + void setLandingCoordinate (const QGeoCoordinate& coordinate); + void setLoiterCoordinate (const QGeoCoordinate& coordinate); + + // Overrides from ComplexMissionItem + + double complexDistance (void) const final; + int lastSequenceNumber (void) const final; + QmlObjectListModel* getMissionItems (void) const final; + bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final; + double greatestDistanceTo (const QGeoCoordinate &other) const final; + void setCruiseSpeed (double cruiseSpeed) final; + QString mapVisualQML (void) const final { return QStringLiteral("FWLandingPatternMapVisual.qml"); } + + // Overrides from VisualMissionItem + + bool dirty (void) const final { return _dirty; } + bool isSimpleItem (void) const final { return false; } + bool isStandaloneCoordinate (void) const final { return false; } + bool specifiesCoordinate (void) const final; + QString commandDescription (void) const final { return "Landing Pattern"; } + QString commandName (void) const final { return "Landing Pattern"; } + QString abbreviation (void) const final { return "L"; } + QGeoCoordinate coordinate (void) const final { return _loiterCoordinate; } + QGeoCoordinate exitCoordinate (void) const final { return _landingCoordinate; } + int sequenceNumber (void) const final { return _sequenceNumber; } + double flightSpeed (void) final { return std::numeric_limits::quiet_NaN(); } + + bool coordinateHasRelativeAltitude (void) const final { return true; } + bool exitCoordinateHasRelativeAltitude (void) const final { return true; } + bool exitCoordinateSameAsEntry (void) const final { return true; } + + void setDirty (bool dirty) final; + void setCoordinate (const QGeoCoordinate& coordinate) final { setLoiterCoordinate(coordinate); } + void setSequenceNumber (int sequenceNumber) final; + void save (QJsonObject& saveObject) const final; + + static const char* jsonComplexItemTypeValue; + +signals: + void loiterCoordinateChanged (QGeoCoordinate coordinate); + void landingCoordinateChanged (QGeoCoordinate coordinate); + void landingCoordSetChanged (bool landingCoordSet); + void loiterClockwiseChanged (bool loiterClockwise); + void loiterAltitudeRelativeChanged (bool loiterAltitudeRelative); + void landingAltitudeRelativeChanged (bool loiterAltitudeRelative); + +private slots: + void _recalcLoiterCoordFromFacts(void); + void _recalcFactsFromCoords(void); + +private: + QPointF _rotatePoint(const QPointF& point, const QPointF& origin, double angle); + + int _sequenceNumber; + bool _dirty; + QGeoCoordinate _loiterCoordinate; + QGeoCoordinate _landingCoordinate; + bool _landingCoordSet; + bool _ignoreRecalcSignals; + + Fact _loiterToLandDistanceFact; + Fact _loiterAltitudeFact; + Fact _loiterRadiusFact; + Fact _landingHeadingFact; + Fact _landingAltitudeFact; + + bool _loiterClockwise; + bool _loiterAltitudeRelative; + bool _landingAltitudeRelative; + + static QMap _metaDataMap; + + static const char* _loiterToLandDistanceName; + static const char* _loiterAltitudeName; + static const char* _loiterRadiusName; + static const char* _landingHeadingName; + static const char* _landingAltitudeName; +}; + +#endif diff --git a/src/MissionManager/GeoFenceController.cc b/src/MissionManager/GeoFenceController.cc index dbf9a54440ea537c3a85bfc534aab742bd1b504a..5a00533dcfc404826d85460af52b8b29344b1828 100644 --- a/src/MissionManager/GeoFenceController.cc +++ b/src/MissionManager/GeoFenceController.cc @@ -20,6 +20,7 @@ #include "JsonHelper.h" #ifndef __mobile__ +#include "MainWindow.h" #include "QGCFileDialog.h" #endif @@ -47,7 +48,19 @@ void GeoFenceController::start(bool editMode) qCDebug(GeoFenceControllerLog) << "start editMode" << editMode; PlanElementController::start(editMode); + _init(); +} + +void GeoFenceController::startStaticActiveVehicle(Vehicle* vehicle) +{ + qCDebug(GeoFenceControllerLog) << "startStaticActiveVehicle"; + PlanElementController::startStaticActiveVehicle(vehicle); + _init(); +} + +void GeoFenceController::_init(void) +{ connect(&_polygon, &QGCMapPolygon::dirtyChanged, this, &GeoFenceController::_polygonDirtyChanged); } @@ -62,10 +75,9 @@ void GeoFenceController::setBreachReturnPoint(const QGeoCoordinate& breachReturn void GeoFenceController::_signalAll(void) { - emit fenceSupportedChanged(fenceSupported()); - emit circleSupportedChanged(circleSupported()); - emit polygonSupportedChanged(polygonSupported()); - emit breachReturnSupportedChanged(breachReturnSupported()); + emit circleEnabledChanged(circleEnabled()); + emit polygonEnabledChanged(polygonEnabled()); + emit breachReturnEnabledChanged(breachReturnEnabled()); emit breachReturnPointChanged(breachReturnPoint()); emit circleRadiusChanged(circleRadius()); emit paramsChanged(params()); @@ -82,17 +94,15 @@ void GeoFenceController::_activeVehicleBeingRemoved(void) void GeoFenceController::_activeVehicleSet(void) { GeoFenceManager* geoFenceManager = _activeVehicle->geoFenceManager(); - connect(geoFenceManager, &GeoFenceManager::circleSupportedChanged, this, &GeoFenceController::_setDirty); - connect(geoFenceManager, &GeoFenceManager::polygonSupportedChanged, this, &GeoFenceController::_setDirty); - connect(geoFenceManager, &GeoFenceManager::fenceSupportedChanged, this, &GeoFenceController::fenceSupportedChanged); - connect(geoFenceManager, &GeoFenceManager::circleSupportedChanged, this, &GeoFenceController::circleSupportedChanged); - connect(geoFenceManager, &GeoFenceManager::polygonSupportedChanged, this, &GeoFenceController::polygonSupportedChanged); - connect(geoFenceManager, &GeoFenceManager::breachReturnSupportedChanged, this, &GeoFenceController::breachReturnSupportedChanged); - connect(geoFenceManager, &GeoFenceManager::circleRadiusChanged, this, &GeoFenceController::circleRadiusChanged); - connect(geoFenceManager, &GeoFenceManager::paramsChanged, this, &GeoFenceController::paramsChanged); - connect(geoFenceManager, &GeoFenceManager::paramLabelsChanged, this, &GeoFenceController::paramLabelsChanged); - connect(geoFenceManager, &GeoFenceManager::loadComplete, this, &GeoFenceController::_loadComplete); - connect(geoFenceManager, &GeoFenceManager::inProgressChanged, this, &GeoFenceController::syncInProgressChanged); + connect(geoFenceManager, &GeoFenceManager::polygonEnabledChanged, this, &GeoFenceController::_setDirty); + connect(geoFenceManager, &GeoFenceManager::circleEnabledChanged, this, &GeoFenceController::circleEnabledChanged); + connect(geoFenceManager, &GeoFenceManager::polygonEnabledChanged, this, &GeoFenceController::polygonEnabledChanged); + connect(geoFenceManager, &GeoFenceManager::breachReturnEnabledChanged, this, &GeoFenceController::breachReturnEnabledChanged); + connect(geoFenceManager, &GeoFenceManager::circleRadiusChanged, this, &GeoFenceController::circleRadiusChanged); + connect(geoFenceManager, &GeoFenceManager::paramsChanged, this, &GeoFenceController::paramsChanged); + connect(geoFenceManager, &GeoFenceManager::paramLabelsChanged, this, &GeoFenceController::paramLabelsChanged); + connect(geoFenceManager, &GeoFenceManager::loadComplete, this, &GeoFenceController::_loadComplete); + connect(geoFenceManager, &GeoFenceManager::inProgressChanged, this, &GeoFenceController::syncInProgressChanged); if (!geoFenceManager->inProgress()) { _loadComplete(geoFenceManager->breachReturnPoint(), geoFenceManager->polygon()); @@ -105,27 +115,13 @@ bool GeoFenceController::_loadJsonFile(QJsonDocument& jsonDoc, QString& errorStr { QJsonObject json = jsonDoc.object(); - // Check for required keys - QStringList requiredKeys; - requiredKeys << JsonHelper::jsonVersionKey << JsonHelper::jsonFileTypeKey; - if (!JsonHelper::validateRequiredKeys(json, requiredKeys, errorString)) { - return false; - } - -#if 0 - // Validate base key types - QStringList keyList; - QList typeList; - keyList << jsonSimpleItemsKey << _jsonVersionKey << _jsonGroundStationKey << _jsonMavAutopilotKey << _jsonComplexItemsKey << _jsonPlannedHomePositionKey; - typeList << QJsonValue::Array << QJsonValue::String << QJsonValue::String << QJsonValue::Double << QJsonValue::Array << QJsonValue::Object; - if (!JsonHelper::validateKeyTypes(json, keyList, typeList, errorString)) { - return false; - } -#endif - - // Version check - if (json[JsonHelper::jsonVersionKey].toString() != "1.0") { - errorString = QStringLiteral("QGroundControl does not support this file version"); + int fileVersion; + if (!JsonHelper::validateQGCJsonFile(json, + _jsonFileTypeValue, // expected file type + 1, // minimum supported version + 1, // maximum supported version + fileVersion, + errorString)) { return false; } @@ -133,7 +129,7 @@ bool GeoFenceController::_loadJsonFile(QJsonDocument& jsonDoc, QString& errorStr return false; } - if (breachReturnSupported()) { + if (breachReturnEnabled()) { if (json.contains(_jsonBreachReturnKey) && !JsonHelper::loadGeoCoordinate(json[_jsonBreachReturnKey], false /* altitudeRequired */, _breachReturnPoint, errorString)) { return false; @@ -142,7 +138,7 @@ bool GeoFenceController::_loadJsonFile(QJsonDocument& jsonDoc, QString& errorStr _breachReturnPoint = QGeoCoordinate(); } - if (polygonSupported()) { + if (polygonEnabled()) { if (!_polygon.loadFromJson(json, false /* reauired */, errorString)) { return false; } @@ -218,7 +214,7 @@ void GeoFenceController::loadFromFile(const QString& filename) QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - errorString = file.errorString(); + errorString = file.errorString() + QStringLiteral(" ") + filename; } else { QJsonDocument jsonDoc; QByteArray bytes = file.readAll(); @@ -243,7 +239,7 @@ void GeoFenceController::loadFromFile(const QString& filename) void GeoFenceController::loadFromFilePicker(void) { #ifndef __mobile__ - QString filename = QGCFileDialog::getOpenFileName(NULL, "Select GeoFence File to load", QString(), "Fence file (*.fence);;All Files (*.*)"); + QString filename = QGCFileDialog::getOpenFileName(MainWindow::instance(), "Select GeoFence File to load", QString(), "Fence file (*.fence);;All Files (*.*)"); if (filename.isEmpty()) { return; @@ -271,7 +267,7 @@ void GeoFenceController::saveToFile(const QString& filename) QJsonObject fenceFileObject; // top level json object fenceFileObject[JsonHelper::jsonFileTypeKey] = _jsonFileTypeValue; - fenceFileObject[JsonHelper::jsonVersionKey] = QStringLiteral("1.0"); + fenceFileObject[JsonHelper::jsonVersionKey] = 1; fenceFileObject[JsonHelper::jsonGroundStationKey] = JsonHelper::jsonGroundStationValue; QStringList paramNames; @@ -283,16 +279,16 @@ void GeoFenceController::saveToFile(const QString& filename) paramNames.append(params[i].value()->name()); } if (paramNames.count() > 0) { - paramMgr->saveToJson(paramMgr->defaultComponentId(), paramNames, fenceFileObject); + paramMgr->saveToJson(_activeVehicle->defaultComponentId(), paramNames, fenceFileObject); } - if (breachReturnSupported()) { + if (breachReturnEnabled()) { QJsonValue jsonBreachReturn; JsonHelper::saveGeoCoordinate(_breachReturnPoint, false /* writeAltitude */, jsonBreachReturn); fenceFileObject[_jsonBreachReturnKey] = jsonBreachReturn; } - if (polygonSupported()) { + if (polygonEnabled()) { _polygon.saveToJson(fenceFileObject); } @@ -306,7 +302,7 @@ void GeoFenceController::saveToFile(const QString& filename) void GeoFenceController::saveToFilePicker(void) { #ifndef __mobile__ - QString filename = QGCFileDialog::getSaveFileName(NULL, "Select file to save GeoFence to", QString(), "Fence file (*.fence);;All Files (*.*)"); + QString filename = QGCFileDialog::getSaveFileName(MainWindow::instance(), "Select file to save GeoFence to", QString(), "Fence file (*.fence);;All Files (*.*)"); if (filename.isEmpty()) { return; @@ -333,9 +329,9 @@ void GeoFenceController::loadFromVehicle(void) void GeoFenceController::sendToVehicle(void) { if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) { - setDirty(false); - _polygon.setDirty(false); _activeVehicle->geoFenceManager()->sendToVehicle(_breachReturnPoint, _polygon.coordinateList()); + _polygon.setDirty(false); + setDirty(false); } else { qCWarning(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress(); } @@ -370,24 +366,19 @@ void GeoFenceController::_polygonDirtyChanged(bool dirty) } } -bool GeoFenceController::fenceSupported(void) const -{ - return _activeVehicle->geoFenceManager()->fenceSupported(); -} - -bool GeoFenceController::circleSupported(void) const +bool GeoFenceController::circleEnabled(void) const { - return _activeVehicle->geoFenceManager()->circleSupported(); + return _activeVehicle->geoFenceManager()->circleEnabled(); } -bool GeoFenceController::polygonSupported(void) const +bool GeoFenceController::polygonEnabled(void) const { - return _activeVehicle->geoFenceManager()->polygonSupported(); + return _activeVehicle->geoFenceManager()->polygonEnabled(); } -bool GeoFenceController::breachReturnSupported(void) const +bool GeoFenceController::breachReturnEnabled(void) const { - return _activeVehicle->geoFenceManager()->breachReturnSupported(); + return _activeVehicle->geoFenceManager()->breachReturnEnabled(); } void GeoFenceController::_setDirty(void) @@ -433,6 +424,7 @@ void GeoFenceController::_loadComplete(const QGeoCoordinate& breachReturn, const _setReturnPointFromManager(breachReturn); _setPolygonFromManager(polygon); setDirty(false); + emit loadComplete(); } QString GeoFenceController::fileExtension(void) const diff --git a/src/MissionManager/GeoFenceController.h b/src/MissionManager/GeoFenceController.h index d5f14cf3f970a6c786034693a2816237588d3914..aff9018179b48ab1952aed4a7e875559c8e38b06 100644 --- a/src/MissionManager/GeoFenceController.h +++ b/src/MissionManager/GeoFenceController.h @@ -29,55 +29,65 @@ public: GeoFenceController(QObject* parent = NULL); ~GeoFenceController(); + Q_PROPERTY(bool circleEnabled READ circleEnabled NOTIFY circleEnabledChanged) + Q_PROPERTY(float circleRadius READ circleRadius NOTIFY circleRadiusChanged) + + Q_PROPERTY(bool polygonEnabled READ polygonEnabled NOTIFY polygonEnabledChanged) + Q_PROPERTY(QGCMapPolygon* polygon READ polygon CONSTANT) + + Q_PROPERTY(bool breachReturnEnabled READ breachReturnEnabled NOTIFY breachReturnEnabledChanged) + Q_PROPERTY(QGeoCoordinate breachReturnPoint READ breachReturnPoint WRITE setBreachReturnPoint NOTIFY breachReturnPointChanged) + + Q_PROPERTY(QVariantList params READ params NOTIFY paramsChanged) + Q_PROPERTY(QStringList paramLabels READ paramLabels NOTIFY paramLabelsChanged) + Q_PROPERTY(QString editorQml READ editorQml NOTIFY editorQmlChanged) + +#if 0 Q_PROPERTY(bool fenceSupported READ fenceSupported NOTIFY fenceSupportedChanged) + Q_PROPERTY(bool fenceEnabled READ fenceEnabled NOTIFY fenceEnabledChanged) Q_PROPERTY(bool circleSupported READ circleSupported NOTIFY circleSupportedChanged) Q_PROPERTY(bool polygonSupported READ polygonSupported NOTIFY polygonSupportedChanged) Q_PROPERTY(bool breachReturnSupported READ breachReturnSupported NOTIFY breachReturnSupportedChanged) - Q_PROPERTY(float circleRadius READ circleRadius NOTIFY circleRadiusChanged) - Q_PROPERTY(QGCMapPolygon* polygon READ polygon CONSTANT) - Q_PROPERTY(QGeoCoordinate breachReturnPoint READ breachReturnPoint WRITE setBreachReturnPoint NOTIFY breachReturnPointChanged) - Q_PROPERTY(QVariantList params READ params NOTIFY paramsChanged) - Q_PROPERTY(QStringList paramLabels READ paramLabels NOTIFY paramLabelsChanged) - Q_PROPERTY(QString editorQml READ editorQml NOTIFY editorQmlChanged) - - void start (bool editMode) final; - void loadFromVehicle (void) final; - void sendToVehicle (void) final; - void loadFromFilePicker (void) final; - void loadFromFile (const QString& filename) final; - void saveToFilePicker (void) final; - void saveToFile (const QString& filename) final; - void removeAll (void) final; - bool syncInProgress (void) const final; - bool dirty (void) const final; - void setDirty (bool dirty) final; +#endif + + void start (bool editMode) final; + void startStaticActiveVehicle (Vehicle* vehicle) final; + void loadFromVehicle (void) final; + void sendToVehicle (void) final; + void loadFromFilePicker (void) final; + void loadFromFile (const QString& filename) final; + void saveToFilePicker (void) final; + void saveToFile (const QString& filename) final; + void removeAll (void) final; + bool syncInProgress (void) const final; + bool dirty (void) const final; + void setDirty (bool dirty) final; QString fileExtension(void) const final; - bool fenceSupported (void) const; - bool circleSupported (void) const; - bool polygonSupported (void) const; - bool breachReturnSupported (void) const; - float circleRadius (void) const; - QGCMapPolygon* polygon (void) { return &_polygon; } - QGeoCoordinate breachReturnPoint (void) const { return _breachReturnPoint; } - QVariantList params (void) const; - QStringList paramLabels (void) const; - QString editorQml (void) const; + bool circleEnabled (void) const; + bool polygonEnabled (void) const; + bool breachReturnEnabled (void) const; + float circleRadius (void) const; + QGCMapPolygon* polygon (void) { return &_polygon; } + QGeoCoordinate breachReturnPoint (void) const { return _breachReturnPoint; } + QVariantList params (void) const; + QStringList paramLabels (void) const; + QString editorQml (void) const; void setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint); signals: - void fenceSupportedChanged (bool fenceSupported); - void circleSupportedChanged (bool circleSupported); - void polygonSupportedChanged (bool polygonSupported); - void breachReturnSupportedChanged (bool breachReturnSupported); - void circleRadiusChanged (float circleRadius); - void polygonPathChanged (const QVariantList& polygonPath); - void breachReturnPointChanged (QGeoCoordinate breachReturnPoint); - void paramsChanged (QVariantList params); - void paramLabelsChanged (QStringList paramLabels); - void editorQmlChanged (QString editorQml); + void circleEnabledChanged (bool circleEnabled); + void polygonEnabledChanged (bool polygonEnabled); + void breachReturnEnabledChanged (bool breachReturnEnabled); + void circleRadiusChanged (float circleRadius); + void polygonPathChanged (const QVariantList& polygonPath); + void breachReturnPointChanged (QGeoCoordinate breachReturnPoint); + void paramsChanged (QVariantList params); + void paramLabelsChanged (QStringList paramLabels); + void editorQmlChanged (QString editorQml); + void loadComplete (void); private slots: void _polygonDirtyChanged(bool dirty); @@ -87,6 +97,7 @@ private slots: void _loadComplete(const QGeoCoordinate& breachReturn, const QList& polygon); private: + void _init(void); void _signalAll(void); bool _loadJsonFile(QJsonDocument& jsonDoc, QString& errorString); diff --git a/src/MissionManager/GeoFenceManager.cc b/src/MissionManager/GeoFenceManager.cc index 24d8d55347557bcc9df290a8c7fa3e84cc8d7807..331cfe5eb237a0ba553edf3e8d0ff83883f101ae 100644 --- a/src/MissionManager/GeoFenceManager.cc +++ b/src/MissionManager/GeoFenceManager.cc @@ -34,7 +34,7 @@ void GeoFenceManager::_sendError(ErrorCode_t errorCode, const QString& errorMsg) void GeoFenceManager::loadFromVehicle(void) { // No geofence support in unknown vehicle - loadComplete(QGeoCoordinate(), QList()); + emit loadComplete(QGeoCoordinate(), QList()); } void GeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const QList& polygon) diff --git a/src/MissionManager/GeoFenceManager.h b/src/MissionManager/GeoFenceManager.h index 20294ed5d8e1fec29db7d40309563b53bf0f7df9..f676e42010af54acbb9cda2c9d5e6da521aa751b 100644 --- a/src/MissionManager/GeoFenceManager.h +++ b/src/MissionManager/GeoFenceManager.h @@ -38,11 +38,9 @@ public: /// Send the current settings to the vehicle virtual void sendToVehicle(const QGeoCoordinate& breachReturn, const QList& polygon); - // Support flags - virtual bool fenceSupported (void) const { return false; } - virtual bool circleSupported (void) const { return false; } - virtual bool polygonSupported (void) const { return false; } - virtual bool breachReturnSupported (void) const { return false; } + virtual bool circleEnabled (void) const { return false; } + virtual bool polygonEnabled (void) const { return false; } + virtual bool breachReturnEnabled (void) const { return false; } virtual float circleRadius (void) const { return 0.0; } QList polygon (void) const { return _polygon; } @@ -51,7 +49,7 @@ public: virtual QVariantList params (void) const { return QVariantList(); } virtual QStringList paramLabels (void) const { return QStringList(); } - virtual QString editorQml(void) const { return QStringLiteral("qrc:/FirmwarePlugin/GeoFenceEditor.qml"); } + virtual QString editorQml(void) const { return QStringLiteral("qrc:/FirmwarePlugin/NoGeoFenceEditor.qml"); } /// Error codes returned in error signal typedef enum { @@ -62,16 +60,15 @@ public: } ErrorCode_t; signals: - void loadComplete (const QGeoCoordinate& breachReturn, const QList& polygon); - void fenceSupportedChanged (bool fenceSupported); - void circleSupportedChanged (bool circleSupported); - void polygonSupportedChanged (bool polygonSupported); - void breachReturnSupportedChanged (bool fenceSupported); - void circleRadiusChanged (float circleRadius); - void inProgressChanged (bool inProgress); - void error (int errorCode, const QString& errorMsg); - void paramsChanged (QVariantList params); - void paramLabelsChanged (QStringList paramLabels); + void loadComplete (const QGeoCoordinate& breachReturn, const QList& polygon); + void circleEnabledChanged (bool circleEnabled); + void polygonEnabledChanged (bool polygonEnabled); + void breachReturnEnabledChanged (bool fenceEnabled); + void circleRadiusChanged (float circleRadius); + void inProgressChanged (bool inProgress); + void error (int errorCode, const QString& errorMsg); + void paramsChanged (QVariantList params); + void paramLabelsChanged (QStringList paramLabels); protected: void _sendError(ErrorCode_t errorCode, const QString& errorMsg); diff --git a/src/MissionManager/MavCmdInfoCommon.json b/src/MissionManager/MavCmdInfoCommon.json index e0567057c0f11d87640cf714117dcab30b5df2ea..622e1cff1fddd14f1e4d9d7431d93c8580170b68 100644 --- a/src/MissionManager/MavCmdInfoCommon.json +++ b/src/MissionManager/MavCmdInfoCommon.json @@ -5,7 +5,7 @@ "mavCmdInfo": [ { - "comment": "MAV_CMD_NAV_LAST: Used for fake home position waypoint", + "comment": "MAV_CMD_NAV_LAST: Used for mission settings / planned home position waypoint", "id": 95, "rawName": "HomeRaw", "friendlyName": "Home Position", @@ -503,23 +503,23 @@ "label": "Type:", "enumStrings": "Airspeed,Ground Speed", "enumValues": "0,1", - "default": 1 + "default": 0 }, "param2": { "label": "Speed:", "units": "m/s", - "default": -1 + "default": 0 }, "param3": { "label": "Throttle:", "units": "%", - "default": -1 + "default": 0 }, "param4": { "label": "Offset:", "enumStrings": "Relative,Absolute", "enumValues": "1,0", - "default": 1 + "default": 0 } }, { diff --git a/src/MissionManager/MissionCommandTree.cc b/src/MissionManager/MissionCommandTree.cc index 1a261c18facf058331f65e01979646ba676c06f8..cbb41630d3eaf0e7b13d7ea7e154e1ca679d02f2 100644 --- a/src/MissionManager/MissionCommandTree.cc +++ b/src/MissionManager/MissionCommandTree.cc @@ -17,11 +17,13 @@ #include "QGroundControlQmlGlobal.h" #include "MissionCommandUIInfo.h" #include "MissionCommandList.h" +#include "SettingsManager.h" #include MissionCommandTree::MissionCommandTree(QGCApplication* app, bool unitTest) : QGCTool(app) + , _settingsManager(NULL) , _unitTest(unitTest) { } @@ -30,6 +32,8 @@ void MissionCommandTree::setToolbox(QGCToolbox* toolbox) { QGCTool::setToolbox(toolbox); + _settingsManager = toolbox->settingsManager(); + #ifdef UNITTEST_BUILD if (_unitTest) { // Load unit testing tree @@ -42,7 +46,7 @@ void MissionCommandTree::setToolbox(QGCToolbox* toolbox) } else { #endif // Load all levels of hierarchy - foreach (MAV_AUTOPILOT firmwareType, _toolbox->firmwarePluginManager()->knownFirmwareTypes()) { + foreach (MAV_AUTOPILOT firmwareType, _toolbox->firmwarePluginManager()->supportedFirmwareTypes()) { FirmwarePlugin* plugin = _toolbox->firmwarePluginManager()->firmwarePluginForAutopilot(firmwareType, MAV_TYPE_QUADROTOR); QList vehicleTypes; @@ -62,7 +66,7 @@ void MissionCommandTree::setToolbox(QGCToolbox* toolbox) MAV_AUTOPILOT MissionCommandTree::_baseFirmwareType(MAV_AUTOPILOT firmwareType) const { - if (qgcApp()->toolbox()->firmwarePluginManager()->knownFirmwareTypes().contains(firmwareType)) { + if (qgcApp()->toolbox()->firmwarePluginManager()->supportedFirmwareTypes().contains(firmwareType)) { return firmwareType; } else { return MAV_AUTOPILOT_GENERIC; @@ -249,7 +253,7 @@ void MissionCommandTree::_baseVehicleInfo(Vehicle* vehicle, MAV_AUTOPILOT& baseF baseVehicleType = _baseVehicleType(vehicle->vehicleType()); } else { // No Vehicle means offline editing - baseFirmwareType = _baseFirmwareType((MAV_AUTOPILOT)QGroundControlQmlGlobal::offlineEditingFirmwareType()->rawValue().toInt()); - baseVehicleType = _baseVehicleType((MAV_TYPE)QGroundControlQmlGlobal::offlineEditingVehicleType()->rawValue().toInt()); + baseFirmwareType = _baseFirmwareType((MAV_AUTOPILOT)_settingsManager->appSettings()->offlineEditingFirmwareType()->rawValue().toInt()); + baseVehicleType = _baseVehicleType((MAV_TYPE)_settingsManager->appSettings()->offlineEditingVehicleType()->rawValue().toInt()); } } diff --git a/src/MissionManager/MissionCommandTree.h b/src/MissionManager/MissionCommandTree.h index 624bada907b435f2782e3320d272bba7d6353b45..2ac32379306139cc249efbe0e1296a370c993002 100644 --- a/src/MissionManager/MissionCommandTree.h +++ b/src/MissionManager/MissionCommandTree.h @@ -19,6 +19,7 @@ class MissionCommandUIInfo; class MissionCommandList; +class SettingsManager; #ifdef UNITTEST_BUILD class MissionCommandTreeTest; #endif @@ -87,7 +88,8 @@ private: /// Collapsed hierarchy for specific vehicle type QMap> _availableCategories; - bool _unitTest; ///< true: running in unit test mode + SettingsManager* _settingsManager; + bool _unitTest; ///< true: running in unit test mode #ifdef UNITTEST_BUILD friend class MissionCommandTreeTest; diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index b6178a6e16a526af2ad69a4f3981bf7a2945e58d..ed4fcd7a1774ec60548c6da86d86792e2d572e86 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -16,22 +16,35 @@ #include "QGCApplication.h" #include "SimpleMissionItem.h" #include "SurveyMissionItem.h" +#include "FixedWingLandingComplexItem.h" #include "JsonHelper.h" #include "ParameterManager.h" #include "QGroundControlQmlGlobal.h" +#include "SettingsManager.h" #ifndef __mobile__ +#include "MainWindow.h" #include "QGCFileDialog.h" #endif QGC_LOGGING_CATEGORY(MissionControllerLog, "MissionControllerLog") -const char* MissionController::jsonSimpleItemsKey = "items"; const char* MissionController::_settingsGroup = "MissionController"; -const char* MissionController::_jsonMavAutopilotKey = "MAV_AUTOPILOT"; -const char* MissionController::_jsonComplexItemsKey = "complexItems"; +const char* MissionController::_jsonFileTypeValue = "Mission"; +const char* MissionController::_jsonItemsKey = "items"; const char* MissionController::_jsonPlannedHomePositionKey = "plannedHomePosition"; +const char* MissionController::_jsonFirmwareTypeKey = "firmwareType"; +const char* MissionController::_jsonVehicleTypeKey = "vehicleType"; +const char* MissionController::_jsonCruiseSpeedKey = "cruiseSpeed"; +const char* MissionController::_jsonHoverSpeedKey = "hoverSpeed"; +const char* MissionController::_jsonParamsKey = "params"; + +// Deprecated V1 format keys +const char* MissionController::_jsonComplexItemsKey = "complexItems"; +const char* MissionController::_jsonMavAutopilotKey = "MAV_AUTOPILOT"; + +const int MissionController::_missionFileVersion = 2; MissionController::MissionController(QObject *parent) : PlanElementController(parent) @@ -41,11 +54,16 @@ MissionController::MissionController(QObject *parent) , _missionItemsRequested(false) , _queuedSend(false) , _missionDistance(0.0) + , _missionTime(0.0) + , _missionHoverDistance(0.0) + , _missionHoverTime(0.0) + , _missionCruiseDistance(0.0) + , _missionCruiseTime(0.0) , _missionMaxTelemetry(0.0) - , _cruiseDistance(0.0) - , _hoverDistance(0.0) { - + _surveyMissionItemName = tr("Survey"); + _fwLandingMissionItemName = tr("Fixed Wing Landing"); + _complexMissionItemNames << _surveyMissionItemName << _fwLandingMissionItemName; } MissionController::~MissionController() @@ -58,10 +76,22 @@ void MissionController::start(bool editMode) qCDebug(MissionControllerLog) << "start editMode" << editMode; PlanElementController::start(editMode); + _init(); +} +void MissionController::startStaticActiveVehicle(Vehicle *vehicle) +{ + qCDebug(MissionControllerLog) << "startStaticActiveVehicle"; + + PlanElementController::startStaticActiveVehicle(vehicle); + _init(); +} + +void MissionController::_init(void) +{ // We start with an empty mission _visualItems = new QmlObjectListModel(this); - _addPlannedHomePosition(_visualItems, false /* addToCenter */); + _addPlannedHomePosition(_activeVehicle, _visualItems, false /* addToCenter */); _initAllVisualItems(); } @@ -87,11 +117,11 @@ void MissionController::_newMissionItemsAvailableFromVehicle(void) _deinitAllVisualItems(); - _visualItems->deleteListAndContents(); + _visualItems->deleteLater(); _visualItems = newControllerMissionItems; if (!_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle() || _visualItems->count() == 0) { - _addPlannedHomePosition(_visualItems,true /* addToCenter */); + _addPlannedHomePosition(_activeVehicle, _visualItems,true /* addToCenter */); } _missionItemsRequested = false; @@ -113,12 +143,18 @@ void MissionController::loadFromVehicle(void) void MissionController::sendToVehicle(void) { - if (_activeVehicle) { + sendItemsToVehicle(_activeVehicle, _visualItems); + _visualItems->setDirty(false); +} + +void MissionController::sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel* visualMissionItems) +{ + if (vehicle) { // Convert to MissionItems so we can send to vehicle QList missionItems; - for (int i=0; i<_visualItems->count(); i++) { - VisualMissionItem* visualItem = qobject_cast(_visualItems->get(i)); + for (int i=0; icount(); i++) { + VisualMissionItem* visualItem = qobject_cast(visualMissionItems->get(i)); if (visualItem->isSimpleItem()) { missionItems.append(new MissionItem(qobject_cast(visualItem)->missionItem())); } else { @@ -127,15 +163,14 @@ void MissionController::sendToVehicle(void) for (int j=0; jcount(); j++) { missionItems.append(new MissionItem(*qobject_cast(complexMissionItems->get(j)))); } - delete complexMissionItems; + complexMissionItems->deleteLater(); } } - _activeVehicle->missionManager()->writeMissionItems(missionItems); - _visualItems->setDirty(false); + vehicle->missionManager()->writeMissionItems(missionItems); for (int i=0; ideleteLater(); } } } @@ -169,15 +204,12 @@ int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int i) } newItem->setDefaultsForCommand(); if ((MAV_CMD)newItem->command() == MAV_CMD_NAV_WAYPOINT) { - double lastValue; - MAV_FRAME lastFrame; + double prevAltitude; + MAV_FRAME prevFrame; - if (_findLastAcceptanceRadius(&lastValue)) { - newItem->missionItem().setParam2(lastValue); - } - if (_findLastAltitude(&lastValue, &lastFrame)) { - newItem->missionItem().setFrame(lastFrame); - newItem->missionItem().setParam7(lastValue); + if (_findPreviousAltitude(i, &prevAltitude, &prevFrame)) { + newItem->missionItem().setFrame(prevFrame); + newItem->missionItem().setParam7(prevAltitude); } } _visualItems->insert(i, newItem); @@ -187,12 +219,21 @@ int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int i) return newItem->sequenceNumber(); } -int MissionController::insertComplexMissionItem(QGeoCoordinate coordinate, int i) +int MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate mapCenterCoordinate, int i) { + ComplexMissionItem* newItem; + int sequenceNumber = _nextSequenceNumber(); - SurveyMissionItem* newItem = new SurveyMissionItem(_activeVehicle, this); + if (itemName == _surveyMissionItemName) { + newItem = new SurveyMissionItem(_activeVehicle, _visualItems); + newItem->setCoordinate(mapCenterCoordinate); + } else if (itemName == _fwLandingMissionItemName) { + newItem = new FixedWingLandingComplexItem(_activeVehicle, _visualItems); + } else { + qWarning() << "Internal error: Unknown complex item:" << itemName; + return sequenceNumber; + } newItem->setSequenceNumber(sequenceNumber); - newItem->setCoordinate(coordinate); _initVisualItem(newItem); _visualItems->insert(i, newItem); @@ -234,15 +275,15 @@ void MissionController::removeAll(void) { if (_visualItems) { _deinitAllVisualItems(); - _visualItems->deleteListAndContents(); + _visualItems->deleteLater(); _visualItems = new QmlObjectListModel(this); - _addPlannedHomePosition(_visualItems, false /* addToCenter */); + _addPlannedHomePosition(_activeVehicle, _visualItems, false /* addToCenter */); _initAllVisualItems(); _visualItems->setDirty(true); } } -bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString) +bool MissionController::_loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString) { QJsonParseError jsonParseError; QJsonDocument jsonDoc(QJsonDocument::fromJson(bytes, &jsonParseError)); @@ -251,28 +292,40 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL errorString = jsonParseError.errorString(); return false; } - QJsonObject json = jsonDoc.object(); - // Check for required keys - QStringList requiredKeys; - requiredKeys << JsonHelper::jsonVersionKey << _jsonPlannedHomePositionKey; - if (!JsonHelper::validateRequiredKeys(json, requiredKeys, errorString)) { - return false; + // V1 file format has no file type key and version key is string. Convert to new format. + if (!json.contains(JsonHelper::jsonFileTypeKey)) { + json[JsonHelper::jsonFileTypeKey] = _jsonFileTypeValue; } - // Validate base key types - QStringList keyList; - QList typeList; - keyList << jsonSimpleItemsKey << JsonHelper::jsonVersionKey << JsonHelper::jsonGroundStationKey << _jsonMavAutopilotKey << _jsonComplexItemsKey << _jsonPlannedHomePositionKey; - typeList << QJsonValue::Array << QJsonValue::String << QJsonValue::String << QJsonValue::Double << QJsonValue::Array << QJsonValue::Object; - if (!JsonHelper::validateKeyTypes(json, keyList, typeList, errorString)) { + int fileVersion; + if (!JsonHelper::validateQGCJsonFile(json, + _jsonFileTypeValue, // expected file type + 1, // minimum supported version + 2, // maximum supported version + fileVersion, + errorString)) { return false; } - // Version check - if (json[JsonHelper::jsonVersionKey].toString() != "1.0") { - errorString = QStringLiteral("QGroundControl does not support this file version"); + if (fileVersion == 1) { + return _loadJsonMissionFileV1(vehicle, json, visualItems, complexItems, errorString); + } else { + return _loadJsonMissionFileV2(vehicle, json, visualItems, complexItems, errorString); + } +} + +bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString) +{ + // Validate root object keys + QList rootKeyInfoList = { + { _jsonPlannedHomePositionKey, QJsonValue::Object, true }, + { _jsonItemsKey, QJsonValue::Array, true }, + { _jsonMavAutopilotKey, QJsonValue::Double, true }, + { _jsonComplexItemsKey, QJsonValue::Array, true }, + }; + if (!JsonHelper::validateKeys(json, rootKeyInfoList, errorString)) { return false; } @@ -287,9 +340,9 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL return false; } - SurveyMissionItem* item = new SurveyMissionItem(_activeVehicle, this); - if (item->load(itemValue.toObject(), errorString)) { - qCDebug(MissionControllerLog) << "Json load: complex item start:stop" << item->sequenceNumber() << item->lastSequenceNumber(); + SurveyMissionItem* item = new SurveyMissionItem(vehicle, visualItems); + const QJsonObject itemObject = itemValue.toObject(); + if (item->load(itemObject, itemObject["id"].toInt(), errorString)) { complexItems->append(item); } else { return false; @@ -301,7 +354,7 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL int nextSimpleItemIndex= 0; int nextComplexItemIndex= 0; int nextSequenceNumber = 1; // Start with 1 since home is in 0 - QJsonArray itemArray(json[jsonSimpleItemsKey].toArray()); + QJsonArray itemArray(json[_jsonItemsKey].toArray()); qCDebug(MissionControllerLog) << "Json load: simple item loop start simpleItemCount:ComplexItemCount" << itemArray.count() << complexItems->count(); do { @@ -329,8 +382,9 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL return false; } - SimpleMissionItem* item = new SimpleMissionItem(_activeVehicle, this); - if (item->load(itemValue.toObject(), errorString)) { + const QJsonObject itemObject = itemValue.toObject(); + SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems); + if (item->load(itemObject, itemObject["id"].toInt(), errorString)) { qCDebug(MissionControllerLog) << "Json load: adding simple item expectedSequence:actualSequence" << nextSequenceNumber << item->sequenceNumber(); visualItems->append(item); } else { @@ -342,21 +396,146 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL } while (nextSimpleItemIndex < itemArray.count() || nextComplexItemIndex < complexItems->count()); if (json.contains(_jsonPlannedHomePositionKey)) { - SimpleMissionItem* item = new SimpleMissionItem(_activeVehicle, this); + SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems); - if (item->load(json[_jsonPlannedHomePositionKey].toObject(), errorString)) { + if (item->load(json[_jsonPlannedHomePositionKey].toObject(), 0, errorString)) { visualItems->insert(0, item); } else { return false; } } else { - _addPlannedHomePosition(visualItems, true /* addToCenter */); + _addPlannedHomePosition(vehicle, visualItems, true /* addToCenter */); } return true; } -bool MissionController::_loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString) +bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString) +{ + // Validate root object keys + QList rootKeyInfoList = { + { _jsonPlannedHomePositionKey, QJsonValue::Array, true }, + { _jsonItemsKey, QJsonValue::Array, true }, + { _jsonFirmwareTypeKey, QJsonValue::Double, true }, + { _jsonVehicleTypeKey, QJsonValue::Double, false }, + { _jsonCruiseSpeedKey, QJsonValue::Double, false }, + { _jsonHoverSpeedKey, QJsonValue::Double, false }, + }; + if (!JsonHelper::validateKeys(json, rootKeyInfoList, errorString)) { + return false; + } + + qCDebug(MissionControllerLog) << "MissionController::_loadJsonMissionFileV2 itemCount:" << json[_jsonItemsKey].toArray().count(); + + // Mission Settings + QGeoCoordinate homeCoordinate; + SettingsManager* settingsManager = qgcApp()->toolbox()->settingsManager(); + if (!JsonHelper::loadGeoCoordinate(json[_jsonPlannedHomePositionKey], true /* altitudeRequired */, homeCoordinate, errorString)) { + return false; + } + if (json.contains(_jsonVehicleTypeKey) && vehicle->isOfflineEditingVehicle()) { + settingsManager->appSettings()->offlineEditingVehicleType()->setRawValue(json[_jsonVehicleTypeKey].toDouble()); + } + if (json.contains(_jsonCruiseSpeedKey)) { + settingsManager->appSettings()->offlineEditingCruiseSpeed()->setRawValue(json[_jsonCruiseSpeedKey].toDouble()); + } + if (json.contains(_jsonHoverSpeedKey)) { + settingsManager->appSettings()->offlineEditingHoverSpeed()->setRawValue(json[_jsonHoverSpeedKey].toDouble()); + } + + SimpleMissionItem* homeItem = new SimpleMissionItem(vehicle, visualItems); + homeItem->setCoordinate(homeCoordinate); + visualItems->insert(0, homeItem); + qCDebug(MissionControllerLog) << "plannedHomePosition" << homeCoordinate; + + // Read mission items + + int nextSequenceNumber = 1; // Start with 1 since home is in 0 + const QJsonArray rgMissionItems(json[_jsonItemsKey].toArray()); + for (int i=0; i itemKeyInfoList = { + { VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, + }; + if (!JsonHelper::validateKeys(itemObject, itemKeyInfoList, errorString)) { + return false; + } + QString itemType = itemObject[VisualMissionItem::jsonTypeKey].toString(); + + if (itemType == VisualMissionItem::jsonTypeSimpleItemValue) { + qCDebug(MissionControllerLog) << "Loading MISSION_ITEM: nextSequenceNumber" << nextSequenceNumber; + SimpleMissionItem* simpleItem = new SimpleMissionItem(vehicle, visualItems); + if (simpleItem->load(itemObject, nextSequenceNumber++, errorString)) { + visualItems->append(simpleItem); + } else { + return false; + } + } else if (itemType == VisualMissionItem::jsonTypeComplexItemValue) { + QList complexItemKeyInfoList = { + { ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true }, + }; + if (!JsonHelper::validateKeys(itemObject, complexItemKeyInfoList, errorString)) { + return false; + } + QString complexItemType = itemObject[ComplexMissionItem::jsonComplexItemTypeKey].toString(); + + if (complexItemType == SurveyMissionItem::jsonComplexItemTypeValue) { + qCDebug(MissionControllerLog) << "Loading Survey: nextSequenceNumber" << nextSequenceNumber; + SurveyMissionItem* surveyItem = new SurveyMissionItem(vehicle, visualItems); + if (!surveyItem->load(itemObject, nextSequenceNumber++, errorString)) { + return false; + } + nextSequenceNumber = surveyItem->lastSequenceNumber() + 1; + qCDebug(MissionControllerLog) << "Survey load complete: nextSequenceNumber" << nextSequenceNumber; + visualItems->append(surveyItem); + complexItems->append(surveyItem); + } else { + errorString = tr("Unsupported complex item type: %1").arg(complexItemType); + } + } else { + errorString = tr("Unknown item type: %1").arg(itemType); + return false; + } + } + + // Fix up the DO_JUMP commands jump sequence number by finding the item with the matching doJumpId + for (int i=0; icount(); i++) { + if (visualItems->value(i)->isSimpleItem()) { + SimpleMissionItem* doJumpItem = visualItems->value(i); + if ((MAV_CMD)doJumpItem->command() == MAV_CMD_DO_JUMP) { + bool found = false; + int findDoJumpId = doJumpItem->missionItem().param1(); + for (int j=0; jcount(); j++) { + if (visualItems->value(j)->isSimpleItem()) { + SimpleMissionItem* targetItem = visualItems->value(j); + if (targetItem->missionItem().doJumpId() == findDoJumpId) { + doJumpItem->missionItem().setParam1(targetItem->sequenceNumber()); + found = true; + break; + } + } + } + if (!found) { + errorString = tr("Could not find doJumpId: %1").arg(findDoJumpId); + return false; + } + } + } + } + + return true; +} + +bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString) { bool addPlannedHomePosition = false; @@ -377,7 +556,7 @@ bool MissionController::_loadTextMissionFile(QTextStream& stream, QmlObjectListM if (versionOk) { while (!stream.atEnd()) { - SimpleMissionItem* item = new SimpleMissionItem(_activeVehicle, this); + SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems); if (item->load(stream)) { visualItems->append(item); @@ -392,7 +571,7 @@ bool MissionController::_loadTextMissionFile(QTextStream& stream, QmlObjectListM } if (addPlannedHomePosition || visualItems->count() == 0) { - _addPlannedHomePosition(visualItems, true /* addToCenter */); + _addPlannedHomePosition(vehicle, visualItems, true /* addToCenter */); // Update sequence numbers in DO_JUMP commands to take into account added home position in index 0 for (int i=1; icount(); i++) { @@ -408,19 +587,49 @@ bool MissionController::_loadTextMissionFile(QTextStream& stream, QmlObjectListM void MissionController::loadFromFile(const QString& filename) { + QmlObjectListModel* newVisualItems = NULL; + QmlObjectListModel* newComplexItems = NULL; + + if (!loadItemsFromFile(_activeVehicle, filename, &newVisualItems, &newComplexItems)) { + return; + } + + if (_visualItems) { + _deinitAllVisualItems(); + _visualItems->deleteLater(); + } + if (_complexItems) { + _complexItems->deleteLater(); + } + + _visualItems = newVisualItems; + _complexItems = newComplexItems; + + if (_visualItems->count() == 0) { + _addPlannedHomePosition(_activeVehicle, _visualItems, true /* addToCenter */); + } + + _initAllVisualItems(); +} + +bool MissionController::loadItemsFromFile(Vehicle* vehicle, const QString& filename, QmlObjectListModel** visualItems, QmlObjectListModel** complexItems) +{ + *visualItems = NULL; + *complexItems = NULL; + QString errorString; if (filename.isEmpty()) { - return; + return false; } - QmlObjectListModel* newVisualItems = new QmlObjectListModel(this); - QmlObjectListModel* newComplexItems = new QmlObjectListModel(this); + *visualItems = new QmlObjectListModel(); + *complexItems = new QmlObjectListModel(); QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - errorString = file.errorString(); + errorString = file.errorString() + QStringLiteral(" ") + filename; } else { QByteArray bytes = file.readAll(); QTextStream stream(&bytes); @@ -428,48 +637,27 @@ void MissionController::loadFromFile(const QString& filename) QString firstLine = stream.readLine(); if (firstLine.contains(QRegExp("QGC.*WPL"))) { stream.seek(0); - _loadTextMissionFile(stream, newVisualItems, errorString); + _loadTextMissionFile(vehicle, stream, *visualItems, errorString); } else { - _loadJsonMissionFile(bytes, newVisualItems, newComplexItems, errorString); + _loadJsonMissionFile(vehicle, bytes, *visualItems, *complexItems, errorString); } } if (!errorString.isEmpty()) { - for (int i=0; icount(); i++) { - newVisualItems->get(i)->deleteLater(); - } - for (int i=0; icount(); i++) { - newComplexItems->get(i)->deleteLater(); - } - delete newVisualItems; - delete newComplexItems; + (*visualItems)->deleteLater(); + (*complexItems)->deleteLater(); qgcApp()->showMessage(errorString); - return; - } - - if (_visualItems) { - _deinitAllVisualItems(); - _visualItems->deleteListAndContents(); - } - if (_complexItems) { - _complexItems->deleteLater(); - } - - _visualItems = newVisualItems; - _complexItems = newComplexItems; - - if (_visualItems->count() == 0) { - _addPlannedHomePosition(_visualItems, true /* addToCenter */); + return false; } - _initAllVisualItems(); + return true; } void MissionController::loadFromFilePicker(void) { #ifndef __mobile__ - QString filename = QGCFileDialog::getOpenFileName(NULL, "Select Mission File to load", QString(), "Mission file (*.mission);;All Files (*.*)"); + QString filename = QGCFileDialog::getOpenFileName(MainWindow::instance(), "Select Mission File to load", QString(), "Mission file (*.mission);;All Files (*.*)"); if (filename.isEmpty()) { return; @@ -497,51 +685,35 @@ void MissionController::saveToFile(const QString& filename) qgcApp()->showMessage(file.errorString()); } else { QJsonObject missionFileObject; // top level json object - QJsonArray simpleItemsObject; - QJsonArray complexItemsObject; - missionFileObject[JsonHelper::jsonVersionKey] = "1.0"; + missionFileObject[JsonHelper::jsonVersionKey] = _missionFileVersion; missionFileObject[JsonHelper::jsonGroundStationKey] = JsonHelper::jsonGroundStationValue; - MAV_AUTOPILOT firmwareType = MAV_AUTOPILOT_GENERIC; - if (_activeVehicle) { - firmwareType = _activeVehicle->firmwareType(); - } else { - // FIXME: Hack duplicated code from QGroundControlQmlGlobal. Had to do this for now since - // QGroundControlQmlGlobal is not available from C++ side. - - QSettings settings; - firmwareType = (MAV_AUTOPILOT)settings.value("OfflineEditingFirmwareType", MAV_AUTOPILOT_ARDUPILOTMEGA).toInt(); - } - missionFileObject[_jsonMavAutopilotKey] = firmwareType; + // Mission settings - // Save planned home position - QJsonObject homePositionObject; SimpleMissionItem* homeItem = qobject_cast(_visualItems->get(0)); - if (homeItem) { - homeItem->missionItem().save(homePositionObject); - } else { + if (!homeItem) { qgcApp()->showMessage(QStringLiteral("Internal error: VisualMissionItem at index 0 not SimpleMissionItem")); return; } - missionFileObject[_jsonPlannedHomePositionKey] = homePositionObject; + QJsonValue coordinateValue; + JsonHelper::saveGeoCoordinate(homeItem->coordinate(), true /* writeAltitude */, coordinateValue); + missionFileObject[_jsonPlannedHomePositionKey] = coordinateValue; + missionFileObject[_jsonFirmwareTypeKey] = _activeVehicle->firmwareType(); + missionFileObject[_jsonVehicleTypeKey] = _activeVehicle->vehicleType(); + missionFileObject[_jsonCruiseSpeedKey] = _activeVehicle->cruiseSpeed(); + missionFileObject[_jsonHoverSpeedKey] = _activeVehicle->hoverSpeed(); // Save the visual items + QJsonArray rgMissionItems; for (int i=1; i<_visualItems->count(); i++) { QJsonObject itemObject; VisualMissionItem* visualItem = qobject_cast(_visualItems->get(i)); visualItem->save(itemObject); - - if (visualItem->isSimpleItem()) { - simpleItemsObject.append(itemObject); - } else { - complexItemsObject.append(itemObject); - } + rgMissionItems.append(itemObject); } - - missionFileObject[jsonSimpleItemsKey] = simpleItemsObject; - missionFileObject[_jsonComplexItemsKey] = complexItemsObject; + missionFileObject[_jsonItemsKey] = rgMissionItems; QJsonDocument saveDoc(missionFileObject); file.write(saveDoc.toJson()); @@ -553,7 +725,7 @@ void MissionController::saveToFile(const QString& filename) void MissionController::saveToFilePicker(void) { #ifndef __mobile__ - QString filename = QGCFileDialog::getSaveFileName(NULL, "Select file to save mission to", QString(), "Mission file (*.mission);;All Files (*.*)"); + QString filename = QGCFileDialog::getSaveFileName(MainWindow::instance(), "Select file to save mission to", QString(), "Mission file (*.mission);;All Files (*.*)"); if (filename.isEmpty()) { return; @@ -595,7 +767,7 @@ void MissionController::_calcPrevWaypointValues(double homeAlt, VisualMissionIte } } -void MissionController::_calcHomeDist(VisualMissionItem* currentItem, VisualMissionItem* homeItem, double* distance) +double MissionController::_calcDistanceToHome(VisualMissionItem* currentItem, VisualMissionItem* homeItem) { QGeoCoordinate currentCoord = currentItem->coordinate(); QGeoCoordinate homeCoord = homeItem->exitCoordinate(); @@ -605,11 +777,7 @@ void MissionController::_calcHomeDist(VisualMissionItem* currentItem, VisualMiss qCDebug(MissionControllerLog) << "distanceOk" << distanceOk; - if (distanceOk) { - *distance = homeCoord.distanceTo(currentCoord); - } else { - *distance = 0.0; - } + return distanceOk ? homeCoord.distanceTo(currentCoord) : 0.0; } void MissionController::_recalcWaypointLines(void) @@ -636,7 +804,7 @@ void MissionController::_recalcWaypointLines(void) VisualMissionItem* item = qobject_cast(_visualItems->get(i)); - // If we still haven't found the first coordinate item and we hit a a takeoff command link back to home + // If we still haven't found the first coordinate item and we hit a takeoff command, link back to home if (firstCoordinateItem && item->isSimpleItem() && (qobject_cast(item)->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF || @@ -656,7 +824,7 @@ void MissionController::_recalcWaypointLines(void) // Create a new segment and wire update notifiers auto linevect = new CoordinateVector(lastCoordinateItem->isSimpleItem() ? lastCoordinateItem->coordinate() : lastCoordinateItem->exitCoordinate(), item->coordinate(), this); auto originNotifier = lastCoordinateItem->isSimpleItem() ? &VisualMissionItem::coordinateChanged : &VisualMissionItem::exitCoordinateChanged, - endNotifier = &VisualMissionItem::coordinateChanged; + endNotifier = &VisualMissionItem::coordinateChanged; // Use signals/slots to update the coordinate endpoints connect(lastCoordinateItem, originNotifier, linevect, &CoordinateVector::setCoordinate1); connect(item, endNotifier, linevect, &CoordinateVector::setCoordinate2); @@ -707,7 +875,7 @@ void MissionController::_recalcAltitudeRangeBearing() qWarning() << "Home item is not SimpleMissionItem"; } - bool showHomePosition = homeItem->showHomePosition(); + bool showHomePosition = homeItem->showHomePosition(); qCDebug(MissionControllerLog) << "_recalcAltitudeRangeBearing"; @@ -727,47 +895,68 @@ void MissionController::_recalcAltitudeRangeBearing() double missionDistance = 0.0; double missionMaxTelemetry = 0.0; + double missionTime = 0.0; + double vtolHoverTime = 0.0; + double vtolCruiseTime = 0.0; + double vtolHoverDistance = 0.0; + double vtolCruiseDistance = 0.0; + double currentCruiseSpeed = _activeVehicle->cruiseSpeed(); + double currentHoverSpeed = _activeVehicle->hoverSpeed(); - bool vtolCalc = (QGroundControlQmlGlobal::offlineEditingVehicleType()->enumStringValue() == "VTOL" || (_activeVehicle && _activeVehicle->vtol())) ? true : false ; - double cruiseDistance = 0.0; - double hoverDistance = 0.0; - bool hoverDistanceCalc = false; - bool hoverTransition = false; - bool cruiseTransition = false; - bool hoverDistanceReset = false; + bool vtolVehicle = _activeVehicle->vtol(); + bool vtolInHover = true; bool linkBackToHome = false; - for (int i=1; i<_visualItems->count(); i++) { VisualMissionItem* item = qobject_cast(_visualItems->get(i)); + SimpleMissionItem* simpleItem = qobject_cast(item); + ComplexMissionItem* complexItem = qobject_cast(item); + // Assume the worst item->setAzimuth(0.0); item->setDistance(0.0); - // If we still haven't found the first coordinate item and we hit a takeoff command link back to home - if (firstCoordinateItem && - item->isSimpleItem() && - qobject_cast(item)->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) { - linkBackToHome = true; - hoverDistanceCalc = true; + if (simpleItem && simpleItem->command() == MavlinkQmlSingleton::MAV_CMD_DO_CHANGE_SPEED) { + // Adjust cruise speed for time calculations + double newSpeed = simpleItem->missionItem().param2(); + if (newSpeed > 0) { + if (_activeVehicle->multiRotor()) { + currentHoverSpeed = newSpeed; + } else { + currentCruiseSpeed = newSpeed; + } + } } - if (item->isSimpleItem() && vtolCalc) { - SimpleMissionItem* simpleItem = qobject_cast(item); - if (simpleItem->command() == MavlinkQmlSingleton::MAV_CMD_DO_VTOL_TRANSITION){ //transition waypoint value - if (simpleItem->missionItem().param1() == 3){ //hover mode value - hoverDistanceCalc = true; - hoverTransition = true; - } - else if (simpleItem->missionItem().param1() == 4){ - hoverDistanceCalc = false; - cruiseTransition = true; + // Link back to home if first item is takeoff and we have home position + if (firstCoordinateItem && simpleItem && simpleItem->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) { + if (showHomePosition) { + linkBackToHome = true; + } + } + + // Update VTOL state + if (simpleItem && vtolVehicle) { + switch (simpleItem->command()) { + case MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF: + vtolInHover = false; + break; + case MavlinkQmlSingleton::MAV_CMD_NAV_LAND: + vtolInHover = false; + break; + case MavlinkQmlSingleton::MAV_CMD_DO_VTOL_TRANSITION: + { + int transitionState = simpleItem->missionItem().param1(); + if (transitionState == MAV_VTOL_STATE_TRANSITION_TO_MC) { + vtolInHover = true; + } else if (transitionState == MAV_VTOL_STATE_TRANSITION_TO_FW) { + vtolInHover = false; } } - if(!hoverTransition && cruiseTransition && !hoverDistanceReset && !linkBackToHome){ - hoverDistance = missionDistance; - hoverDistanceReset = true; + break; + default: + break; } } @@ -792,62 +981,60 @@ void MissionController::_recalcAltitudeRangeBearing() if (!item->isStandaloneCoordinate()) { firstCoordinateItem = false; - if (lastCoordinateItem != homeItem || (showHomePosition && linkBackToHome)) { - double azimuth, distance, altDifference, telemetryDistance; + if (lastCoordinateItem != homeItem || linkBackToHome) { + // This is a subsequent waypoint or we are forcing the first waypoint back to home + double azimuth, distance, altDifference; - // Subsequent coordinate items link to last coordinate item. If the last coordinate item - // is an invalid home position we skip the line _calcPrevWaypointValues(homePositionAltitude, item, lastCoordinateItem, &azimuth, &distance, &altDifference); item->setAltDifference(altDifference); item->setAzimuth(azimuth); item->setDistance(distance); missionDistance += distance; - - if (item->isSimpleItem()) { - _calcHomeDist(item, homeItem, &telemetryDistance); - - if (vtolCalc) { - SimpleMissionItem* simpleItem = qobject_cast(item); - if (simpleItem->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF || hoverDistanceCalc){ - hoverDistance += distance; - } - cruiseDistance = missionDistance - hoverDistance; - if(simpleItem->command() == MavlinkQmlSingleton::MAV_CMD_NAV_LAND && !linkBackToHome && !cruiseTransition && !hoverTransition){ - hoverDistance = cruiseDistance; - cruiseDistance = missionDistance - hoverDistance; - } + missionMaxTelemetry = qMax(missionMaxTelemetry, _calcDistanceToHome(item, homeItem)); + + // Calculate mission time + if (vtolVehicle) { + if (vtolInHover) { + double hoverTime = distance / _activeVehicle->hoverSpeed(); + missionTime += hoverTime; + vtolHoverTime += hoverTime; + vtolHoverDistance += distance; + } else { + double cruiseTime = distance / currentCruiseSpeed; + missionTime += cruiseTime; + vtolCruiseTime += cruiseTime; + vtolCruiseDistance += distance; } } else { - missionDistance += qobject_cast(item)->complexDistance(); - telemetryDistance = qobject_cast(item)->greatestDistanceTo(homeItem->exitCoordinate()); - - if (vtolCalc){ - cruiseDistance += qobject_cast(item)->complexDistance(); //assume all survey missions undertaken in cruise - } - } - - if (telemetryDistance > missionMaxTelemetry) { - missionMaxTelemetry = telemetryDistance; + missionTime += distance / (_activeVehicle->multiRotor() ? currentHoverSpeed : currentCruiseSpeed); } } - else if (lastCoordinateItem == homeItem && !item->isSimpleItem()){ - missionDistance += qobject_cast(item)->complexDistance(); - missionMaxTelemetry = qobject_cast(item)->greatestDistanceTo(homeItem->exitCoordinate()); - - if (vtolCalc){ - cruiseDistance += qobject_cast(item)->complexDistance(); //assume all survey missions undertaken in cruise - } + if (complexItem) { + // Add in distance/time inside survey as well + // This code assumes all surveys are done cruise not hover + double complexDistance = complexItem->complexDistance(); + double cruiseSpeed = _activeVehicle->multiRotor() ? currentHoverSpeed : currentCruiseSpeed; + missionDistance += complexDistance; + missionTime += complexDistance / cruiseSpeed; + missionMaxTelemetry = qMax(missionMaxTelemetry, complexItem->greatestDistanceTo(homeItem->exitCoordinate())); + + // Let the complex item know the current cruise speed + complexItem->setCruiseSpeed(cruiseSpeed); } - lastCoordinateItem = item; } + + lastCoordinateItem = item; } } - setMissionDistance(missionDistance); - setMissionMaxTelemetry(missionMaxTelemetry); - setCruiseDistance(cruiseDistance); - setHoverDistance(hoverDistance); + _setMissionMaxTelemetry(missionMaxTelemetry); + _setMissionDistance(missionDistance); + _setMissionTime(missionTime); + _setMissionHoverDistance(vtolHoverDistance); + _setMissionHoverTime(vtolHoverTime); + _setMissionCruiseDistance(vtolCruiseDistance); + _setMissionCruiseTime(vtolCruiseTime); // Walk the list again calculating altitude percentages double altRange = maxAltSeen - minAltSeen; @@ -882,7 +1069,7 @@ void MissionController::_recalcSequence(void) ComplexMissionItem* complexItem = qobject_cast(item); if (complexItem) { - sequenceNumber = complexItem->lastSequenceNumber() + 1; + sequenceNumber = complexItem->lastSequenceNumber() + 1; } else { qWarning() << "isSimpleItem == false, yet not ComplexMissionItem"; } @@ -993,6 +1180,7 @@ void MissionController::_initVisualItem(VisualMissionItem* visualItem) connect(visualItem, &VisualMissionItem::specifiesCoordinateChanged, this, &MissionController::_recalcWaypointLines); connect(visualItem, &VisualMissionItem::coordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines); connect(visualItem, &VisualMissionItem::exitCoordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines); + connect(visualItem, &VisualMissionItem::flightSpeedChanged, this, &MissionController::_recalcAltitudeRangeBearing); if (visualItem->isSimpleItem()) { // We need to track commandChanged on simple item since recalc has special handling for takeoff command @@ -1052,6 +1240,8 @@ void MissionController::_activeVehicleSet(void) connect(missionManager, &MissionManager::currentItemChanged, this, &MissionController::_currentMissionItemChanged); connect(_activeVehicle, &Vehicle::homePositionAvailableChanged, this, &MissionController::_activeVehicleHomePositionAvailableChanged); connect(_activeVehicle, &Vehicle::homePositionChanged, this, &MissionController::_activeVehicleHomePositionChanged); + connect(_activeVehicle, &Vehicle::cruiseSpeedChanged, this, &MissionController::_recalcAltitudeRangeBearing); + connect(_activeVehicle, &Vehicle::hoverSpeedChanged, this, &MissionController::_recalcAltitudeRangeBearing); if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) { // We are switching between two previously existing vehicles. We have to manually ask for the items from the Vehicle. @@ -1095,7 +1285,15 @@ void MissionController::_activeVehicleHomePositionChanged(const QGeoCoordinate& } } -void MissionController::setMissionDistance(double missionDistance) +void MissionController::_setMissionMaxTelemetry(double missionMaxTelemetry) +{ + if (!qFuzzyCompare(_missionMaxTelemetry, missionMaxTelemetry)) { + _missionMaxTelemetry = missionMaxTelemetry; + emit missionMaxTelemetryChanged(_missionMaxTelemetry); + } +} + +void MissionController::_setMissionDistance(double missionDistance) { if (!qFuzzyCompare(_missionDistance, missionDistance)) { _missionDistance = missionDistance; @@ -1103,27 +1301,43 @@ void MissionController::setMissionDistance(double missionDistance) } } -void MissionController::setMissionMaxTelemetry(double missionMaxTelemetry) +void MissionController::_setMissionTime(double missionTime) { - if (!qFuzzyCompare(_missionMaxTelemetry, missionMaxTelemetry)) { - _missionMaxTelemetry = missionMaxTelemetry; - emit missionMaxTelemetryChanged(_missionMaxTelemetry); + if (!qFuzzyCompare(_missionTime, missionTime)) { + _missionTime = missionTime; + emit missionTimeChanged(); + } +} + +void MissionController::_setMissionHoverTime(double missionHoverTime) +{ + if (!qFuzzyCompare(_missionHoverTime, missionHoverTime)) { + _missionHoverTime = missionHoverTime; + emit missionHoverTimeChanged(); + } +} + +void MissionController::_setMissionHoverDistance(double missionHoverDistance) +{ + if (!qFuzzyCompare(_missionHoverDistance, missionHoverDistance)) { + _missionHoverDistance = missionHoverDistance; + emit missionHoverDistanceChanged(_missionHoverDistance); } } -void MissionController::setCruiseDistance(double cruiseDistance) +void MissionController::_setMissionCruiseTime(double missionCruiseTime) { - if (!qFuzzyCompare(_cruiseDistance, cruiseDistance)) { - _cruiseDistance = cruiseDistance; - emit cruiseDistanceChanged(_cruiseDistance); + if (!qFuzzyCompare(_missionCruiseTime, missionCruiseTime)) { + _missionCruiseTime = missionCruiseTime; + emit missionCruiseTimeChanged(); } } -void MissionController::setHoverDistance(double hoverDistance) +void MissionController::_setMissionCruiseDistance(double missionCruiseDistance) { - if (!qFuzzyCompare(_hoverDistance, hoverDistance)) { - _hoverDistance = hoverDistance; - emit hoverDistanceChanged(_hoverDistance); + if (!qFuzzyCompare(_missionCruiseDistance, missionCruiseDistance)) { + _missionCruiseDistance = missionCruiseDistance; + emit missionCruiseDistanceChanged(_missionCruiseDistance); } } @@ -1132,61 +1346,36 @@ void MissionController::_inProgressChanged(bool inProgress) emit syncInProgressChanged(inProgress); } -bool MissionController::_findLastAltitude(double* lastAltitude, MAV_FRAME* frame) +bool MissionController::_findPreviousAltitude(int newIndex, double* prevAltitude, MAV_FRAME* prevFrame) { - bool found = false; - double foundAltitude; - MAV_FRAME foundFrame; + bool found = false; + double foundAltitude; + MAV_FRAME foundFrame; - // Don't use home position - for (int i=1; i<_visualItems->count(); i++) { + if (newIndex > _visualItems->count()) { + return false; + } + newIndex--; + + for (int i=newIndex; i>0; i--) { VisualMissionItem* visualItem = qobject_cast(_visualItems->get(i)); if (visualItem->specifiesCoordinate() && !visualItem->isStandaloneCoordinate()) { - if (visualItem->isSimpleItem()) { SimpleMissionItem* simpleItem = qobject_cast(visualItem); - if ((MAV_CMD)simpleItem->command() != MAV_CMD_NAV_TAKEOFF) { + if ((MAV_CMD)simpleItem->command() == MAV_CMD_NAV_WAYPOINT) { foundAltitude = simpleItem->exitCoordinate().altitude(); foundFrame = simpleItem->missionItem().frame(); found = true; + break; } } } } if (found) { - *lastAltitude = foundAltitude; - *frame = foundFrame; - } - - return found; -} - -bool MissionController::_findLastAcceptanceRadius(double* lastAcceptanceRadius) -{ - bool found = false; - double foundAcceptanceRadius; - - for (int i=0; i<_visualItems->count(); i++) { - VisualMissionItem* visualItem = qobject_cast(_visualItems->get(i)); - - if (visualItem->isSimpleItem()) { - SimpleMissionItem* simpleItem = qobject_cast(visualItem); - - if (simpleItem) { - if ((MAV_CMD)simpleItem->command() == MAV_CMD_NAV_WAYPOINT) { - foundAcceptanceRadius = simpleItem->missionItem().param2(); - found = true; - } - } else { - qWarning() << "isSimpleItem == true, yet not SimpleMissionItem"; - } - } - } - - if (found) { - *lastAcceptanceRadius = foundAcceptanceRadius; + *prevAltitude = foundAltitude; + *prevFrame = foundFrame; } return found; @@ -1205,33 +1394,45 @@ double MissionController::_normalizeLon(double lon) } /// Add the home position item to the front of the list -void MissionController::_addPlannedHomePosition(QmlObjectListModel* visualItems, bool addToCenter) +void MissionController::_addPlannedHomePosition(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter) { - SimpleMissionItem* homeItem = new SimpleMissionItem(_activeVehicle, this); + bool homePositionSet = false; + + SimpleMissionItem* homeItem = new SimpleMissionItem(vehicle, visualItems); visualItems->insert(0, homeItem); if (visualItems->count() > 1 && addToCenter) { - VisualMissionItem* item = qobject_cast(visualItems->get(1)); - - double north = _normalizeLat(item->coordinate().latitude()); - double south = north; - double east = _normalizeLon(item->coordinate().longitude()); - double west = east; + double north, south, east, west; + bool firstCoordSet = false; - for (int i=2; icount(); i++) { - item = qobject_cast(visualItems->get(i)); - - double lat = _normalizeLat(item->coordinate().latitude()); - double lon = _normalizeLon(item->coordinate().longitude()); + for (int i=1; icount(); i++) { + VisualMissionItem* item = qobject_cast(visualItems->get(i)); + + if (item->specifiesCoordinate()) { + if (firstCoordSet) { + double lat = _normalizeLat(item->coordinate().latitude()); + double lon = _normalizeLon(item->coordinate().longitude()); + north = fmax(north, lat); + south = fmin(south, lat); + east = fmax(east, lon); + west = fmin(west, lon); + } else { + firstCoordSet = true; + north = _normalizeLat(item->coordinate().latitude()); + south = north; + east = _normalizeLon(item->coordinate().longitude()); + west = east; + } + } + } - north = fmax(north, lat); - south = fmin(south, lat); - east = fmax(east, lon); - west = fmin(west, lon); + if (firstCoordSet) { + homePositionSet = true; + homeItem->setCoordinate(QGeoCoordinate((south + ((north - south) / 2)) - 90.0, (west + ((east - west) / 2)) - 180.0, 0.0)); } + } - homeItem->setCoordinate(QGeoCoordinate((south + ((north - south) / 2)) - 90.0, (west + ((east - west) / 2)) - 180.0, 0.0)); - } else { + if (!homePositionSet) { homeItem->setCoordinate(qgcApp()->lastKnownHomePosition()); } } @@ -1290,3 +1491,21 @@ QString MissionController::fileExtension(void) const { return QGCApplication::missionFileExtension; } + +double MissionController::cruiseSpeed(void) const +{ + if (_activeVehicle) { + return _activeVehicle->cruiseSpeed(); + } else { + return 0.0f; + } +} + +double MissionController::hoverSpeed(void) const +{ + if (_activeVehicle) { + return _activeVehicle->hoverSpeed(); + } else { + return 0.0f; + } +} diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index fc1f288d3f000f613a65ee8abc1ddd839e5be79d..13032292873e579c3122203c6ee0914dd5cf7599 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -34,15 +34,20 @@ public: MissionController(QObject* parent = NULL); ~MissionController(); - Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged) - Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged) - Q_PROPERTY(QmlObjectListModel* complexVisualItems READ complexVisualItems NOTIFY complexVisualItemsChanged) - Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged) + Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged) + Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged) + Q_PROPERTY(QmlObjectListModel* complexVisualItems READ complexVisualItems NOTIFY complexVisualItemsChanged) + Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged) - Q_PROPERTY(double missionDistance READ missionDistance NOTIFY missionDistanceChanged) - Q_PROPERTY(double missionMaxTelemetry READ missionMaxTelemetry NOTIFY missionMaxTelemetryChanged) - Q_PROPERTY(double cruiseDistance READ cruiseDistance NOTIFY cruiseDistanceChanged) - Q_PROPERTY(double hoverDistance READ hoverDistance NOTIFY hoverDistanceChanged) + Q_PROPERTY(QStringList complexMissionItemNames MEMBER _complexMissionItemNames CONSTANT) + + Q_PROPERTY(double missionDistance READ missionDistance NOTIFY missionDistanceChanged) + Q_PROPERTY(double missionTime READ missionTime NOTIFY missionTimeChanged) + Q_PROPERTY(double missionHoverDistance READ missionHoverDistance NOTIFY missionHoverDistanceChanged) + Q_PROPERTY(double missionCruiseDistance READ missionCruiseDistance NOTIFY missionCruiseDistanceChanged) + Q_PROPERTY(double missionHoverTime READ missionHoverTime NOTIFY missionHoverTimeChanged) + Q_PROPERTY(double missionCruiseTime READ missionCruiseTime NOTIFY missionCruiseTimeChanged) + Q_PROPERTY(double missionMaxTelemetry READ missionMaxTelemetry NOTIFY missionMaxTelemetryChanged) Q_INVOKABLE void removeMissionItem(int index); @@ -52,22 +57,36 @@ public: Q_INVOKABLE int insertSimpleMissionItem(QGeoCoordinate coordinate, int i); /// Add a new complex mission item to the list + /// @param itemName: Name of complex item to create (from complexMissionItemNames) + /// @param mapCenterCoordinate: coordinate for current center of map /// @param i: index to insert at /// @return Sequence number for new item - Q_INVOKABLE int insertComplexMissionItem(QGeoCoordinate coordinate, int i); + Q_INVOKABLE int insertComplexMissionItem(QString itemName, QGeoCoordinate mapCenterCoordinate, int i); + + /// Loads the mission items from the specified file + /// @param[in] vehicle Vehicle we are loading items for + /// @param[in] filename File to load from + /// @param[out] visualItems Visual items loaded, returns NULL if error + /// @param[out] complexItems Complex items loaded, returns NULL if error + /// @return success/fail + static bool loadItemsFromFile(Vehicle* vehicle, const QString& filename, QmlObjectListModel** visualItems, QmlObjectListModel** complexItems); + + /// Sends the mission items to the specified vehicle + static void sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel* visualMissionItems); // Overrides from PlanElementController - void start (bool editMode) final; - void loadFromVehicle (void) final; - void sendToVehicle (void) final; - void loadFromFilePicker (void) final; - void loadFromFile (const QString& filename) final; - void saveToFilePicker (void) final; - void saveToFile (const QString& filename) final; - void removeAll (void) final; - bool syncInProgress (void) const final; - bool dirty (void) const final; - void setDirty (bool dirty) final; + void start (bool editMode) final; + void startStaticActiveVehicle (Vehicle* vehicle) final; + void loadFromVehicle (void) final; + void sendToVehicle (void) final; + void loadFromFilePicker (void) final; + void loadFromFile (const QString& filename) final; + void saveToFilePicker (void) final; + void saveToFile (const QString& filename) final; + void removeAll (void) final; + bool syncInProgress (void) const final; + bool dirty (void) const final; + void setDirty (bool dirty) final; QString fileExtension(void) const final; @@ -79,16 +98,14 @@ public: QmlObjectListModel* waypointLines (void) { return &_waypointLines; } double missionDistance (void) const { return _missionDistance; } + double missionTime (void) const { return _missionTime; } + double missionHoverDistance (void) const { return _missionHoverDistance; } + double missionHoverTime (void) const { return _missionHoverTime; } + double missionCruiseDistance (void) const { return _missionCruiseDistance; } + double missionCruiseTime (void) const { return _missionCruiseTime; } double missionMaxTelemetry (void) const { return _missionMaxTelemetry; } - double cruiseDistance (void) const { return _cruiseDistance; } - double hoverDistance (void) const { return _hoverDistance; } - - void setMissionDistance (double missionDistance ); - void setMissionMaxTelemetry (double missionMaxTelemetry); - void setCruiseDistance (double cruiseDistance ); - void setHoverDistance (double hoverDistance ); - - static const char* jsonSimpleItemsKey; ///< Key for simple items in a json file + double cruiseSpeed (void) const; + double hoverSpeed (void) const; signals: void plannedHomePositionChanged(QGeoCoordinate plannedHomePosition); @@ -97,9 +114,16 @@ signals: void waypointLinesChanged(void); void newItemsFromVehicle(void); void missionDistanceChanged(double missionDistance); + void missionTimeChanged(void); + void missionHoverDistanceChanged(double missionHoverDistance); + void missionHoverTimeChanged(void); + void missionCruiseDistanceChanged(double missionCruiseDistance); + void missionCruiseTimeChanged(void); void missionMaxTelemetryChanged(double missionMaxTelemetry); void cruiseDistanceChanged(double cruiseDistance); void hoverDistanceChanged(double hoverDistance); + void cruiseSpeedChanged(double cruiseSpeed); + void hoverSpeedChanged(double hoverSpeed); private slots: void _newMissionItemsAvailableFromVehicle(); @@ -113,6 +137,7 @@ private slots: void _homeCoordinateChanged(void); private: + void _init(void); void _recalcSequence(void); void _recalcChildItems(void); void _recalcAll(void); @@ -122,15 +147,23 @@ private: void _deinitVisualItem(VisualMissionItem* item); void _setupActiveVehicle(Vehicle* activeVehicle, bool forceLoadFromVehicle); static void _calcPrevWaypointValues(double homeAlt, VisualMissionItem* currentItem, VisualMissionItem* prevItem, double* azimuth, double* distance, double* altDifference); - static void _calcHomeDist(VisualMissionItem* currentItem, VisualMissionItem* homeItem, double* distance); - bool _findLastAltitude(double* lastAltitude, MAV_FRAME* frame); - bool _findLastAcceptanceRadius(double* lastAcceptanceRadius); - void _addPlannedHomePosition(QmlObjectListModel* visualItems, bool addToCenter); - double _normalizeLat(double lat); - double _normalizeLon(double lon); - bool _loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); - bool _loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString); + static double _calcDistanceToHome(VisualMissionItem* currentItem, VisualMissionItem* homeItem); + bool _findPreviousAltitude(int newIndex, double* prevAltitude, MAV_FRAME* prevFrame); + static double _normalizeLat(double lat); + static double _normalizeLon(double lon); + static void _addPlannedHomePosition(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter); + static bool _loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); + static bool _loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); + static bool _loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); + static bool _loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString); int _nextSequenceNumber(void); + void _setMissionDistance(double missionDistance); + void _setMissionTime(double missionTime); + void _setMissionHoverDistance(double missionHoverDistance); + void _setMissionHoverTime(double missionHoverTime); + void _setMissionCruiseDistance(double missionCruiseDistance); + void _setMissionCruiseTime(double missionCruiseTime); + void _setMissionMaxTelemetry(double missionMaxTelemetry); // Overrides from PlanElementController void _activeVehicleBeingRemoved(void) final; @@ -145,14 +178,31 @@ private: bool _missionItemsRequested; bool _queuedSend; double _missionDistance; - double _missionMaxTelemetry; - double _cruiseDistance; - double _hoverDistance; + double _missionTime; + double _missionHoverDistance; + double _missionHoverTime; + double _missionCruiseDistance; + double _missionCruiseTime; + double _missionMaxTelemetry; + QString _surveyMissionItemName; + QString _fwLandingMissionItemName; + QStringList _complexMissionItemNames; static const char* _settingsGroup; + static const char* _jsonFileTypeValue; + static const char* _jsonFirmwareTypeKey; + static const char* _jsonVehicleTypeKey; + static const char* _jsonCruiseSpeedKey; + static const char* _jsonHoverSpeedKey; + static const char* _jsonItemsKey; + static const char* _jsonPlannedHomePositionKey; + static const char* _jsonParamsKey; + + // Deprecated V1 format keys static const char* _jsonMavAutopilotKey; static const char* _jsonComplexItemsKey; - static const char* _jsonPlannedHomePositionKey; + + static const int _missionFileVersion; }; #endif diff --git a/src/MissionManager/MissionItem.cc b/src/MissionManager/MissionItem.cc index 8b7df76ce216df70ec97c7c6c3b39b0108748cb9..bf8de33f96ea13ee3b176799373cadcbe08fd4fa 100644 --- a/src/MissionManager/MissionItem.cc +++ b/src/MissionManager/MissionItem.cc @@ -15,22 +15,25 @@ #include "FirmwarePluginManager.h" #include "QGCApplication.h" #include "JsonHelper.h" +#include "VisualMissionItem.h" -const char* MissionItem::_itemType = "missionItem"; -const char* MissionItem::_jsonTypeKey = "type"; -const char* MissionItem::_jsonIdKey = "id"; const char* MissionItem::_jsonFrameKey = "frame"; const char* MissionItem::_jsonCommandKey = "command"; +const char* MissionItem::_jsonAutoContinueKey = "autoContinue"; +const char* MissionItem::_jsonCoordinateKey = "coordinate"; +const char* MissionItem::_jsonParamsKey = "params"; +const char* MissionItem::_jsonDoJumpIdKey = "doJumpId"; + +// Deprecated V1 format keys const char* MissionItem::_jsonParam1Key = "param1"; const char* MissionItem::_jsonParam2Key = "param2"; const char* MissionItem::_jsonParam3Key = "param3"; const char* MissionItem::_jsonParam4Key = "param4"; -const char* MissionItem::_jsonAutoContinueKey = "autoContinue"; -const char* MissionItem::_jsonCoordinateKey = "coordinate"; MissionItem::MissionItem(QObject* parent) : QObject(parent) , _sequenceNumber(0) + , _doJumpId(-1) , _isCurrentItem(false) , _autoContinueFact (0, "AutoContinue", FactMetaData::valueTypeUint32) , _commandFact (0, "", FactMetaData::valueTypeUint32) @@ -48,6 +51,8 @@ MissionItem::MissionItem(QObject* parent) _frameFact.setRawValue(MAV_FRAME_GLOBAL_RELATIVE_ALT); setAutoContinue(true); + + connect(&_param2Fact, &Fact::rawValueChanged, this, &MissionItem::_param2Changed); } MissionItem::MissionItem(int sequenceNumber, @@ -65,6 +70,7 @@ MissionItem::MissionItem(int sequenceNumber, QObject* parent) : QObject(parent) , _sequenceNumber(sequenceNumber) + , _doJumpId(-1) , _isCurrentItem(isCurrentItem) , _commandFact (0, "", FactMetaData::valueTypeUint32) , _frameFact (0, "", FactMetaData::valueTypeUint32) @@ -91,11 +97,14 @@ MissionItem::MissionItem(int sequenceNumber, _param5Fact.setRawValue(param5); _param6Fact.setRawValue(param6); _param7Fact.setRawValue(param7); + + connect(&_param2Fact, &Fact::rawValueChanged, this, &MissionItem::_param2Changed); } MissionItem::MissionItem(const MissionItem& other, QObject* parent) : QObject(parent) , _sequenceNumber(0) + , _doJumpId(-1) , _isCurrentItem(false) , _commandFact (0, "", FactMetaData::valueTypeUint32) , _frameFact (0, "", FactMetaData::valueTypeUint32) @@ -112,10 +121,14 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent) _frameFact.setRawValue(MAV_FRAME_GLOBAL_RELATIVE_ALT); *this = other; + + connect(&_param2Fact, &Fact::rawValueChanged, this, &MissionItem::_param2Changed); } const MissionItem& MissionItem::operator=(const MissionItem& other) { + _doJumpId = other._doJumpId; + setCommand(other.command()); setFrame(other.frame()); setSequenceNumber(other._sequenceNumber); @@ -132,25 +145,26 @@ const MissionItem& MissionItem::operator=(const MissionItem& other) return *this; } + MissionItem::~MissionItem() { + } void MissionItem::save(QJsonObject& json) const { - json[_jsonTypeKey] = _itemType; - json[_jsonIdKey] = sequenceNumber(); + json[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeSimpleItemValue; json[_jsonFrameKey] = frame(); json[_jsonCommandKey] = command(); - json[_jsonParam1Key] = param1(); - json[_jsonParam2Key] = param2(); - json[_jsonParam3Key] = param3(); - json[_jsonParam4Key] = param4(); json[_jsonAutoContinueKey] = autoContinue(); + json[_jsonDoJumpIdKey] = _sequenceNumber; - QJsonArray coordinateArray; - coordinateArray << param5() << param6() << param7(); - json[_jsonCoordinateKey] = coordinateArray; + QJsonArray rgParams = { param1(), param2(), param3(), param4() }; + json[_jsonParamsKey] = rgParams; + + QJsonValue coordinateValue; + JsonHelper::saveGeoCoordinate(QGeoCoordinate(param5(), param6(), param7()), true /* writeAltitude */, coordinateValue); + json[_jsonCoordinateKey] = coordinateValue; } bool MissionItem::load(QTextStream &loadStream) @@ -175,41 +189,98 @@ bool MissionItem::load(QTextStream &loadStream) return false; } -bool MissionItem::load(const QJsonObject& json, QString& errorString) +bool MissionItem::_convertJsonV1ToV2(const QJsonObject& json, QJsonObject& v2Json, QString& errorString) { - QStringList requiredKeys; + // V1 format type = "missionItem", V2 format type = "MissionItem" + // V1 format has params in separate param[1-n] keys + // V2 format has params in params array + v2Json = json; - requiredKeys << _jsonTypeKey << _jsonIdKey << _jsonFrameKey << _jsonCommandKey << - _jsonParam1Key << _jsonParam2Key << _jsonParam3Key << _jsonParam4Key << - _jsonAutoContinueKey << _jsonCoordinateKey; - if (!JsonHelper::validateRequiredKeys(json, requiredKeys, errorString)) { + if (json.contains(_jsonParamsKey)) { + // Already V2 format + return true; + } + + QList keyInfoList = { + { VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, + { _jsonParam1Key, QJsonValue::Double, true }, + { _jsonParam2Key, QJsonValue::Double, true }, + { _jsonParam3Key, QJsonValue::Double, true }, + { _jsonParam4Key, QJsonValue::Double, true }, + }; + if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) { return false; } - if (json[_jsonTypeKey] != _itemType) { - errorString = QString("type found: %1 must be: %2").arg(json[_jsonTypeKey].toString()).arg(_itemType); + if (v2Json[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("missionItem")) { + v2Json[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeSimpleItemValue; + } + + QJsonArray rgParams = { json[_jsonParam1Key].toDouble(), json[_jsonParam2Key].toDouble(), json[_jsonParam3Key].toDouble(), json[_jsonParam4Key].toDouble() }; + v2Json[_jsonParamsKey] = rgParams; + v2Json.remove(_jsonParam1Key); + v2Json.remove(_jsonParam2Key); + v2Json.remove(_jsonParam3Key); + v2Json.remove(_jsonParam4Key); + + return true; +} + +bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& errorString) +{ + QJsonObject v2Json; + if (!_convertJsonV1ToV2(json, v2Json, errorString)) { + return false; + } + + QList keyInfoList = { + { VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, + { _jsonFrameKey, QJsonValue::Double, true }, + { _jsonCommandKey, QJsonValue::Double, true }, + { _jsonParamsKey, QJsonValue::Array, true }, + { _jsonAutoContinueKey, QJsonValue::Bool, true }, + { _jsonCoordinateKey, QJsonValue::Array, true }, + { _jsonDoJumpIdKey, QJsonValue::Double, false }, + }; + if (!JsonHelper::validateKeys(v2Json, keyInfoList, errorString)) { + return false; + } + + if (v2Json[VisualMissionItem::jsonTypeKey] != VisualMissionItem::jsonTypeSimpleItemValue) { + errorString = tr("Type found: %1 must be: %2").arg(v2Json[VisualMissionItem::jsonTypeKey].toString()).arg(VisualMissionItem::jsonTypeSimpleItemValue); + return false; + } + + QJsonArray rgParams = v2Json[_jsonParamsKey].toArray(); + if (rgParams.count() != 4) { + errorString = tr("%1 key must contains 4 values").arg(_jsonParamsKey); return false; } // Make sure to set these first since they can signal other changes - setFrame((MAV_FRAME)json[_jsonFrameKey].toInt()); - setCommand((MAV_CMD)json[_jsonCommandKey].toInt()); + setFrame((MAV_FRAME)v2Json[_jsonFrameKey].toInt()); + setCommand((MAV_CMD)v2Json[_jsonCommandKey].toInt()); QGeoCoordinate coordinate; - if (!JsonHelper::loadGeoCoordinate(json[_jsonCoordinateKey], true /* altitudeRequired */, coordinate, errorString)) { + if (!JsonHelper::loadGeoCoordinate(v2Json[_jsonCoordinateKey], true /* altitudeRequired */, coordinate, errorString)) { return false; } setParam5(coordinate.latitude()); setParam6(coordinate.longitude()); setParam7(coordinate.altitude()); + _doJumpId = -1; + if (v2Json.contains(_jsonDoJumpIdKey)) { + _doJumpId = v2Json[_jsonDoJumpIdKey].toInt(); + } setIsCurrentItem(false); - setSequenceNumber(json[_jsonIdKey].toInt()); - setParam1(json[_jsonParam1Key].toDouble()); - setParam2(json[_jsonParam2Key].toDouble()); - setParam3(json[_jsonParam3Key].toDouble()); - setParam4(json[_jsonParam4Key].toDouble()); - setAutoContinue(json[_jsonAutoContinueKey].toBool()); + setSequenceNumber(sequenceNumber); + setAutoContinue(v2Json[_jsonAutoContinueKey].toBool()); + + setParam1(rgParams[0].toDouble()); + setParam2(rgParams[1].toDouble()); + setParam3(rgParams[2].toDouble()); + setParam4(rgParams[3].toDouble()); return true; } @@ -312,3 +383,21 @@ QGeoCoordinate MissionItem::coordinate(void) const { return QGeoCoordinate(param5(), param6(), param7()); } + +double MissionItem::flightSpeed(void) const +{ + double flightSpeed = std::numeric_limits::quiet_NaN(); + + if (_commandFact.rawValue().toInt() == MAV_CMD_DO_CHANGE_SPEED && _param2Fact.rawValue().toDouble() > 0) { + flightSpeed = _param2Fact.rawValue().toDouble(); + } + + return flightSpeed; +} + +void MissionItem::_param2Changed(QVariant value) +{ + if (_commandFact.rawValue().toInt() == MAV_CMD_DO_CHANGE_SPEED && _param2Fact.rawValue().toDouble() > 0) { + emit flightSpeedChanged(value.toDouble()); + } +} diff --git a/src/MissionManager/MissionItem.h b/src/MissionManager/MissionItem.h index ee52892aee77a38afd799a3da72e88a62f36da4c..5ed2b4ef0051a6e3101ea7ae31e12da134467342 100644 --- a/src/MissionManager/MissionItem.h +++ b/src/MissionManager/MissionItem.h @@ -74,6 +74,10 @@ public: double param6 (void) const { return _param6Fact.rawValue().toDouble(); } double param7 (void) const { return _param7Fact.rawValue().toDouble(); } QGeoCoordinate coordinate (void) const; + int doJumpId (void) const { return _doJumpId; } + + /// @return Flight speed change value if this item supports it. If not it returns NaN. + double flightSpeed (void) const; void setCommand (MAV_CMD command); void setSequenceNumber (int sequenceNumber); @@ -91,17 +95,24 @@ public: void save(QJsonObject& json) const; bool load(QTextStream &loadStream); - bool load(const QJsonObject& json, QString& errorString); + bool load(const QJsonObject& json, int sequenceNumber, QString& errorString); bool relativeAltitude(void) const { return frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT; } signals: - void isCurrentItemChanged (bool isCurrentItem); - void sequenceNumberChanged (int sequenceNumber); + void isCurrentItemChanged (bool isCurrentItem); + void sequenceNumberChanged (int sequenceNumber); + void flightSpeedChanged (double flightSpeed); + +private slots: + void _param2Changed (QVariant value); private: - int _sequenceNumber; - bool _isCurrentItem; + bool _convertJsonV1ToV2(const QJsonObject& json, QJsonObject& v2Json, QString& errorString); + + int _sequenceNumber; + int _doJumpId; + bool _isCurrentItem; Fact _autoContinueFact; Fact _commandFact; @@ -115,17 +126,18 @@ private: Fact _param7Fact; // Keys for Json save - static const char* _itemType; - static const char* _jsonTypeKey; - static const char* _jsonIdKey; static const char* _jsonFrameKey; static const char* _jsonCommandKey; + static const char* _jsonAutoContinueKey; + static const char* _jsonCoordinateKey; + static const char* _jsonParamsKey; + static const char* _jsonDoJumpIdKey; + + // Deprecated V1 format keys static const char* _jsonParam1Key; static const char* _jsonParam2Key; static const char* _jsonParam3Key; static const char* _jsonParam4Key; - static const char* _jsonAutoContinueKey; - static const char* _jsonCoordinateKey; friend class SurveyMissionItem; friend class SimpleMissionItem; diff --git a/src/MissionManager/MissionItemTest.cc b/src/MissionManager/MissionItemTest.cc index a408bf9119f6d1b3e6577eb21535d0e6765b1081..bb7d95e529917d93d5b63ef1408b2034e804b657 100644 --- a/src/MissionManager/MissionItemTest.cc +++ b/src/MissionManager/MissionItemTest.cc @@ -226,7 +226,7 @@ void MissionItemTest::_testFactSignals(void) void MissionItemTest::_checkExpectedMissionItem(const MissionItem& missionItem) { - QCOMPARE(missionItem.sequenceNumber(), 10); + QCOMPARE(missionItem.sequenceNumber(), _seq); QCOMPARE(missionItem.isCurrentItem(), false); QCOMPARE(missionItem.frame(), (MAV_FRAME)3); QCOMPARE(missionItem.command(), (MAV_CMD)80); @@ -264,33 +264,71 @@ void MissionItemTest::_testSimpleLoadFromStream(void) _checkExpectedMissionItem(simpleMissionItem.missionItem()); } -void MissionItemTest::_testLoadFromJson(void) +void MissionItemTest::_testLoadFromJsonV1(void) { MissionItem missionItem; QString errorString; QJsonArray coordinateArray; coordinateArray << -10.0 << -20.0 <<-30.0; QJsonObject jsonObject; - jsonObject.insert("autoContinue", true); - jsonObject.insert("command", 80); - jsonObject.insert("frame", 3); - jsonObject.insert("id", 10); - jsonObject.insert("param1", 10); - jsonObject.insert("param2", 20); - jsonObject.insert("param3", 30); - jsonObject.insert("param4", 40); - jsonObject.insert("type", "missionItem"); - jsonObject.insert("coordinate", coordinateArray); + jsonObject.insert(MissionItem::_jsonAutoContinueKey, true); + jsonObject.insert(MissionItem::_jsonCommandKey, 80); + jsonObject.insert(MissionItem::_jsonFrameKey, 3); + jsonObject.insert(MissionItem::_jsonParam1Key, 10); + jsonObject.insert(MissionItem::_jsonParam2Key, 20); + jsonObject.insert(MissionItem::_jsonParam3Key, 30); + jsonObject.insert(MissionItem::_jsonParam4Key, 40); + jsonObject.insert(VisualMissionItem::jsonTypeKey, VisualMissionItem::jsonTypeSimpleItemValue); + jsonObject.insert(MissionItem::_jsonCoordinateKey, coordinateArray); + // We only need to test the differences between V1 and V2 + + QStringList removeKeys; + removeKeys << MissionItem::_jsonParam1Key << MissionItem::_jsonParam2Key << MissionItem::_jsonParam3Key << MissionItem::_jsonParam4Key; + foreach (const QString& removeKey, removeKeys) { + QJsonObject badObject = jsonObject; + badObject.remove(removeKey); + QCOMPARE(missionItem.load(badObject, _seq, errorString), false); + QVERIFY(!errorString.isEmpty()); + qDebug() << errorString; + } + + // Test good load + + QVERIFY(missionItem.load(jsonObject, _seq, errorString)); + _checkExpectedMissionItem(missionItem); +} + +void MissionItemTest::_testLoadFromJsonV2(void) +{ + MissionItem missionItem; + QString errorString; + QJsonArray coordinateArray; + coordinateArray << -10.0 << -20.0 <<-30.0; + QJsonObject jsonObject; + jsonObject.insert(MissionItem::_jsonAutoContinueKey, true); + jsonObject.insert(MissionItem::_jsonCommandKey, 80); + jsonObject.insert(MissionItem::_jsonFrameKey, 3); + jsonObject.insert(VisualMissionItem::jsonTypeKey, VisualMissionItem::jsonTypeSimpleItemValue); + jsonObject.insert(MissionItem::_jsonCoordinateKey, coordinateArray); + + QJsonArray rgParams = { 10, 20, 30, 40 }; + jsonObject.insert(MissionItem::_jsonParamsKey, rgParams); + // Test missing key detection QStringList removeKeys; - removeKeys << "autoContinue" << "command" << "frame" << "id" << "param1" << "param2" << "param3" << "param4" << "type" << "coordinate"; + removeKeys << MissionItem::_jsonAutoContinueKey << + MissionItem::_jsonCommandKey << + MissionItem::_jsonFrameKey << + MissionItem::_jsonParamsKey << + VisualMissionItem::jsonTypeKey << + MissionItem::_jsonCoordinateKey; foreach(const QString& removeKey, removeKeys) { QJsonObject badObject = jsonObject; badObject.remove(removeKey); - QCOMPARE(missionItem.load(badObject, errorString), false); + QCOMPARE(missionItem.load(badObject, _seq, errorString), false); QVERIFY(!errorString.isEmpty()); qDebug() << errorString; } @@ -300,7 +338,7 @@ void MissionItemTest::_testLoadFromJson(void) QJsonObject badObject = jsonObject; badObject.remove("coordinate"); badObject["coordinate"] = 10; - QCOMPARE(missionItem.load(badObject, errorString), false); + QCOMPARE(missionItem.load(badObject, _seq, errorString), false); QVERIFY(!errorString.isEmpty()); qDebug() << errorString; @@ -309,7 +347,7 @@ void MissionItemTest::_testLoadFromJson(void) badObject = jsonObject; badObject.remove("coordinate"); badObject["coordinate"] = badCoordinateArray; - QCOMPARE(missionItem.load(badObject, errorString), false); + QCOMPARE(missionItem.load(badObject, _seq, errorString), false); QVERIFY(!errorString.isEmpty()); qDebug() << errorString; @@ -318,7 +356,7 @@ void MissionItemTest::_testLoadFromJson(void) badObject = jsonObject; badObject.remove("coordinate"); badObject["coordinate"] = badCoordinateArray_second; - QCOMPARE(missionItem.load(badObject, errorString), false); + QCOMPARE(missionItem.load(badObject, _seq, errorString), false); QVERIFY(!errorString.isEmpty()); qDebug() << errorString; @@ -329,7 +367,7 @@ void MissionItemTest::_testLoadFromJson(void) badObject = jsonObject; badObject.remove("coordinate"); badObject["coordinate"] = badCoordinateArray_third; - QCOMPARE(missionItem.load(badObject, errorString), false); + QCOMPARE(missionItem.load(badObject, _seq, errorString), false); QVERIFY(!errorString.isEmpty()); qDebug() << errorString; @@ -338,13 +376,17 @@ void MissionItemTest::_testLoadFromJson(void) badObject = jsonObject; badObject.remove("type"); badObject["type"] = "foo"; - QCOMPARE(missionItem.load(badObject, errorString), false); + QCOMPARE(missionItem.load(badObject, _seq, errorString), false); QVERIFY(!errorString.isEmpty()); qDebug() << errorString; // Test good load - QVERIFY(missionItem.load(jsonObject, errorString)); + bool result = missionItem.load(jsonObject, _seq, errorString); + if (!result) { + qDebug() << errorString; + QVERIFY(result); + } _checkExpectedMissionItem(missionItem); } @@ -356,21 +398,19 @@ void MissionItemTest::_testSimpleLoadFromJson(void) SimpleMissionItem simpleMissionItem(NULL); QString errorString; QJsonArray coordinateArray; - coordinateArray << -10.0 << -20.0 << -30.0; QJsonObject jsonObject; - jsonObject.insert("autoContinue", true); - jsonObject.insert("command", 80); - jsonObject.insert("frame", 3); - jsonObject.insert("id", 10); - jsonObject.insert("param1", 10); - jsonObject.insert("param2", 20); - jsonObject.insert("param3", 30); - jsonObject.insert("param4", 40); - jsonObject.insert("type", "missionItem"); - jsonObject.insert("coordinate", coordinateArray); - - - QVERIFY(simpleMissionItem.load(jsonObject, errorString)); + + coordinateArray << -10.0 << -20.0 <<-30.0; + jsonObject.insert(MissionItem::_jsonAutoContinueKey, true); + jsonObject.insert(MissionItem::_jsonCommandKey, 80); + jsonObject.insert(MissionItem::_jsonFrameKey, 3); + jsonObject.insert(VisualMissionItem::jsonTypeKey, VisualMissionItem::jsonTypeSimpleItemValue); + jsonObject.insert(MissionItem::_jsonCoordinateKey, coordinateArray); + + QJsonArray rgParams = { 10, 20, 30, 40 }; + jsonObject.insert(MissionItem::_jsonParamsKey, rgParams); + + QVERIFY(simpleMissionItem.load(jsonObject, _seq, errorString)); _checkExpectedMissionItem(simpleMissionItem.missionItem()); } @@ -378,7 +418,7 @@ void MissionItemTest::_testSaveToJson(void) { MissionItem missionItem; - missionItem.setSequenceNumber(10); + missionItem.setSequenceNumber(_seq); missionItem.setIsCurrentItem(true); missionItem.setFrame((MAV_FRAME)3); missionItem.setCommand((MAV_CMD)80); @@ -395,9 +435,9 @@ void MissionItemTest::_testSaveToJson(void) QJsonObject jsonObject; QString errorString; missionItem.save(jsonObject); - QVERIFY(missionItem.load(jsonObject, errorString)); + QVERIFY(missionItem.load(jsonObject, _seq, errorString)); - QCOMPARE(missionItem.sequenceNumber(), 10); + QCOMPARE(missionItem.sequenceNumber(), _seq); QCOMPARE(missionItem.isCurrentItem(), false); QCOMPARE(missionItem.frame(), (MAV_FRAME)3); QCOMPARE(missionItem.command(), (MAV_CMD)80); @@ -410,295 +450,3 @@ void MissionItemTest::_testSaveToJson(void) QCOMPARE(missionItem.param7(), -30.1234567); QCOMPARE(missionItem.autoContinue(), true); } - -#if 0 -void MissionItemTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t failureMode) -{ - _mockLink->setMissionItemFailureMode(failureMode); - - // Setup our test case data - QList missionItems; - - // Editor has a home position item on the front, so we do the same - MissionItem* homeItem = new MissionItem(NULL /* Vehicle */, this); - homeItem->setCommand(MAV_CMD_NAV_WAYPOINT); - homeItem->setCoordinate(QGeoCoordinate(47.3769, 8.549444, 0)); - homeItem->setSequenceNumber(0); - missionItems.append(homeItem); - - for (size_t i=0; i<_cTestCases; i++) { - const TestCase_t* testCase = &_rgTestCases[i]; - - MissionItem* missionItem = new MissionItem(this); - - QTextStream loadStream(testCase->itemStream, QIODevice::ReadOnly); - QVERIFY(missionItem->load(loadStream)); - - // Mission Manager expects to get 1-base sequence numbers for write - missionItem->setSequenceNumber(missionItem->sequenceNumber() + 1); - - missionItems.append(missionItem); - } - - // Send the items to the vehicle - _missionManager->writeMissionItems(missionItems); - - // writeMissionItems should emit these signals before returning: - // inProgressChanged - // newMissionItemsAvailable - QVERIFY(_missionManager->inProgress()); - QCOMPARE(_multiSpyMissionManager->checkSignalByMask(inProgressChangedSignalMask | newMissionItemsAvailableSignalMask), true); - _checkInProgressValues(true); - - _multiSpyMissionManager->clearAllSignals(); - - if (failureMode == MockLinkMissionItemHandler::FailNone) { - // This should be clean run - - // Wait for write sequence to complete. We should get: - // inProgressChanged(false) signal - _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); - QCOMPARE(_multiSpyMissionManager->checkOnlySignalByMask(inProgressChangedSignalMask), true); - - // Validate inProgressChanged signal value - _checkInProgressValues(false); - - // Validate item count in mission manager - - int expectedCount = (int)_cTestCases; - if (_mockLink->getFirmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { - // Home position at position 0 comes from vehicle - expectedCount++; - } - - QCOMPARE(_missionManager->missionItems().count(), expectedCount); - } else { - // This should be a failed run - - setExpectedMessageBox(QMessageBox::Ok); - - // Wait for write sequence to complete. We should get: - // inProgressChanged(false) signal - // error(errorCode, QString) signal - _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); - QCOMPARE(_multiSpyMissionManager->checkSignalByMask(inProgressChangedSignalMask | errorSignalMask), true); - - // Validate inProgressChanged signal value - _checkInProgressValues(false); - - // Validate error signal values - QSignalSpy* spy = _multiSpyMissionManager->getSpyByIndex(errorSignalIndex); - QList signalArgs = spy->takeFirst(); - QCOMPARE(signalArgs.count(), 2); - qDebug() << signalArgs[1].toString(); - - checkExpectedMessageBox(); - } - - _multiSpyMissionManager->clearAllSignals(); -} - -void MissionItemTest::_roundTripItems(MockLinkMissionItemHandler::FailureMode_t failureMode) -{ - _writeItems(MockLinkMissionItemHandler::FailNone); - - _mockLink->setMissionItemFailureMode(failureMode); - - // Read the items back from the vehicle - _missionManager->requestMissionItems(); - - // requestMissionItems should emit inProgressChanged signal before returning so no need to wait for it - QVERIFY(_missionManager->inProgress()); - QCOMPARE(_multiSpyMissionManager->checkOnlySignalByMask(inProgressChangedSignalMask), true); - _checkInProgressValues(true); - - _multiSpyMissionManager->clearAllSignals(); - - if (failureMode == MockLinkMissionItemHandler::FailNone) { - // This should be clean run - - // Now wait for read sequence to complete. We should get: - // inProgressChanged(false) signal to signal completion - // newMissionItemsAvailable signal - _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); - QCOMPARE(_multiSpyMissionManager->checkSignalByMask(newMissionItemsAvailableSignalMask | inProgressChangedSignalMask), true); - _checkInProgressValues(false); - - } else { - // This should be a failed run - - setExpectedMessageBox(QMessageBox::Ok); - - // Wait for read sequence to complete. We should get: - // inProgressChanged(false) signal to signal completion - // error(errorCode, QString) signal - // newMissionItemsAvailable signal - _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); - QCOMPARE(_multiSpyMissionManager->checkSignalByMask(newMissionItemsAvailableSignalMask | inProgressChangedSignalMask | errorSignalMask), true); - - // Validate inProgressChanged signal value - _checkInProgressValues(false); - - // Validate error signal values - QSignalSpy* spy = _multiSpyMissionManager->getSpyByIndex(errorSignalIndex); - QList signalArgs = spy->takeFirst(); - QCOMPARE(signalArgs.count(), 2); - qDebug() << signalArgs[1].toString(); - - checkExpectedMessageBox(); - } - - _multiSpyMissionManager->clearAllSignals(); - - // Validate returned items - - size_t cMissionItemsExpected; - - if (failureMode == MockLinkMissionItemHandler::FailNone) { - cMissionItemsExpected = (int)_cTestCases; - if (_mockLink->getFirmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { - // Home position at position 0 comes from vehicle - cMissionItemsExpected++; - } - } else { - cMissionItemsExpected = 0; - } - - QCOMPARE(_missionManager->missionItems().count(), (int)cMissionItemsExpected); - - size_t firstActualItem = 0; - if (_mockLink->getFirmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { - // First item is home position, don't validate it - firstActualItem++; - } - - int testCaseIndex = 0; - for (size_t actualItemIndex=firstActualItem; actualItemIndexexpectedItem.sequenceNumber; - if (_mockLink->getFirmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { - // Account for home position in first item - expectedSequenceNumber++; - } - - MissionItem* actual = _missionManager->missionItems()[actualItemIndex]; - - qDebug() << "Test case" << testCaseIndex; - QCOMPARE(actual->sequenceNumber(), expectedSequenceNumber); - QCOMPARE(actual->coordinate().latitude(), testCase->expectedItem.coordinate.latitude()); - QCOMPARE(actual->coordinate().longitude(), testCase->expectedItem.coordinate.longitude()); - QCOMPARE(actual->coordinate().altitude(), testCase->expectedItem.coordinate.altitude()); - QCOMPARE((int)actual->command(), (int)testCase->expectedItem.command); - QCOMPARE(actual->param1(), testCase->expectedItem.param1); - QCOMPARE(actual->param2(), testCase->expectedItem.param2); - QCOMPARE(actual->param3(), testCase->expectedItem.param3); - QCOMPARE(actual->param4(), testCase->expectedItem.param4); - QCOMPARE(actual->autoContinue(), testCase->expectedItem.autocontinue); - QCOMPARE(actual->frame(), testCase->expectedItem.frame); - - testCaseIndex++; - } - -} - -void MissionItemTest::_testWriteFailureHandlingWorker(void) -{ - /* - /// Called to send a MISSION_ACK message while the MissionManager is in idle state - void sendUnexpectedMissionAck(MAV_MISSION_RESULT ackType) { _missionItemHandler.sendUnexpectedMissionAck(ackType); } - - /// Called to send a MISSION_ITEM message while the MissionManager is in idle state - void sendUnexpectedMissionItem(void) { _missionItemHandler.sendUnexpectedMissionItem(); } - - /// Called to send a MISSION_REQUEST message while the MissionManager is in idle state - void sendUnexpectedMissionRequest(void) { _missionItemHandler.sendUnexpectedMissionRequest(); } - */ - - typedef struct { - const char* failureText; - MockLinkMissionItemHandler::FailureMode_t failureMode; - } TestCase_t; - - static const TestCase_t rgTestCases[] = { - { "No Failure", MockLinkMissionItemHandler::FailNone }, - { "FailWriteRequest0NoResponse", MockLinkMissionItemHandler::FailWriteRequest0NoResponse }, - { "FailWriteRequest1NoResponse", MockLinkMissionItemHandler::FailWriteRequest1NoResponse }, - { "FailWriteRequest0IncorrectSequence", MockLinkMissionItemHandler::FailWriteRequest0IncorrectSequence }, - { "FailWriteRequest1IncorrectSequence", MockLinkMissionItemHandler::FailWriteRequest1IncorrectSequence }, - { "FailWriteRequest0ErrorAck", MockLinkMissionItemHandler::FailWriteRequest0ErrorAck }, - { "FailWriteRequest1ErrorAck", MockLinkMissionItemHandler::FailWriteRequest1ErrorAck }, - { "FailWriteFinalAckNoResponse", MockLinkMissionItemHandler::FailWriteFinalAckNoResponse }, - { "FailWriteFinalAckErrorAck", MockLinkMissionItemHandler::FailWriteFinalAckErrorAck }, - { "FailWriteFinalAckMissingRequests", MockLinkMissionItemHandler::FailWriteFinalAckMissingRequests }, - }; - - for (size_t i=0; iresetMissionItemHandler(); - } -} - -void MissionItemTest::_testReadFailureHandlingWorker(void) -{ - /* - /// Called to send a MISSION_ACK message while the MissionManager is in idle state - void sendUnexpectedMissionAck(MAV_MISSION_RESULT ackType) { _missionItemHandler.sendUnexpectedMissionAck(ackType); } - - /// Called to send a MISSION_ITEM message while the MissionManager is in idle state - void sendUnexpectedMissionItem(void) { _missionItemHandler.sendUnexpectedMissionItem(); } - - /// Called to send a MISSION_REQUEST message while the MissionManager is in idle state - void sendUnexpectedMissionRequest(void) { _missionItemHandler.sendUnexpectedMissionRequest(); } - */ - - typedef struct { - const char* failureText; - MockLinkMissionItemHandler::FailureMode_t failureMode; - } TestCase_t; - - static const TestCase_t rgTestCases[] = { - { "No Failure", MockLinkMissionItemHandler::FailNone }, - { "FailReadRequestListNoResponse", MockLinkMissionItemHandler::FailReadRequestListNoResponse }, - { "FailReadRequest0NoResponse", MockLinkMissionItemHandler::FailReadRequest0NoResponse }, - { "FailReadRequest1NoResponse", MockLinkMissionItemHandler::FailReadRequest1NoResponse }, - { "FailReadRequest0IncorrectSequence", MockLinkMissionItemHandler::FailReadRequest0IncorrectSequence }, - { "FailReadRequest1IncorrectSequence", MockLinkMissionItemHandler::FailReadRequest1IncorrectSequence }, - { "FailReadRequest0ErrorAck", MockLinkMissionItemHandler::FailReadRequest0ErrorAck }, - { "FailReadRequest1ErrorAck", MockLinkMissionItemHandler::FailReadRequest1ErrorAck }, - }; - - for (size_t i=0; iresetMissionItemHandler(); - _multiSpyMissionManager->clearAllSignals(); - } -} - -void MissionItemTest::_testWriteFailureHandlingAPM(void) -{ - _initForFirmwareType(MAV_AUTOPILOT_ARDUPILOTMEGA); - _testWriteFailureHandlingWorker(); -} - -void MissionItemTest::_testReadFailureHandlingAPM(void) -{ - _initForFirmwareType(MAV_AUTOPILOT_ARDUPILOTMEGA); - _testReadFailureHandlingWorker(); -} - - -void MissionItemTest::_testWriteFailureHandlingPX4(void) -{ - _initForFirmwareType(MAV_AUTOPILOT_PX4); - _testWriteFailureHandlingWorker(); -} - -void MissionItemTest::_testReadFailureHandlingPX4(void) -{ - _initForFirmwareType(MAV_AUTOPILOT_PX4); - _testReadFailureHandlingWorker(); -} -#endif diff --git a/src/MissionManager/MissionItemTest.h b/src/MissionManager/MissionItemTest.h index 8572356060e619f42bdbb5390879570672c16fd8..4dd1f6b358d3c034b9a3386a8b98124b6faf9ff3 100644 --- a/src/MissionManager/MissionItemTest.h +++ b/src/MissionManager/MissionItemTest.h @@ -29,12 +29,15 @@ private slots: void _testFactSignals(void); void _testLoadFromStream(void); void _testSimpleLoadFromStream(void); - void _testLoadFromJson(void); + void _testLoadFromJsonV1(void); + void _testLoadFromJsonV2(void); void _testSimpleLoadFromJson(void); void _testSaveToJson(void); private: void _checkExpectedMissionItem(const MissionItem& missionItem); + + int _seq = 10; }; #endif diff --git a/src/MissionManager/MissionLoader.h b/src/MissionManager/MissionLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..36360cbc4900adf3137da854aba995275a2e2e70 --- /dev/null +++ b/src/MissionManager/MissionLoader.h @@ -0,0 +1,193 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +#ifndef MissionController_H +#define MissionController_H + +#include "PlanElementController.h" +#include "QmlObjectListModel.h" +#include "Vehicle.h" +#include "QGCLoggingCategory.h" +#include "MavlinkQmlSingleton.h" +#include "VisualMissionItem.h" + +#include + +class CoordinateVector; + +Q_DECLARE_LOGGING_CATEGORY(MissionControllerLog) + +typedef QPair VisualItemPair; +typedef QHash CoordVectHashTable; +class MissionController : public PlanElementController +{ + Q_OBJECT + +public: + MissionController(QObject* parent = NULL); + ~MissionController(); + + Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged) + Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged) + Q_PROPERTY(QmlObjectListModel* complexVisualItems READ complexVisualItems NOTIFY complexVisualItemsChanged) + Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged) + + Q_PROPERTY(double missionDistance READ missionDistance NOTIFY missionDistanceChanged) + Q_PROPERTY(double missionTime READ missionTime NOTIFY missionTimeChanged) + Q_PROPERTY(double missionHoverDistance READ missionHoverDistance NOTIFY missionHoverDistanceChanged) + Q_PROPERTY(double missionCruiseDistance READ missionCruiseDistance NOTIFY missionCruiseDistanceChanged) + Q_PROPERTY(double missionHoverTime READ missionHoverTime NOTIFY missionHoverTimeChanged) + Q_PROPERTY(double missionCruiseTime READ missionCruiseTime NOTIFY missionCruiseTimeChanged) + Q_PROPERTY(double missionMaxTelemetry READ missionMaxTelemetry NOTIFY missionMaxTelemetryChanged) + + Q_INVOKABLE void removeMissionItem(int index); + + /// Add a new simple mission item to the list + /// @param i: index to insert at + /// @return Sequence number for new item + Q_INVOKABLE int insertSimpleMissionItem(QGeoCoordinate coordinate, int i); + + /// Add a new complex mission item to the list + /// @param i: index to insert at + /// @return Sequence number for new item + Q_INVOKABLE int insertComplexMissionItem(QGeoCoordinate coordinate, int i); + + // Overrides from PlanElementController + void start (bool editMode) final; + void startStaticActiveVehicle (Vehicle* vehicle) final; + void loadFromVehicle (void) final; + void sendToVehicle (void) final; + void loadFromFilePicker (void) final; + void loadFromFile (const QString& filename) final; + void saveToFilePicker (void) final; + void saveToFile (const QString& filename) final; + void removeAll (void) final; + bool syncInProgress (void) const final; + bool dirty (void) const final; + void setDirty (bool dirty) final; + + QString fileExtension(void) const final; + + // Property accessors + + QGeoCoordinate plannedHomePosition (void); + QmlObjectListModel* visualItems (void) { return _visualItems; } + QmlObjectListModel* complexVisualItems (void) { return _complexItems; } + QmlObjectListModel* waypointLines (void) { return &_waypointLines; } + + double missionDistance (void) const { return _missionDistance; } + double missionTime (void) const { return _missionTime; } + double missionHoverDistance (void) const { return _missionHoverDistance; } + double missionHoverTime (void) const { return _missionHoverTime; } + double missionCruiseDistance (void) const { return _missionCruiseDistance; } + double missionCruiseTime (void) const { return _missionCruiseTime; } + double missionMaxTelemetry (void) const { return _missionMaxTelemetry; } + double cruiseSpeed (void) const; + double hoverSpeed (void) const; + + static void createVisualItemsFromFile(const QString& filename); + +signals: + void plannedHomePositionChanged(QGeoCoordinate plannedHomePosition); + void visualItemsChanged(void); + void complexVisualItemsChanged(void); + void waypointLinesChanged(void); + void newItemsFromVehicle(void); + void missionDistanceChanged(double missionDistance); + void missionTimeChanged(void); + void missionHoverDistanceChanged(double missionHoverDistance); + void missionHoverTimeChanged(void); + void missionCruiseDistanceChanged(double missionCruiseDistance); + void missionCruiseTimeChanged(void); + void missionMaxTelemetryChanged(double missionMaxTelemetry); + void cruiseDistanceChanged(double cruiseDistance); + void hoverDistanceChanged(double hoverDistance); + void cruiseSpeedChanged(double cruiseSpeed); + void hoverSpeedChanged(double hoverSpeed); + +private slots: + void _newMissionItemsAvailableFromVehicle(); + void _itemCommandChanged(void); + void _activeVehicleHomePositionAvailableChanged(bool homePositionAvailable); + void _activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition); + void _inProgressChanged(bool inProgress); + void _currentMissionItemChanged(int sequenceNumber); + void _recalcWaypointLines(void); + void _recalcAltitudeRangeBearing(void); + void _homeCoordinateChanged(void); + +private: + void _init(void); + void _recalcSequence(void); + void _recalcChildItems(void); + void _recalcAll(void); + void _initAllVisualItems(void); + void _deinitAllVisualItems(void); + void _initVisualItem(VisualMissionItem* item); + void _deinitVisualItem(VisualMissionItem* item); + void _setupActiveVehicle(Vehicle* activeVehicle, bool forceLoadFromVehicle); + static void _calcPrevWaypointValues(double homeAlt, VisualMissionItem* currentItem, VisualMissionItem* prevItem, double* azimuth, double* distance, double* altDifference); + static double _calcDistanceToHome(VisualMissionItem* currentItem, VisualMissionItem* homeItem); + bool _findLastAltitude(double* lastAltitude, MAV_FRAME* frame); + bool _findLastAcceptanceRadius(double* lastAcceptanceRadius); + void _addPlannedHomePosition(QmlObjectListModel* visualItems, bool addToCenter); + double _normalizeLat(double lat); + double _normalizeLon(double lon); + bool _loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); + bool _loadJsonMissionFileV1(const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); + bool _loadJsonMissionFileV2(const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); + bool _loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString); + int _nextSequenceNumber(void); + void _setMissionDistance(double missionDistance); + void _setMissionTime(double missionTime); + void _setMissionHoverDistance(double missionHoverDistance); + void _setMissionHoverTime(double missionHoverTime); + void _setMissionCruiseDistance(double missionCruiseDistance); + void _setMissionCruiseTime(double missionCruiseTime); + void _setMissionMaxTelemetry(double missionMaxTelemetry); + + // Overrides from PlanElementController + void _activeVehicleBeingRemoved(void) final; + void _activeVehicleSet(void) final; + +private: + QmlObjectListModel* _visualItems; + QmlObjectListModel* _complexItems; + QmlObjectListModel _waypointLines; + CoordVectHashTable _linesTable; + bool _firstItemsFromVehicle; + bool _missionItemsRequested; + bool _queuedSend; + double _missionDistance; + double _missionTime; + double _missionHoverDistance; + double _missionHoverTime; + double _missionCruiseDistance; + double _missionCruiseTime; + double _missionMaxTelemetry; + + static const char* _settingsGroup; + static const char* _jsonFileTypeValue; + static const char* _jsonFirmwareTypeKey; + static const char* _jsonVehicleTypeKey; + static const char* _jsonCruiseSpeedKey; + static const char* _jsonHoverSpeedKey; + static const char* _jsonItemsKey; + static const char* _jsonPlannedHomePositionKey; + static const char* _jsonParamsKey; + + // Deprecated V1 format keys + static const char* _jsonMavAutopilotKey; + static const char* _jsonComplexItemsKey; + + static const int _missionFileVersion; +}; + +#endif diff --git a/src/MissionManager/MissionManager.cc b/src/MissionManager/MissionManager.cc index fa0ce387b47ab6f5c78e78a13338ee36efc9c0dc..c41aed3455c2833eac0c88474e2015aa1aa94285 100644 --- a/src/MissionManager/MissionManager.cc +++ b/src/MissionManager/MissionManager.cc @@ -23,7 +23,7 @@ MissionManager::MissionManager(Vehicle* vehicle) : _vehicle(vehicle) , _dedicatedLink(NULL) , _ackTimeoutTimer(NULL) - , _retryAck(AckNone) + , _expectedAck(AckNone) , _readTransactionInProgress(false) , _writeTransactionInProgress(false) , _currentMissionItem(-1) @@ -81,7 +81,17 @@ void MissionManager::writeMissionItems(const QList& missionItems) for (int i=0; i<_missionItems.count(); i++) { _itemIndicesToWrite << i; } + _writeTransactionInProgress = true; + _retryCount = 0; + emit inProgressChanged(true); + _writeMissionCount(); +} + +/// This begins the write sequence with the vehicle. This may be called during a retry. +void MissionManager::_writeMissionCount(void) +{ + qCDebug(MissionManagerLog) << "_writeMissionCount retry count" << _retryCount; mavlink_message_t message; mavlink_mission_count_t missionCount; @@ -99,7 +109,6 @@ void MissionManager::writeMissionItems(const QList& missionItems) _vehicle->sendMessageOnLink(_dedicatedLink, message); _startAckTimeout(AckMissionRequest); - emit inProgressChanged(true); } void MissionManager::writeArduPilotGuidedMissionItem(const QGeoCoordinate& gotoCoord, bool altChangeOnly) @@ -153,75 +162,128 @@ void MissionManager::requestMissionItems(void) qCDebug(MissionManagerLog) << "requestMissionItems called while transaction in progress"; return; } - + + _retryCount = 0; + _readTransactionInProgress = true; + emit inProgressChanged(true); + _requestList(); +} + +/// Internal call to request list of mission items. May be called during a retry sequence. +void MissionManager::_requestList(void) +{ + qCDebug(MissionManagerLog) << "_requestList retry count" << _retryCount; + mavlink_message_t message; mavlink_mission_request_list_t request; - - _requestItemRetryCount = 0; + _itemIndicesToRead.clear(); - _readTransactionInProgress = true; _clearMissionItems(); - + request.target_system = _vehicle->id(); request.target_component = MAV_COMP_ID_MISSIONPLANNER; - + _dedicatedLink = _vehicle->priorityLink(); mavlink_msg_mission_request_list_encode_chan(qgcApp()->toolbox()->mavlinkProtocol()->getSystemId(), qgcApp()->toolbox()->mavlinkProtocol()->getComponentId(), _dedicatedLink->mavlinkChannel(), &message, &request); - + _vehicle->sendMessageOnLink(_dedicatedLink, message); _startAckTimeout(AckMissionCount); - emit inProgressChanged(true); } void MissionManager::_ackTimeout(void) { - AckType_t timedOutAck = _retryAck; - - _retryAck = AckNone; - - if (timedOutAck == AckNone) { - qCWarning(MissionManagerLog) << "_ackTimeout timeout with AckNone"; - _sendError(InternalError, "Internal error occurred during Mission Item communication: _ackTimeOut:_retryAck == AckNone"); + if (_expectedAck == AckNone) { return; } - - _sendError(AckTimeoutError, QString("Vehicle did not respond to mission item communication: %1").arg(_ackTypeToString(timedOutAck))); - _finishTransaction(false); + + switch (_expectedAck) { + case AckNone: + qCWarning(MissionManagerLog) << "_ackTimeout timeout with AckNone"; + _sendError(InternalError, "Internal error occurred during Mission Item communication: _ackTimeOut:_expectedAck == AckNone"); + break; + case AckMissionCount: + // MISSION_COUNT message expected + if (_retryCount > _maxRetryCount) { + _sendError(VehicleError, QStringLiteral("Mission request list failed, maximum retries exceeded.")); + _finishTransaction(false); + } else { + _retryCount++; + qCDebug(MissionManagerLog) << "Retrying REQUEST_LIST retry Count" << _retryCount; + _requestList(); + } + break; + case AckMissionItem: + // MISSION_ITEM expected + if (_retryCount > _maxRetryCount) { + _sendError(VehicleError, QStringLiteral("Mission read failed, maximum retries exceeded.")); + _finishTransaction(false); + } else { + _retryCount++; + qCDebug(MissionManagerLog) << "Retrying MISSION_REQUEST retry Count" << _retryCount; + _requestNextMissionItem(); + } + break; + case AckMissionRequest: + // MISSION_REQUEST is expected, or MISSION_ACK to end sequence + if (_itemIndicesToWrite.count() == 0) { + // Vehicle did not send final MISSION_ACK at end of sequence + _sendError(VehicleError, QStringLiteral("Mission write failed, vehicle failed to send final ack.")); + _finishTransaction(false); + } else if (_itemIndicesToWrite[0] == 0) { + // Vehicle did not respond to MISSION_COUNT, try again + if (_retryCount > _maxRetryCount) { + _sendError(VehicleError, QStringLiteral("Mission write mission count failed, maximum retries exceeded.")); + _finishTransaction(false); + } else { + _retryCount++; + qCDebug(MissionManagerLog) << "Retrying MISSION_COUNT retry Count" << _retryCount; + _writeMissionCount(); + } + } else { + // Vehicle did not request all items from ground station + _sendError(AckTimeoutError, QString("Vehicle did not request all items from ground station: %1").arg(_ackTypeToString(_expectedAck))); + _expectedAck = AckNone; + _finishTransaction(false); + } + break; + case AckGuidedItem: + // MISSION_REQUEST is expected, or MISSION_ACK to end sequence + default: + _sendError(AckTimeoutError, QString("Vehicle did not respond to mission item communication: %1").arg(_ackTypeToString(_expectedAck))); + _expectedAck = AckNone; + _finishTransaction(false); + } } void MissionManager::_startAckTimeout(AckType_t ack) { - _retryAck = ack; + _expectedAck = ack; _ackTimeoutTimer->start(); } -bool MissionManager::_stopAckTimeout(AckType_t expectedAck) +/// Checks the received ack against the expected ack. If they match the ack timeout timer will be stopped. +/// @return true: received ack matches expected ack +bool MissionManager::_checkForExpectedAck(AckType_t receivedAck) { - bool success = false; - AckType_t savedRetryAck = _retryAck; - - _retryAck = AckNone; - - _ackTimeoutTimer->stop(); - - if (savedRetryAck != expectedAck) { - if (savedRetryAck == AckNone) { - // Don't annoy the user with warnings about unexpected mission commands, just ignore them; ArduPilot updates home position using + if (receivedAck == _expectedAck) { + _expectedAck = AckNone; + _ackTimeoutTimer->stop(); + return true; + } else { + if (_expectedAck == AckNone) { + // Don't worry about unexpected mission commands, just ignore them; ArduPilot updates home position using // spurious MISSION_ITEMs. } else { - _sendError(ProtocolOrderError, QString("Vehicle responded incorrectly to mission item protocol sequence: %1:%2").arg(_ackTypeToString(savedRetryAck)).arg(_ackTypeToString(expectedAck))); - _finishTransaction(false); + // We just warn in this case, this could be crap left over from a previous transaction or the vehicle going bonkers. + // Whatever it is we let the ack timeout handle any error output to the user. + qCDebug(MissionManagerLog) << QString("Out of sequence ack expected:received %1:%2").arg(_ackTypeToString(_expectedAck)).arg(_ackTypeToString(receivedAck)); } - success = false; - } else { - success = true; + return false; } - - return success; } void MissionManager::_readTransactionComplete(void) @@ -251,9 +313,11 @@ void MissionManager::_handleMissionCount(const mavlink_message_t& message) { mavlink_mission_count_t missionCount; - if (!_stopAckTimeout(AckMissionCount)) { + if (!_checkForExpectedAck(AckMissionCount)) { return; } + + _retryCount = 0; mavlink_msg_mission_count_decode(&message, &missionCount); qCDebug(MissionManagerLog) << "_handleMissionCount count:" << missionCount.count; @@ -271,13 +335,13 @@ void MissionManager::_handleMissionCount(const mavlink_message_t& message) void MissionManager::_requestNextMissionItem(void) { - qCDebug(MissionManagerLog) << "_requestNextMissionItem sequenceNumber:" << _itemIndicesToRead[0]; - if (_itemIndicesToRead.count() == 0) { _sendError(InternalError, "Internal Error: Call to Vehicle _requestNextMissionItem with no more indices to read"); return; } - + + qCDebug(MissionManagerLog) << "_requestNextMissionItem sequenceNumber:retry" << _itemIndicesToRead[0] << _retryCount; + mavlink_message_t message; mavlink_mission_request_t missionRequest; @@ -299,7 +363,7 @@ void MissionManager::_handleMissionItem(const mavlink_message_t& message) { mavlink_mission_item_t missionItem; - if (!_stopAckTimeout(AckMissionItem)) { + if (!_checkForExpectedAck(AckMissionItem)) { return; } @@ -308,7 +372,6 @@ void MissionManager::_handleMissionItem(const mavlink_message_t& message) qCDebug(MissionManagerLog) << "_handleMissionItem sequenceNumber:" << missionItem.seq; if (_itemIndicesToRead.contains(missionItem.seq)) { - _requestItemRetryCount = 0; _itemIndicesToRead.removeOne(missionItem.seq); MissionItem* item = new MissionItem(missionItem.seq, @@ -333,13 +396,12 @@ void MissionManager::_handleMissionItem(const mavlink_message_t& message) _missionItems.append(item); } else { qCDebug(MissionManagerLog) << "_handleMissionItem mission item received item index which was not requested, disregrarding:" << missionItem.seq; - if (++_requestItemRetryCount > _maxRetryCount) { - _sendError(RequestRangeError, QString("Vehicle would not send item %1 after max retries. Read from Vehicle failed.").arg(_itemIndicesToRead[0])); - _finishTransaction(false); - return; - } + // We have to put the ack timeout back since it was removed above + _startAckTimeout(AckMissionItem); + return; } + _retryCount = 0; if (_itemIndicesToRead.count() == 0) { _readTransactionComplete(); } else { @@ -357,7 +419,7 @@ void MissionManager::_handleMissionRequest(const mavlink_message_t& message) { mavlink_mission_request_t missionRequest; - if (!_stopAckTimeout(AckMissionRequest)) { + if (!_checkForExpectedAck(AckMissionRequest)) { return; } @@ -411,14 +473,14 @@ void MissionManager::_handleMissionAck(const mavlink_message_t& message) { mavlink_mission_ack_t missionAck; - // Save the retry ack before calling _stopAckTimeout since we'll need it to determine what + // Save the retry ack before calling _checkForExpectedAck since we'll need it to determine what // type of a protocol sequence we are in. - AckType_t savedRetryAck = _retryAck; + AckType_t savedExpectedAck = _expectedAck; // We can get a MISSION_ACK with an error at any time, so if the Acks don't match it is not - // a protocol sequence error. Call _stopAckTimeout with _retryAck so it will succeed no + // a protocol sequence error. Call _checkForExpectedAck with _retryAck so it will succeed no // matter what. - if (!_stopAckTimeout(_retryAck)) { + if (!_checkForExpectedAck(_expectedAck)) { return; } @@ -426,7 +488,7 @@ void MissionManager::_handleMissionAck(const mavlink_message_t& message) qCDebug(MissionManagerLog) << "_handleMissionAck type:" << _missionResultToString((MAV_MISSION_RESULT)missionAck.type); - switch (savedRetryAck) { + switch (savedExpectedAck) { case AckNone: // State machine is idle. Vehicle is confused. _sendError(VehicleError, QString("Vehicle sent unexpected MISSION_ACK message, error: %1").arg(_missionResultToString((MAV_MISSION_RESULT)missionAck.type))); @@ -438,7 +500,7 @@ void MissionManager::_handleMissionAck(const mavlink_message_t& message) break; case AckMissionItem: // MISSION_ITEM expected - _sendError(VehicleError, QString("Vehicle returned error: %1. Partial list of mission items may have been returned.").arg(_missionResultToString((MAV_MISSION_RESULT)missionAck.type))); + _sendError(VehicleError, QString("Vehicle returned error: %1.").arg(_missionResultToString((MAV_MISSION_RESULT)missionAck.type))); _finishTransaction(false); break; case AckMissionRequest: @@ -459,7 +521,7 @@ void MissionManager::_handleMissionAck(const mavlink_message_t& message) case AckGuidedItem: // MISSION_REQUEST is expected, or MISSION_ACK to end sequence if (missionAck.type == MAV_MISSION_ACCEPTED) { - qCDebug(MissionManagerLog) << "_handleMissionAck guide mode item accepted"; + qCDebug(MissionManagerLog) << "_handleMissionAck guided mode item accepted"; _finishTransaction(true); } else { _sendError(VehicleError, QString("Vehicle returned error: %1. Vehicle did not accept guided item.").arg(_missionResultToString((MAV_MISSION_RESULT)missionAck.type))); @@ -587,12 +649,14 @@ void MissionManager::_finishTransaction(bool success) emit newMissionItemsAvailable(); } - _readTransactionInProgress = false; - _writeTransactionInProgress = false; _itemIndicesToRead.clear(); _itemIndicesToWrite.clear(); - emit inProgressChanged(false); + if (_readTransactionInProgress || _writeTransactionInProgress) { + _readTransactionInProgress = false; + _writeTransactionInProgress = false; + emit inProgressChanged(false); + } } bool MissionManager::inProgress(void) diff --git a/src/MissionManager/MissionManager.h b/src/MissionManager/MissionManager.h index 6a4602abeb37bf897667959ebee47083399ce3f7..7e3ce2171f9dff31409adce137d0ae87db689093 100644 --- a/src/MissionManager/MissionManager.h +++ b/src/MissionManager/MissionManager.h @@ -62,7 +62,7 @@ public: } ErrorCode_t; // These values are public so the unit test can set appropriate signal wait times - static const int _ackTimeoutMilliseconds= 2000; + static const int _ackTimeoutMilliseconds = 1000; static const int _maxRetryCount = 5; signals: @@ -85,7 +85,7 @@ private: } AckType_t; void _startAckTimeout(AckType_t ack); - bool _stopAckTimeout(AckType_t expectedAck); + bool _checkForExpectedAck(AckType_t receivedAck); void _readTransactionComplete(void); void _handleMissionCount(const mavlink_message_t& message); void _handleMissionItem(const mavlink_message_t& message); @@ -98,14 +98,16 @@ private: QString _ackTypeToString(AckType_t ackType); QString _missionResultToString(MAV_MISSION_RESULT result); void _finishTransaction(bool success); + void _requestList(void); + void _writeMissionCount(void); private: Vehicle* _vehicle; LinkInterface* _dedicatedLink; QTimer* _ackTimeoutTimer; - AckType_t _retryAck; - int _requestItemRetryCount; + AckType_t _expectedAck; + int _retryCount; bool _readTransactionInProgress; bool _writeTransactionInProgress; diff --git a/src/MissionManager/MissionManagerTest.cc b/src/MissionManager/MissionManagerTest.cc index 35a91d71e17cb1016a89d9cf7c2b7395520e16b5..f6e94581c45a3454a8136dcc78af91cce2f8b3e4 100644 --- a/src/MissionManager/MissionManagerTest.cc +++ b/src/MissionManager/MissionManagerTest.cc @@ -27,7 +27,7 @@ MissionManagerTest::MissionManagerTest(void) } -void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t failureMode) +void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t failureMode, bool shouldFail) { _mockLink->setMissionItemFailureMode(failureMode); @@ -67,29 +67,9 @@ void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t f _multiSpyMissionManager->clearAllSignals(); - if (failureMode == MockLinkMissionItemHandler::FailNone) { - // This should be clean run - - // Wait for write sequence to complete. We should get: - // inProgressChanged(false) signal - _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); - QCOMPARE(_multiSpyMissionManager->checkOnlySignalByMask(inProgressChangedSignalMask), true); - - // Validate inProgressChanged signal value - _checkInProgressValues(false); - - // Validate item count in mission manager - - int expectedCount = (int)_cTestCases; - if (_mockLink->getFirmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { - // Home position at position 0 comes from vehicle - expectedCount++; - } - - QCOMPARE(_missionManager->missionItems().count(), expectedCount); - } else { + if (shouldFail) { // This should be a failed run - + setExpectedMessageBox(QMessageBox::Ok); // Wait for write sequence to complete. We should get: @@ -97,10 +77,10 @@ void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t f // error(errorCode, QString) signal _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); QCOMPARE(_multiSpyMissionManager->checkSignalByMask(inProgressChangedSignalMask | errorSignalMask), true); - + // Validate inProgressChanged signal value _checkInProgressValues(false); - + // Validate error signal values QSignalSpy* spy = _multiSpyMissionManager->getSpyByIndex(errorSignalIndex); QList signalArgs = spy->takeFirst(); @@ -108,14 +88,34 @@ void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t f qDebug() << signalArgs[1].toString(); checkExpectedMessageBox(); + } else { + // This should be clean run + + // Wait for write sequence to complete. We should get: + // inProgressChanged(false) signal + _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); + QCOMPARE(_multiSpyMissionManager->checkOnlySignalByMask(inProgressChangedSignalMask), true); + + // Validate inProgressChanged signal value + _checkInProgressValues(false); + + // Validate item count in mission manager + + int expectedCount = (int)_cTestCases; + if (_mockLink->getFirmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { + // Home position at position 0 comes from vehicle + expectedCount++; + } + + QCOMPARE(_missionManager->missionItems().count(), expectedCount); } _multiSpyMissionManager->clearAllSignals(); } -void MissionManagerTest::_roundTripItems(MockLinkMissionItemHandler::FailureMode_t failureMode) +void MissionManagerTest::_roundTripItems(MockLinkMissionItemHandler::FailureMode_t failureMode, bool shouldFail) { - _writeItems(MockLinkMissionItemHandler::FailNone); + _writeItems(MockLinkMissionItemHandler::FailNone, false); _mockLink->setMissionItemFailureMode(failureMode); @@ -129,19 +129,9 @@ void MissionManagerTest::_roundTripItems(MockLinkMissionItemHandler::FailureMode _multiSpyMissionManager->clearAllSignals(); - if (failureMode == MockLinkMissionItemHandler::FailNone) { - // This should be clean run - - // Now wait for read sequence to complete. We should get: - // inProgressChanged(false) signal to signal completion - // newMissionItemsAvailable signal - _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); - QCOMPARE(_multiSpyMissionManager->checkSignalByMask(newMissionItemsAvailableSignalMask | inProgressChangedSignalMask), true); - _checkInProgressValues(false); - - } else { + if (shouldFail) { // This should be a failed run - + setExpectedMessageBox(QMessageBox::Ok); // Wait for read sequence to complete. We should get: @@ -150,17 +140,26 @@ void MissionManagerTest::_roundTripItems(MockLinkMissionItemHandler::FailureMode // newMissionItemsAvailable signal _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); QCOMPARE(_multiSpyMissionManager->checkSignalByMask(newMissionItemsAvailableSignalMask | inProgressChangedSignalMask | errorSignalMask), true); - + // Validate inProgressChanged signal value _checkInProgressValues(false); - + // Validate error signal values QSignalSpy* spy = _multiSpyMissionManager->getSpyByIndex(errorSignalIndex); QList signalArgs = spy->takeFirst(); QCOMPARE(signalArgs.count(), 2); qDebug() << signalArgs[1].toString(); - + checkExpectedMessageBox(); + } else { + // This should be clean run + + // Now wait for read sequence to complete. We should get: + // inProgressChanged(false) signal to signal completion + // newMissionItemsAvailable signal + _multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime); + QCOMPARE(_multiSpyMissionManager->checkSignalByMask(newMissionItemsAvailableSignalMask | inProgressChangedSignalMask), true); + _checkInProgressValues(false); } _multiSpyMissionManager->clearAllSignals(); @@ -169,14 +168,14 @@ void MissionManagerTest::_roundTripItems(MockLinkMissionItemHandler::FailureMode size_t cMissionItemsExpected; - if (failureMode == MockLinkMissionItemHandler::FailNone) { + if (shouldFail) { + cMissionItemsExpected = 0; + } else { cMissionItemsExpected = (int)_cTestCases; if (_mockLink->getFirmwareType() == MAV_AUTOPILOT_ARDUPILOTMEGA) { // Home position at position 0 comes from vehicle cMissionItemsExpected++; } - } else { - cMissionItemsExpected = 0; } QCOMPARE(_missionManager->missionItems().count(), (int)cMissionItemsExpected); @@ -233,24 +232,27 @@ void MissionManagerTest::_testWriteFailureHandlingWorker(void) typedef struct { const char* failureText; MockLinkMissionItemHandler::FailureMode_t failureMode; - } TestCase_t; + bool shouldFail; + } WriteTestCase_t; - static const TestCase_t rgTestCases[] = { - { "No Failure", MockLinkMissionItemHandler::FailNone }, - { "FailWriteRequest0NoResponse", MockLinkMissionItemHandler::FailWriteRequest0NoResponse }, - { "FailWriteRequest1NoResponse", MockLinkMissionItemHandler::FailWriteRequest1NoResponse }, - { "FailWriteRequest0IncorrectSequence", MockLinkMissionItemHandler::FailWriteRequest0IncorrectSequence }, - { "FailWriteRequest1IncorrectSequence", MockLinkMissionItemHandler::FailWriteRequest1IncorrectSequence }, - { "FailWriteRequest0ErrorAck", MockLinkMissionItemHandler::FailWriteRequest0ErrorAck }, - { "FailWriteRequest1ErrorAck", MockLinkMissionItemHandler::FailWriteRequest1ErrorAck }, - { "FailWriteFinalAckNoResponse", MockLinkMissionItemHandler::FailWriteFinalAckNoResponse }, - { "FailWriteFinalAckErrorAck", MockLinkMissionItemHandler::FailWriteFinalAckErrorAck }, - { "FailWriteFinalAckMissingRequests", MockLinkMissionItemHandler::FailWriteFinalAckMissingRequests }, + static const WriteTestCase_t rgTestCases[] = { + { "No Failure", MockLinkMissionItemHandler::FailNone, false }, + { "FailWriteMissionCountNoResponse", MockLinkMissionItemHandler::FailWriteMissionCountNoResponse, true }, + { "FailWriteMissionCountFirstResponse", MockLinkMissionItemHandler::FailWriteMissionCountFirstResponse, false }, + { "FailWriteRequest1NoResponse", MockLinkMissionItemHandler::FailWriteRequest1NoResponse, true }, + { "FailWriteRequest0IncorrectSequence", MockLinkMissionItemHandler::FailWriteRequest0IncorrectSequence, true }, + { "FailWriteRequest1IncorrectSequence", MockLinkMissionItemHandler::FailWriteRequest1IncorrectSequence, true }, + { "FailWriteRequest0ErrorAck", MockLinkMissionItemHandler::FailWriteRequest0ErrorAck, true }, + { "FailWriteRequest1ErrorAck", MockLinkMissionItemHandler::FailWriteRequest1ErrorAck, true }, + { "FailWriteFinalAckNoResponse", MockLinkMissionItemHandler::FailWriteFinalAckNoResponse, true }, + { "FailWriteFinalAckErrorAck", MockLinkMissionItemHandler::FailWriteFinalAckErrorAck, true }, + { "FailWriteFinalAckMissingRequests", MockLinkMissionItemHandler::FailWriteFinalAckMissingRequests, true }, }; for (size_t i=0; ifailureText; + _writeItems(pCase->failureMode, pCase->shouldFail); _mockLink->resetMissionItemHandler(); } } @@ -271,22 +273,31 @@ void MissionManagerTest::_testReadFailureHandlingWorker(void) typedef struct { const char* failureText; MockLinkMissionItemHandler::FailureMode_t failureMode; - } TestCase_t; + bool shouldFail; + } ReadTestCase_t; - static const TestCase_t rgTestCases[] = { - { "No Failure", MockLinkMissionItemHandler::FailNone }, - { "FailReadRequestListNoResponse", MockLinkMissionItemHandler::FailReadRequestListNoResponse }, - { "FailReadRequest0NoResponse", MockLinkMissionItemHandler::FailReadRequest0NoResponse }, - { "FailReadRequest1NoResponse", MockLinkMissionItemHandler::FailReadRequest1NoResponse }, - { "FailReadRequest0IncorrectSequence", MockLinkMissionItemHandler::FailReadRequest0IncorrectSequence }, - { "FailReadRequest1IncorrectSequence", MockLinkMissionItemHandler::FailReadRequest1IncorrectSequence }, - { "FailReadRequest0ErrorAck", MockLinkMissionItemHandler::FailReadRequest0ErrorAck }, - { "FailReadRequest1ErrorAck", MockLinkMissionItemHandler::FailReadRequest1ErrorAck }, + /* + static const ReadTestCase_t rgTestCases[] = { + { "FailReadRequest1FirstResponse", MockLinkMissionItemHandler::FailReadRequest1FirstResponse, false }, + };*/ + + static const ReadTestCase_t rgTestCases[] = { + { "No Failure", MockLinkMissionItemHandler::FailNone, false }, + { "FailReadRequestListNoResponse", MockLinkMissionItemHandler::FailReadRequestListNoResponse, true }, + { "FailReadRequestListFirstResponse", MockLinkMissionItemHandler::FailReadRequestListFirstResponse, false }, + { "FailReadRequest0NoResponse", MockLinkMissionItemHandler::FailReadRequest0NoResponse, true }, + { "FailReadRequest1NoResponse", MockLinkMissionItemHandler::FailReadRequest1NoResponse, true }, + { "FailReadRequest1FirstResponse", MockLinkMissionItemHandler::FailReadRequest1FirstResponse, false }, + { "FailReadRequest0IncorrectSequence", MockLinkMissionItemHandler::FailReadRequest0IncorrectSequence, true }, + { "FailReadRequest1IncorrectSequence", MockLinkMissionItemHandler::FailReadRequest1IncorrectSequence, true }, + { "FailReadRequest0ErrorAck", MockLinkMissionItemHandler::FailReadRequest0ErrorAck, true }, + { "FailReadRequest1ErrorAck", MockLinkMissionItemHandler::FailReadRequest1ErrorAck, true }, }; - + for (size_t i=0; ifailureText; + _roundTripItems(pCase->failureMode, pCase->shouldFail); _mockLink->resetMissionItemHandler(); _multiSpyMissionManager->clearAllSignals(); } diff --git a/src/MissionManager/MissionManagerTest.h b/src/MissionManager/MissionManagerTest.h index 03cfd07ab61db1f3a297ae3a54c93b9d18203f47..e8bd7a5970f4536a933df45b91bb5926667656e4 100644 --- a/src/MissionManager/MissionManagerTest.h +++ b/src/MissionManager/MissionManagerTest.h @@ -33,13 +33,13 @@ private slots: void _testReadFailureHandlingAPM(void); private: - void _roundTripItems(MockLinkMissionItemHandler::FailureMode_t failureMode); - void _writeItems(MockLinkMissionItemHandler::FailureMode_t failureMode); + void _roundTripItems(MockLinkMissionItemHandler::FailureMode_t failureMode, bool shouldFail); + void _writeItems(MockLinkMissionItemHandler::FailureMode_t failureMode, bool shouldFail); void _testWriteFailureHandlingWorker(void); void _testReadFailureHandlingWorker(void); - static const MissionControllerManagerTest::TestCase_t _rgTestCases[]; - static const size_t _cTestCases; + static const TestCase_t _rgTestCases[]; + static const size_t _cTestCases; }; #endif diff --git a/src/MissionManager/PlanElementController.cc b/src/MissionManager/PlanElementController.cc index c384d259e9999e6d0cad14a7f02acb608764e37c..a904796dbd7d5d3eb44ccd2a26c4388ef3b152ed 100644 --- a/src/MissionManager/PlanElementController.cc +++ b/src/MissionManager/PlanElementController.cc @@ -32,6 +32,12 @@ void PlanElementController::start(bool editMode) _activeVehicleChanged(_multiVehicleMgr->activeVehicle()); } +void PlanElementController::startStaticActiveVehicle(Vehicle* vehicle) +{ + _editMode = false; + _activeVehicleChanged(vehicle); +} + void PlanElementController::_activeVehicleChanged(Vehicle* activeVehicle) { if (_activeVehicle) { @@ -48,4 +54,6 @@ void PlanElementController::_activeVehicleChanged(Vehicle* activeVehicle) // Whenever vehicle changes we need to update syncInProgress emit syncInProgressChanged(syncInProgress()); + + emit vehicleChanged(_activeVehicle); } diff --git a/src/MissionManager/PlanElementController.h b/src/MissionManager/PlanElementController.h index 63c4abe3558db73ab4440fe98e8932de15ee3008..a498d07d6c2fe0aaf5320dfae9cde2db70f3a193 100644 --- a/src/MissionManager/PlanElementController.h +++ b/src/MissionManager/PlanElementController.h @@ -35,10 +35,16 @@ public: Q_PROPERTY(QString fileExtension READ fileExtension CONSTANT) virtual QString fileExtension(void) const = 0; + Q_PROPERTY(Vehicle* vehicle READ vehicle NOTIFY vehicleChanged) + /// Should be called immediately upon Component.onCompleted. /// @param editMode true: controller being used in Plan view, false: controller being used in Fly view Q_INVOKABLE virtual void start(bool editMode); + /// Starts the controller using a single static active vehicle. Will not track global active vehicle changes. + /// @param editMode true: controller being used in Plan view, false: controller being used in Fly view + Q_INVOKABLE virtual void startStaticActiveVehicle(Vehicle* vehicle); + Q_INVOKABLE virtual void loadFromVehicle(void) = 0; Q_INVOKABLE virtual void sendToVehicle(void) = 0; Q_INVOKABLE virtual void loadFromFilePicker(void) = 0; @@ -51,9 +57,12 @@ public: virtual bool dirty (void) const = 0; virtual void setDirty (bool dirty) = 0; + Vehicle* vehicle(void) { return _activeVehicle; } + signals: void syncInProgressChanged (bool syncInProgress); void dirtyChanged (bool dirty); + void vehicleChanged (Vehicle* vehicle); protected: MultiVehicleManager* _multiVehicleMgr; diff --git a/src/MissionManager/RallyPointController.cc b/src/MissionManager/RallyPointController.cc index e924c2531f7414f671e875dabef395cea5bba263..adc43f62fb958dbca3a72df5167c2e6af5e8d859 100644 --- a/src/MissionManager/RallyPointController.cc +++ b/src/MissionManager/RallyPointController.cc @@ -20,6 +20,8 @@ #include "ParameterManager.h" #include "JsonHelper.h" #include "SimpleMissionItem.h" +#include "QGroundControlQmlGlobal.h" +#include "SettingsManager.h" #ifndef __mobile__ #include "QGCFileDialog.h" @@ -46,13 +48,6 @@ RallyPointController::~RallyPointController() } -void RallyPointController::start(bool editMode) -{ - qCDebug(RallyPointControllerLog) << "start editMode" << editMode; - - PlanElementController::start(editMode); -} - void RallyPointController::_activeVehicleBeingRemoved(void) { _activeVehicle->rallyPointManager()->disconnect(this); @@ -75,8 +70,13 @@ bool RallyPointController::_loadJsonFile(QJsonDocument& jsonDoc, QString& errorS { QJsonObject json = jsonDoc.object(); - int fileMajorVersion, fileMinorVersion; - if (!JsonHelper::validateQGCJsonFile(json, _jsonFileTypeValue, 1 /* supportedMajorVersion */, 0 /* supportedMinorVersion */, fileMajorVersion, fileMinorVersion, errorString)) { + int fileVersion; + if (!JsonHelper::validateQGCJsonFile(json, + _jsonFileTypeValue, // expected file type + 1, // minimum supported version + 1, // maximum supported version + fileVersion, + errorString)) { return false; } @@ -113,7 +113,7 @@ void RallyPointController::loadFromFile(const QString& filename) QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - errorString = file.errorString(); + errorString = file.errorString() + QStringLiteral(" ") + filename; } else { QJsonDocument jsonDoc; QByteArray bytes = file.readAll(); @@ -166,7 +166,7 @@ void RallyPointController::saveToFile(const QString& filename) QJsonObject jsonObject; jsonObject[JsonHelper::jsonFileTypeKey] = _jsonFileTypeValue; - jsonObject[JsonHelper::jsonVersionKey] = QStringLiteral("1.0"); + jsonObject[JsonHelper::jsonVersionKey] = 1; jsonObject[JsonHelper::jsonGroundStationKey] = JsonHelper::jsonGroundStationValue; QJsonArray rgPoints; @@ -254,6 +254,7 @@ void RallyPointController::_loadComplete(const QList rgPoints) _points.swapObjectList(pointList); setDirty(false); _setFirstPointCurrent(); + emit loadComplete(); } QString RallyPointController::fileExtension(void) const @@ -267,7 +268,7 @@ void RallyPointController::addPoint(QGeoCoordinate point) if (_points.count()) { defaultAlt = qobject_cast(_points[_points.count() - 1])->coordinate().altitude(); } else { - defaultAlt = SimpleMissionItem::defaultAltitude; + defaultAlt = qgcApp()->toolbox()->settingsManager()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble(); } point.setAltitude(defaultAlt); RallyPoint* newPoint = new RallyPoint(point, this); diff --git a/src/MissionManager/RallyPointController.h b/src/MissionManager/RallyPointController.h index 7ac1af8be575a9edb11b66bbf04e0ee68a3d7b2c..1c040a689efdc1fcf127481fb3c7bae41ee7b904 100644 --- a/src/MissionManager/RallyPointController.h +++ b/src/MissionManager/RallyPointController.h @@ -37,7 +37,6 @@ public: Q_INVOKABLE void addPoint(QGeoCoordinate point); Q_INVOKABLE void removePoint(QObject* rallyPoint); - void start (bool editMode) final; void loadFromVehicle (void) final; void sendToVehicle (void) final; void loadFromFilePicker (void) final; @@ -61,6 +60,7 @@ public: signals: void rallyPointsSupportedChanged(bool rallyPointsSupported); void currentRallyPointChanged(QObject* rallyPoint); + void loadComplete(void); private slots: void _loadComplete(const QList rgPoints); diff --git a/src/MissionManager/RallyPointManager.cc b/src/MissionManager/RallyPointManager.cc index 2698fc5df512cb9fb20de36a17ef3374df7e0b45..ba92da6a14bf18a6a63dabe71f76be0ef3b7b2dd 100644 --- a/src/MissionManager/RallyPointManager.cc +++ b/src/MissionManager/RallyPointManager.cc @@ -34,7 +34,7 @@ void RallyPointManager::_sendError(ErrorCode_t errorCode, const QString& errorMs void RallyPointManager::loadFromVehicle(void) { // No support in generic vehicle - loadComplete(QList()); + emit loadComplete(QList()); } void RallyPointManager::sendToVehicle(const QList& rgPoints) diff --git a/src/MissionManager/SimpleMissionItem.cc b/src/MissionManager/SimpleMissionItem.cc index 35614a1eb5fc562f3b2d2e888e4273cd41ff194e..d206a0595dfbcc6fdf598691dbe51b46e5f16e1d 100644 --- a/src/MissionManager/SimpleMissionItem.cc +++ b/src/MissionManager/SimpleMissionItem.cc @@ -17,15 +17,15 @@ #include "JsonHelper.h" #include "MissionCommandTree.h" #include "MissionCommandUIInfo.h" +#include "QGroundControlQmlGlobal.h" +#include "SettingsManager.h" -const double SimpleMissionItem::defaultAltitude = 50.0; - -FactMetaData* SimpleMissionItem::_altitudeMetaData = NULL; -FactMetaData* SimpleMissionItem::_commandMetaData = NULL; -FactMetaData* SimpleMissionItem::_defaultParamMetaData = NULL; -FactMetaData* SimpleMissionItem::_frameMetaData = NULL; -FactMetaData* SimpleMissionItem::_latitudeMetaData = NULL; -FactMetaData* SimpleMissionItem::_longitudeMetaData = NULL; +FactMetaData* SimpleMissionItem::_altitudeMetaData = NULL; +FactMetaData* SimpleMissionItem::_commandMetaData = NULL; +FactMetaData* SimpleMissionItem::_defaultParamMetaData = NULL; +FactMetaData* SimpleMissionItem::_frameMetaData = NULL; +FactMetaData* SimpleMissionItem::_latitudeMetaData = NULL; +FactMetaData* SimpleMissionItem::_longitudeMetaData = NULL; struct EnumInfo_s { const char * label; @@ -65,12 +65,16 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, QObject* parent) , _syncingAltitudeRelativeToHomeAndFrame (false) , _syncingHeadingDegreesAndParam4 (false) { + _editorQml = QStringLiteral("qrc:/qml/SimpleItemEditor.qml"); + _altitudeRelativeToHomeFact.setRawValue(true); _setupMetaData(); _connectSignals(); setDefaultsForCommand(); + + connect(&_missionItem, &MissionItem::flightSpeedChanged, this, &SimpleMissionItem::flightSpeedChanged); } SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, const MissionItem& missionItem, QObject* parent) @@ -93,6 +97,8 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, const MissionItem& missio , _syncingAltitudeRelativeToHomeAndFrame (false) , _syncingHeadingDegreesAndParam4 (false) { + _editorQml = QStringLiteral("qrc:/qml/SimpleItemEditor.qml"); + _altitudeRelativeToHomeFact.setRawValue(true); _setupMetaData(); @@ -118,6 +124,8 @@ SimpleMissionItem::SimpleMissionItem(const SimpleMissionItem& other, QObject* pa , _syncingAltitudeRelativeToHomeAndFrame (false) , _syncingHeadingDegreesAndParam4 (false) { + _editorQml = QStringLiteral("qrc:/qml/SimpleItemEditor.qml"); + _setupMetaData(); _connectSignals(); @@ -248,9 +256,9 @@ bool SimpleMissionItem::load(QTextStream &loadStream) return _missionItem.load(loadStream); } -bool SimpleMissionItem::load(const QJsonObject& json, QString& errorString) +bool SimpleMissionItem::load(const QJsonObject& json, int sequenceNumber, QString& errorString) { - return _missionItem.load(json, errorString); + return _missionItem.load(json, sequenceNumber, errorString); } bool SimpleMissionItem::isStandaloneCoordinate(void) const @@ -526,7 +534,7 @@ void SimpleMissionItem::_syncFrameToAltitudeRelativeToHome(void) void SimpleMissionItem::setDefaultsForCommand(void) { // We set these global defaults first, then if there are param defaults they will get reset - _missionItem.setParam7(defaultAltitude); + _missionItem.setParam7(qgcApp()->toolbox()->settingsManager()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble()); MAV_CMD command = (MAV_CMD)this->command(); const MissionCommandUIInfo* uiInfo = _commandTree->getUIInfo(_vehicle, command); @@ -607,3 +615,8 @@ void SimpleMissionItem::setSequenceNumber(int sequenceNumber) emit abbreviationChanged(); } } + +double SimpleMissionItem::flightSpeed(void) +{ + return missionItem().flightSpeed(); +} diff --git a/src/MissionManager/SimpleMissionItem.h b/src/MissionManager/SimpleMissionItem.h index a079478b24bf34f90ee507077ebacf756e130e93..e3d508ae92d458531494095c7a5cf1864a1cfd8f 100644 --- a/src/MissionManager/SimpleMissionItem.h +++ b/src/MissionManager/SimpleMissionItem.h @@ -71,12 +71,10 @@ public: void setDistance (double distance); bool load(QTextStream &loadStream); - bool load(const QJsonObject& json, QString& errorString); + bool load(const QJsonObject& json, int sequenceNumber, QString& errorString); bool relativeAltitude(void) { return _missionItem.frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT; } - static const double defaultAltitude; - MissionItem& missionItem(void) { return _missionItem; } // Overrides from VisualMissionItem @@ -91,6 +89,7 @@ public: QGeoCoordinate coordinate (void) const final { return _missionItem.coordinate(); } QGeoCoordinate exitCoordinate (void) const final { return coordinate(); } int sequenceNumber (void) const final { return _missionItem.sequenceNumber(); } + double flightSpeed (void) final; bool coordinateHasRelativeAltitude (void) const final { return _missionItem.relativeAltitude(); } bool exitCoordinateHasRelativeAltitude (void) const final { return coordinateHasRelativeAltitude(); } diff --git a/src/MissionManager/SimpleMissionItemTest.cc b/src/MissionManager/SimpleMissionItemTest.cc index 097fbec3d302fd4b5784dd37a99d3d0603d924ff..3339cedbcfcf2942abb50ad7d2d4c6e163a9c75b 100644 --- a/src/MissionManager/SimpleMissionItemTest.cc +++ b/src/MissionManager/SimpleMissionItemTest.cc @@ -11,6 +11,8 @@ #include "SimpleMissionItemTest.h" #include "SimpleMissionItem.h" #include "QGCApplication.h" +#include "QGroundControlQmlGlobal.h" +#include "SettingsManager.h" const SimpleMissionItemTest::ItemInfo_t SimpleMissionItemTest::_rgItemInfo[] = { { MAV_CMD_NAV_WAYPOINT, MAV_FRAME_GLOBAL_RELATIVE_ALT }, @@ -139,7 +141,7 @@ void SimpleMissionItemTest::_testDefaultValues(void) item.missionItem().setCommand(MAV_CMD_NAV_WAYPOINT); item.missionItem().setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT); - QCOMPARE(item.missionItem().param7(), SimpleMissionItem::defaultAltitude); + QCOMPARE(item.missionItem().param7(), qgcApp()->toolbox()->settingsManager()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble()); } void SimpleMissionItemTest::_testSignals(void) @@ -224,7 +226,7 @@ void SimpleMissionItemTest::_testSignals(void) // dirtyChanged // Check that changing to the same coordinate does not signal - simpleMissionItem.setCoordinate(QGeoCoordinate(50.1234567, 60.1234567, SimpleMissionItem::defaultAltitude)); + simpleMissionItem.setCoordinate(QGeoCoordinate(50.1234567, 60.1234567, qgcApp()->toolbox()->settingsManager()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble())); QVERIFY(multiSpy->checkNoSignals()); // Check that actually changing coordinate signals correctly diff --git a/src/MissionManager/SurveyMissionItem.cc b/src/MissionManager/SurveyMissionItem.cc index aae975f13fed8d193a9a8cd65f78c51555981fbb..954fc3cf2ac97451df1b5f5185f6e3a46ba5c960 100644 --- a/src/MissionManager/SurveyMissionItem.cc +++ b/src/MissionManager/SurveyMissionItem.cc @@ -12,14 +12,15 @@ #include "JsonHelper.h" #include "MissionController.h" #include "QGCGeo.h" +#include "QGroundControlQmlGlobal.h" #include QGC_LOGGING_CATEGORY(SurveyMissionItemLog, "SurveyMissionItemLog") -const char* SurveyMissionItem::_jsonTypeKey = "type"; +const char* SurveyMissionItem::jsonComplexItemTypeValue = "survey"; + const char* SurveyMissionItem::_jsonPolygonObjectKey = "polygon"; -const char* SurveyMissionItem::_jsonIdKey = "id"; const char* SurveyMissionItem::_jsonGridObjectKey = "grid"; const char* SurveyMissionItem::_jsonGridAltitudeKey = "altitude"; const char* SurveyMissionItem::_jsonGridAltitudeRelativeKey = "relativeAltitude"; @@ -30,7 +31,7 @@ const char* SurveyMissionItem::_jsonCameraTriggerKey = "cameraTrigg const char* SurveyMissionItem::_jsonCameraTriggerDistanceKey = "cameraTriggerDistance"; const char* SurveyMissionItem::_jsonGroundResolutionKey = "groundResolution"; const char* SurveyMissionItem::_jsonFrontalOverlapKey = "imageFrontalOverlap"; -const char* SurveyMissionItem::_jsonSideOverlapKey = "imageSizeOverlap"; +const char* SurveyMissionItem::_jsonSideOverlapKey = "imageSideOverlap"; const char* SurveyMissionItem::_jsonCameraSensorWidthKey = "sensorWidth"; const char* SurveyMissionItem::_jsonCameraSensorHeightKey = "sensorHeight"; const char* SurveyMissionItem::_jsonCameraResolutionWidthKey = "resolutionWidth"; @@ -56,8 +57,6 @@ const char* SurveyMissionItem::_cameraResolutionWidthFactName = "Camera reso const char* SurveyMissionItem::_cameraResolutionHeightFactName = "Camera resolution height"; const char* SurveyMissionItem::_cameraFocalLengthFactName = "Focal length"; -const char* SurveyMissionItem::_complexType = "survey"; - QMap SurveyMissionItem::_metaDataMap; SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent) @@ -72,6 +71,7 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent) , _surveyDistance(0.0) , _cameraShots(0) , _coveredArea(0.0) + , _timeBetweenShots(0.0) , _gridAltitudeFact (0, _gridAltitudeFactName, FactMetaData::valueTypeDouble) , _gridAngleFact (0, _gridAngleFactName, FactMetaData::valueTypeDouble) , _gridSpacingFact (0, _gridSpacingFactName, FactMetaData::valueTypeDouble) @@ -86,6 +86,8 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent) , _cameraResolutionHeightFact (0, _cameraResolutionHeightFactName, FactMetaData::valueTypeUint32) , _cameraFocalLengthFact (0, _cameraFocalLengthFactName, FactMetaData::valueTypeDouble) { + _editorQml = "qrc:/qml/SurveyItemEditor.qml"; + if (_metaDataMap.isEmpty()) { _metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/Survey.FactMetaData.json"), NULL /* metaDataParent */); } @@ -134,7 +136,15 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent) connect(&_cameraResolutionHeightFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged); connect(&_cameraFocalLengthFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged); - connect(this, &SurveyMissionItem::cameraTriggerChanged, this, &SurveyMissionItem::_cameraTriggerChanged); + connect(this, &SurveyMissionItem::cameraTriggerChanged, this, &SurveyMissionItem::_cameraTriggerChanged); + + connect(&_cameraTriggerDistanceFact, &Fact::valueChanged, this, &SurveyMissionItem::timeBetweenShotsChanged); + + // NULL check since object creation during unit testing passes NULL for vehicle + if (_vehicle) { + connect(_vehicle, &Vehicle::cruiseSpeedChanged, this, &SurveyMissionItem::timeBetweenShotsChanged); + connect(_vehicle, &Vehicle::hoverSpeedChanged, this, &SurveyMissionItem::timeBetweenShotsChanged); + } } void SurveyMissionItem::_setSurveyDistance(double surveyDistance) @@ -239,12 +249,12 @@ void SurveyMissionItem::setDirty(bool dirty) void SurveyMissionItem::save(QJsonObject& saveObject) const { - saveObject[JsonHelper::jsonVersionKey] = 2; - saveObject[_jsonTypeKey] = _complexType; - saveObject[_jsonIdKey] = sequenceNumber(); - saveObject[_jsonCameraTriggerKey] = _cameraTrigger; - saveObject[_jsonManualGridKey] = _manualGrid; - saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitude; + saveObject[JsonHelper::jsonVersionKey] = 3; + saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; + saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; + saveObject[_jsonCameraTriggerKey] = _cameraTrigger; + saveObject[_jsonManualGridKey] = _manualGrid; + saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitude; if (_cameraTrigger) { saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble(); @@ -306,98 +316,114 @@ void SurveyMissionItem::_clear(void) } -bool SurveyMissionItem::load(const QJsonObject& complexObject, QString& errorString) +bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumber, QString& errorString) { - struct jsonKeyInfo_s { - const char* key; - QJsonValue::Type type; - bool required; - }; + QJsonObject v2Object = complexObject; - QList mainKeyInfoList = { - { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, - { _jsonTypeKey, QJsonValue::String, true }, - { _jsonPolygonObjectKey, QJsonValue::Array, true }, - { _jsonIdKey, QJsonValue::Double, true }, - { _jsonGridObjectKey, QJsonValue::Object, true }, - { _jsonCameraObjectKey, QJsonValue::Object, false }, - { _jsonCameraTriggerKey, QJsonValue::Bool, true }, - { _jsonCameraTriggerDistanceKey, QJsonValue::Double, false }, - { _jsonManualGridKey, QJsonValue::Bool, true }, - { _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true }, + // We need to pull version first to determine what validation/conversion needs to be performed. + QList versionKeyInfoList = { + { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, }; - - QList gridKeyInfoList = { - { _jsonGridAltitudeKey, QJsonValue::Double, true }, - { _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true }, - { _jsonGridAngleKey, QJsonValue::Double, true }, - { _jsonGridSpacingKey, QJsonValue::Double, true }, - { _jsonTurnaroundDistKey, QJsonValue::Double, true }, - }; - - QList cameraKeyInfoList = { - { _jsonGroundResolutionKey, QJsonValue::Double, true }, - { _jsonFrontalOverlapKey, QJsonValue::Double, true }, - { _jsonSideOverlapKey, QJsonValue::Double, true }, - { _jsonCameraSensorWidthKey, QJsonValue::Double, true }, - { _jsonCameraSensorHeightKey, QJsonValue::Double, true }, - { _jsonCameraResolutionWidthKey, QJsonValue::Double, true }, - { _jsonCameraResolutionHeightKey, QJsonValue::Double, true }, - { _jsonCameraFocalLengthKey, QJsonValue::Double, true }, - { _jsonCameraNameKey, QJsonValue::String, true }, - { _jsonCameraOrientationLandscapeKey, QJsonValue::Bool, true }, - }; - - if (!JsonHelper::validateKeys(complexObject, mainKeyInfoList, errorString)) { + if (!JsonHelper::validateKeys(v2Object, versionKeyInfoList, errorString)) { return false; } - if (!JsonHelper::validateKeys(complexObject[_jsonGridObjectKey].toObject(), gridKeyInfoList, errorString)) { + + int version = v2Object[JsonHelper::jsonVersionKey].toInt(); + if (version != 2 && version != 3) { + errorString = tr("QGroundControl does not support this version of survey items"); return false; } + if (version == 2) { + // Convert to v3 + if (v2Object.contains(VisualMissionItem::jsonTypeKey) && v2Object[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("survey")) { + v2Object[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; + v2Object[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; + } + } - // Version check - if (complexObject[JsonHelper::jsonVersionKey].toInt() != 2) { - errorString = tr("QGroundControl does not support this version of survey items"); + QList mainKeyInfoList = { + { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, + { VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, + { ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true }, + { _jsonPolygonObjectKey, QJsonValue::Array, true }, + { _jsonGridObjectKey, QJsonValue::Object, true }, + { _jsonCameraObjectKey, QJsonValue::Object, false }, + { _jsonCameraTriggerKey, QJsonValue::Bool, true }, + { _jsonCameraTriggerDistanceKey, QJsonValue::Double, false }, + { _jsonManualGridKey, QJsonValue::Bool, true }, + { _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true }, + }; + if (!JsonHelper::validateKeys(v2Object, mainKeyInfoList, errorString)) { return false; } - QString complexType = complexObject[_jsonTypeKey].toString(); - if (complexType != _complexType) { - errorString = tr("QGroundControl does not support loading this complex mission item type: %1").arg(complexType); + + QString itemType = v2Object[VisualMissionItem::jsonTypeKey].toString(); + QString complexType = v2Object[ComplexMissionItem::jsonComplexItemTypeKey].toString(); + if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) { + errorString = tr("QGroundControl does not support loading this complex mission item type: %1:2").arg(itemType).arg(complexType); return false; } _clear(); - setSequenceNumber(complexObject[_jsonIdKey].toInt()); + setSequenceNumber(sequenceNumber); - _manualGrid = complexObject[_jsonManualGridKey].toBool(true); - _cameraTrigger = complexObject[_jsonCameraTriggerKey].toBool(false); - _fixedValueIsAltitude = complexObject[_jsonFixedValueIsAltitudeKey].toBool(true); - _gridAltitudeRelative = complexObject[_jsonGridAltitudeRelativeKey].toBool(true); - - QJsonObject gridObject = complexObject[_jsonGridObjectKey].toObject(); + _manualGrid = v2Object[_jsonManualGridKey].toBool(true); + _cameraTrigger = v2Object[_jsonCameraTriggerKey].toBool(false); + _fixedValueIsAltitude = v2Object[_jsonFixedValueIsAltitudeKey].toBool(true); + _gridAltitudeRelative = v2Object[_jsonGridAltitudeRelativeKey].toBool(true); + QList gridKeyInfoList = { + { _jsonGridAltitudeKey, QJsonValue::Double, true }, + { _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true }, + { _jsonGridAngleKey, QJsonValue::Double, true }, + { _jsonGridSpacingKey, QJsonValue::Double, true }, + { _jsonTurnaroundDistKey, QJsonValue::Double, true }, + }; + QJsonObject gridObject = v2Object[_jsonGridObjectKey].toObject(); + if (!JsonHelper::validateKeys(gridObject, gridKeyInfoList, errorString)) { + return false; + } _gridAltitudeFact.setRawValue (gridObject[_jsonGridAltitudeKey].toDouble()); _gridAngleFact.setRawValue (gridObject[_jsonGridAngleKey].toDouble()); _gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble()); _turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble()); if (_cameraTrigger) { - if (!complexObject.contains(_jsonCameraTriggerDistanceKey)) { + if (!v2Object.contains(_jsonCameraTriggerDistanceKey)) { errorString = tr("%1 but %2 is missing").arg("cameraTrigger = true").arg("cameraTriggerDistance"); return false; } - _cameraTriggerDistanceFact.setRawValue(complexObject[_jsonCameraTriggerDistanceKey].toDouble()); + _cameraTriggerDistanceFact.setRawValue(v2Object[_jsonCameraTriggerDistanceKey].toDouble()); } if (!_manualGrid) { - if (!complexObject.contains(_jsonCameraObjectKey)) { + if (!v2Object.contains(_jsonCameraObjectKey)) { errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera"); return false; } - QJsonObject cameraObject = complexObject[_jsonCameraObjectKey].toObject(); + QJsonObject cameraObject = v2Object[_jsonCameraObjectKey].toObject(); + // Older code had typo on "imageSideOverlap" incorrectly being "imageSizeOverlap" + QString incorrectImageSideOverlap = "imageSizeOverlap"; + if (cameraObject.contains(incorrectImageSideOverlap)) { + cameraObject[_jsonSideOverlapKey] = cameraObject[incorrectImageSideOverlap]; + cameraObject.remove(incorrectImageSideOverlap); + } + + QList cameraKeyInfoList = { + { _jsonGroundResolutionKey, QJsonValue::Double, true }, + { _jsonFrontalOverlapKey, QJsonValue::Double, true }, + { _jsonSideOverlapKey, QJsonValue::Double, true }, + { _jsonCameraSensorWidthKey, QJsonValue::Double, true }, + { _jsonCameraSensorHeightKey, QJsonValue::Double, true }, + { _jsonCameraResolutionWidthKey, QJsonValue::Double, true }, + { _jsonCameraResolutionHeightKey, QJsonValue::Double, true }, + { _jsonCameraFocalLengthKey, QJsonValue::Double, true }, + { _jsonCameraNameKey, QJsonValue::String, true }, + { _jsonCameraOrientationLandscapeKey, QJsonValue::Bool, true }, + }; if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) { return false; } @@ -416,7 +442,7 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, QString& errorStr } // Polygon shape - QJsonArray polygonArray(complexObject[_jsonPolygonObjectKey].toArray()); + QJsonArray polygonArray(v2Object[_jsonPolygonObjectKey].toArray()); for (int i=0; iappend(item); if (_cameraTrigger && i == 0) { + // Turn on camera MissionItem* item = new MissionItem(seqNum++, // sequence number MAV_CMD_DO_SET_CAM_TRIGG_DIST, // MAV_CMD MAV_FRAME_MISSION, // MAV_FRAME @@ -779,6 +806,7 @@ QmlObjectListModel* SurveyMissionItem::getMissionItems(void) const } if (_cameraTrigger) { + // Turn off camera MissionItem* item = new MissionItem(seqNum++, // sequence number MAV_CMD_DO_SET_CAM_TRIGG_DIST, // MAV_CMD MAV_FRAME_MISSION, // MAV_FRAME @@ -796,10 +824,9 @@ QmlObjectListModel* SurveyMissionItem::getMissionItems(void) const void SurveyMissionItem::_cameraTriggerChanged(void) { setDirty(true); - if (_gridPoints.count()) { - // If we have grid turn on/off camera trigger will add/remove two camera trigger mission items - emit lastSequenceNumberChanged(lastSequenceNumber()); - } + // Camera trigger adds items + emit lastSequenceNumberChanged(lastSequenceNumber()); + // We now have camera shot count emit cameraShotsChanged(cameraShots()); } @@ -812,3 +839,16 @@ void SurveyMissionItem::_cameraValueChanged(void) { emit cameraValueChanged(); } + +double SurveyMissionItem::timeBetweenShots(void) const +{ + return _cruiseSpeed == 0 ? 0 : _cameraTriggerDistanceFact.rawValue().toDouble() / _cruiseSpeed; +} + +void SurveyMissionItem::setCruiseSpeed(double cruiseSpeed) +{ + if (!qFuzzyCompare(_cruiseSpeed, cruiseSpeed)) { + _cruiseSpeed = cruiseSpeed; + emit timeBetweenShotsChanged(); + } +} diff --git a/src/MissionManager/SurveyMissionItem.h b/src/MissionManager/SurveyMissionItem.h index 58bed7eaace2908a3b02e6dbd99506baa90eb8fd..6ad612d57eccef3417f2d68863c11650f546add8 100644 --- a/src/MissionManager/SurveyMissionItem.h +++ b/src/MissionManager/SurveyMissionItem.h @@ -48,6 +48,7 @@ public: Q_PROPERTY(bool cameraOrientationLandscape MEMBER _cameraOrientationLandscape NOTIFY cameraOrientationLandscapeChanged) Q_PROPERTY(bool manualGrid MEMBER _manualGrid NOTIFY manualGridChanged) Q_PROPERTY(QString camera MEMBER _camera NOTIFY cameraChanged) + Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged) Q_INVOKABLE void clearPolygon(void); Q_INVOKABLE void addPolygonCoordinate(const QGeoCoordinate coordinate); @@ -72,14 +73,18 @@ public: int cameraShots(void) const; double coveredArea(void) const { return _coveredArea; } + double timeBetweenShots(void) const; // Overrides from ComplexMissionItem double complexDistance (void) const final { return _surveyDistance; } int lastSequenceNumber (void) const final; QmlObjectListModel* getMissionItems (void) const final; - bool load (const QJsonObject& complexObject, QString& errorString) final; + bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final; double greatestDistanceTo (const QGeoCoordinate &other) const final; + void setCruiseSpeed (double cruiseSpeed) final; + QString mapVisualQML (void) const final { return QStringLiteral("SurveyComplexItem.qml"); } + // Overrides from VisualMissionItem @@ -93,6 +98,7 @@ public: QGeoCoordinate coordinate (void) const final { return _coordinate; } QGeoCoordinate exitCoordinate (void) const final { return _exitCoordinate; } int sequenceNumber (void) const final { return _sequenceNumber; } + double flightSpeed (void) final { return std::numeric_limits::quiet_NaN(); } bool coordinateHasRelativeAltitude (void) const final { return _gridAltitudeRelative; } bool exitCoordinateHasRelativeAltitude (void) const final { return _gridAltitudeRelative; } @@ -104,6 +110,8 @@ public: void setTurnaroundDist (double dist) { _turnaroundDistFact.setRawValue(dist); } void save (QJsonObject& saveObject) const final; + static const char* jsonComplexItemTypeValue; + signals: void polygonPathChanged (void); void altitudeChanged (double altitude); @@ -119,6 +127,7 @@ signals: void cameraOrientationLandscapeChanged (bool cameraOrientationLandscape); void cameraChanged (QString camera); void manualGridChanged (bool manualGrid); + void timeBetweenShotsChanged (void); private slots: void _cameraTriggerChanged(void); @@ -156,6 +165,8 @@ private: double _surveyDistance; int _cameraShots; double _coveredArea; + double _timeBetweenShots; + double _cruiseSpeed; Fact _gridAltitudeFact; Fact _gridAngleFact; @@ -173,9 +184,7 @@ private: static QMap _metaDataMap; - static const char* _jsonTypeKey; static const char* _jsonPolygonObjectKey; - static const char* _jsonIdKey; static const char* _jsonGridObjectKey; static const char* _jsonGridAltitudeKey; static const char* _jsonGridAltitudeRelativeKey; @@ -198,7 +207,6 @@ private: static const char* _jsonCameraOrientationLandscapeKey; static const char* _jsonFixedValueIsAltitudeKey; - static const char* _gridAltitudeFactName; static const char* _gridAngleFactName; static const char* _gridSpacingFactName; @@ -212,8 +220,6 @@ private: static const char* _cameraResolutionWidthFactName; static const char* _cameraResolutionHeightFactName; static const char* _cameraFocalLengthFactName; - - static const char* _complexType; }; #endif diff --git a/src/MissionManager/VisualMissionItem.cc b/src/MissionManager/VisualMissionItem.cc index e0b8faf16a2673d7f9a6fc371986ddf3c05b6dcc..db8b1ba780894057b781a421be6f8a3008f8065d 100644 --- a/src/MissionManager/VisualMissionItem.cc +++ b/src/MissionManager/VisualMissionItem.cc @@ -16,6 +16,10 @@ #include "QGCApplication.h" #include "JsonHelper.h" +const char* VisualMissionItem::jsonTypeKey = "type"; +const char* VisualMissionItem::jsonTypeSimpleItemValue = "SimpleItem"; +const char* VisualMissionItem::jsonTypeComplexItemValue = "ComplexItem"; + VisualMissionItem::VisualMissionItem(Vehicle* vehicle, QObject* parent) : QObject(parent) , _vehicle(vehicle) diff --git a/src/MissionManager/VisualMissionItem.h b/src/MissionManager/VisualMissionItem.h index 6e1fa8daff949ecd87fca03ba0ce11f57a7a16ee..a4ad9419d12f2ea5bb48cb5ad0e476419cc36b60 100644 --- a/src/MissionManager/VisualMissionItem.h +++ b/src/MissionManager/VisualMissionItem.h @@ -40,13 +40,16 @@ public: const VisualMissionItem& operator=(const VisualMissionItem& other); - // The following properties are calculated/set by the MissionControll recalc methods + // The following properties are calculated/set by the MissionController recalc methods Q_PROPERTY(double altDifference READ altDifference WRITE setAltDifference NOTIFY altDifferenceChanged) ///< Change in altitude from previous waypoint Q_PROPERTY(double altPercent READ altPercent WRITE setAltPercent NOTIFY altPercentChanged) ///< Percent of total altitude change in mission altitude Q_PROPERTY(double azimuth READ azimuth WRITE setAzimuth NOTIFY azimuthChanged) ///< Azimuth to previous waypoint Q_PROPERTY(double distance READ distance WRITE setDistance NOTIFY distanceChanged) ///< Distance to previous waypoint + /// This property returns whether the item supports changing flight speed. If it does not it will return NaN. + Q_PROPERTY(double flightSpeed READ flightSpeed NOTIFY flightSpeedChanged) + // Visual mission items have two coordinates associated with them: /// This is the entry point for a waypoint line into the item. For a simple item it is also the location of the item @@ -75,6 +78,7 @@ public: Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY specifiesCoordinateChanged) ///< Item is associated with a coordinate position Q_PROPERTY(bool isStandaloneCoordinate READ isStandaloneCoordinate NOTIFY isStandaloneCoordinateChanged) ///< Waypoint line does not go through item Q_PROPERTY(bool isSimpleItem READ isSimpleItem NOTIFY isSimpleItemChanged) ///< Simple or Complex MissionItem + Q_PROPERTY(QString editorQml MEMBER _editorQml CONSTANT) ///< Qml code for editing this item /// List of child mission items. Child mission item are subsequent mision items which do not specify a coordinate. They /// are shown next to the exitCoordinate indidcator in the ui. @@ -110,6 +114,7 @@ public: virtual QGeoCoordinate coordinate (void) const = 0; virtual QGeoCoordinate exitCoordinate (void) const = 0; virtual int sequenceNumber (void) const = 0; + virtual double flightSpeed (void) = 0; virtual bool coordinateHasRelativeAltitude (void) const = 0; virtual bool exitCoordinateHasRelativeAltitude (void) const = 0; @@ -123,6 +128,10 @@ public: /// @param saveObject Save the item to this json object virtual void save(QJsonObject& saveObject) const = 0; + static const char* jsonTypeKey; ///< Json file attribute which specifies the item type + static const char* jsonTypeSimpleItemValue; ///< Item type is MISSION_ITEM + static const char* jsonTypeComplexItemValue; ///< Item type is Complex Item + signals: void altDifferenceChanged (double altDifference); void altPercentChanged (double altPercent); @@ -139,6 +148,7 @@ signals: void isSimpleItemChanged (bool isSimpleItem); void specifiesCoordinateChanged (void); void isStandaloneCoordinateChanged (void); + void flightSpeedChanged (double flightSpeed); void coordinateHasRelativeAltitudeChanged (bool coordinateHasRelativeAltitude); void exitCoordinateHasRelativeAltitudeChanged (bool exitCoordinateHasRelativeAltitude); @@ -152,6 +162,7 @@ protected: double _altPercent; ///< Percent of total altitude change in mission double _azimuth; ///< Azimuth to previous waypoint double _distance; ///< Distance to previous waypoint + QString _editorQml; ///< Qml resource for editing item /// This is used to reference any subsequent mission items which do not specify a coordinate. QmlObjectListModel _childItems; diff --git a/src/MultiVehicle/MultiVehicleView.qml b/src/MultiVehicle/MultiVehicleView.qml new file mode 100644 index 0000000000000000000000000000000000000000..2aa15bf61bfa72fd2a8d9b4047868b0a6c4eef0b --- /dev/null +++ b/src/MultiVehicle/MultiVehicleView.qml @@ -0,0 +1,268 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Controls 1.3 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controllers 1.0 +import QGroundControl.FactSystem 1.0 + +/// Multi-Vehicle View +QGCView { + id: qgcView + viewPanel: panel + + property real _margins: ScreenTools.defaultFontPixelWidth + property var _fileDialogController + + readonly property string _loadingText: qsTr("Loading...") + + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + + QGCViewPanel { + id: panel + anchors.fill: parent + + Rectangle { + anchors.fill: parent + color: qgcPal.window + + QGCFlickable { + anchors.fill: parent + contentHeight: vehicleColumn.height + flickableDirection: Flickable.VerticalFlick + clip: true + + Column { + id: vehicleColumn + anchors.margins: _margins + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + spacing: _margins + + QGCLabel { text: qsTr("All Vehicles") } + + Repeater { + model: QGroundControl.multiVehicleManager.vehicles + + Column { + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelHeight / 2 + + MissionController { + id: missionController + + Component.onCompleted: startStaticActiveVehicle(object) + + property bool missionAvailable: visualItems && visualItems.count > 1 + + function loadFromSelectedFile() { + if (ScreenTools.isMobile) { + _fileDialogController = missionController + qgcView.showDialog(mobileFilePicker, qsTr("Select Mission File"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) + } else { + missionController.loadFromFilePicker() + missionController.sendToVehicle() + } + } + } // MissionController + + GeoFenceController { + id: geoFenceController + + Component.onCompleted: startStaticActiveVehicle(object) + + property bool fenceAvailable: fenceSupported && (circleSupported || polygonSupported) + + function loadFromSelectedFile() { + if (ScreenTools.isMobile) { + _fileDialogController = geoFenceController + qgcView.showDialog(mobileFilePicker, qsTr("Select Fence File"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) + } else { + geoFenceController.loadFromFilePicker() + geoFenceController.sendToVehicle() + } + } + } // GeoFenceController + + RallyPointController { + id: rallyPointController + + Component.onCompleted: startStaticActiveVehicle(object) + + property bool pointsAvailable: rallyPointsSupported && points.count + + function loadFromSelectedFile() { + if (ScreenTools.isMobile) { + _fileDialogController = rallyPointController + qgcView.showDialog(mobileFilePicker, qsTr("Select Rally Point File"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) + } else { + rallyPointController.loadFromFilePicker() + rallyPointController.sendToVehicle() + } + } + } // RallyPointController + + QGCLabel { + text: "Vehicle #" + object.id + } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: vehicleDisplayColumn.height + (_margins * 2) + color: qgcPal.windowShade + + Column { + id: vehicleDisplayColumn + anchors.margins: _margins + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + + Row { + id: indicatorRow + spacing: _margins + visible: !object.connectionLost + + Rectangle { + width: missionLabel.contentWidth + _margins + height: ScreenTools.defaultFontPixelHeight + _margins + radius: height / 4 + color: missionController.missionAvailable ? "green" : qgcPal.window + border.width: 1 + border.color: qgcPal.text + + QGCLabel { + id: missionLabel + anchors.margins: _margins / 2 + anchors.left: parent.left + anchors.top: parent.top + text: missionController.syncInProgress ? _loadingText : qsTr("Mission") + } + + MouseArea { + anchors.fill: parent + enabled: !missionController.syncInProgress + onClicked: missionController.loadFromSelectedFile() + } + } + + Rectangle { + width: fenceLabel.contentWidth + _margins + height: ScreenTools.defaultFontPixelHeight + _margins + radius: height / 4 + color: geoFenceController.fenceAvailable ? "green" : qgcPal.window + border.width: 1 + border.color: qgcPal.text + + QGCLabel { + id: fenceLabel + anchors.margins: _margins / 2 + anchors.left: parent.left + anchors.top: parent.top + text: geoFenceController.syncInProgress ? _loadingText : qsTr("Fence") + } + + MouseArea { + anchors.fill: parent + enabled: !geoFenceController.syncInProgress + onClicked: geoFenceController.loadFromSelectedFile() + } + } + + Rectangle { + width: rallyLabel.contentWidth + _margins + height: ScreenTools.defaultFontPixelHeight + _margins + radius: height / 4 + color: rallyPointController.pointsAvailable ? "green" : qgcPal.window + border.width: 1 + border.color: qgcPal.text + + QGCLabel { + id: rallyLabel + anchors.margins: _margins / 2 + anchors.left: parent.left + anchors.top: parent.top + text: rallyPointController.syncInProgress ? _loadingText : qsTr("Rally") + } + + MouseArea { + anchors.fill: parent + enabled: !rallyPointController.syncInProgress + onClicked: rallyPointController.loadFromSelectedFile() + } + } + + FlightModeDropdown { activeVehicle: object } + + GuidedBar { activeVehicle: object } + } // Row - contents display + + Flow { + anchors.left: parent.left + anchors.right: parent.right + layoutDirection: Qt.LeftToRight + spacing: _margins + + Repeater { + model: [ "battery.voltage", "battery.percentRemaining", "altitudeRelative", "altitudeAMSL", "groundSpeed", "heading"] + + Column { + property Fact fact: object.getFact(modelData) + + QGCLabel { + anchors.horizontalCenter: parent.horizontalCenter + text: fact.shortDescription + } + Row { + anchors.horizontalCenter: parent.horizontalCenter + //spacing: ScreenTools.defaultFontPixelWidth + + QGCLabel { + text: fact.enumOrValueString + } + QGCLabel { + text: fact.units + } + } + } + } // Repeater - Small + } // Flow + } // Column + } // Rectangle - contents display + } // Column - layout for vehicle + } // Repeater - vehicle repeater + } // Column + } // QGCFlickable + } // Rectangle - View background + } // QGCViewPanel + + Component { + id: mobileFilePicker + + QGCMobileFileDialog { + openDialog: true + fileExtension: _fileDialogController.fileExtension + + onFilenameReturned: { + _fileDialogController.loadFromFile(filename) + _fileDialogController.sendToVehicle() + } + } + } +} // QGCView diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 137c5806bfeb983dff65d9ce4f386ead2d754c10..7933933f9a6c4cd85cdc739ad508fc16f950e740 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -39,9 +39,7 @@ #include "CmdLineOptParser.h" #include "UDPLink.h" #include "LinkManager.h" -#include "HomePositionManager.h" #include "UASMessageHandler.h" -#include "AutoPilotPluginManager.h" #include "QGCTemporaryFile.h" #include "QGCPalette.h" #include "QGCMapPalette.h" @@ -49,14 +47,6 @@ #include "ViewWidgetController.h" #include "ParameterEditorController.h" #include "CustomCommandWidgetController.h" -#include "PX4AdvancedFlightModesController.h" -#include "PX4SimpleFlightModesController.h" -#include "APMFlightModesComponentController.h" -#include "AirframeComponentController.h" -#include "SensorsComponentController.h" -#include "APMSensorsComponentController.h" -#include "PowerComponentController.h" -#include "RadioComponentController.h" #include "ESP8266ComponentController.h" #include "ScreenToolsController.h" #include "QGCMobileFileDialogController.h" @@ -65,11 +55,6 @@ #include "VehicleComponent.h" #include "FirmwarePluginManager.h" #include "MultiVehicleManager.h" -#include "APM/ArduCopterFirmwarePlugin.h" -#include "APM/ArduPlaneFirmwarePlugin.h" -#include "APM/ArduRoverFirmwarePlugin.h" -#include "APM/APMAirframeComponentController.h" -#include "PX4/PX4FirmwarePlugin.h" #include "Vehicle.h" #include "MavlinkQmlSingleton.h" #include "JoystickConfigController.h" @@ -77,10 +62,8 @@ #include "QmlObjectListModel.h" #include "MissionManager.h" #include "QGroundControlQmlGlobal.h" -#include "HomePositionManager.h" #include "FlightMapSettings.h" #include "CoordinateVector.h" -#include "MainToolBarController.h" #include "MissionController.h" #include "GeoFenceController.h" #include "RallyPointController.h" @@ -88,7 +71,6 @@ #include "VideoSurface.h" #include "VideoReceiver.h" #include "LogDownloadController.h" -#include "PX4AirframeLoader.h" #include "ValuesWidgetController.h" #include "AppMessages.h" #include "SimulatedPosition.h" @@ -97,8 +79,9 @@ #include "MissionCommandTree.h" #include "QGCMapPolygon.h" #include "ParameterManager.h" +#include "SettingsManager.h" -#ifndef __ios__ +#ifndef NO_SERIAL_LINK #include "SerialLink.h" #endif @@ -133,9 +116,6 @@ const char* QGCApplication::telemetryFileExtension = "tlog"; const char* QGCApplication::_deleteAllSettingsKey = "DeleteAllSettingsNextBoot"; const char* QGCApplication::_settingsVersionKey = "SettingsVersion"; -const char* QGCApplication::_promptFlightDataSave = "PromptFLightDataSave"; -const char* QGCApplication::_promptFlightDataSaveNotArmed = "PromptFLightDataSaveNotArmed"; -const char* QGCApplication::_styleKey = "StyleIsDark"; const char* QGCApplication::_lastKnownHomePositionLatKey = "LastKnownHomePositionLat"; const char* QGCApplication::_lastKnownHomePositionLonKey = "LastKnownHomePositionLon"; const char* QGCApplication::_lastKnownHomePositionAltKey = "LastKnownHomePositionAlt"; @@ -186,11 +166,6 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) : QApplication(argc, argv) #endif , _runningUnitTests(unitTesting) -#if defined (__mobile__) - , _styleIsDark(false) -#else - , _styleIsDark(true) -#endif , _fakeMobile(false) , _settingsUpgraded(false) #ifdef QT_DEBUG @@ -354,8 +329,12 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) _toolbox->setChildToolboxes(); } -QGCApplication::~QGCApplication() +void QGCApplication::_shutdown(void) { + // This code is specifically not in the destructor since the application object may not be available in the destructor. + // This cause problems for deleting object like settings which are in the toolbox which may have qml references. By + // moving them here and having main.cc call this prior to deleting the app object we make sure app object is still + // around while these things are shutting down. #ifndef __mobile__ MainWindow* mainWindow = MainWindow::instance(); if (mainWindow) { @@ -366,6 +345,11 @@ QGCApplication::~QGCApplication() delete _toolbox; } +QGCApplication::~QGCApplication() +{ + // Place shutdown code in _shutdown +} + void QGCApplication::_initCommon(void) { QSettings settings; @@ -393,18 +377,8 @@ void QGCApplication::_initCommon(void) qmlRegisterUncreatableType ("QGroundControl.FlightMap", 1, 0, "QGCMapPolygon", "Reference only"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ParameterEditorController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMFlightModesComponentController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "PX4AdvancedFlightModesController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "PX4SimpleFlightModesController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMAirframeComponentController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "AirframeComponentController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMSensorsComponentController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "SensorsComponentController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "PowerComponentController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "RadioComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ESP8266ComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ScreenToolsController"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "MainToolBarController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "MissionController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "GeoFenceController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "RallyPointController"); @@ -430,8 +404,7 @@ bool QGCApplication::_initForNormalAppBoot(void) { QSettings settings; - _styleIsDark = settings.value(_styleKey, _styleIsDark).toBool(); - _loadCurrentStyle(); + _loadCurrentStyleSheet(); // Exit main application when last window is closed connect(this, &QGCApplication::lastWindowClosed, this, QGCApplication::quit); @@ -455,6 +428,9 @@ bool QGCApplication::_initForNormalAppBoot(void) // Load known link configurations toolbox()->linkManager()->loadLinkConfigurationList(); + // Probe for joysticks + toolbox()->joystickManager()->init(); + if (_settingsUpgraded) { settings.clear(); settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION); @@ -462,13 +438,15 @@ bool QGCApplication::_initForNormalAppBoot(void) "Your saved settings have been reset to defaults."); } + // Connect links with flag AutoconnectLink + toolbox()->linkManager()->startAutoConnectedLinks(); + if (getQGCMapEngine()->wasCacheReset()) { showMessage("The Offline Map Cache database has been upgraded. " "Your old map cache sets have been reset."); } settings.sync(); - return true; } @@ -489,32 +467,6 @@ void QGCApplication::clearDeleteAllSettingsNextBoot(void) settings.remove(_deleteAllSettingsKey); } -bool QGCApplication::promptFlightDataSave(void) -{ - QSettings settings; - - return settings.value(_promptFlightDataSave, true).toBool(); -} - -bool QGCApplication::promptFlightDataSaveNotArmed(void) -{ - QSettings settings; - - return settings.value(_promptFlightDataSaveNotArmed, false).toBool(); -} - -void QGCApplication::setPromptFlightDataSave(bool promptForSave) -{ - QSettings settings; - settings.setValue(_promptFlightDataSave, promptForSave); -} - -void QGCApplication::setPromptFlightDataSaveNotArmed(bool promptForSave) -{ - QSettings settings; - settings.setValue(_promptFlightDataSaveNotArmed, promptForSave); -} - /// @brief Returns the QGCApplication object singleton. QGCApplication* qgcApp(void) { @@ -578,17 +530,7 @@ void QGCApplication::saveTempFlightDataLogOnMainThread(QString tempLogfile) } #endif -void QGCApplication::setStyle(bool styleIsDark) -{ - QSettings settings; - - settings.setValue(_styleKey, styleIsDark); - _styleIsDark = styleIsDark; - _loadCurrentStyle(); - emit styleChanged(_styleIsDark); -} - -void QGCApplication::_loadCurrentStyle(void) +void QGCApplication::_loadCurrentStyleSheet(void) { #ifndef __mobile__ bool success = true; @@ -604,7 +546,7 @@ void QGCApplication::_loadCurrentStyle(void) success = false; } - if (success && !_styleIsDark) { + if (success && !_toolbox->settingsManager()->appSettings()->indoorPalette()->rawValue().toBool()) { // Load the slave light stylesheet. QFile styleSheet(_lightStyleFile); if (styleSheet.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -622,8 +564,6 @@ void QGCApplication::_loadCurrentStyle(void) setStyle("plastique"); } #endif - - QGCPalette::setGlobalTheme(_styleIsDark ? QGCPalette::Dark : QGCPalette::Light); } void QGCApplication::reportMissingParameter(int componentId, const QString& name) @@ -650,7 +590,7 @@ void QGCApplication::_missingParamsDisplay(void) showMessage(QString("Parameters missing from firmware: %1. You may be running an older version of firmware QGC does not work correctly with or your firmware has a bug in it.").arg(params)); } -QObject* QGCApplication::_rootQmlObject(void) +QObject* QGCApplication::_rootQmlObject() { #ifdef __mobile__ return _qmlAppEngine->rootObjects()[0]; diff --git a/src/QGCApplication.h b/src/QGCApplication.h index a5c9e764356439003ea7fd0ee4335b038c82b3b1..91bb3a28745a17a3833d12d508e89a9efd1b2ac2 100644 --- a/src/QGCApplication.h +++ b/src/QGCApplication.h @@ -27,12 +27,10 @@ #include "LinkManager.h" #include "MAVLinkProtocol.h" #include "FlightMapSettings.h" -#include "HomePositionManager.h" #include "FirmwarePluginManager.h" #include "MultiVehicleManager.h" #include "JoystickManager.h" #include "GAudioOutput.h" -#include "AutoPilotPluginManager.h" #include "UASMessageHandler.h" #include "FactSystem.h" @@ -77,24 +75,9 @@ public: /// @brief Clears the persistent flag to delete all settings the next time QGroundControl is started. void clearDeleteAllSettingsNextBoot(void); - /// @return true: Prompt to save log file when vehicle goes away - bool promptFlightDataSave(void); - - /// @return true: Prompt to save log file even if vehicle was not armed - bool promptFlightDataSaveNotArmed(void); - - void setPromptFlightDataSave(bool promptForSave); - void setPromptFlightDataSaveNotArmed(bool promptForSave); - /// @brief Returns truee if unit test are being run bool runningUnitTests(void) { return _runningUnitTests; } - /// @return true: dark ui style, false: light ui style - bool styleIsDark(void) { return _styleIsDark; } - - /// Set the current UI style - void setStyle(bool styleIsDark); - /// Used to report a missing Parameter. Warning will be displayed to user. Method may be called /// multiple times. void reportMissingParameter(int componentId, const QString& name); @@ -138,10 +121,6 @@ public slots: #endif signals: - /// Signals that the style has changed - /// @param darkStyle true: dark style, false: light style - void styleChanged(bool darkStyle); - /// This is connected to MAVLinkProtocol::checkForLostLogFiles. We signal this to ourselves to call the slot /// on the MAVLinkProtocol thread; void checkForLostLogFiles(void); @@ -161,13 +140,20 @@ public: /// unit tests. Although public should only be called by main. bool _initForUnitTests(void); + void _loadCurrentStyleSheet(void); + static QGCApplication* _app; ///< Our own singleton. Should be reference directly by qgcApp +public: + // Although public, these methods are internal and should only be called by UnitTest code + + /// Shutdown the application object + void _shutdown(void); + private slots: void _missingParamsDisplay(void); private: - void _loadCurrentStyle(void); QObject* _rootQmlObject(void); #ifdef __mobile__ @@ -178,7 +164,6 @@ private: static const char* _darkStyleFile; static const char* _lightStyleFile; - bool _styleIsDark; ///< true: dark style, false: light style static const int _missingParamsDelayedDisplayTimerTimeout = 1000; ///< Timeout to wait for next missing fact to come in before display QTimer _missingParamsDelayedDisplayTimer; ///< Timer use to delay missing fact display QStringList _missingParams; ///< List of missing facts to be displayed @@ -197,15 +182,13 @@ private: static const char* _settingsVersionKey; ///< Settings key which hold settings version static const char* _deleteAllSettingsKey; ///< If this settings key is set on boot, all settings will be deleted - static const char* _promptFlightDataSave; ///< Settings key for promptFlightDataSave - static const char* _promptFlightDataSaveNotArmed; ///< Settings key for promptFlightDataSaveNotArmed - static const char* _styleKey; ///< Settings key for UI style static const char* _lastKnownHomePositionLatKey; static const char* _lastKnownHomePositionLonKey; static const char* _lastKnownHomePositionAltKey; /// Unit Test have access to creating and destroying singletons friend class UnitTest; + }; /// @brief Returns the QGCApplication object singleton. diff --git a/src/QGCFileDialog.cc b/src/QGCFileDialog.cc index 9e82eb1669c991acdc278a13f11d5229e10d56c6..59ff5db458057a6f2d24fe43bfb244fa5f5be3e7 100644 --- a/src/QGCFileDialog.cc +++ b/src/QGCFileDialog.cc @@ -12,10 +12,8 @@ #include "QGCApplication.h" #include "MainWindow.h" -#ifdef QT_DEBUG -#ifndef __mobile__ -#include "UnitTest.h" -#endif +#ifdef UNITTEST_BUILD + #include "UnitTest.h" #endif #include @@ -30,12 +28,10 @@ QString QGCFileDialog::getExistingDirectory( { _validate(options); -#ifdef QT_DEBUG -#ifndef __mobile__ +#ifdef UNITTEST_BUILD if (qgcApp()->runningUnitTests()) { return UnitTest::_getExistingDirectory(parent, caption, dir, options); } else -#endif #endif { return QFileDialog::getExistingDirectory(parent, caption, dir, options); @@ -51,12 +47,10 @@ QString QGCFileDialog::getOpenFileName( { _validate(options); -#ifdef QT_DEBUG -#ifndef __mobile__ +#ifdef UNITTEST_BUILD if (qgcApp()->runningUnitTests()) { return UnitTest::_getOpenFileName(parent, caption, dir, filter, options); } else -#endif #endif { return QFileDialog::getOpenFileName(parent, caption, dir, filter, NULL, options); @@ -72,12 +66,10 @@ QStringList QGCFileDialog::getOpenFileNames( { _validate(options); -#ifdef QT_DEBUG -#ifndef __mobile__ +#ifdef UNITTEST_BUILD if (qgcApp()->runningUnitTests()) { return UnitTest::_getOpenFileNames(parent, caption, dir, filter, options); } else -#endif #endif { return QFileDialog::getOpenFileNames(parent, caption, dir, filter, NULL, options); @@ -95,12 +87,10 @@ QString QGCFileDialog::getSaveFileName( { _validate(options); -#ifdef QT_DEBUG -#ifndef __mobile__ +#ifdef UNITTEST_BUILD if (qgcApp()->runningUnitTests()) { return UnitTest::_getSaveFileName(parent, caption, dir, filter, defaultSuffix, options); } else -#endif #endif { QString defaultSuffixCopy(defaultSuffix); diff --git a/src/QGCLoggingCategory.cc b/src/QGCLoggingCategory.cc index f83818fb817be0263f5bb9f724cbe71a7d42593c..b2220c18a7c75932643538b350f4d1308c5da290 100644 --- a/src/QGCLoggingCategory.cc +++ b/src/QGCLoggingCategory.cc @@ -20,7 +20,8 @@ QGC_LOGGING_CATEGORY(FirmwareUpgradeLog, "FirmwareUpgradeLog") QGC_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog, "FirmwareUpgradeVerboseLog") QGC_LOGGING_CATEGORY(MissionCommandsLog, "MissionCommandsLog") QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog") -QGC_LOGGING_CATEGORY(ParameterManagerLog, "ParameterManagerLog") +QGC_LOGGING_CATEGORY(ParameterManagerLog, "ParameterManagerLog") +QGC_LOGGING_CATEGORY(GeotaggingLog, "GeotaggingLog") QGCLoggingCategoryRegister* _instance = NULL; const char* QGCLoggingCategoryRegister::_filterRulesSettingsGroup = "LoggingFilters"; diff --git a/src/QGCLoggingCategory.h b/src/QGCLoggingCategory.h index 9dad9bbccc14bac4114c9008869a366b4e3d6f7e..13dfcb1996b3f9006c96d0500dc16fce9262df48 100644 --- a/src/QGCLoggingCategory.h +++ b/src/QGCLoggingCategory.h @@ -23,6 +23,7 @@ Q_DECLARE_LOGGING_CATEGORY(FirmwareUpgradeVerboseLog) Q_DECLARE_LOGGING_CATEGORY(MissionCommandsLog) Q_DECLARE_LOGGING_CATEGORY(MissionItemLog) Q_DECLARE_LOGGING_CATEGORY(ParameterManagerLog) +Q_DECLARE_LOGGING_CATEGORY(GeotaggingLog) /// @def QGC_LOGGING_CATEGORY /// This is a QGC specific replacement for Q_LOGGING_CATEGORY. It will register the category name into a diff --git a/src/QGCMapPalette.cc b/src/QGCMapPalette.cc index 5779dfff8f51cb4214830f9c1dfa63622617ed06..0bdd60f77d678b797e6821cb28cf6aa59ffbd4d1 100644 --- a/src/QGCMapPalette.cc +++ b/src/QGCMapPalette.cc @@ -15,6 +15,7 @@ QColor QGCMapPalette::_thumbJoystick[QGCMapPalette::_cColorGroups] = { QColor(255,255,255,127), QColor(0,0,0,127) }; QColor QGCMapPalette::_text [QGCMapPalette::_cColorGroups] = { QColor(255,255,255), QColor(0,0,0) }; +QColor QGCMapPalette::_textOutline [QGCMapPalette::_cColorGroups] = { QColor(0,0,0), QColor(255,255,255) }; QGCMapPalette::QGCMapPalette(QObject* parent) : QObject(parent) diff --git a/src/QGCMapPalette.h b/src/QGCMapPalette.h index 14698c06b67a02f9ff3f4ec21d13f62d4df128a4..7896c6746ab879fe1920b083e91e2ea15a3f6a6e 100644 --- a/src/QGCMapPalette.h +++ b/src/QGCMapPalette.h @@ -43,6 +43,7 @@ class QGCMapPalette : public QObject Q_PROPERTY(bool lightColors READ lightColors WRITE setLightColors NOTIFY paletteChanged) Q_PROPERTY(QColor text READ text NOTIFY paletteChanged) + Q_PROPERTY(QColor textOutline READ textOutline NOTIFY paletteChanged) Q_PROPERTY(QColor thumbJoystick READ thumbJoystick NOTIFY paletteChanged) public: @@ -50,6 +51,7 @@ public: /// Text color QColor text(void) const { return _text[_lightColors ? 0 : 1]; } + QColor textOutline(void) const { return _textOutline[_lightColors ? 0 : 1]; } /// Thumb joystick indicator QColor thumbJoystick(void) const { return _thumbJoystick[_lightColors ? 0 : 1]; } @@ -68,6 +70,7 @@ private: static QColor _thumbJoystick[_cColorGroups]; static QColor _text[_cColorGroups]; + static QColor _textOutline[_cColorGroups]; }; #endif diff --git a/src/QGCMessageBox.h b/src/QGCMessageBox.h index 8ecc447432021016ae88c68cf1818fde68efe0ba..7cc2d811156e47dbd237394877449a79d68f2a7b 100644 --- a/src/QGCMessageBox.h +++ b/src/QGCMessageBox.h @@ -20,11 +20,8 @@ #include "MainWindow.h" #include "QGCApplication.h" -#ifdef QT_DEBUG -#ifndef __mobile__ -#include "UnitTest.h" -#endif - +#ifdef UNITTEST_BUILD + #include "UnitTest.h" #endif /// @file @@ -99,12 +96,10 @@ private: qDebug() << "QGCMessageBox (unit testing)" << title << text; -#ifdef QT_DEBUG -#ifndef __mobile__ +#ifdef UNITTEST_BUILD if (qgcApp()->runningUnitTests()) { return UnitTest::_messageBox(icon, title, text, buttons, defaultButton); } else -#endif #endif { #ifdef __macos__ diff --git a/src/QGCMobileFileDialogController.cc b/src/QGCMobileFileDialogController.cc index 42e09581b7ed7275bb82389f992d8ec6e9ee08dd..f7e4630156bf90f960bb679db36b0032b2984c18 100644 --- a/src/QGCMobileFileDialogController.cc +++ b/src/QGCMobileFileDialogController.cc @@ -33,6 +33,7 @@ QStringList QGCMobileFileDialogController::getFiles(const QString& fileExtension QString QGCMobileFileDialogController::fullPath(const QString& filename, const QString& fileExtension) { + qDebug() << "QGCMobileFileDialogController::fullPath" << filename << fileExtension; QString saveLocation(_getSaveLocation()); if (saveLocation.isEmpty()) { return filename; @@ -52,6 +53,7 @@ QString QGCMobileFileDialogController::fullPath(const QString& filename, const Q bool QGCMobileFileDialogController::fileExists(const QString& filename, const QString& fileExtension) { QFile file(fullPath(filename, fileExtension)); + qDebug() << "QGCMobileFileDialogController::fileExists" << file.fileName(); return file.exists(); } @@ -59,10 +61,15 @@ QString QGCMobileFileDialogController::_getSaveLocation(void) { QStringList docDirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); if (docDirs.count() <= 0) { - qCWarning(QGCMobileFileDialogControllerLog) << "No Documents location"; + qCWarning(QGCMobileFileDialogControllerLog) << "No save location"; return QString(); } - qCDebug(QGCMobileFileDialogControllerLog) << "Save directory" << docDirs.at(0); + + QString saveDirectory = docDirs[0]; + if (!QDir(saveDirectory).exists()) { + QDir().mkdir(saveDirectory); + } + qCDebug(QGCMobileFileDialogControllerLog) << "Save directory" << saveDirectory; - return docDirs.at(0); + return saveDirectory; } diff --git a/src/QGCPalette.cc b/src/QGCPalette.cc index 6e6ea60953cf1b08bb20b3a2cc2423be48e2cf82..2c6a304cfe28a389501f2e7a9f2f549026cc4fbe 100644 --- a/src/QGCPalette.cc +++ b/src/QGCPalette.cc @@ -42,7 +42,7 @@ QColor QGCPalette::_text[QGCPalette::_cThemes][QGCPalette::_cColorGroups] = { QColor QGCPalette::_warningText[QGCPalette::_cThemes][QGCPalette::_cColorGroups] = { { QColor("#cc0808"), QColor("#cc0808") }, - { QColor("#e4e428"), QColor("#e4e428") } + { QColor("#fd5d13"), QColor("#fd5d13") } }; QColor QGCPalette::_button[QGCPalette::_cThemes][QGCPalette::_cColorGroups] = { @@ -57,7 +57,7 @@ QColor QGCPalette::_buttonText[QGCPalette::_cThemes][QGCPalette::_cColorGroups] QColor QGCPalette::_buttonHighlight[QGCPalette::_cThemes][QGCPalette::_cColorGroups] = { { QColor("#e4e4e4"), QColor("#33b5e5") }, - { QColor(0x58, 0x58, 0x58), QColor(237, 235, 51) }, + { QColor(0x58, 0x58, 0x58), QColor(0xed, 0xd4, 0x69) }, }; QColor QGCPalette::_buttonHighlightText[QGCPalette::_cThemes][QGCPalette::_cColorGroups] = { diff --git a/src/QGCQuickWidget.cc b/src/QGCQuickWidget.cc index a3628bc6d525e0e6a12005df507861908839be72..2c77673c5055fff67075c33f8f39c13c8a4c3843 100644 --- a/src/QGCQuickWidget.cc +++ b/src/QGCQuickWidget.cc @@ -9,7 +9,6 @@ #include "QGCQuickWidget.h" -#include "AutoPilotPluginManager.h" #include "MultiVehicleManager.h" #include "JoystickManager.h" #include "QGCApplication.h" diff --git a/src/QGCToolbox.cc b/src/QGCToolbox.cc index 5c63154bed9d133066c588a4cf4f52803b46efe1..f67e57bae205a62072ebe9769b9ee3be564c1753 100644 --- a/src/QGCToolbox.cc +++ b/src/QGCToolbox.cc @@ -8,7 +8,6 @@ ****************************************************************************/ -#include "AutoPilotPluginManager.h" #include "FactSystem.h" #include "FirmwarePluginManager.h" #include "FlightMapSettings.h" @@ -16,7 +15,6 @@ #ifndef __mobile__ #include "GPSManager.h" #endif -#include "HomePositionManager.h" #include "JoystickManager.h" #include "LinkManager.h" #include "MAVLinkProtocol.h" @@ -28,17 +26,23 @@ #include "FollowMe.h" #include "PositionManager.h" #include "VideoManager.h" +#include "MAVLinkLogManager.h" +#include "QGCCorePlugin.h" +#include "QGCOptions.h" +#include "SettingsManager.h" + +#if defined(QGC_CUSTOM_BUILD) +#include CUSTOMHEADER +#endif QGCToolbox::QGCToolbox(QGCApplication* app) : _audioOutput(NULL) - , _autopilotPluginManager(NULL) , _factSystem(NULL) , _firmwarePluginManager(NULL) , _flightMapSettings(NULL) #ifndef __mobile__ , _gpsManager(NULL) #endif - , _homePositionManager(NULL) , _imageProvider(NULL) , _joystickManager(NULL) , _linkManager(NULL) @@ -50,16 +54,22 @@ QGCToolbox::QGCToolbox(QGCApplication* app) , _followMe(NULL) , _qgcPositionManager(NULL) , _videoManager(NULL) + , _mavlinkLogManager(NULL) + , _corePlugin(NULL) + , _settingsManager(NULL) { + // SettingsManager must be first so settings are available to any subsequent tools + _settingsManager = new SettingsManager(app); + + //-- Scan and load plugins + _scanAndLoadPlugins(app); _audioOutput = new GAudioOutput(app); - _autopilotPluginManager = new AutoPilotPluginManager(app); _factSystem = new FactSystem(app); _firmwarePluginManager = new FirmwarePluginManager(app); _flightMapSettings = new FlightMapSettings(app); #ifndef __mobile__ _gpsManager = new GPSManager(app); #endif - _homePositionManager = new HomePositionManager(app); _imageProvider = new QGCImageProvider(app); _joystickManager = new JoystickManager(app); _linkManager = new LinkManager(app); @@ -71,19 +81,22 @@ QGCToolbox::QGCToolbox(QGCApplication* app) _qgcPositionManager = new QGCPositionManager(app); _followMe = new FollowMe(app); _videoManager = new VideoManager(app); + _mavlinkLogManager = new MAVLinkLogManager(app); } void QGCToolbox::setChildToolboxes(void) { + // SettingsManager must be first so settings are available to any subsequent tools + _settingsManager->setToolbox(this); + + _corePlugin->setToolbox(this); _audioOutput->setToolbox(this); - _autopilotPluginManager->setToolbox(this); _factSystem->setToolbox(this); _firmwarePluginManager->setToolbox(this); _flightMapSettings->setToolbox(this); #ifndef __mobile__ _gpsManager->setToolbox(this); #endif - _homePositionManager->setToolbox(this); _imageProvider->setToolbox(this); _joystickManager->setToolbox(this); _linkManager->setToolbox(this); @@ -95,17 +108,17 @@ void QGCToolbox::setChildToolboxes(void) _followMe->setToolbox(this); _qgcPositionManager->setToolbox(this); _videoManager->setToolbox(this); + _mavlinkLogManager->setToolbox(this); } QGCToolbox::~QGCToolbox() { delete _videoManager; + delete _mavlinkLogManager; delete _audioOutput; - delete _autopilotPluginManager; delete _factSystem; delete _firmwarePluginManager; delete _flightMapSettings; - delete _homePositionManager; delete _joystickManager; delete _linkManager; delete _mavlinkProtocol; @@ -115,6 +128,20 @@ QGCToolbox::~QGCToolbox() delete _uasMessageHandler; delete _followMe; delete _qgcPositionManager; + delete _corePlugin; +} + +void QGCToolbox::_scanAndLoadPlugins(QGCApplication* app) +{ +#if defined (QGC_CUSTOM_BUILD) + //-- Create custom plugin (Static) + _corePlugin = (QGCCorePlugin*) new CUSTOMCLASS(app); + if(_corePlugin) { + return; + } +#endif + //-- No plugins found, use default instance + _corePlugin = new QGCCorePlugin(app); } QGCTool::QGCTool(QGCApplication* app) @@ -122,7 +149,6 @@ QGCTool::QGCTool(QGCApplication* app) , _app(app) , _toolbox(NULL) { - } void QGCTool::setToolbox(QGCToolbox* toolbox) diff --git a/src/QGCToolbox.h b/src/QGCToolbox.h index 540c917f3b268bdba33c886418ae324ee6df42b9..762996fd522828ae76db1c10366cbdcc37774427 100644 --- a/src/QGCToolbox.h +++ b/src/QGCToolbox.h @@ -13,13 +13,11 @@ #include -class AutoPilotPluginManager; class FactSystem; class FirmwarePluginManager; class FlightMapSettings; class GAudioOutput; class GPSManager; -class HomePositionManager; class JoystickManager; class FollowMe; class LinkManager; @@ -32,6 +30,9 @@ class QGCImageProvider; class UASMessageHandler; class QGCPositionManager; class VideoManager; +class MAVLinkLogManager; +class QGCCorePlugin; +class SettingsManager; /// This is used to manage all of our top level services/tools class QGCToolbox { @@ -40,11 +41,9 @@ public: QGCToolbox(QGCApplication* app); ~QGCToolbox(); - AutoPilotPluginManager* autopilotPluginManager(void) { return _autopilotPluginManager; } FirmwarePluginManager* firmwarePluginManager(void) { return _firmwarePluginManager; } FlightMapSettings* flightMapSettings(void) { return _flightMapSettings; } GAudioOutput* audioOutput(void) { return _audioOutput; } - HomePositionManager* homePositionManager(void) { return _homePositionManager; } JoystickManager* joystickManager(void) { return _joystickManager; } LinkManager* linkManager(void) { return _linkManager; } MAVLinkProtocol* mavlinkProtocol(void) { return _mavlinkProtocol; } @@ -56,33 +55,40 @@ public: FollowMe* followMe(void) { return _followMe; } QGCPositionManager* qgcPositionManager(void) { return _qgcPositionManager; } VideoManager* videoManager(void) { return _videoManager; } + MAVLinkLogManager* mavlinkLogManager(void) { return _mavlinkLogManager; } + QGCCorePlugin* corePlugin(void) { return _corePlugin; } + SettingsManager* settingsManager(void) { return _settingsManager; } + #ifndef __mobile__ GPSManager* gpsManager(void) { return _gpsManager; } #endif private: void setChildToolboxes(void); + void _scanAndLoadPlugins(QGCApplication *app); + GAudioOutput* _audioOutput; - AutoPilotPluginManager* _autopilotPluginManager; FactSystem* _factSystem; FirmwarePluginManager* _firmwarePluginManager; FlightMapSettings* _flightMapSettings; #ifndef __mobile__ GPSManager* _gpsManager; #endif - HomePositionManager* _homePositionManager; QGCImageProvider* _imageProvider; JoystickManager* _joystickManager; LinkManager* _linkManager; MAVLinkProtocol* _mavlinkProtocol; MissionCommandTree* _missionCommandTree; MultiVehicleManager* _multiVehicleManager; - QGCMapEngineManager* _mapEngineManager; + QGCMapEngineManager* _mapEngineManager; UASMessageHandler* _uasMessageHandler; FollowMe* _followMe; QGCPositionManager* _qgcPositionManager; VideoManager* _videoManager; + MAVLinkLogManager* _mavlinkLogManager; + QGCCorePlugin* _corePlugin; + SettingsManager* _settingsManager; friend class QGCApplication; }; diff --git a/src/QmlControls/AppMessages.qml b/src/QmlControls/AppMessages.qml index f851faaf9ae5a3d7c37db8d7961402bd1a3a0f00..de919c5511c3751bb779377ee399b4c20383d650 100644 --- a/src/QmlControls/AppMessages.qml +++ b/src/QmlControls/AppMessages.qml @@ -96,7 +96,7 @@ QGCView { } } - ListView { + QGCListView { Component.onCompleted: { loaded = true } diff --git a/src/QmlControls/DropButton.qml b/src/QmlControls/DropButton.qml index f7eae40a5a1fe473724f5d8e9d49030fcef49fdb..b8deec86f369ea8eb32e78d056137550bad188eb 100644 --- a/src/QmlControls/DropButton.qml +++ b/src/QmlControls/DropButton.qml @@ -2,11 +2,13 @@ import QtQuick 2.4 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2 +import QGroundControl 1.0 import QGroundControl.ScreenTools 1.0 import QGroundControl.Palette 1.0 Item { id: _root + z: QGroundControl.zOrderWidgets signal clicked() property alias buttonImage: roundButton.buttonImage @@ -15,6 +17,7 @@ Item { property int dropDirection: dropDown property alias dropDownComponent: dropDownLoader.sourceComponent property real viewportMargins: 0 + property real topMargin: parent.height - ScreenTools.availableHeight property alias lightBorders: roundButton.lightBorders width: radius * 2 @@ -35,7 +38,7 @@ Item { property real _viewportMaxLeft: -x + viewportMargins property real _viewportMaxRight: parent.width - (viewportMargins * 2) - x - property real _viewportMaxTop: -y + viewportMargins + property real _viewportMaxTop: -y + viewportMargins + topMargin property real _viewportMaxBottom: parent.height - (viewportMargins * 2) - y // Set up ExclusiveGroup support. We use the checked property to drive visibility of drop down. @@ -53,8 +56,6 @@ Item { checked = false } - Component.onCompleted: _calcPositions() - function _calcPositions() { var dropComponentWidth = dropDownLoader.item.width var dropComponentHeight = dropDownLoader.item.height @@ -111,7 +112,7 @@ Item { dropItemHolderRect.y = 0 if (dropDirection == dropLeft) { - dropDownItem.x = dropDownItem.width + _dropMargin + dropDownItem.x = -(dropDownItem.width + _dropMargin) dropItemHolderRect.x = 0 } else { @@ -161,6 +162,7 @@ Item { id: roundButton radius: parent.width / 2 onClicked: { + _calcPositions() _root.clicked() } } @@ -216,20 +218,11 @@ Item { Item { id: dropItemHolderRect - //color: qgcPal.button - //radius: _dropCornerRadius Loader { id: dropDownLoader x: _dropMargin y: _dropMargin - - Connections { - target: dropDownLoader.item - - onWidthChanged: _calcPositions() - onHeightChanged: _calcPositions() - } } } } // Item - dropDownItem diff --git a/src/QmlControls/DropPanel.qml b/src/QmlControls/DropPanel.qml new file mode 100644 index 0000000000000000000000000000000000000000..68303bb3b7c2222fd3bb7c5e31df8028804bfef2 --- /dev/null +++ b/src/QmlControls/DropPanel.qml @@ -0,0 +1,162 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +Item { + id: _root + z: QGroundControl.zOrderWidgets + visible: false + + signal clicked() + property real radius: ScreenTools.isMobile ? ScreenTools.defaultFontPixelHeight * 1.75 : ScreenTools.defaultFontPixelHeight * 1.25 + property real viewportMargins: 0 + property var toolStrip + + + width: radius * 2 + height: radius * 2 + + // Should be an enum but that get's into the whole problem of creating a singleton which isn't worth the effort + readonly property int dropLeft: 1 + readonly property int dropRight: 2 + readonly property int dropUp: 3 + readonly property int dropDown: 4 + + readonly property real _arrowBaseWidth: radius // Width of long side of arrow + readonly property real _arrowPointHeight: radius * 0.666 // Height is long side to point + readonly property real _dropCornerRadius: ScreenTools.defaultFontPixelWidth * 0.5 + readonly property real _dropCornerRadiusX2: _dropCornerRadius * 2 + readonly property real _dropMargin: _dropCornerRadius + readonly property real _dropMarginX2: _dropMargin * 2 + + property var _dropEdgeTopPoint + property real _dropEdgeHeight + property alias _dropDownComponent: dropDownLoader.sourceComponent + property real _viewportMaxTop: 0 + property real _viewportMaxBottom: parent.parent.height - parent.y + property var _dropPanelCancel + + function show(panelEdgeTopPoint, panelEdgeHeight, panelComponent) { + _dropEdgeTopPoint = panelEdgeTopPoint + _dropEdgeHeight = panelEdgeHeight + _dropDownComponent = panelComponent + _calcPositions() + visible = true + _dropPanelCancel = dropPanelCancelComponent.createObject(toolStrip.parent) + } + + function hide() { + if (_dropPanelCancel) { + _dropPanelCancel.destroy() + } + if (visible) { + visible = false + _dropDownComponent = undefined + toolStrip.uncheckAll() + } + } + + function _calcPositions() { + var dropComponentWidth = dropDownLoader.item.width + var dropComponentHeight = dropDownLoader.item.height + var dropRectWidth = dropComponentWidth + _dropMarginX2 + var dropRectHeight = dropComponentHeight + _dropMarginX2 + + dropItemHolderRect.width = dropRectWidth + dropItemHolderRect.height = dropRectHeight + + dropDownItem.width = dropComponentWidth + _dropMarginX2 + dropDownItem.height = dropComponentHeight + _dropMarginX2 + + dropDownItem.width += _arrowPointHeight + + dropDownItem.y = _dropEdgeTopPoint.y -(dropDownItem.height / 2) + radius + + dropItemHolderRect.y = 0 + + dropDownItem.x = _dropEdgeTopPoint.x + _dropMargin + dropItemHolderRect.x = _arrowPointHeight + + // Validate that dropdown is within viewport + dropDownItem.y = Math.min(dropDownItem.y + dropDownItem.height, _viewportMaxBottom) - dropDownItem.height + dropDownItem.y = Math.max(dropDownItem.y, _viewportMaxTop) + + // Arrow points + arrowCanvas.arrowPoint.y = (_dropEdgeTopPoint.y + radius) - dropDownItem.y + arrowCanvas.arrowPoint.x = 0 + arrowCanvas.arrowBase1.x = _arrowPointHeight + arrowCanvas.arrowBase1.y = arrowCanvas.arrowPoint.y - (_arrowBaseWidth / 2) + arrowCanvas.arrowBase2.x = arrowCanvas.arrowBase1.x + arrowCanvas.arrowBase2.y = arrowCanvas.arrowBase1.y + _arrowBaseWidth + arrowCanvas.requestPaint() + } // function - _calcPositions + + QGCPalette { id: qgcPal } + + Component { + // Overlay which is used to cancel the panel when the user clicks away + id: dropPanelCancelComponent + + MouseArea { + anchors.fill: parent + z: toolStrip.z - 1 + onClicked: dropPanel.hide() + } + } + + Item { + id: dropDownItem + + Canvas { + id: arrowCanvas + anchors.fill: parent + + property var arrowPoint: Qt.point(0, 0) + property var arrowBase1: Qt.point(0, 0) + property var arrowBase2: Qt.point(0, 0) + + onPaint: { + var context = getContext("2d") + context.reset() + context.beginPath() + + context.moveTo(dropItemHolderRect.x, dropItemHolderRect.y) + context.lineTo(dropItemHolderRect.x + dropItemHolderRect.width, dropItemHolderRect.y) + context.lineTo(dropItemHolderRect.x + dropItemHolderRect.width, dropItemHolderRect.y + dropItemHolderRect.height) + context.lineTo(dropItemHolderRect.x, dropItemHolderRect.y + dropItemHolderRect.height) + context.lineTo(arrowBase2.x, arrowBase2.y) + context.lineTo(arrowPoint.x, arrowPoint.y) + context.lineTo(arrowBase1.x, arrowBase1.y) + context.lineTo(dropItemHolderRect.x, dropItemHolderRect.y) + context.closePath() + context.fillStyle = qgcPal.windowShade + context.fill() + } + } // Canvas - arrowCanvas + + Item { + id: dropItemHolderRect + + Loader { + id: dropDownLoader + x: _dropMargin + y: _dropMargin + + property var dropPanel: _root + } + } + } // Item - dropDownItem +} diff --git a/src/QmlControls/FactSliderPanel.qml b/src/QmlControls/FactSliderPanel.qml index e900e838238ce59951533b253dffd950b2bb55a0..2d1fc417e245e435957b3d772acca4ded064dc88 100644 --- a/src/QmlControls/FactSliderPanel.qml +++ b/src/QmlControls/FactSliderPanel.qml @@ -12,6 +12,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 import QGroundControl.Palette 1.0 import QGroundControl.Controls 1.0 import QGroundControl.ScreenTools 1.0 @@ -110,6 +111,25 @@ Column { onValueChanged: { if (_loadComplete) { fact.value = value + } + } + + activeFocusOnPress: true + + MultiPointTouchArea { + anchors.fill: parent + + minimumTouchPoints: 1 + maximumTouchPoints: 1 + mouseEnabled: false + } + + // Block wheel events + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton + onWheel: { + wheel.accepted = true } } } // Slider diff --git a/src/QmlControls/FlightModeDropdown.qml b/src/QmlControls/FlightModeDropdown.qml new file mode 100644 index 0000000000000000000000000000000000000000..80543860611f3e0648d25e0a9489a3fbb27b8739 --- /dev/null +++ b/src/QmlControls/FlightModeDropdown.qml @@ -0,0 +1,65 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.5 + +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 + +Item { + width: flightModeLabel.visible ? flightModeLabel.width : flightModeCombo.width + height: flightModeLabel.visible ? flightModeLabel.height : flightModeCombo.height + + property var activeVehicle ///< Vehicle to show flight modes for + + property int _maxFMCharLength: 10 ///< Maximum number of chars in a flight mode + property string flightMode: activeVehicle ? activeVehicle.flightMode : qsTr("N/A", "No data to display") + + onActiveVehicleChanged: _activeVehicleChanged() + + onFlightModeChanged: { + if (flightModeCombo.visible) { + flightModeCombo.currentIndex = flightModeCombo.find(flightMode) + } + } + + Component.onCompleted: _activeVehicleChanged() + + function _activeVehicleChanged() { + if (activeVehicle.flightModeSetAvailable) { + var maxFMChars = 0 + for (var i=0; i + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 + +// Label control whichs pop up a flight mode change menu when clicked +QGCLabel { + id: flightModeMenuLabel + text: activeVehicle ? activeVehicle.flightMode : qsTr("N/A", "No data to display") + + property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + + Menu { + id: flightModesMenu + } + + Component { + id: flightModeMenuItemComponent + + MenuItem { + onTriggered: activeVehicle.flightMode = text + } + } + + property var flightModesMenuItems: [] + + function updateFlightModesMenu() { + if (activeVehicle && activeVehicle.flightModeSetAvailable) { + // Remove old menu items + for (var i = 0; i < flightModesMenuItems.length; i++) { + flightModesMenu.removeItem(flightModesMenuItems[i]) + } + flightModesMenuItems.length = 0 + // Add new items + for (var i = 0; i < activeVehicle.flightModes.length; i++) { + var menuItem = flightModeMenuItemComponent.createObject(null, { "text": activeVehicle.flightModes[i] }) + flightModesMenuItems.push(menuItem) + flightModesMenu.insertItem(i, menuItem) + } + } + } + + Component.onCompleted: flightModeMenuLabel.updateFlightModesMenu() + + Connections { + target: QGroundControl.multiVehicleManager + onActiveVehicleChanged: flightModeMenuLabel.updateFlightModesMenu() + } + + MouseArea { + visible: activeVehicle && activeVehicle.flightModeSetAvailable + anchors.fill: parent + onClicked: flightModesMenu.popup() + } +} diff --git a/src/QmlControls/GuidedBar.qml b/src/QmlControls/GuidedBar.qml new file mode 100644 index 0000000000000000000000000000000000000000..66705d51684eb3a6f8b9ddb3d3488a5ed600b4a1 --- /dev/null +++ b/src/QmlControls/GuidedBar.qml @@ -0,0 +1,269 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.5 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +//-- Guided mode bar + +Rectangle { + id: guidedModeBar + width: guidedModeColumn.width + (_margins * 2) + height: guidedModeColumn.height + (_margins * 2) + radius: ScreenTools.defaultFontPixelHeight * 0.25 + color: backgroundColor + + property var activeVehicle ///< Vehicle to show guided bar for + property real fontPointSize: ScreenTools.defaultFontPointSize ///< point size for fonts in control + property color backgroundColor: qgcPal.windowShadeDark ///< Background color for bar + + // Values for _confirmActionCode + readonly property int confirmHome: 1 + readonly property int confirmLand: 2 + readonly property int confirmTakeoff: 3 + readonly property int confirmArm: 4 + readonly property int confirmDisarm: 5 + readonly property int confirmEmergencyStop: 6 + readonly property int confirmChangeAlt: 7 + readonly property int confirmGoTo: 8 + readonly property int confirmRetask: 9 + readonly property int confirmOrbit: 10 + + property int _confirmActionCode + property real _showMargin: _margins + property real _hideMargin: _margins - guidedModeBar.height + property real _barMargin: _showMargin + property bool _showConfirm: false + property string _confirmText + property bool _showAltitude: false + property real _confirmAltitude + + function actionConfirmed(altitude) { + _showConfirm = false + switch (_confirmActionCode) { + case confirmHome: + activeVehicle.guidedModeRTL() + break; + case confirmLand: + activeVehicle.guidedModeLand() + break; + case confirmTakeoff: + activeVehicle.guidedModeTakeoff(altitude) + break; + case confirmArm: + activeVehicle.armed = true + break; + case confirmDisarm: + activeVehicle.armed = false + break; + case confirmEmergencyStop: + activeVehicle.emergencyStop() + break; + case confirmChangeAlt: + activeVehicle.guidedModeChangeAltitude(altitude) + break; + case confirmGoTo: + activeVehicle.guidedModeGotoLocation(_flightMap._gotoHereCoordinate) + break; + case confirmRetask: + activeVehicle.setCurrentMissionSequence(_flightMap._retaskSequence) + break; + case confirmOrbit: + //-- All parameters controlled by RC + activeVehicle.guidedModeOrbit() + //-- Center on current flight map position and orbit with a 50m radius (velocity/direction controlled by the RC) + //activeVehicle.guidedModeOrbit(QGroundControl.flightMapPosition, 50.0) + break; + default: + console.warn(qsTr("Internal error: unknown _confirmActionCode"), _confirmActionCode) + } + } + + function actionRejected() { + _showConfirm = false + /* + altitudeSlider.visible = false + _flightMap._gotoHereCoordinate = QtPositioning.coordinate() + guidedModeHideTimer.restart() + */ + } + + function confirmAction(actionCode) { + //guidedModeHideTimer.stop() + _confirmActionCode = actionCode + _showAltitude = false + switch (_confirmActionCode) { + case confirmArm: + _confirmText = qsTr("Arm vehicle?") + break; + case confirmDisarm: + _confirmText = qsTr("Disarm vehicle?") + break; + case confirmEmergencyStop: + _confirmText = qsTr("STOP ALL MOTORS?") + break; + case confirmTakeoff: + _showAltitude = true + setInitialValueMeters(3) + _confirmText = qsTr("Takeoff vehicle?") + break; + case confirmLand: + _confirmText = qsTr("Land vehicle?") + break; + case confirmHome: + _confirmText = qsTr("Return to land?") + break; + case confirmChangeAlt: + _showAltitude = true + setInitialValueAppSettingsDistanceUnits(activeVehicle.altitudeRelative.value) + _confirmText = qsTr("Change altitude?") + break; + case confirmGoTo: + _confirmText = qsTr("Move vehicle?") + break; + case confirmRetask: + _confirmText = qsTr("Change active waypoint?") + break; + case confirmOrbit: + _confirmText = qsTr("Enter orbit mode?") + break; + } + _showConfirm = true + } + + function setInitialValueMeters(meters) { + _confirmAltitude = QGroundControl.metersToAppSettingsDistanceUnits(meters) + } + + function setInitialValueAppSettingsDistanceUnits(height) { + _confirmAltitude = height + } + + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + + Column { + id: guidedModeColumn + anchors.margins: _margins + anchors.top: parent.top + anchors.left: parent.left + spacing: _margins + + /* + QGCLabel { + anchors.horizontalCenter: parent.horizontalCenter + color: _lightWidgetBorders ? qgcPal.mapWidgetBorderDark : qgcPal.mapWidgetBorderLight + text: "Click in map to move vehicle" + visible: gotoEnabled + }*/ + + Row { + spacing: _margins * 2 + visible: !_showConfirm + + QGCButton { + pointSize: fontPointSize + text: (activeVehicle && activeVehicle.armed) ? (activeVehicle.flying ? qsTr("Emergency Stop") : qsTr("Disarm")) : qsTr("Arm") + visible: activeVehicle + onClicked: confirmAction(activeVehicle.armed ? (activeVehicle.flying ? confirmEmergencyStop : confirmDisarm) : confirmArm) + } + + QGCButton { + pointSize: fontPointSize + text: qsTr("RTL") + visible: (activeVehicle && activeVehicle.armed) && activeVehicle.guidedModeSupported && activeVehicle.flying + onClicked: confirmAction(confirmHome) + } + + QGCButton { + pointSize: fontPointSize + text: (activeVehicle && activeVehicle.flying) ? qsTr("Land"): qsTr("Takeoff") + visible: activeVehicle && activeVehicle.guidedModeSupported && activeVehicle.armed + onClicked: confirmAction(activeVehicle.flying ? confirmLand : confirmTakeoff) + } + + QGCButton { + pointSize: fontPointSize + text: qsTr("Pause") + visible: (activeVehicle && activeVehicle.armed) && activeVehicle.pauseVehicleSupported && activeVehicle.flying + onClicked: { + guidedModeHideTimer.restart() + activeVehicle.pauseVehicle() + } + } + + QGCButton { + pointSize: fontPointSize + text: qsTr("Change Altitude") + visible: (activeVehicle && activeVehicle.flying) && activeVehicle.guidedModeSupported && activeVehicle.armed + onClicked: confirmAction(confirmChangeAlt) + } + + QGCButton { + pointSize: fontPointSize + text: qsTr("Orbit") + visible: (activeVehicle && activeVehicle.flying) && activeVehicle.orbitModeSupported && activeVehicle.armed + onClicked: confirmAction(confirmOrbit) + } + + } // Row + + Column { + visible: _showConfirm + + QGCLabel { + anchors.horizontalCenter: parent.horizontalCenter + text: _confirmText + } + + Row { + anchors.horizontalCenter: parent.horizontalCenter + spacing: ScreenTools.defaultFontPixelWidth + + Row { + visible: _showAltitude + + QGCLabel { + text: qsTr("Alt (rel)") + } + + QGCLabel { + text: QGroundControl.appSettingsDistanceUnitsString + } + + QGCTextField { + id: altField + text: _confirmAltitude.toFixed(1) + } + } + + QGCButton { + text: qsTr("Yes") + + onClicked: { + var value = parseFloat(altField.text) + if (isNaN(value)) { + actionRejected() + } else { + actionConfirmed(QGroundControl.appSettingsDistanceUnitsToMeters(value)) + } + } + } + + QGCButton { + text: qsTr("No") + onClicked: actionRejected() + } + } + } // Column + } // Column +} // Rectangle - Guided mode buttons diff --git a/src/QmlControls/MissionCommandDialog.qml b/src/QmlControls/MissionCommandDialog.qml index 48f5454babbcde18e78ca4814826f2423c354ca8..1a8503ecffb74b2c3b32d26bb211f17dc6211d95 100644 --- a/src/QmlControls/MissionCommandDialog.qml +++ b/src/QmlControls/MissionCommandDialog.qml @@ -51,7 +51,7 @@ QGCViewDialog { onActivated: categorySelected(textAt(index)) } - ListView { + QGCListView { id: commandList anchors.margins: ScreenTools.defaultFontPixelHeight anchors.left: parent.left @@ -101,5 +101,5 @@ QGCViewDialog { } } } - } // ListView + } // QGCListView } // QGCViewDialog diff --git a/src/QmlControls/MissionItemIndexLabel.qml b/src/QmlControls/MissionItemIndexLabel.qml index 9561f61c0502328ca8e9d9399a8a21e7071de207..7e6bb8e74b40a89c090ddbc7ad135384cef977f9 100644 --- a/src/QmlControls/MissionItemIndexLabel.qml +++ b/src/QmlControls/MissionItemIndexLabel.qml @@ -5,38 +5,75 @@ import QtQuick.Controls.Styles 1.2 import QGroundControl.ScreenTools 1.0 import QGroundControl.Palette 1.0 -Rectangle { - id: root - - property alias label: _label.text - property bool checked: false - property bool small: false +Canvas { + id: root + width: _width + (_singleChar ? 0 : _label.width) + height: specifiesCoordinate ? (_width * 1.5) : _width signal clicked - width: _width - height: _width - radius: _width / 2 - border.width: small ? 1 : 2 - border.color: "white" - color: checked ? "green" : qgcPal.mapButtonHighlight + property alias label: _label.text + property bool checked: false + property bool small: false + property var color: checked ? "green" : qgcPal.mapButtonHighlight + property real anchorPointX: _width / 2 + property real anchorPointY: _width * 1.5 + property bool specifiesCoordinate: true + + property real _width: small ? ScreenTools.defaultFontPixelHeight * ScreenTools.smallFontPointRatio * 1.25 : ScreenTools.defaultFontPixelHeight * 1.25 + property bool _singleChar: _label.text.length <= 1 - property real _width: small ? ScreenTools.defaultFontPixelHeight * ScreenTools.smallFontPointRatio * 1.75 : ScreenTools.defaultFontPixelHeight * 1.75 + onColorChanged: requestPaint() QGCPalette { id: qgcPal } + function paintSingleCoordinate(context) { + context.arc(_width / 2, _width / 2, _width / 2, (Math.PI / 8) * 7, Math.PI / 8); + context.lineTo(_width / 2, _width * 1.5) + } + + function paintSingleNoCoordinate(context) { + context.arc(_width / 2, _width / 2, _width / 2, Math.PI * 2, 0); + } + + function paintMultipleCoordinate(context) { + context.arc(_width / 2, _width / 2, _width / 2, (Math.PI / 8) * 7, (Math.PI / 2) * 3); + context.lineTo(_label.width, 0) + context.arc(_label.width, _width / 2, _width / 2, (Math.PI / 2) * 3, Math.PI / 2); + context.lineTo((_width / 4) * 3, _width) + context.lineTo(_width / 2, _width * 1.5) + } + + onPaint: { + var context = getContext("2d") + context.reset() + context.beginPath() + if (_singleChar) { + if (specifiesCoordinate) { + paintSingleCoordinate(context) + } else { + paintSingleNoCoordinate(context) + } + } else { + paintMultipleCoordinate(context) + } + context.closePath() + context.fillStyle = color + context.fill() + } + QGCLabel { - id: _label - anchors.fill: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: "white" - font.pointSize: small ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize + id: _label + x: Math.round((_width / 2) - (_singleChar ? (width / 2) : (ScreenTools.defaultFontPixelWidth / 2))) + y: Math.round((_width / 2) - (height / 2)) + color: "white" + font.pointSize: small ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize + + onWidthChanged: requestPaint() } MouseArea { anchors.fill: parent onClicked: parent.clicked() } - } diff --git a/src/QmlControls/OfflineMapButton.qml b/src/QmlControls/OfflineMapButton.qml index 6ff13ee764d663da91516ce9d89e2f35e2f6cd2b..8bfa2704f27dc7a6ab3a38f2199a7c0ec191e3a1 100644 --- a/src/QmlControls/OfflineMapButton.qml +++ b/src/QmlControls/OfflineMapButton.qml @@ -1,21 +1,24 @@ -import QtQuick 2.5 -import QtQuick.Controls 1.2 +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.2 import QGroundControl.Palette 1.0 import QGroundControl.ScreenTools 1.0 -Rectangle -{ - id: __mapButton - - property var __qgcPal: QGCPalette { colorGroupEnabled: enabled } - property bool __showHighlight: (__pressed | __hovered | checked) && !__forceHoverOff - - property bool __forceHoverOff: false - property int __lastGlobalMouseX: 0 - property int __lastGlobalMouseY: 0 - property bool __pressed: false - property bool __hovered: false +Rectangle { + id: mapButton + anchors.margins: ScreenTools.defaultFontPixelWidth + color: _showHighlight ? qgcPal.buttonHighlight : qgcPal.button + border.width: _showBorder ? 1: 0 + border.color: qgcPal.buttonText property bool checked: false property bool complete: false @@ -23,25 +26,34 @@ Rectangle property int tiles: 0 property string size: "" + property bool _showHighlight: (_pressed | _hovered | checked) && !_forceHoverOff + property bool _showBorder: qgcPal.globalTheme === QGCPalette.Light + + property bool _forceHoverOff: false + property int _lastGlobalMouseX: 0 + property int _lastGlobalMouseY: 0 + property bool _pressed: false + property bool _hovered: false + signal clicked() - color: __showHighlight ? __qgcPal.buttonHighlight : __qgcPal.button - anchors.margins: ScreenTools.defaultFontPixelWidth + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + Row { anchors.centerIn: parent QGCLabel { id: nameLabel - width: __mapButton.width * 0.4 - color: __showHighlight ? __qgcPal.buttonHighlightText : __qgcPal.buttonText + width: mapButton.width * 0.4 + color: _showHighlight ? qgcPal.buttonHighlightText : qgcPal.buttonText anchors.verticalCenter: parent.verticalCenter } QGCLabel { id: sizeLabel - width: __mapButton.width * 0.4 + width: mapButton.width * 0.4 horizontalAlignment: Text.AlignRight anchors.verticalCenter: parent.verticalCenter - color: __showHighlight ? __qgcPal.buttonHighlightText : __qgcPal.buttonText - text: __mapButton.size + (tiles > 0 ? " (" + tiles + " tiles)" : "") + color: _showHighlight ? qgcPal.buttonHighlightText : qgcPal.buttonText + text: mapButton.size + (tiles > 0 ? " (" + tiles + " tiles)" : "") } Item { width: ScreenTools.defaultFontPixelWidth * 2 @@ -66,7 +78,7 @@ Rectangle source: "/res/buttonRight.svg" mipmap: true fillMode: Image.PreserveAspectFit - color: __showHighlight ? __qgcPal.buttonHighlightText : __qgcPal.buttonText + color: _showHighlight ? qgcPal.buttonHighlightText : qgcPal.buttonText anchors.verticalCenter: parent.verticalCenter } } @@ -75,20 +87,18 @@ Rectangle anchors.fill: parent hoverEnabled: true onMouseXChanged: { - __lastGlobalMouseX = ScreenTools.mouseX() - __lastGlobalMouseY = ScreenTools.mouseY() + _lastGlobalMouseX = ScreenTools.mouseX() + _lastGlobalMouseY = ScreenTools.mouseY() } onMouseYChanged: { - __lastGlobalMouseX = ScreenTools.mouseX() - __lastGlobalMouseY = ScreenTools.mouseY() - } - onEntered: { __hovered = true; __forceHoverOff = false; hoverTimer.start() } - onExited: { __hovered = false; __forceHoverOff = false; hoverTimer.stop() } - onPressed: { __pressed = true; } - onReleased: { __pressed = false; } - onClicked: { - __mapButton.clicked() + _lastGlobalMouseX = ScreenTools.mouseX() + _lastGlobalMouseY = ScreenTools.mouseY() } + onEntered: { _hovered = true; _forceHoverOff = false; hoverTimer.start() } + onExited: { _hovered = false; _forceHoverOff = false; hoverTimer.stop() } + onPressed: { _pressed = true; } + onReleased: { _pressed = false; } + onClicked: mapButton.clicked() } Timer { @@ -96,10 +106,10 @@ Rectangle interval: 250 repeat: true onTriggered: { - if (__lastGlobalMouseX !== ScreenTools.mouseX() || __lastGlobalMouseY !== ScreenTools.mouseY()) { - __forceHoverOff = true + if (_lastGlobalMouseX !== ScreenTools.mouseX() || _lastGlobalMouseY !== ScreenTools.mouseY()) { + _forceHoverOff = true } else { - __forceHoverOff = false + _forceHoverOff = false } } } diff --git a/src/QmlControls/ParameterEditor.qml b/src/QmlControls/ParameterEditor.qml index b1e72301d522b1e1254535c7f2c89dfd7f27e622..61621b69ed9cbfd749a6486568ea10dfcf69fd8a 100644 --- a/src/QmlControls/ParameterEditor.qml +++ b/src/QmlControls/ParameterEditor.qml @@ -56,6 +56,17 @@ QGCView { anchors.right: parent.right spacing: ScreenTools.defaultFontPixelWidth + Timer { + id: clearTimer + interval: 100; + running: false; + repeat: false + onTriggered: { + searchText.text = "" + controller.searchText = "" + } + } + QGCLabel { anchors.baseline: clearButton.baseline text: qsTr("Search:") @@ -71,7 +82,12 @@ QGCView { QGCButton { id: clearButton text: qsTr("Clear") - onClicked: searchText.text = "" + onClicked: { + if(ScreenTools.isMobile) { + Qt.inputMethod.hide(); + } + clearTimer.start() + } } } // Row - Header @@ -96,7 +112,7 @@ QGCView { text: qsTr("Load from file...") onTriggered: { if (ScreenTools.isMobile) { - qgcView.showDialog(mobileFilePicker, qsTr("Select Parameter File"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel) + qgcView.showDialog(mobileFilePicker, qsTr("Select Parameter File"), qgcView.showDialogDefaultWidth, StandardButton.Cancel) } else { controller.loadFromFilePicker() } @@ -118,6 +134,11 @@ QGCView { onTriggered: controller.clearRCToParam() visible: _showRCToParam } + MenuSeparator { } + MenuItem { + text: qsTr("Reboot Vehicle") + onTriggered: showDialog(rebootVehicleConfirmComponent, qsTr("Reboot Vehicle"), qgcView.showDialogDefaultWidth, StandardButton.Cancel | StandardButton.Ok) + } } } @@ -180,7 +201,7 @@ QGCView { } /// Parameter list - ListView { + QGCListView { id: editorListView anchors.leftMargin: ScreenTools.defaultFontPixelWidth anchors.left: _searchFilter ? parent.left : groupScroll.right @@ -263,7 +284,7 @@ QGCView { Component { id: mobileFilePicker - QGCMobileFileDialog { + QGCMobileFileOpenDialog { fileExtension: QGroundControl.parameterFileExtension onFilenameReturned: controller.loadFromFile(filename) } @@ -272,8 +293,7 @@ QGCView { Component { id: mobileFileSaver - QGCMobileFileDialog { - openDialog: false + QGCMobileFileSaveDialog { fileExtension: QGroundControl.parameterFileExtension onFilenameReturned: controller.saveToFile(filename) } @@ -295,4 +315,21 @@ QGCView { } } } + + Component { + id: rebootVehicleConfirmComponent + + QGCViewDialog { + function accept() { + QGroundControl.multiVehicleManager.activeVehicle.rebootVehicle() + hideDialog() + } + + QGCLabel { + width: parent.width + wrapMode: Text.WordWrap + text: qsTr("Select Ok to reboot vehicle.") + } + } + } } // QGCView diff --git a/src/QmlControls/ParameterEditorController.cc b/src/QmlControls/ParameterEditorController.cc index 16eafae33887304e471381d1cd0448686280525e..6613ef4ed3dc105521afd257a8356ce070432447 100644 --- a/src/QmlControls/ParameterEditorController.cc +++ b/src/QmlControls/ParameterEditorController.cc @@ -12,7 +12,6 @@ /// @author Don Gagne #include "ParameterEditorController.h" -#include "AutoPilotPluginManager.h" #include "QGCApplication.h" #include "ParameterManager.h" @@ -34,7 +33,10 @@ ParameterEditorController::ParameterEditorController(void) _componentIds += QString("%1").arg(componentId); } - _currentGroup = groupMap[_currentComponentId].keys()[0]; + // Be careful about no parameters + if (groupMap.contains(_currentComponentId) && groupMap[_currentComponentId].size() != 0) { + _currentGroup = groupMap[_currentComponentId].keys()[0]; + } _updateParameters(); connect(this, &ParameterEditorController::searchTextChanged, this, &ParameterEditorController::_updateParameters); @@ -113,7 +115,7 @@ void ParameterEditorController::saveToFile(const QString& filename) void ParameterEditorController::saveToFilePicker(void) { #ifndef __mobile__ - QString fileName = QGCFileDialog::getSaveFileName(NULL, + QString fileName = QGCFileDialog::getSaveFileName(MainWindow::instance(), "Save Parameters", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "Parameter Files (*.params)", @@ -153,7 +155,7 @@ void ParameterEditorController::loadFromFile(const QString& filename) void ParameterEditorController::loadFromFilePicker(void) { #ifndef __mobile__ - QString fileName = QGCFileDialog::getOpenFileName(NULL, + QString fileName = QGCFileDialog::getOpenFileName(MainWindow::instance(), "Load Parameters", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "Parameter Files (*.params);;All Files (*)"); diff --git a/src/QmlControls/ParameterEditorController.h b/src/QmlControls/ParameterEditorController.h index 74e2d3e05e34a9cf999c876fd78d70a53547f2e4..2c8b275fa595a18cff0248fc77338c42ed2d99a5 100644 --- a/src/QmlControls/ParameterEditorController.h +++ b/src/QmlControls/ParameterEditorController.h @@ -36,20 +36,20 @@ public: Q_PROPERTY(QmlObjectListModel* parameters MEMBER _parameters CONSTANT) Q_PROPERTY(QVariantList componentIds MEMBER _componentIds CONSTANT) - Q_INVOKABLE QStringList getGroupsForComponent(int componentId); - Q_INVOKABLE QStringList getParametersForGroup(int componentId, QString group); + Q_INVOKABLE QStringList getGroupsForComponent(int componentId); + Q_INVOKABLE QStringList getParametersForGroup(int componentId, QString group); Q_INVOKABLE QStringList searchParametersForComponent(int componentId, const QString& searchText, bool searchInName=true, bool searchInDescriptions=true); - Q_INVOKABLE void clearRCToParam(void); + Q_INVOKABLE void clearRCToParam(void); Q_INVOKABLE void saveToFilePicker(void); Q_INVOKABLE void loadFromFilePicker(void); Q_INVOKABLE void saveToFile(const QString& filename); Q_INVOKABLE void loadFromFile(const QString& filename); Q_INVOKABLE void refresh(void); Q_INVOKABLE void resetAllToDefaults(void); - Q_INVOKABLE void setRCToParam(const QString& paramName); + Q_INVOKABLE void setRCToParam(const QString& paramName); - QList model(void); + QList model(void); signals: void searchTextChanged(QString searchText); diff --git a/src/QmlControls/ParameterEditorDialog.qml b/src/QmlControls/ParameterEditorDialog.qml index d43190b06e4d696945104cb609801e1ceee656d1..41b8966e383d12b29eee821d6bf70977b4a6865d 100644 --- a/src/QmlControls/ParameterEditorDialog.qml +++ b/src/QmlControls/ParameterEditorDialog.qml @@ -7,12 +7,9 @@ * ****************************************************************************/ - -/// @file -/// @author Don Gagne - import QtQuick 2.5 import QtQuick.Controls 1.3 +import QtQuick.Layouts 1.2 import QGroundControl.Controls 1.0 import QGroundControl.Palette 1.0 @@ -29,7 +26,8 @@ QGCViewDialog { property bool validate: false property string validateValue - property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 20 + property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 20 + property bool _longDescriptionAvailable: fact.longDescription != "" ParameterEditorController { id: controller; factPanel: parent } @@ -68,7 +66,6 @@ QGCViewDialog { validationError.text = fact.validate(validateValue, false /* convertOnly */) forceSave.visible = true } - //valueField.forceActiveFocus() } QGCFlickable { @@ -83,28 +80,24 @@ QGCViewDialog { anchors.right: parent.right QGCLabel { + id: validationError width: parent.width wrapMode: Text.WordWrap - visible: fact.shortDescription - text: fact.shortDescription - } - - QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - visible: fact.longDescription - text: fact.longDescription + color: qgcPal.warningText } - Row { - spacing: defaultTextWidth + RowLayout { + spacing: defaultTextWidth + anchors.left: parent.left + anchors.right: parent.right QGCTextField { - id: valueField - text: validate ? validateValue : fact.valueString - visible: fact.enumStrings.length == 0 || validate - //focus: true - + id: valueField + text: validate ? validateValue : fact.valueString + visible: fact.enumStrings.length == 0 || validate + unitsLabel: fact.units + showUnits: fact.units != "" + Layout.fillWidth: true inputMethodHints: ScreenTools.isiOS ? Qt.ImhNone : // iOS numeric keyboard has not done button, we can't use it Qt.ImhFormattedNumbersOnly // Forces use of virtual numeric keyboard @@ -113,7 +106,6 @@ QGCViewDialog { QGCButton { anchors.baseline: valueField.baseline visible: fact.defaultValueAvailable - width: _editFieldWidth text: qsTr("Reset to default") onClicked: { @@ -126,7 +118,8 @@ QGCViewDialog { QGCComboBox { id: factCombo - width: valueField.width + anchors.left: parent.left + anchors.right: parent.right visible: _showCombo model: fact.enumStrings @@ -158,63 +151,55 @@ QGCViewDialog { } QGCLabel { - text: fact.name - visible: fact.componentId > 0 // > 0 means it's a parameter fact + width: parent.width + wrapMode: Text.WordWrap + visible: !longDescriptionLabel.visible + text: fact.shortDescription } - Column { - spacing: defaultTextHeight / 2 - anchors.left: parent.left - anchors.right: parent.right - - Row { - spacing: defaultTextWidth - - QGCLabel { text: qsTr("Units:") } - QGCLabel { text: fact.units ? fact.units : qsTr("none") } - } - - Row { - spacing: defaultTextWidth - visible: !fact.minIsDefaultForType - - QGCLabel { text: qsTr("Minimum value:") } - QGCLabel { text: fact.minString } - } + QGCLabel { + id: longDescriptionLabel + width: parent.width + wrapMode: Text.WordWrap + visible: fact.longDescription != "" + text: fact.longDescription + } - Row { - spacing: defaultTextWidth - visible: !fact.maxIsDefaultForType + Row { + spacing: defaultTextWidth - QGCLabel { text: qsTr("Maximum value:") } - QGCLabel { text: fact.maxString } + QGCLabel { + id: minValueDisplay + text: qsTr("Min: ") + fact.minString + visible: !fact.minIsDefaultForType } - Row { - spacing: defaultTextWidth - - QGCLabel { text: qsTr("Default value:") } - QGCLabel { text: fact.defaultValueAvailable ? fact.defaultValueString : qsTr("none") } + QGCLabel { + text: qsTr("Max: ") + fact.maxString + visible: !fact.maxIsDefaultForType } QGCLabel { - visible: fact.rebootRequired - text: "Reboot required after change" + text: qsTr("Default: ") + fact.defaultValueString + visible: fact.defaultValueAvailable } - } // Column + } QGCLabel { - width: parent.width - wrapMode: Text.WordWrap - text: qsTr("Warning: Modifying values while vehicle is in flight can lead to vehicle instability and possible vehicle loss. ") + - qsTr("Make sure you know what you are doing and double-check your values before Save!") + text: qsTr("Parameter name: ") + fact.name + visible: fact.componentId > 0 // > 0 means it's a parameter fact + } + + QGCLabel { + visible: fact.rebootRequired + text: "Reboot required after change" } QGCLabel { - id: validationError width: parent.width wrapMode: Text.WordWrap - color: qsTr("yellow") + text: qsTr("Warning: Modifying values while vehicle is in flight can lead to vehicle instability and possible vehicle loss. ") + + qsTr("Make sure you know what you are doing and double-check your values before Save!") } QGCCheckBox { diff --git a/src/QmlControls/QGCButton.qml b/src/QmlControls/QGCButton.qml index 1417af567db569d9f34772ca36977a71a614ac3e..55fe10af6573b596b8fba91a6a76857a679613f9 100644 --- a/src/QmlControls/QGCButton.qml +++ b/src/QmlControls/QGCButton.qml @@ -22,7 +22,8 @@ Button { property int __lastGlobalMouseX: 0 property int __lastGlobalMouseY: 0 - property int __padding: Math.round(ScreenTools.defaultFontPixelHeight * 0.5) + property int _horizontalPadding: ScreenTools.defaultFontPixelWidth + property int _verticalPadding: Math.round(ScreenTools.defaultFontPixelHeight / 2) Connections { target: __behavior @@ -50,41 +51,26 @@ Button { style: ButtonStyle { /*! The padding between the background and the label components. */ padding { - top: __padding - left: __padding - right: control.menu !== null ? Math.round(ScreenTools.defaultFontPixelHeight) : __padding - bottom: __padding + top: _verticalPadding + bottom: _verticalPadding + left: _horizontalPadding + right: _horizontalPadding } /*! This defines the background of the button. */ - background: Item { - property bool down: control.pressed || (control.checkable && control.checked) - implicitWidth: Math.round(ScreenTools.defaultFontPixelWidth * 4.5) - implicitHeight: ScreenTools.isMobile ? Math.max(25, Math.round(ScreenTools.defaultFontPixelHeight * 2)) : Math.max(25, Math.round(ScreenTools.defaultFontPixelHeight * 1.2)) - - Rectangle { - anchors.fill: parent - border.width: _showBorder ? 1: 0 - border.color: _qgcPal.buttonText - color: _showHighlight ? - control._qgcPal.buttonHighlight : - (primary ? control._qgcPal.primaryButton : control._qgcPal.button) - } - - Image { - id: imageItem - visible: control.menu !== null - source: "/qmlimages/arrow-down.png" - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: __padding - opacity: control.enabled ? 0.6 : 0.5 - } + background: Rectangle { + implicitWidth: ScreenTools.implicitButtonWidth + implicitHeight: ScreenTools.implicitButtonHeight + border.width: _showBorder ? 1: 0 + border.color: _qgcPal.buttonText + color: _showHighlight ? + control._qgcPal.buttonHighlight : + (primary ? control._qgcPal.primaryButton : control._qgcPal.button) } /*! This defines the label of the button. */ label: Item { - implicitWidth: control.menu === null ? row.implicitWidth : row.implicitWidth + ScreenTools.defaultFontPixelWidth + implicitWidth: row.implicitWidth implicitHeight: row.implicitHeight baselineOffset: row.y + text.y + text.baselineOffset @@ -94,20 +80,20 @@ Button { spacing: ScreenTools.defaultFontPixelWidth * 0.25 Image { - source: control.iconSource + source: control.iconSource anchors.verticalCenter: parent.verticalCenter } Text { - id: text - antialiasing: true - text: control.text - font.pointSize: pointSize - font.family: ScreenTools.normalFontFamily + id: text anchors.verticalCenter: parent.verticalCenter - color: _showHighlight ? - control._qgcPal.buttonHighlightText : - (primary ? control._qgcPal.primaryButtonText : control._qgcPal.buttonText) + antialiasing: true + text: control.text + font.pointSize: pointSize + font.family: ScreenTools.normalFontFamily + color: _showHighlight ? + control._qgcPal.buttonHighlightText : + (primary ? control._qgcPal.primaryButtonText : control._qgcPal.buttonText) } } } diff --git a/src/QmlControls/QGCCheckBox.qml b/src/QmlControls/QGCCheckBox.qml index f57d521439e7aedee6728a65a832460c2b2b317f..7cf0c4bc64580dc41024076f1399b6fb9689bb2c 100644 --- a/src/QmlControls/QGCCheckBox.qml +++ b/src/QmlControls/QGCCheckBox.qml @@ -1,30 +1,32 @@ -import QtQuick 2.2 -import QtQuick.Controls 1.2 -import QtQuick.Controls.Styles 1.2 +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.2 -import QGroundControl.Palette 1.0 -import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.ScreenTools 1.0 CheckBox { property var __qgcPal: QGCPalette { colorGroupEnabled: enabled } style: CheckBoxStyle { label: Item { - implicitWidth: text.implicitWidth + 2 + implicitWidth: text.implicitWidth + 2 implicitHeight: text.implicitHeight baselineOffset: text.baselineOffset + Rectangle { - anchors.fill: text - anchors.margins: -1 + anchors.margins: -1 anchors.leftMargin: -3 anchors.rightMargin: -3 - visible: control.activeFocus - height: 6 - radius: 3 - color: "#224f9fef" - border.color: "#47b" - opacity: 0.6 + anchors.fill: text + visible: control.activeFocus + height: 6 + radius: 3 + color: "#224f9fef" + border.color: "#47b" + opacity: 0.6 } + Text { id: text text: control.text @@ -34,6 +36,54 @@ CheckBox { color: control.__qgcPal.text anchors.verticalCenter: parent.verticalCenter } - } - } + } // label + + indicator: Item { + implicitWidth: ScreenTools.implicitCheckBoxWidth + implicitHeight: implicitWidth + + Rectangle { + anchors.fill: parent + anchors.bottomMargin: -1 + color: "#44ffffff" + radius: baserect.radius + } + + Rectangle { + id: baserect + gradient: Gradient { + GradientStop {color: "#eee" ; position: 0} + GradientStop {color: control.pressed ? "#eee" : "#fff" ; position: 0.1} + GradientStop {color: "#fff" ; position: 1} + } + radius: ScreenTools.defaultFontPixelHeight * 0.16 + anchors.fill: parent + border.color: control.activeFocus ? "#47b" : "#999" + } + + Image { + source: "/qmlimages/check.png" + opacity: control.checkedState === Qt.Checked ? control.enabled ? 1 : 0.5 : 0 + anchors.centerIn: parent + anchors.verticalCenterOffset: 1 + Behavior on opacity {NumberAnimation {duration: 80}} + } + + Rectangle { + anchors.fill: parent + anchors.margins: Math.round(baserect.radius) + antialiasing: true + gradient: Gradient { + GradientStop {color: control.pressed ? "#555" : "#999" ; position: 0} + GradientStop {color: "#555" ; position: 1} + } + radius: baserect.radius - 1 + anchors.centerIn: parent + anchors.alignWhenCentered: true + border.color: "#222" + Behavior on opacity {NumberAnimation {duration: 80}} + opacity: control.checkedState === Qt.PartiallyChecked ? control.enabled ? 1 : 0.5 : 0 + } + } // indicator + } // style } diff --git a/src/QmlControls/QGCComboBox.qml b/src/QmlControls/QGCComboBox.qml index c8f24b13bc9b5a7cee98a83157d5a6a41c03ae35..1a7402167bcdb7ac8cbbf33e2a2c4bfe5fe073f5 100644 --- a/src/QmlControls/QGCComboBox.qml +++ b/src/QmlControls/QGCComboBox.qml @@ -18,8 +18,8 @@ ComboBox { control._qgcPal.buttonText background: Item { - implicitWidth: Math.round(ScreenTools.defaultFontPixelWidth * 4.5) - implicitHeight: ScreenTools.isMobile ? Math.max(25, Math.round(ScreenTools.defaultFontPixelHeight * 2)) : Math.max(25, Math.round(ScreenTools.defaultFontPixelHeight * 1.2)) + implicitWidth: ScreenTools.implicitComboBoxWidth + implicitHeight: ScreenTools.implicitComboBoxHeight Rectangle { anchors.fill: parent @@ -38,4 +38,24 @@ ComboBox { } } } + + // Capture Wheel events to disable scrolling options in ComboBox. + // As a side effect, this also prevents scrolling the page when + // mouse is over a ComboBox, but this would also the case when + // scrolling items in the ComboBox is enabled. + MouseArea { + anchors.fill: parent + onWheel: { + // do nothing + wheel.accepted = true; + } + onPressed: { + // propogate to ComboBox + mouse.accepted = false; + } + onReleased: { + // propogate to ComboBox + mouse.accepted = false; + } + } } diff --git a/src/QmlControls/QGCFlickable.qml b/src/QmlControls/QGCFlickable.qml index 52b1b0c44ec4608aee91356dcf10a1d793f68ef4..c3a7dfdd5b5e988afaa9b9d538547fd2b48cf4d0 100644 --- a/src/QmlControls/QGCFlickable.qml +++ b/src/QmlControls/QGCFlickable.qml @@ -1,11 +1,12 @@ -import QtQuick 2.5 +import QtQuick 2.5 -import QGroundControl.Palette 1.0 -import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 +/// QGC version of Flickable control that shows horizontal/vertial scroll indicators Flickable { id: root boundsBehavior: Flickable.StopAtBounds + clip: true property color indicatorColor: qgcPal.text diff --git a/src/QmlControls/QGCGroupBox.qml b/src/QmlControls/QGCGroupBox.qml new file mode 100644 index 0000000000000000000000000000000000000000..60217970c117981a59c2882b5e245d351a1c208e --- /dev/null +++ b/src/QmlControls/QGCGroupBox.qml @@ -0,0 +1,32 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Controls 2.0 + +import QGroundControl.Palette 1.0 +import QGroundControl.ScreenTools 1.0 + +GroupBox { + id: control + + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + + background: Rectangle { + y: control.topPadding - control.padding + width: parent.width + height: parent.height - control.topPadding + control.padding + color: qgcPal.windowShade + } + + label: QGCLabel { + width: control.availableWidth + text: control.title + } +} diff --git a/src/QmlControls/QGCListView.qml b/src/QmlControls/QGCListView.qml new file mode 100644 index 0000000000000000000000000000000000000000..3c5205a9eacaf2de079e9363f3ab858cbc5c6bf0 --- /dev/null +++ b/src/QmlControls/QGCListView.qml @@ -0,0 +1,20 @@ +import QtQuick 2.5 + +import QGroundControl.Palette 1.0 + +/// QGC version of ListVIew control that shows horizontal/vertial scroll indicators +ListView { + id: root + boundsBehavior: Flickable.StopAtBounds + + property color indicatorColor: qgcPal.text + + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + + Component.onCompleted: { + var indicatorComponent = Qt.createComponent("QGCFlickableVerticalIndicator.qml") + indicatorComponent.createObject(root) + indicatorComponent = Qt.createComponent("QGCFlickableHorizontalIndicator.qml") + indicatorComponent.createObject(root) + } +} diff --git a/src/QmlControls/QGCMapLabel.qml b/src/QmlControls/QGCMapLabel.qml new file mode 100644 index 0000000000000000000000000000000000000000..ebc49222c884341862d7748c23486f5dfa15780e --- /dev/null +++ b/src/QmlControls/QGCMapLabel.qml @@ -0,0 +1,16 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.2 + +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 + +/// Text control used for displaying text of Maps +QGCLabel { + property var map + + QGCMapPalette { id: mapPal; lightColors: map.isSatelliteMap } + + color: mapPal.text + style: Text.Outline + styleColor: mapPal.textOutline +} diff --git a/src/QmlControls/QGCMobileFileDialog.qml b/src/QmlControls/QGCMobileFileDialog.qml deleted file mode 100644 index 91928a84fe086028efabd36226c5bcc531ddfc59..0000000000000000000000000000000000000000 --- a/src/QmlControls/QGCMobileFileDialog.qml +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -import QtQuick 2.5 -import QtQuick.Controls 1.3 -import QtQuick.Dialogs 1.2 - -import QGroundControl 1.0 -import QGroundControl.ScreenTools 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.Controllers 1.0 -import QGroundControl.Palette 1.0 - -/// Simple file picker for mobile -QGCViewDialog { - property bool openDialog: true ///< true: Show file open dialog, false: show file save dialog - property string fileExtension ///< File extension for file listing - - signal filenameReturned(string filename) - - readonly property real _margins: ScreenTools.defaultFontPixelHeight / 2 - - function accept() { - if (!openDialog) { - console.log("filename", dialogLoader.item.filename) - if (!dialogLoader.item.replaceMessageShown) { - if (controller.fileExists(dialogLoader.item.filename, fileExtension)) { - dialogLoader.item.replaceMessageShown = true - return - } - } - filenameReturned(controller.fullPath(dialogLoader.item.filename, fileExtension)) - } - hideDialog() - } - - QGCMobileFileDialogController { id: controller } - QGCPalette { id: qgcPal; colorGroupEnabled: true } - - Loader { - id: dialogLoader - anchors.fill: parent - sourceComponent: openDialog ? openDialogComponent : saveDialogComponent - } - - Component { - id: saveDialogComponent - - Column { - anchors.left: parent.left - anchors.right: parent.right - spacing: ScreenTools.defaultFontPixelHeight - - property alias filename: filenameTextField.text - property alias replaceMessageShown: replaceMessage.visible - - QGCLabel { - text: qsTr("File name:") - } - - QGCTextField { - id: filenameTextField - onTextChanged: replaceMessage.visible = false - } - - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: qsTr("File names must end with .%1 file extension. If missing it will be added.").arg(fileExtension) - } - - QGCLabel { - id: replaceMessage - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: qsTr("The file %1 exists. Click Save again to replace it.").arg(filename) - visible: false - color: qgcPal.warningText - } - } - } - - Component { - id: openDialogComponent - - Item { - anchors.margins: _margins - anchors.fill: parent - - ListView { - anchors.fill: parent - spacing: _margins / 2 - orientation: ListView.Vertical - model: controller.getFiles(fileExtension) - - delegate: QGCButton { - text: modelData - - onClicked: { - hideDialog() - filenameReturned(controller.fullPath(modelData, fileExtension)) - } - } - } - - QGCLabel { - text: qsTr("No files") - visible: controller.getFiles(fileExtension).length == 0 - } - } - } -} diff --git a/src/QmlControls/QGCMobileFileOpenDialog.qml b/src/QmlControls/QGCMobileFileOpenDialog.qml new file mode 100644 index 0000000000000000000000000000000000000000..6577840424d3f55fb1be77ad9225f8d134e65ebc --- /dev/null +++ b/src/QmlControls/QGCMobileFileOpenDialog.qml @@ -0,0 +1,56 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.3 +import QtQuick.Dialogs 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Controllers 1.0 +import QGroundControl.Palette 1.0 + +/// Simple file open dialog for mobile +QGCViewDialog { + property string fileExtension ///< File extension for file listing + + signal filenameReturned(string filename) + + readonly property real _margins: ScreenTools.defaultFontPixelHeight / 2 + + QGCMobileFileDialogController { id: controller } + QGCPalette { id: qgcPal; colorGroupEnabled: true } + + Item { + anchors.margins: _margins + anchors.fill: parent + + QGCListView { + anchors.fill: parent + spacing: _margins / 2 + orientation: ListView.Vertical + model: controller.getFiles(fileExtension) + + delegate: QGCButton { + text: modelData + + onClicked: { + hideDialog() + filenameReturned(controller.fullPath(modelData, fileExtension)) + } + } + } + + QGCLabel { + text: qsTr("No files") + visible: controller.getFiles(fileExtension).length == 0 + } + } +} diff --git a/src/QmlControls/QGCMobileFileSaveDialog.qml b/src/QmlControls/QGCMobileFileSaveDialog.qml new file mode 100644 index 0000000000000000000000000000000000000000..06abfda2bf900c854ece0b03439e7ce7e68a8134 --- /dev/null +++ b/src/QmlControls/QGCMobileFileSaveDialog.qml @@ -0,0 +1,79 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.3 +import QtQuick.Dialogs 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Controllers 1.0 +import QGroundControl.Palette 1.0 + +/// Simple file picker for mobile +QGCViewDialog { + property string fileExtension ///< File extension for file listing + + signal filenameReturned(string filename) + + readonly property real _margins: ScreenTools.defaultFontPixelHeight / 2 + + function accept() { + if (filenameTextField.text == "") { + return + } + if (!replaceMessage.visible) { + if (controller.fileExists(filenameTextField.text, fileExtension)) { + console.log("File exists") + replaceMessage.visible = true + return + } + } + filenameReturned(controller.fullPath(filenameTextField.text, fileExtension)) + hideDialog() + } + + QGCMobileFileDialogController { id: controller } + QGCPalette { id: qgcPal; colorGroupEnabled: true } + + Column { + anchors.left: parent.left + anchors.right: parent.right + spacing: ScreenTools.defaultFontPixelHeight + + QGCLabel { + text: qsTr("File name:") + } + + QGCTextField { + id: filenameTextField + onTextChanged: replaceMessage.visible = false + } + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: qsTr("File names must end with .%1 file extension. If missing it will be added.").arg(fileExtension) + } + + QGCLabel { + id: replaceMessage + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: qsTr("The file %1 exists. Click Save again to replace it.").arg(filenameTextField.text) + visible: false + color: qgcPal.warningText + } + } +} + diff --git a/src/QmlControls/QGCRadioButton.qml b/src/QmlControls/QGCRadioButton.qml index 4747e3d41b169660b683c052508e83802fa67011..cfcb5072c873e0540ca1efefed5b4ec06d338793 100644 --- a/src/QmlControls/QGCRadioButton.qml +++ b/src/QmlControls/QGCRadioButton.qml @@ -1,20 +1,23 @@ -import QtQuick 2.2 -import QtQuick.Controls 1.2 -import QtQuick.Controls.Styles 1.2 +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.2 -import QGroundControl.Palette 1.0 -import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.ScreenTools 1.0 RadioButton { - property var color: _qgcPal.text ///< Text color + property var color: qgcPal.text ///< Text color + property int textStyle: Text.Normal + property color textStyleColor: qgcPal.text - property var _qgcPal: QGCPalette { colorGroupEnabled: enabled } + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } style: RadioButtonStyle { label: Item { implicitWidth: text.implicitWidth + ScreenTools.defaultFontPixelWidth * 0.25 implicitHeight: text.implicitHeight baselineOffset: text.y + text.baselineOffset + Rectangle { anchors.fill: text anchors.margins: -1 @@ -27,6 +30,7 @@ RadioButton { border.color: "#47b" opacity: 0.6 } + Text { id: text text: control.text @@ -34,6 +38,8 @@ RadioButton { font.family: ScreenTools.normalFontFamily antialiasing: true color: control.color + style: control.textStyle + styleColor: control.textStyleColor anchors.centerIn: parent } } diff --git a/src/QmlControls/QGCTextField.qml b/src/QmlControls/QGCTextField.qml index 732bc35619a632056840d5a48a9224b54a928be0..8b5497e905879ee1a466bde6267596e8899939cc 100644 --- a/src/QmlControls/QGCTextField.qml +++ b/src/QmlControls/QGCTextField.qml @@ -26,7 +26,15 @@ TextField { QGCPalette { id: qgcPal; colorGroupEnabled: enabled } textColor: qgcPal.textFieldText - height: Math.round(Math.max(25, ScreenTools.defaultFontPixelHeight * (ScreenTools.isMobile ? 2.5 : 1.2))) + + implicitHeight: ScreenTools.implicitTextFieldHeight + + onEditingFinished: { + if (ScreenTools.isMobile) { + // Toss focus on mobile after Done on virtual keyboard. Prevent strange interactions. + focus = false + } + } QGCLabel { id: unitsLabelWidthGenerator @@ -97,9 +105,10 @@ TextField { } MouseArea { - anchors.fill: unitsHelpLayout - enabled: control.activeFocus - onClicked: root.helpClicked() + anchors.margins: ScreenTools.isMobile ? -(ScreenTools.defaultFontPixelWidth * 0.66) : 0 // Larger touch area for mobile + anchors.fill: unitsHelpLayout + enabled: control.activeFocus + onClicked: root.helpClicked() } } diff --git a/src/QmlControls/QGCToolBarButton.qml b/src/QmlControls/QGCToolBarButton.qml index 106267f33299977f4ad43bbe9717faa49f7a205a..f7d6c8ac9d2c149eafe7cd12f049be1eb2f91b51 100644 --- a/src/QmlControls/QGCToolBarButton.qml +++ b/src/QmlControls/QGCToolBarButton.qml @@ -17,6 +17,7 @@ import QGroundControl.ScreenTools 1.0 Item { id: _root + width: height state: "HelpShown" clip: true diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir index a04b37ba7efe013425c99d90376bf71bf2314b70..97d45d62665e9b25cff1937e7b704527ec30b274 100644 --- a/src/QmlControls/QGroundControl.Controls.qmldir +++ b/src/QmlControls/QGroundControl.Controls.qmldir @@ -3,12 +3,18 @@ Module QGroundControl.Controls AnalyzePage 1.0 AnalyzePage.qml AppMessages 1.0 AppMessages.qml ClickableColor 1.0 ClickableColor.qml +ComplexMissionItem 1.0 ComplexMissionItem.qml DropButton 1.0 DropButton.qml +DropPanel 1.0 DropPanel.qml ExclusiveGroupItem 1.0 ExclusiveGroupItem.qml FactSliderPanel 1.0 FactSliderPanel.qml +FlightModeDropdown 1.0 FlightModeDropdown.qml +FlightModeMenu 1.0 FlightModeMenu.qml +GuidedBar 1.0 GuidedBar.qml IndicatorButton 1.0 IndicatorButton.qml JoystickThumbPad 1.0 JoystickThumbPad.qml MainToolBar 1.0 MainToolBar.qml +MainToolBarIndicators 1.0 MainToolBarIndicators.qml MissionCommandDialog 1.0 MissionCommandDialog.qml MissionItemEditor 1.0 MissionItemEditor.qml MissionItemIndexLabel 1.0 MissionItemIndexLabel.qml @@ -25,8 +31,12 @@ QGCCheckBox 1.0 QGCCheckBox.qml QGCColoredImage 1.0 QGCColoredImage.qml QGCComboBox 1.0 QGCComboBox.qml QGCFlickable 1.0 QGCFlickable.qml +QGCGroupBox 1.0 QGCGroupBox.qml QGCLabel 1.0 QGCLabel.qml -QGCMobileFileDialog 1.0 QGCMobileFileDialog.qml +QGCListView 1.0 QGCListView.qml +QGCMapLabel 1.0 QGCMapLabel.qml +QGCMobileFileOpenDialog 1.0 QGCMobileFileOpenDialog.qml +QGCMobileFileSaveDialog 1.0 QGCMobileFileSaveDialog.qml QGCMovableItem 1.0 QGCMovableItem.qml QGCPipable 1.0 QGCPipable.qml QGCRadioButton 1.0 QGCRadioButton.qml @@ -42,6 +52,8 @@ SetupPage 1.0 SetupPage.qml SignalStrength 1.0 SignalStrength.qml SliderSwitch 1.0 SliderSwitch.qml SubMenuButton 1.0 SubMenuButton.qml +SurveyComplexItem 1.0 SurveyComplexItem.qml +ToolStrip 1.0 ToolStrip.qml VehicleRotationCal 1.0 VehicleRotationCal.qml VehicleSummaryRow 1.0 VehicleSummaryRow.qml ViewWidget 1.0 ViewWidget.qml diff --git a/src/QmlControls/QGroundControlQmlGlobal.cc b/src/QmlControls/QGroundControlQmlGlobal.cc index abd618bc3897b52f0bf93d8c893255da351a0ea2..af893774ea8496833310aeb7d2c8f17394ad3c1e 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.cc +++ b/src/QmlControls/QGroundControlQmlGlobal.cc @@ -19,38 +19,20 @@ static const char* kQmlGlobalKeyName = "QGCQml"; -SettingsFact* QGroundControlQmlGlobal::_distanceUnitsFact = NULL; -FactMetaData* QGroundControlQmlGlobal::_distanceUnitsMetaData = NULL; -SettingsFact* QGroundControlQmlGlobal::_areaUnitsFact = NULL; -FactMetaData* QGroundControlQmlGlobal::_areaUnitsMetaData = NULL; -SettingsFact* QGroundControlQmlGlobal::_speedUnitsFact = NULL; -FactMetaData* QGroundControlQmlGlobal::_speedUnitsMetaData = NULL; -SettingsFact* QGroundControlQmlGlobal::_offlineEditingFirmwareTypeFact = NULL; -SettingsFact* QGroundControlQmlGlobal::_offlineEditingVehicleTypeFact = NULL; -SettingsFact* QGroundControlQmlGlobal::_offlineEditingCruiseSpeedFact = NULL; -SettingsFact* QGroundControlQmlGlobal::_offlineEditingHoverSpeedFact = NULL; -SettingsFact* QGroundControlQmlGlobal::_batteryPercentRemainingAnnounceFact = NULL; - -const char* QGroundControlQmlGlobal::_virtualTabletJoystickKey = "VirtualTabletJoystick"; -const char* QGroundControlQmlGlobal::_baseFontPointSizeKey = "BaseDeviceFontPointSize"; - QGroundControlQmlGlobal::QGroundControlQmlGlobal(QGCApplication* app) : QGCTool(app) , _flightMapSettings(NULL) - , _homePositionManager(NULL) , _linkManager(NULL) , _multiVehicleManager(NULL) , _mapEngineManager(NULL) , _qgcPositionManager(NULL) , _missionCommandTree(NULL) , _videoManager(NULL) - , _virtualTabletJoystick(false) - , _baseFontPointSize(0.0) + , _mavlinkLogManager(NULL) + , _corePlugin(NULL) + , _firmwarePluginManager(NULL) + , _settingsManager(NULL) { - QSettings settings; - _virtualTabletJoystick = settings.value(_virtualTabletJoystickKey, false).toBool(); - _baseFontPointSize = settings.value(_baseFontPointSizeKey, 0.0).toDouble(); - // We clear the parent on this object since we run into shutdown problems caused by hybrid qml app. Instead we let it leak on shutdown. setParent(NULL); } @@ -60,21 +42,23 @@ QGroundControlQmlGlobal::~QGroundControlQmlGlobal() } - void QGroundControlQmlGlobal::setToolbox(QGCToolbox* toolbox) { QGCTool::setToolbox(toolbox); + _flightMapSettings = toolbox->flightMapSettings(); - _homePositionManager = toolbox->homePositionManager(); _linkManager = toolbox->linkManager(); _multiVehicleManager = toolbox->multiVehicleManager(); _mapEngineManager = toolbox->mapEngineManager(); _qgcPositionManager = toolbox->qgcPositionManager(); _missionCommandTree = toolbox->missionCommandTree(); _videoManager = toolbox->videoManager(); + _mavlinkLogManager = toolbox->mavlinkLogManager(); + _corePlugin = toolbox->corePlugin(); + _firmwarePluginManager = toolbox->firmwarePluginManager(); + _settingsManager = toolbox->settingsManager(); } - void QGroundControlQmlGlobal::saveGlobalSetting (const QString& key, const QString& value) { QSettings settings; @@ -153,8 +137,8 @@ void QGroundControlQmlGlobal::stopAllMockLinks(void) #ifdef QT_DEBUG LinkManager* linkManager = qgcApp()->toolbox()->linkManager(); - for (int i=0; ilinks()->count(); i++) { - LinkInterface* link = linkManager->links()->value(i); + for (int i=0; ilinks().count(); i++) { + LinkInterface* link = linkManager->links()[i]; MockLink* mockLink = qobject_cast(link); if (mockLink) { @@ -164,30 +148,6 @@ void QGroundControlQmlGlobal::stopAllMockLinks(void) #endif } -void QGroundControlQmlGlobal::setIsDarkStyle(bool dark) -{ - qgcApp()->setStyle(dark); - emit isDarkStyleChanged(dark); -} - -void QGroundControlQmlGlobal::setIsAudioMuted(bool muted) -{ - qgcApp()->toolbox()->audioOutput()->mute(muted); - emit isAudioMutedChanged(muted); -} - -void QGroundControlQmlGlobal::setIsSaveLogPrompt(bool prompt) -{ - qgcApp()->setPromptFlightDataSave(prompt); - emit isSaveLogPromptChanged(prompt); -} - -void QGroundControlQmlGlobal::setIsSaveLogPromptNotArmed(bool prompt) -{ - qgcApp()->setPromptFlightDataSaveNotArmed(prompt); - emit isSaveLogPromptNotArmedChanged(prompt); -} - void QGroundControlQmlGlobal::setIsVersionCheckEnabled(bool enable) { qgcApp()->toolbox()->mavlinkProtocol()->enableVersionCheck(enable); @@ -200,141 +160,11 @@ void QGroundControlQmlGlobal::setMavlinkSystemID(int id) emit mavlinkSystemIDChanged(id); } -void QGroundControlQmlGlobal::setVirtualTabletJoystick(bool enabled) -{ - if (_virtualTabletJoystick != enabled) { - QSettings settings; - settings.setValue(_virtualTabletJoystickKey, enabled); - _virtualTabletJoystick = enabled; - emit virtualTabletJoystickChanged(enabled); - } -} - -void QGroundControlQmlGlobal::setBaseFontPointSize(qreal size) -{ - if (size >= 6.0 && size <= 48.0) { - QSettings settings; - settings.setValue(_baseFontPointSizeKey, size); - _baseFontPointSize = size; - emit baseFontPointSizeChanged(size); - } -} - -SettingsFact* QGroundControlQmlGlobal::_createSettingsFact(const QString& name) -{ - SettingsFact* fact; - FactMetaData* metaData = nameToMetaDataMap()[name]; - - fact = new SettingsFact(QString(), name, metaData->type(), metaData->rawDefaultValue()); - fact->setMetaData(metaData); - - return fact; -} - -Fact* QGroundControlQmlGlobal::offlineEditingFirmwareType(void) -{ - if (!_offlineEditingFirmwareTypeFact) { - _offlineEditingFirmwareTypeFact = _createSettingsFact(QStringLiteral("OfflineEditingFirmwareType")); - } - - return _offlineEditingFirmwareTypeFact; -} - -Fact* QGroundControlQmlGlobal::offlineEditingVehicleType(void) -{ - if (!_offlineEditingVehicleTypeFact) { - _offlineEditingVehicleTypeFact = _createSettingsFact(QStringLiteral("OfflineEditingVehicleType")); - } - - return _offlineEditingVehicleTypeFact; -} - -Fact* QGroundControlQmlGlobal::offlineEditingCruiseSpeed(void) -{ - if (!_offlineEditingCruiseSpeedFact) { - _offlineEditingCruiseSpeedFact = _createSettingsFact(QStringLiteral("OfflineEditingCruiseSpeed")); - } - return _offlineEditingCruiseSpeedFact; -} - -Fact* QGroundControlQmlGlobal::offlineEditingHoverSpeed(void) +int QGroundControlQmlGlobal::supportedFirmwareCount() { - if (!_offlineEditingHoverSpeedFact) { - _offlineEditingHoverSpeedFact = _createSettingsFact(QStringLiteral("OfflineEditingHoverSpeed")); - } - return _offlineEditingHoverSpeedFact; + return _firmwarePluginManager->supportedFirmwareTypes().count(); } -Fact* QGroundControlQmlGlobal::distanceUnits(void) -{ - if (!_distanceUnitsFact) { - // Distance/Area/Speed units settings can't be loaded from json since it creates an infinite loop of meta data loading. - QStringList enumStrings; - QVariantList enumValues; - - _distanceUnitsFact = new SettingsFact(QString(), "DistanceUnits", FactMetaData::valueTypeUint32, DistanceUnitsMeters); - _distanceUnitsMetaData = new FactMetaData(FactMetaData::valueTypeUint32); - - enumStrings << "Feet" << "Meters"; - enumValues << QVariant::fromValue((uint32_t)DistanceUnitsFeet) << QVariant::fromValue((uint32_t)DistanceUnitsMeters); - - _distanceUnitsMetaData->setEnumInfo(enumStrings, enumValues); - _distanceUnitsFact->setMetaData(_distanceUnitsMetaData); - } - - return _distanceUnitsFact; - -} - -Fact* QGroundControlQmlGlobal::areaUnits(void) -{ - if (!_areaUnitsFact) { - // Distance/Area/Speed units settings can't be loaded from json since it creates an infinite loop of meta data loading. - QStringList enumStrings; - QVariantList enumValues; - - _areaUnitsFact = new SettingsFact(QString(), "AreaUnits", FactMetaData::valueTypeUint32, AreaUnitsSquareMeters); - _areaUnitsMetaData = new FactMetaData(FactMetaData::valueTypeUint32); - - enumStrings << "SquareFeet" << "SquareMeters" << "SquareKilometers" << "Hectares" << "Acres" << "SquareMiles"; - enumValues << QVariant::fromValue((uint32_t)AreaUnitsSquareFeet) << QVariant::fromValue((uint32_t)AreaUnitsSquareMeters) << QVariant::fromValue((uint32_t)AreaUnitsSquareKilometers) << QVariant::fromValue((uint32_t)AreaUnitsHectares) << QVariant::fromValue((uint32_t)AreaUnitsAcres) << QVariant::fromValue((uint32_t)AreaUnitsSquareMiles); - - _areaUnitsMetaData->setEnumInfo(enumStrings, enumValues); - _areaUnitsFact->setMetaData(_areaUnitsMetaData); - } - - return _areaUnitsFact; - -} - -Fact* QGroundControlQmlGlobal::speedUnits(void) -{ - if (!_speedUnitsFact) { - // Distance/Area/Speed units settings can't be loaded from json since it creates an infinite loop of meta data loading. - QStringList enumStrings; - QVariantList enumValues; - - _speedUnitsFact = new SettingsFact(QString(), "SpeedUnits", FactMetaData::valueTypeUint32, SpeedUnitsMetersPerSecond); - _speedUnitsMetaData = new FactMetaData(FactMetaData::valueTypeUint32); - - enumStrings << "Feet/second" << "Meters/second" << "Miles/hour" << "Kilometers/hour" << "Knots"; - enumValues << QVariant::fromValue((uint32_t)SpeedUnitsFeetPerSecond) << QVariant::fromValue((uint32_t)SpeedUnitsMetersPerSecond) << QVariant::fromValue((uint32_t)SpeedUnitsMilesPerHour) << QVariant::fromValue((uint32_t)SpeedUnitsKilometersPerHour) << QVariant::fromValue((uint32_t)SpeedUnitsKnots); - - _speedUnitsMetaData->setEnumInfo(enumStrings, enumValues); - _speedUnitsFact->setMetaData(_speedUnitsMetaData); - } - - return _speedUnitsFact; -} - -Fact* QGroundControlQmlGlobal::batteryPercentRemainingAnnounce(void) -{ - if (!_batteryPercentRemainingAnnounceFact) { - _batteryPercentRemainingAnnounceFact = _createSettingsFact(QStringLiteral("batteryPercentRemainingAnnounce")); - } - - return _batteryPercentRemainingAnnounceFact; -} bool QGroundControlQmlGlobal::linesIntersect(QPointF line1A, QPointF line1B, QPointF line2A, QPointF line2B) { @@ -343,13 +173,3 @@ bool QGroundControlQmlGlobal::linesIntersect(QPointF line1A, QPointF line1B, QPo return QLineF(line1A, line1B).intersect(QLineF(line2A, line2B), &intersectPoint) == QLineF::BoundedIntersection && intersectPoint != line1A && intersectPoint != line1B; } - -QMap& QGroundControlQmlGlobal::nameToMetaDataMap(void) { - static QMap map; - - if (map.isEmpty()) { - map = FactMetaData::createMapFromJsonFile(":/json/QGroundControlQmlGlobal.json", NULL); - } - - return map; -} diff --git a/src/QmlControls/QGroundControlQmlGlobal.h b/src/QmlControls/QGroundControlQmlGlobal.h index 69180218490dda7bbdcb5a6de89eadafc3d14f48..047e3f86e94e6e61b3ce4b8dd6d39ba35b69ef8c 100644 --- a/src/QmlControls/QGroundControlQmlGlobal.h +++ b/src/QmlControls/QGroundControlQmlGlobal.h @@ -17,7 +17,6 @@ #include "QGCToolbox.h" #include "QGCApplication.h" #include "LinkManager.h" -#include "HomePositionManager.h" #include "FlightMapSettings.h" #include "SettingsFact.h" #include "FactMetaData.h" @@ -38,67 +37,28 @@ public: QGroundControlQmlGlobal(QGCApplication* app); ~QGroundControlQmlGlobal(); - enum DistanceUnits { - DistanceUnitsFeet = 0, - DistanceUnitsMeters - }; - - enum AreaUnits { - AreaUnitsSquareFeet = 0, - AreaUnitsSquareMeters, - AreaUnitsSquareKilometers, - AreaUnitsHectares, - AreaUnitsAcres, - AreaUnitsSquareMiles, - }; - - enum SpeedUnits { - SpeedUnitsFeetPerSecond = 0, - SpeedUnitsMetersPerSecond, - SpeedUnitsMilesPerHour, - SpeedUnitsKilometersPerHour, - SpeedUnitsKnots, - }; - - Q_ENUMS(DistanceUnits) - Q_ENUMS(AreaUnits) - Q_ENUMS(SpeedUnits) - Q_PROPERTY(FlightMapSettings* flightMapSettings READ flightMapSettings CONSTANT) - Q_PROPERTY(HomePositionManager* homePositionManager READ homePositionManager CONSTANT) Q_PROPERTY(LinkManager* linkManager READ linkManager CONSTANT) Q_PROPERTY(MultiVehicleManager* multiVehicleManager READ multiVehicleManager CONSTANT) Q_PROPERTY(QGCMapEngineManager* mapEngineManager READ mapEngineManager CONSTANT) Q_PROPERTY(QGCPositionManager* qgcPositionManger READ qgcPositionManger CONSTANT) Q_PROPERTY(MissionCommandTree* missionCommandTree READ missionCommandTree CONSTANT) Q_PROPERTY(VideoManager* videoManager READ videoManager CONSTANT) + Q_PROPERTY(MAVLinkLogManager* mavlinkLogManager READ mavlinkLogManager CONSTANT) + Q_PROPERTY(QGCCorePlugin* corePlugin READ corePlugin CONSTANT) + Q_PROPERTY(SettingsManager* settingsManager READ settingsManager CONSTANT) + + Q_PROPERTY(int supportedFirmwareCount READ supportedFirmwareCount CONSTANT) Q_PROPERTY(qreal zOrderTopMost READ zOrderTopMost CONSTANT) ///< z order for top most items, toolbar, main window sub view Q_PROPERTY(qreal zOrderWidgets READ zOrderWidgets CONSTANT) ///< z order value to widgets, for example: zoom controls, hud widgetss Q_PROPERTY(qreal zOrderMapItems READ zOrderMapItems CONSTANT) ///< z order value for map items, for example: mission item indicators - // Various QGC settings exposed to Qml - Q_PROPERTY(bool isAdvancedMode READ isAdvancedMode CONSTANT) ///< Global "Advance Mode" preference. Certain UI elements and features are different based on this. - Q_PROPERTY(bool isDarkStyle READ isDarkStyle WRITE setIsDarkStyle NOTIFY isDarkStyleChanged) // TODO: Should be in ScreenTools? - Q_PROPERTY(bool isAudioMuted READ isAudioMuted WRITE setIsAudioMuted NOTIFY isAudioMutedChanged) - Q_PROPERTY(bool isSaveLogPrompt READ isSaveLogPrompt WRITE setIsSaveLogPrompt NOTIFY isSaveLogPromptChanged) - Q_PROPERTY(bool isSaveLogPromptNotArmed READ isSaveLogPromptNotArmed WRITE setIsSaveLogPromptNotArmed NOTIFY isSaveLogPromptNotArmedChanged) - Q_PROPERTY(bool virtualTabletJoystick READ virtualTabletJoystick WRITE setVirtualTabletJoystick NOTIFY virtualTabletJoystickChanged) - Q_PROPERTY(qreal baseFontPointSize READ baseFontPointSize WRITE setBaseFontPointSize NOTIFY baseFontPointSizeChanged) - + //------------------------------------------------------------------------- // MavLink Protocol Q_PROPERTY(bool isVersionCheckEnabled READ isVersionCheckEnabled WRITE setIsVersionCheckEnabled NOTIFY isVersionCheckEnabledChanged) Q_PROPERTY(int mavlinkSystemID READ mavlinkSystemID WRITE setMavlinkSystemID NOTIFY mavlinkSystemIDChanged) - Q_PROPERTY(Fact* offlineEditingFirmwareType READ offlineEditingFirmwareType CONSTANT) - Q_PROPERTY(Fact* offlineEditingVehicleType READ offlineEditingVehicleType CONSTANT) - Q_PROPERTY(Fact* offlineEditingCruiseSpeed READ offlineEditingCruiseSpeed CONSTANT) - Q_PROPERTY(Fact* offlineEditingHoverSpeed READ offlineEditingHoverSpeed CONSTANT) - Q_PROPERTY(Fact* distanceUnits READ distanceUnits CONSTANT) - Q_PROPERTY(Fact* areaUnits READ areaUnits CONSTANT) - Q_PROPERTY(Fact* speedUnits READ speedUnits CONSTANT) - Q_PROPERTY(Fact* batteryPercentRemainingAnnounce READ batteryPercentRemainingAnnounce CONSTANT) - Q_PROPERTY(QGeoCoordinate lastKnownHomePosition READ lastKnownHomePosition CONSTANT) Q_PROPERTY(QGeoCoordinate flightMapPosition MEMBER _flightMapPosition NOTIFY flightMapPositionChanged) Q_PROPERTY(double flightMapZoom MEMBER _flightMapZoom NOTIFY flightMapZoomChanged) @@ -111,6 +71,8 @@ public: Q_PROPERTY(QString appSettingsDistanceUnitsString READ appSettingsDistanceUnitsString CONSTANT) Q_PROPERTY(QString appSettingsAreaUnitsString READ appSettingsAreaUnitsString CONSTANT) + Q_PROPERTY(QString qgcVersion READ qgcVersion CONSTANT) + Q_INVOKABLE void saveGlobalSetting (const QString& key, const QString& value); Q_INVOKABLE QString loadGlobalSetting (const QString& key, const QString& defaultValue); Q_INVOKABLE void saveBoolGlobalSetting (const QString& key, bool value); @@ -146,61 +108,41 @@ public: Q_INVOKABLE QStringList loggingCategories(void) const { return QGCLoggingCategoryRegister::instance()->registeredCategories(); } /// Turns on/off logging for the specified category. State is saved in app settings. - Q_INVOKABLE void setCategoryLoggingOn(const QString& category, bool enable) { QGCLoggingCategoryRegister::instance()->setCategoryLoggingOn(category, enable); }; + Q_INVOKABLE void setCategoryLoggingOn(const QString& category, bool enable) { QGCLoggingCategoryRegister::instance()->setCategoryLoggingOn(category, enable); } /// Returns true if logging is turned on for the specified category. - Q_INVOKABLE bool categoryLoggingOn(const QString& category) { return QGCLoggingCategoryRegister::instance()->categoryLoggingOn(category); }; + Q_INVOKABLE bool categoryLoggingOn(const QString& category) { return QGCLoggingCategoryRegister::instance()->categoryLoggingOn(category); } /// Updates the logging filter rules after settings have changed Q_INVOKABLE void updateLoggingFilterRules(void) { QGCLoggingCategoryRegister::instance()->setFilterRulesFromSettings(QString()); } Q_INVOKABLE bool linesIntersect(QPointF xLine1, QPointF yLine1, QPointF xLine2, QPointF yLine2); + Q_INVOKABLE QString urlToLocalFile(QUrl url) { return url.toLocalFile(); } + // Property accesors - FlightMapSettings* flightMapSettings () { return _flightMapSettings; } - HomePositionManager* homePositionManager () { return _homePositionManager; } - LinkManager* linkManager () { return _linkManager; } - MultiVehicleManager* multiVehicleManager () { return _multiVehicleManager; } - QGCMapEngineManager* mapEngineManager () { return _mapEngineManager; } - QGCPositionManager* qgcPositionManger () { return _qgcPositionManager; } - MissionCommandTree* missionCommandTree () { return _missionCommandTree; } - VideoManager* videoManager () { return _videoManager; } - - qreal zOrderTopMost () { return 1000; } - qreal zOrderWidgets () { return 100; } - qreal zOrderMapItems () { return 50; } - - bool isDarkStyle () { return _app->styleIsDark(); } - bool isAudioMuted () { return _toolbox->audioOutput()->isMuted(); } - bool isSaveLogPrompt () { return _app->promptFlightDataSave(); } - bool isSaveLogPromptNotArmed () { return _app->promptFlightDataSaveNotArmed(); } - bool virtualTabletJoystick () { return _virtualTabletJoystick; } - qreal baseFontPointSize () { return _baseFontPointSize; } + FlightMapSettings* flightMapSettings () { return _flightMapSettings; } + LinkManager* linkManager () { return _linkManager; } + MultiVehicleManager* multiVehicleManager () { return _multiVehicleManager; } + QGCMapEngineManager* mapEngineManager () { return _mapEngineManager; } + QGCPositionManager* qgcPositionManger () { return _qgcPositionManager; } + MissionCommandTree* missionCommandTree () { return _missionCommandTree; } + VideoManager* videoManager () { return _videoManager; } + MAVLinkLogManager* mavlinkLogManager () { return _mavlinkLogManager; } + QGCCorePlugin* corePlugin () { return _corePlugin; } + SettingsManager* settingsManager () { return _settingsManager; } + + qreal zOrderTopMost () { return 1000; } + qreal zOrderWidgets () { return 100; } + qreal zOrderMapItems () { return 50; } bool isVersionCheckEnabled () { return _toolbox->mavlinkProtocol()->versionCheckEnabled(); } int mavlinkSystemID () { return _toolbox->mavlinkProtocol()->getSystemId(); } QGeoCoordinate lastKnownHomePosition() { return qgcApp()->lastKnownHomePosition(); } - static Fact* offlineEditingFirmwareType (void); - static Fact* offlineEditingVehicleType (void); - static Fact* offlineEditingCruiseSpeed (void); - static Fact* offlineEditingHoverSpeed (void); - static Fact* distanceUnits (void); - static Fact* areaUnits (void); - static Fact* speedUnits (void); - static Fact* batteryPercentRemainingAnnounce(void); - - //-- TODO: Make this into an actual preference. - bool isAdvancedMode () { return false; } - - void setIsDarkStyle (bool dark); - void setIsAudioMuted (bool muted); - void setIsSaveLogPrompt (bool prompt); - void setIsSaveLogPromptNotArmed (bool prompt); - void setVirtualTabletJoystick (bool enabled); - void setBaseFontPointSize (qreal size); + int supportedFirmwareCount (); void setIsVersionCheckEnabled (bool enable); void setMavlinkSystemID (int id); @@ -209,16 +151,12 @@ public: QString missionFileExtension(void) const { return QGCApplication::missionFileExtension; } QString telemetryFileExtension(void) const { return QGCApplication::telemetryFileExtension; } + QString qgcVersion(void) const { return qgcApp()->applicationVersion(); } + // Overrides from QGCTool virtual void setToolbox(QGCToolbox* toolbox); signals: - void isDarkStyleChanged (bool dark); - void isAudioMutedChanged (bool muted); - void isSaveLogPromptChanged (bool prompt); - void isSaveLogPromptNotArmedChanged (bool prompt); - void virtualTabletJoystickChanged (bool enabled); - void baseFontPointSizeChanged (qreal size); void isMultiplexingEnabledChanged (bool enabled); void isVersionCheckEnabledChanged (bool enabled); void mavlinkSystemIDChanged (int id); @@ -226,38 +164,20 @@ signals: void flightMapZoomChanged (double flightMapZoom); private: - static SettingsFact* _createSettingsFact(const QString& name); - static QMap& nameToMetaDataMap(void); - FlightMapSettings* _flightMapSettings; - HomePositionManager* _homePositionManager; LinkManager* _linkManager; MultiVehicleManager* _multiVehicleManager; QGCMapEngineManager* _mapEngineManager; QGCPositionManager* _qgcPositionManager; MissionCommandTree* _missionCommandTree; VideoManager* _videoManager; + MAVLinkLogManager* _mavlinkLogManager; + QGCCorePlugin* _corePlugin; + FirmwarePluginManager* _firmwarePluginManager; + SettingsManager* _settingsManager; - bool _virtualTabletJoystick; - qreal _baseFontPointSize; QGeoCoordinate _flightMapPosition; double _flightMapZoom; - - // These are static so they are available to C++ code as well as Qml - static SettingsFact* _offlineEditingFirmwareTypeFact; - static SettingsFact* _offlineEditingVehicleTypeFact; - static SettingsFact* _offlineEditingCruiseSpeedFact; - static SettingsFact* _offlineEditingHoverSpeedFact; - static SettingsFact* _distanceUnitsFact; - static FactMetaData* _distanceUnitsMetaData; - static SettingsFact* _areaUnitsFact; - static FactMetaData* _areaUnitsMetaData; - static SettingsFact* _speedUnitsFact; - static FactMetaData* _speedUnitsMetaData; - static SettingsFact* _batteryPercentRemainingAnnounceFact; - - static const char* _virtualTabletJoystickKey; - static const char* _baseFontPointSizeKey; }; #endif diff --git a/src/QmlControls/QGroundControlQmlGlobal.json b/src/QmlControls/QGroundControlQmlGlobal.json deleted file mode 100644 index f32ee0b637d55d227731d1a01f5e3dfa4033074e..0000000000000000000000000000000000000000 --- a/src/QmlControls/QGroundControlQmlGlobal.json +++ /dev/null @@ -1,48 +0,0 @@ -[ -{ - "name": "OfflineEditingFirmwareType", - "shortDescription": "Offline editing firmware type", - "type": "uint32", - "enumStrings": "ArduPilot Firmware,PX4 Pro Firmware,Mavlink Generic Firmware", - "enumValues": "3,12,0", - "defaultValue": 3 -}, -{ - "name": "OfflineEditingVehicleType", - "shortDescription": "Offline editing vehicle type", - "type": "uint32", - "enumStrings": "Fixedwing,Multicopter,VTOL,Rover,Sub", - "enumValues": "1,2,19,10,12", - "defaultValue": 1 -}, -{ - "name": "OfflineEditingCruiseSpeed", - "shortDescription": "Offline editing cruise speed", - "longDescription": "This value defines the cruising speed for forward flight vehicles for use in calculating mission duration when not connected to a vehicle.", - "type": "double", - "defaultValue": 16.0, - "min": 1.0, - "units": "m/s", - "decimalPlaces": 2 -}, -{ - "name": "OfflineEditingHoverSpeed", - "shortDescription": "Offline editing hover speed", - "longDescription": "This value defines the cruising speed for multi-rotor vehicles for use in calculating mission duration when not connected to a vehicle.", - "type": "double", - "defaultValue": 4.0, - "min": 1.0, - "units": "m/s", - "decimalPlaces": 2 -}, -{ - "name": "batteryPercentRemainingAnnounce", - "shortDescription": "Announce battery remaining percent", - "longDescription": "QGroundControl will announce the remaining battery percent when it falls below the specified percentage.", - "type": "uint32", - "defaultValue": 30, - "units": "%", - "min": 0, - "max": 100 -} -] diff --git a/src/QmlControls/ScreenTools.qml b/src/QmlControls/ScreenTools.qml index a39be4d577585b886ac22bccd364826ae026a0bc..0d2d2a27f1aff60e1feea92e8368c7c85770d166 100644 --- a/src/QmlControls/ScreenTools.qml +++ b/src/QmlControls/ScreenTools.qml @@ -47,6 +47,7 @@ Item { property real largeFontPointSize: 10 property real availableHeight: 0 + property real toolbarHeight: 0 readonly property real smallFontPointRatio: 0.75 readonly property real mediumFontPointRatio: 1.25 @@ -59,6 +60,14 @@ Item { property bool isTinyScreen: (Screen.width / Screen.pixelDensity) < 120 // 120mm property bool isShortScreen: ScreenToolsController.isMobile && ((Screen.height / Screen.width) < 0.6) // Nexus 7 for example + // The implicit heights/widths for our custom control set + property real implicitButtonWidth: Math.round(defaultFontPixelWidth * (isMobile ? 7.0 : 5.0)) + property real implicitButtonHeight: Math.round(defaultFontPixelHeight * (isMobile ? 2.0 : 1.6)) + property real implicitCheckBoxWidth: Math.round(defaultFontPixelHeight * (isMobile ? 1.5 : 1.0)) + property real implicitTextFieldHeight: Math.round(defaultFontPixelHeight * (isMobile ? 2.0 : 1.6)) + property real implicitComboBoxHeight: Math.round(defaultFontPixelHeight * (isMobile ? 2.0 : 1.6)) + property real implicitComboBoxWidth: Math.round(defaultFontPixelWidth * (isMobile ? 7.0 : 5.0)) + readonly property string normalFontFamily: "opensans" readonly property string demiboldFontFamily: "opensans-demibold" @@ -66,10 +75,10 @@ Item { I've disabled (in release builds) until I figure out why. Changes require a restart for now. */ Connections { - target: QGroundControl - onBaseFontPointSizeChanged: { + target: QGroundControl.settingsManager.appSettings.appFontPointSize + onValueChanged: { if(ScreenToolsController.isDebug) - _setBasePointSize(QGroundControl.baseFontPointSize) + _setBasePointSize(QGroundControl.settingsManager.appSettings.appFontPointSize.value) } } @@ -87,11 +96,12 @@ Item { function _setBasePointSize(pointSize) { _textMeasure.font.pointSize = pointSize defaultFontPointSize = pointSize - defaultFontPixelHeight = _textMeasure.fontHeight - defaultFontPixelWidth = _textMeasure.fontWidth + defaultFontPixelHeight = Math.round(_textMeasure.fontHeight/2.0)*2 + defaultFontPixelWidth = Math.round(_textMeasure.fontWidth/2.0)*2 smallFontPointSize = defaultFontPointSize * _screenTools.smallFontPointRatio mediumFontPointSize = defaultFontPointSize * _screenTools.mediumFontPointRatio largeFontPointSize = defaultFontPointSize * _screenTools.largeFontPointRatio + toolbarHeight = defaultFontPixelHeight * 3 * QGroundControl.corePlugin.options.toolbarHeightMultiplier } Text { @@ -106,9 +116,10 @@ Item { property real fontWidth: contentWidth property real fontHeight: contentHeight Component.onCompleted: { - var baseSize = QGroundControl.baseFontPointSize; + var _appFontPointSizeFact = QGroundControl.settingsManager.appSettings.appFontPointSize + var baseSize = _appFontPointSizeFact.value //-- If this is the first time (not saved in settings) - if(baseSize < 6 || baseSize > 48) { + if(baseSize < _appFontPointSizeFact.min || baseSize > _appFontPointSizeFact.max) { //-- Init base size base on the platform if(ScreenToolsController.isMobile) { //-- Check iOS really tiny screens (iPhone 4s/5/5s) @@ -137,7 +148,7 @@ Item { else baseSize = _defaultFont.font.pointSize; } - QGroundControl.baseFontPointSize = baseSize + _appFontPointSizeFact.value = baseSize //-- Release build doesn't get signal if(!ScreenToolsController.isDebug) _screenTools._setBasePointSize(baseSize); diff --git a/src/QmlControls/ScreenToolsController.h b/src/QmlControls/ScreenToolsController.h index 47d7dcb012da95cb12e2e580afd9f53cdaa8e50a..86e5ee247543df4869be67a404047a7fc92944b7 100644 --- a/src/QmlControls/ScreenToolsController.h +++ b/src/QmlControls/ScreenToolsController.h @@ -42,34 +42,35 @@ public: Q_INVOKABLE int mouseX(void) { return QCursor::pos().x(); } Q_INVOKABLE int mouseY(void) { return QCursor::pos().y(); } +#if defined(__mobile__) + bool isMobile () { return true; } +#else + bool isMobile () { return qgcApp()->fakeMobile(); } +#endif + #if defined (__android__) bool isAndroid () { return true; } bool isiOS () { return false; } - bool isMobile () { return true; } bool isLinux () { return false; } bool isMacOS () { return false; } #elif defined(__ios__) bool isAndroid () { return false; } bool isiOS () { return true; } - bool isMobile () { return true; } bool isLinux () { return false; } bool isMacOS () { return false; } #elif defined(__macos__) bool isAndroid () { return false; } bool isiOS () { return false; } - bool isMobile () { return qgcApp()->fakeMobile(); } bool isLinux () { return false; } bool isMacOS () { return true; } #elif defined(Q_OS_LINUX) bool isAndroid () { return false; } bool isiOS () { return false; } - bool isMobile () { return qgcApp()->fakeMobile(); } bool isLinux () { return true; } bool isMacOS () { return false; } #else bool isAndroid () { return false; } bool isiOS () { return false; } - bool isMobile () { return qgcApp()->fakeMobile(); } bool isLinux () { return false; } bool isMacOS () { return false; } #endif diff --git a/src/QmlControls/SubMenuButton.qml b/src/QmlControls/SubMenuButton.qml index 640458cebe182dbf142621aabc27445b8ebbd839..6698d27f1fd852760ba2bffe346306a4cecf8276 100644 --- a/src/QmlControls/SubMenuButton.qml +++ b/src/QmlControls/SubMenuButton.qml @@ -7,9 +7,11 @@ import QGroundControl.Palette 1.0 import QGroundControl.ScreenTools 1.0 Button { + id: _rootButton property bool setupComplete: true ///< true: setup complete indicator shows as completed property bool setupIndicator: true ///< true: show setup complete indicator property string imageResource: "/qmlimages/subMenuButtonImage.png" ///< Button image + property size sourceSize: Qt.size(ScreenTools.defaultFontPixelHeight * 2, ScreenTools.defaultFontPixelHeight * 2) text: "Button" ///< Pass in your own button text @@ -40,9 +42,10 @@ Button { width: ScreenTools.defaultFontPixelHeight * 2 height: ScreenTools.defaultFontPixelHeight * 2 fillMode: Image.PreserveAspectFit - smooth: true + mipmap: true color: control.setupComplete ? qgcPal.button : "red" source: control.imageResource + sourceSize: _rootButton.sourceSize } QGCLabel { diff --git a/src/QmlControls/ToolStrip.qml b/src/QmlControls/ToolStrip.qml new file mode 100644 index 0000000000000000000000000000000000000000..0df07900f9996c583ed29054e225714acffa6926 --- /dev/null +++ b/src/QmlControls/ToolStrip.qml @@ -0,0 +1,225 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Controls 1.2 + +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +Rectangle { + id: _root + color: qgcPal.window + width: ScreenTools.defaultFontPixelWidth * 6 + height: buttonStripColumn.height + (buttonStripColumn.anchors.margins * 2) + radius: _radius + + property string title: "Title" + property alias model: repeater.model + property var showAlternateIcon ///< List of bool values, one for each button in strip - true: show alternate icon, false: show normal icon + property var rotateImage ///< List of bool values, one for each button in strip - true: animation rotation, false: static image + property var buttonEnabled ///< List of bool values, one for each button in strip - true: button enabled, false: button disabled + property var buttonVisible ///< List of bool values, one for each button in strip - true: button visible, false: button invisible + property real maxHeight ///< Maximum height for control, determines whether text is hidden to make control shorter + + signal clicked(int index, bool checked) + + readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2 + readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2 + readonly property real _buttonSpacing: ScreenTools.defaultFontPixelWidth + + // All of the following values, connections and function are to support the ability to determine + // whether to show or hide the optional elements on the fly. + + property bool _showOptionalElements: true + property bool _needRecalc: true + + Component.onCompleted: recalcShowOptionalElements() + + onMaxHeightChanged: recalcShowOptionalElements() + + Connections { + target: ScreenTools + + onDefaultFontPixelWidthChanged: recalcShowOptionalElements() + onDefaultFontPixelHeightChanged: recalcShowOptionalElements() + } + + onHeightChanged: { + if (_needRecalc) { + _needRecalc = false + if (maxHeight && height > maxHeight) { + _showOptionalElements = false + } + } + } + + function recalcShowOptionalElements() { + if (_showOptionalElements) { + if (maxHeight && height > maxHeight) { + _showOptionalElements = false + } + } else { + _needRecalc = true + _showOptionalElements = true + } + + } + + QGCPalette { id: qgcPal } + ExclusiveGroup { id: dropButtonsExclusiveGroup } + + function uncheckAll() { + dropButtonsExclusiveGroup.current = null + // Signal all toggles as off + for (var i=0; i(); qRegisterMetaType(); qRegisterMetaType>(); - connect(&_worker, &QGCCacheWorker::updateTotals, this, &QGCMapEngine::_updateTotals); + connect(&_worker, &QGCCacheWorker::updateTotals, this, &QGCMapEngine::_updateTotals); + connect(&_worker, &QGCCacheWorker::internetStatus, this, &QGCMapEngine::_internetStatus); } //----------------------------------------------------------------------------- @@ -483,5 +485,19 @@ QGCCreateTileSetTask::~QGCCreateTileSetTask() delete _tileSet; } +//----------------------------------------------------------------------------- +void +QGCMapEngine::testInternet() +{ + getQGCMapEngine()->addTask(new QGCTestInternetTask()); +} + +//----------------------------------------------------------------------------- +void +QGCMapEngine::_internetStatus(bool active) +{ + _isInternetActive = active; +} + // Resolution math: https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Resolution_and_Scale diff --git a/src/QtLocationPlugin/QGCMapEngine.h b/src/QtLocationPlugin/QGCMapEngine.h index 8b38d130004f07a4715e1e9d916f96631f8f02a3..8ecedd98026987938a8fb49c1af341a15937ac77 100644 --- a/src/QtLocationPlugin/QGCMapEngine.h +++ b/src/QtLocationPlugin/QGCMapEngine.h @@ -86,7 +86,9 @@ public: void setMaxMemCache (quint32 size); const QString getCachePath () { return _cachePath; } const QString getCacheFilename () { return _cacheFile; } + void testInternet (); bool wasCacheReset () { return _cacheWasReset; } + bool isInternetActive () { return _isInternetActive; } UrlFactory* urlFactory () { return _urlFactory; } @@ -103,6 +105,7 @@ public: private slots: void _updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize); void _pruned (); + void _internetStatus (bool active); signals: void updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize); @@ -123,6 +126,7 @@ private: quint32 _maxMemCache; bool _prunning; bool _cacheWasReset; + bool _isInternetActive; }; extern QGCMapEngine* getQGCMapEngine(); diff --git a/src/QtLocationPlugin/QGCMapEngineData.h b/src/QtLocationPlugin/QGCMapEngineData.h index 1e70939ba771a48fa4235b393ef7e722df5ea1af..5765aa8560d6b9fd3fa08388b7a25690d54b9641 100644 --- a/src/QtLocationPlugin/QGCMapEngineData.h +++ b/src/QtLocationPlugin/QGCMapEngineData.h @@ -110,6 +110,7 @@ public: enum TaskType { taskInit, + taskTestInternet, taskCacheTile, taskFetchTile, taskFetchTileSets, @@ -129,7 +130,7 @@ public: virtual TaskType type () { return _type; } - void setError(QString errorString) + void setError(QString errorString = QString()) { emit error(_type, errorString); } @@ -141,6 +142,16 @@ private: TaskType _type; }; +//----------------------------------------------------------------------------- +class QGCTestInternetTask : public QGCMapTask +{ + Q_OBJECT +public: + QGCTestInternetTask() + : QGCMapTask(QGCMapTask::taskTestInternet) + {} +}; + //----------------------------------------------------------------------------- class QGCFetchTileSetTask : public QGCMapTask { diff --git a/src/QtLocationPlugin/QGCMapTileSet.cpp b/src/QtLocationPlugin/QGCMapTileSet.cpp index 71f770f3c7344910e543058959137bb3b8118e1f..f5c0e10821e2294cf372102081fe090263121d69 100644 --- a/src/QtLocationPlugin/QGCMapTileSet.cpp +++ b/src/QtLocationPlugin/QGCMapTileSet.cpp @@ -232,11 +232,20 @@ void QGCCachedTileSet::_prepareDownload() _tilesToDownload.removeFirst(); QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL(tile->type(), tile->x(), tile->y(), tile->z(), _networkManager); request.setAttribute(QNetworkRequest::User, tile->hash()); +#if !defined(__mobile__) + QNetworkProxy proxy = _networkManager->proxy(); + QNetworkProxy tProxy; + tProxy.setType(QNetworkProxy::DefaultProxy); + _networkManager->setProxy(tProxy); +#endif QNetworkReply* reply = _networkManager->get(request); reply->setParent(0); connect(reply, &QNetworkReply::finished, this, &QGCCachedTileSet::_networkReplyFinished); connect(reply, static_cast(&QNetworkReply::error), this, &QGCCachedTileSet::_networkReplyError); _replies.insert(tile->hash(), reply); +#if !defined(__mobile__) + _networkManager->setProxy(proxy); +#endif delete tile; //-- Refill queue if running low if(!_batchRequested && !_noMoreTiles && _tilesToDownload.count() < (QGCMapEngine::concurrentDownloads(_type) * 10)) { @@ -309,7 +318,7 @@ QGCCachedTileSet::_networkReplyError(QNetworkReply::NetworkError error) if (!reply) { return; } - //-- Upodate error count + //-- Update error count _errorCount++; emit errorCountChanged(); //-- Get tile hash diff --git a/src/QtLocationPlugin/QGCMapUrlEngine.cpp b/src/QtLocationPlugin/QGCMapUrlEngine.cpp index 9d1adec9ebf9725c653e87a21c1555f74bd3dd3a..43eebe1e3346541144f19471b4740ca57a6c5c5a 100644 --- a/src/QtLocationPlugin/QGCMapUrlEngine.cpp +++ b/src/QtLocationPlugin/QGCMapUrlEngine.cpp @@ -45,10 +45,10 @@ UrlFactory::UrlFactory() #ifndef QGC_NO_GOOGLE_MAPS // Google version strings - _versionGoogleMap = "m@338000000"; - _versionGoogleSatellite = "198"; + _versionGoogleMap = "m@354000000"; + _versionGoogleSatellite = "692"; _versionGoogleLabels = "h@336"; - _versionGoogleTerrain = "t@132,r@338000000"; + _versionGoogleTerrain = "t@354,r@354000000"; _secGoogleWord = "Galileo"; #endif // BingMaps diff --git a/src/QtLocationPlugin/QGCTileCacheWorker.cpp b/src/QtLocationPlugin/QGCTileCacheWorker.cpp index 91ec4d160ed98ae356519e7f0e27e1cfa709a7c0..254e4c9e29a3aabe4390ece38e1657eaa9fc096f 100644 --- a/src/QtLocationPlugin/QGCTileCacheWorker.cpp +++ b/src/QtLocationPlugin/QGCTileCacheWorker.cpp @@ -93,20 +93,15 @@ QGCCacheWorker::enqueueTask(QGCMapTask* task) task->deleteLater(); return false; } - if(!_taskQueue.contains(task)) - { - _mutex.lock(); - _taskQueue.enqueue(task); - _mutex.unlock(); - if(this->isRunning()) { - _waitc.wakeAll(); - } else { - this->start(QThread::NormalPriority); - } - return true; + _mutex.lock(); + _taskQueue.enqueue(task); + _mutex.unlock(); + if(this->isRunning()) { + _waitc.wakeAll(); + } else { + this->start(QThread::HighPriority); } - //-- Should never happen - return false; + return true; } //----------------------------------------------------------------------------- @@ -158,6 +153,9 @@ QGCCacheWorker::run() case QGCMapTask::taskReset: _resetCacheDatabase(task); break; + case QGCMapTask::taskTestInternet: + _testInternet(); + break; } task->deleteLater(); //-- Check for update timeout @@ -454,6 +452,7 @@ QGCCacheWorker::_createTileSet(QGCMapTask *mtask) task->tileSet()->setId(setID); //-- Prepare Download List quint64 tileCount = 0; + _db->transaction(); for(int z = task->tileSet()->minZoom(); z <= task->tileSet()->maxZoom(); z++) { QGCTileSet set = QGCMapEngine::getTileCount(z, task->tileSet()->topleftLon(), task->tileSet()->topleftLat(), @@ -493,6 +492,7 @@ QGCCacheWorker::_createTileSet(QGCMapTask *mtask) } } } + _db->commit(); //-- Done _updateSetTotals(task->tileSet()); task->setTileSetSaved(); @@ -660,6 +660,7 @@ QGCCacheWorker::_init() qCritical() << "Could not find suitable cache directory."; _failed = true; } + _testInternet(); return _failed; } @@ -747,3 +748,17 @@ QGCCacheWorker::_createDB() } _failed = !_valid; } + +//----------------------------------------------------------------------------- +void +QGCCacheWorker::_testInternet() +{ + QTcpSocket socket; + socket.connectToHost("8.8.8.8", 53); + if (socket.waitForConnected(2500)) { + emit internetStatus(true); + return; + } + qWarning() << "No Internet Access"; + emit internetStatus(false); +} diff --git a/src/QtLocationPlugin/QGCTileCacheWorker.h b/src/QtLocationPlugin/QGCTileCacheWorker.h index da63535fa9800cfaf5034df9c5aef069e7dbe636..1b87e1d4fa24305f538c4ef1bc0f4f3864510faa 100644 --- a/src/QtLocationPlugin/QGCTileCacheWorker.h +++ b/src/QtLocationPlugin/QGCTileCacheWorker.h @@ -59,6 +59,7 @@ private: void _deleteTileSet (QGCMapTask* mtask); void _resetCacheDatabase (QGCMapTask* mtask); void _pruneCache (QGCMapTask* mtask); + void _testInternet (); quint64 _findTile (const QString hash); bool _findTileSetID (const QString name, quint64& setID); @@ -70,6 +71,7 @@ private: signals: void updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize); + void internetStatus (bool active); private: QQueue _taskQueue; diff --git a/src/QtLocationPlugin/QGeoMapReplyQGC.cpp b/src/QtLocationPlugin/QGeoMapReplyQGC.cpp index 2e1ec5bdcbf87bbe5f985b3d50634a1348a5a4d0..c8625226653482d124a2d3d46e1810578368c21a 100644 --- a/src/QtLocationPlugin/QGeoMapReplyQGC.cpp +++ b/src/QtLocationPlugin/QGeoMapReplyQGC.cpp @@ -46,11 +46,14 @@ #include "QGCMapEngine.h" #include "QGeoMapReplyQGC.h" +#include "QGeoTileFetcherQGC.h" #include #include #include +int QGeoTiledMapReplyQGC::_requestCount = 0; + //----------------------------------------------------------------------------- QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager, const QNetworkRequest &request, const QGeoTileSpec &spec, QObject *parent) : QGeoTiledMapReply(spec, parent) @@ -59,15 +62,7 @@ QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager , _networkManager(networkManager) { if(_request.url().isEmpty()) { - if(!_badMapBox.size()) { - QFile b(":/res/notile.png"); - if(b.open(QFile::ReadOnly)) - _badMapBox = b.readAll(); - } - setMapImageData(_badMapBox); - setMapImageFormat("png"); - setFinished(true); - setCached(false); + _returnBadTile(); } else { QGCFetchTileTask* task = getQGCMapEngine()->createFetchTileTask((UrlFactory::MapType)spec.mapId(), spec.x(), spec.y(), spec.zoom()); connect(task, &QGCFetchTileTask::tileFetched, this, &QGeoTiledMapReplyQGC::cacheReply); @@ -78,31 +73,49 @@ QGeoTiledMapReplyQGC::QGeoTiledMapReplyQGC(QNetworkAccessManager *networkManager //----------------------------------------------------------------------------- QGeoTiledMapReplyQGC::~QGeoTiledMapReplyQGC() +{ + _clearReply(); +} + +//----------------------------------------------------------------------------- +void +QGeoTiledMapReplyQGC::_clearReply() { if (_reply) { _reply->deleteLater(); _reply = 0; + _requestCount--; } } + //----------------------------------------------------------------------------- void -QGeoTiledMapReplyQGC::abort() +QGeoTiledMapReplyQGC::_returnBadTile() { - if (_reply) - _reply->abort(); + if(!_badMapBox.size()) { + QFile b(":/res/notile.png"); + if(b.open(QFile::ReadOnly)) + _badMapBox = b.readAll(); + } + setMapImageData(_badMapBox); + setMapImageFormat("png"); + setFinished(true); + setCached(false); } //----------------------------------------------------------------------------- void -QGeoTiledMapReplyQGC::replyDestroyed() +QGeoTiledMapReplyQGC::abort() { - _reply = 0; + if (_reply) + _reply->abort(); } //----------------------------------------------------------------------------- void QGeoTiledMapReplyQGC::networkReplyFinished() { + _timer.stop(); if (!_reply) { return; } @@ -117,46 +130,54 @@ QGeoTiledMapReplyQGC::networkReplyFinished() getQGCMapEngine()->cacheTile((UrlFactory::MapType)tileSpec().mapId(), tileSpec().x(), tileSpec().y(), tileSpec().zoom(), a, format); } setFinished(true); - _reply->deleteLater(); - _reply = 0; + _clearReply(); } //----------------------------------------------------------------------------- void QGeoTiledMapReplyQGC::networkReplyError(QNetworkReply::NetworkError error) { + _timer.stop(); if (!_reply) { return; } if (error != QNetworkReply::OperationCanceledError) { qWarning() << "Fetch tile error:" << _reply->errorString(); } - _reply->deleteLater(); - _reply = 0; - if(!_badTile.size()) { - QFile b(":/res/notile.png"); - if(b.open(QFile::ReadOnly)) - _badTile = b.readAll(); - } - setMapImageData(_badTile); - setMapImageFormat("png"); - setFinished(true); - setCached(false); + _returnBadTile(); + _clearReply(); } //----------------------------------------------------------------------------- void QGeoTiledMapReplyQGC::cacheError(QGCMapTask::TaskType type, QString /*errorString*/) { - if(type != QGCMapTask::taskFetchTile) { - qWarning() << "QGeoTiledMapReplyQGC::cacheError() for wrong task"; + if(_networkManager->networkAccessible() < QNetworkAccessManager::Accessible || !getQGCMapEngine()->isInternetActive()) { + _returnBadTile(); + } else { + if(type != QGCMapTask::taskFetchTile) { + qWarning() << "QGeoTiledMapReplyQGC::cacheError() for wrong task"; + } + //-- Tile not in cache. Get it off the Internet. +#if !defined(__mobile__) + QNetworkProxy proxy = _networkManager->proxy(); + QNetworkProxy tProxy; + tProxy.setType(QNetworkProxy::DefaultProxy); + _networkManager->setProxy(tProxy); +#endif + _reply = _networkManager->get(_request); + _reply->setParent(0); + connect(_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); +#if !defined(__mobile__) + _networkManager->setProxy(proxy); +#endif + //- Wait for an answer up to 10 seconds + connect(&_timer, &QTimer::timeout, this, &QGeoTiledMapReplyQGC::timeout); + _timer.setSingleShot(true); + _timer.start(10000); + _requestCount++; } - //-- Tile not in cache. Get it off the Internet. - _reply = _networkManager->get(_request); - _reply->setParent(0); - connect(_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); - connect(_reply, SIGNAL(destroyed()), this, SLOT(replyDestroyed())); } //----------------------------------------------------------------------------- @@ -169,3 +190,12 @@ QGeoTiledMapReplyQGC::cacheReply(QGCCacheTile* tile) setCached(true); tile->deleteLater(); } + +//----------------------------------------------------------------------------- +void +QGeoTiledMapReplyQGC::timeout() +{ + if(_reply) { + _reply->abort(); + } +} diff --git a/src/QtLocationPlugin/QGeoMapReplyQGC.h b/src/QtLocationPlugin/QGeoMapReplyQGC.h index b66791090344cd64801a144e567f91bead548209..46c38e52972a9b58a3d43e5c9bc132fa1715c816 100644 --- a/src/QtLocationPlugin/QGeoMapReplyQGC.h +++ b/src/QtLocationPlugin/QGeoMapReplyQGC.h @@ -49,6 +49,7 @@ #include #include +#include #include "QGCMapEngineData.h" @@ -61,11 +62,15 @@ public: void abort(); private slots: - void replyDestroyed (); void networkReplyFinished (); void networkReplyError (QNetworkReply::NetworkError error); void cacheReply (QGCCacheTile* tile); void cacheError (QGCMapTask::TaskType type, QString errorString); + void timeout (); + +private: + void _clearReply (); + void _returnBadTile (); private: QNetworkReply* _reply; @@ -73,6 +78,8 @@ private: QNetworkAccessManager* _networkManager; QByteArray _badMapBox; QByteArray _badTile; + QTimer _timer; + static int _requestCount; }; #endif // QGEOMAPREPLYQGC_H diff --git a/src/QtLocationPlugin/QGeoTileFetcherQGC.cpp b/src/QtLocationPlugin/QGeoTileFetcherQGC.cpp index 485154716e0014b4aeba0510930118d800ef8ea1..1b38673ceaee27b445a41d2c61e61609b1b312de 100644 --- a/src/QtLocationPlugin/QGeoTileFetcherQGC.cpp +++ b/src/QtLocationPlugin/QGeoTileFetcherQGC.cpp @@ -57,6 +57,10 @@ QGeoTileFetcherQGC::QGeoTileFetcherQGC(QGeoTiledMappingManagerEngine *parent) : QGeoTileFetcher(parent) , _networkManager(new QNetworkAccessManager(this)) { + //-- Check internet status every 30 seconds or so + connect(&_timer, &QTimer::timeout, this, &QGeoTileFetcherQGC::timeout); + _timer.setSingleShot(false); + _timer.start(30000); } //----------------------------------------------------------------------------- @@ -73,3 +77,12 @@ QGeoTileFetcherQGC::getTileImage(const QGeoTileSpec &spec) QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL((UrlFactory::MapType)spec.mapId(), spec.x(), spec.y(), spec.zoom(), _networkManager); return new QGeoTiledMapReplyQGC(_networkManager, request, spec); } + +//----------------------------------------------------------------------------- +void +QGeoTileFetcherQGC::timeout() +{ + if(!getQGCMapEngine()->isInternetActive()) { + getQGCMapEngine()->testInternet(); + } +} diff --git a/src/QtLocationPlugin/QGeoTileFetcherQGC.h b/src/QtLocationPlugin/QGeoTileFetcherQGC.h index 54f507a7a7b8436bd51805159910b52f28d2c45b..9c86633244311f1a2718314dbc113ac0c44fa2a5 100644 --- a/src/QtLocationPlugin/QGeoTileFetcherQGC.h +++ b/src/QtLocationPlugin/QGeoTileFetcherQGC.h @@ -48,6 +48,7 @@ #define QGEOTILEFETCHERQGC_H #include +#include #include "QGCMapUrlEngine.h" class QGeoTiledMappingManagerEngine; @@ -59,10 +60,13 @@ class QGeoTileFetcherQGC : public QGeoTileFetcher public: explicit QGeoTileFetcherQGC (QGeoTiledMappingManagerEngine *parent = 0); ~QGeoTileFetcherQGC(); +public slots: + void timeout (); private: QGeoTiledMapReply* getTileImage (const QGeoTileSpec &spec); private: QNetworkAccessManager* _networkManager; + QTimer _timer; }; #endif // QGEOTILEFETCHERQGC_H diff --git a/src/QtLocationPlugin/QMLControl/OfflineMap.qml b/src/QtLocationPlugin/QMLControl/OfflineMap.qml index a80510eba64452f189e81ad26836a86e4eea0124..985afec75452171ae0d30eaba22e507885ec307f 100644 --- a/src/QtLocationPlugin/QMLControl/OfflineMap.qml +++ b/src/QtLocationPlugin/QMLControl/OfflineMap.qml @@ -7,7 +7,6 @@ * ****************************************************************************/ - import QtQuick 2.5 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2 @@ -38,6 +37,7 @@ QGCView { property string savedMapType: "" property bool _showPreview: true property bool _defaultSet: offlineMapView && offlineMapView._currentSelection && offlineMapView._currentSelection.defaultSet + property real _margins: ScreenTools.defaultFontPixelWidth /2 property bool _saveRealEstate: ScreenTools.isTinyScreen || ScreenTools.isShortScreen property real _adjustableFontPointSize: _saveRealEstate ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize @@ -327,6 +327,17 @@ QGCView { anchors.fill: parent } + CenterMapDropButton { + anchors.margins: _margins + anchors.left: parent.left + anchors.top: parent.top + map: _map + z: QGroundControl.zOrderTopMost + showMission: false + showAllItems: false + visible: addNewSetView.visible + } + MapScale { anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2 anchors.bottomMargin: anchors.leftMargin @@ -475,97 +486,95 @@ QGCView { anchors.fill: parent visible: false - Map { - id: minZoomPreview - anchors.leftMargin: ScreenTools.defaultFontPixelWidth /2 - anchors.topMargin: anchors.leftMargin - anchors.top: parent.top - anchors.left: parent.left - width: parent.width / 4 - height: parent.height / 4 - center: _map.center - activeMapType: _map.activeMapType - zoomLevel: sliderMinZoom.value - gesture.enabled: false - visible: _showPreview - - property bool isSatelliteMap: activeMapType.name.indexOf("Satellite") > -1 || activeMapType.name.indexOf("Hybrid") > -1 - - plugin: Plugin { name: "QGroundControl" } - - MapScale { - anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2 - anchors.bottomMargin: anchors.leftMargin - anchors.left: parent.left - anchors.bottom: parent.bottom - mapControl: parent + Column { + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: _margins + anchors.left: parent.left + spacing: _margins + + QGCButton { + text: "Show zoom previews" + visible: !_showPreview + onClicked: _showPreview = !_showPreview } - } - Map { - id: maxZoomPreview - anchors.topMargin: minZoomPreview.anchors.topMargin - anchors.left: minZoomPreview.left - anchors.top: minZoomPreview.bottom - width: minZoomPreview.width - height: minZoomPreview.height - center: _map.center - activeMapType: _map.activeMapType - zoomLevel: sliderMaxZoom.value - gesture.enabled: false - visible: _showPreview - - property bool isSatelliteMap: activeMapType.name.indexOf("Satellite") > -1 || activeMapType.name.indexOf("Hybrid") > -1 - - plugin: Plugin { name: "QGroundControl" } - - MapScale { - anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2 - anchors.bottomMargin: anchors.leftMargin - anchors.left: parent.left - anchors.bottom: parent.bottom - mapControl: parent - } - } + Map { + id: minZoomPreview + width: addNewSetView.width / 4 + height: addNewSetView.height / 4 + center: _map.center + activeMapType: _map.activeMapType + zoomLevel: sliderMinZoom.value + gesture.enabled: false + visible: _showPreview + + property bool isSatelliteMap: activeMapType.name.indexOf("Satellite") > -1 || activeMapType.name.indexOf("Hybrid") > -1 + + plugin: Plugin { name: "QGroundControl" } + + MapScale { + anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2 + anchors.bottomMargin: anchors.leftMargin + anchors.left: parent.left + anchors.bottom: parent.bottom + mapControl: parent + } - Rectangle { - anchors.fill: minZoomPreview - border.color: _mapAdjustedColor - color: "transparent" - visible: _showPreview - QGCLabel { - anchors.centerIn: parent - color: _mapAdjustedColor - text: qsTr("Min Zoom: %1").arg(sliderMinZoom.value) - } - MouseArea { - anchors.fill: parent - onClicked: _showPreview = false - } - } + Rectangle { + anchors.fill: parent + border.color: _mapAdjustedColor + color: "transparent" - Rectangle { - anchors.fill: maxZoomPreview - border.color: _mapAdjustedColor - color: "transparent" - visible: _showPreview - QGCLabel { - anchors.centerIn: parent - color: _mapAdjustedColor - text: qsTr("Max Zoom: %1").arg(sliderMaxZoom.value) - } - MouseArea { - anchors.fill: parent - onClicked: _showPreview = false - } - } + QGCMapLabel { + anchors.centerIn: parent + map: minZoomPreview + text: qsTr("Min Zoom: %1").arg(sliderMinZoom.value) + } + MouseArea { + anchors.fill: parent + onClicked: _showPreview = false + } + } + } // Map + + Map { + id: maxZoomPreview + width: minZoomPreview.width + height: minZoomPreview.height + center: _map.center + activeMapType: _map.activeMapType + zoomLevel: sliderMaxZoom.value + gesture.enabled: false + visible: _showPreview + + property bool isSatelliteMap: activeMapType.name.indexOf("Satellite") > -1 || activeMapType.name.indexOf("Hybrid") > -1 + + plugin: Plugin { name: "QGroundControl" } + + MapScale { + anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2 + anchors.bottomMargin: anchors.leftMargin + anchors.left: parent.left + anchors.bottom: parent.bottom + mapControl: parent + } - QGCButton { - anchors.left: minZoomPreview.left - anchors.top: minZoomPreview.top - text: "Show zoom previews" - visible: !_showPreview - onClicked: _showPreview = !_showPreview + Rectangle { + anchors.fill: parent + border.color: _mapAdjustedColor + color: "transparent" + + QGCMapLabel { + anchors.centerIn: parent + map: maxZoomPreview + text: qsTr("Max Zoom: %1").arg(sliderMaxZoom.value) + } + MouseArea { + anchors.fill: parent + onClicked: _showPreview = false + } + } + } // Map } //-- Add new set dialog @@ -574,7 +583,7 @@ QGCView { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right width: ScreenTools.defaultFontPixelWidth * 24 - height: Math.min(parent.height - (anchors.margins * 2), addNewSetFlickable.y + addNewSetColumn.height + ScreenTools.defaultFontPixelHeight) + height: Math.min(parent.height - (anchors.margins * 2), addNewSetFlickable.y + addNewSetColumn.height + addNewSetLabel.anchors.margins) color: Qt.rgba(qgcPal.window.r, qgcPal.window.g, qgcPal.window.b, 0.85) radius: ScreenTools.defaultFontPixelWidth * 0.5 diff --git a/src/RunGuard.cc b/src/RunGuard.cc new file mode 100644 index 0000000000000000000000000000000000000000..5e8a4925337b5b58aee1890b12ce975ecb7dec70 --- /dev/null +++ b/src/RunGuard.cc @@ -0,0 +1,87 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "RunGuard.h" + +#include + +namespace +{ + +QString generateKeyHash( const QString& key, const QString& salt ) +{ + QByteArray data; + + data.append( key.toUtf8() ); + data.append( salt.toUtf8() ); + data = QCryptographicHash::hash( data, QCryptographicHash::Sha1 ).toHex(); + + return data; +} + +} + +RunGuard::RunGuard( const QString& key ) + : key( key ) + , memLockKey( generateKeyHash( key, "_memLockKey" ) ) + , sharedmemKey( generateKeyHash( key, "_sharedmemKey" ) ) + , sharedMem( sharedmemKey ) + , memLock( memLockKey, 1 ) +{ + memLock.acquire(); + { + QSharedMemory fix( sharedmemKey ); // Fix for *nix: http://habrahabr.ru/post/173281/ + fix.attach(); + } + memLock.release(); +} + +RunGuard::~RunGuard() +{ + release(); +} + +bool RunGuard::isAnotherRunning() +{ + if ( sharedMem.isAttached() ) + return false; + + memLock.acquire(); + const bool isRunning = sharedMem.attach(); + if ( isRunning ) + sharedMem.detach(); + memLock.release(); + + return isRunning; +} + +bool RunGuard::tryToRun() +{ + if ( isAnotherRunning() ) // Extra check + return false; + + memLock.acquire(); + const bool result = sharedMem.create( sizeof( quint64 ) ); + memLock.release(); + if ( !result ) + { + release(); + return false; + } + + return true; +} + +void RunGuard::release() +{ + memLock.acquire(); + if ( sharedMem.isAttached() ) + sharedMem.detach(); + memLock.release(); +} diff --git a/src/RunGuard.h b/src/RunGuard.h new file mode 100644 index 0000000000000000000000000000000000000000..0e82f5b6231e8d51816aa43e016c5e3ab36bbdeb --- /dev/null +++ b/src/RunGuard.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef RunGuard_H +#define RunGuard_H + +#include +#include +#include + +class RunGuard +{ +public: + RunGuard( const QString& key ); + ~RunGuard(); + + bool isAnotherRunning(); + bool tryToRun(); + void release(); + +private: + const QString key; + const QString memLockKey; + const QString sharedmemKey; + + QSharedMemory sharedMem; + QSystemSemaphore memLock; + + Q_DISABLE_COPY( RunGuard ) +}; + +#endif diff --git a/src/Settings/App.SettingsGroup.json b/src/Settings/App.SettingsGroup.json new file mode 100644 index 0000000000000000000000000000000000000000..a3b074c840e3453bbda5721a086abfbc59f1af76 --- /dev/null +++ b/src/Settings/App.SettingsGroup.json @@ -0,0 +1,111 @@ +[ +{ + "name": "OfflineEditingFirmwareType", + "shortDescription": "Offline editing firmware type", + "type": "uint32", + "enumStrings": "ArduPilot,PX4 Pro,Mavlink Generic", + "enumValues": "3,12,0", + "defaultValue": 3 +}, +{ + "name": "OfflineEditingVehicleType", + "shortDescription": "Offline editing vehicle type", + "type": "uint32", + "enumStrings": "Fixed Wing,Multi-Rotor,VTOL,Rover,Sub", + "enumValues": "1,2,19,10,12", + "defaultValue": 1 +}, +{ + "name": "OfflineEditingCruiseSpeed", + "shortDescription": "Offline editing cruise speed", + "longDescription": "This value defines the cruising speed for forward flight vehicles for use in calculating mission duration when not connected to a vehicle.", + "type": "double", + "defaultValue": 16.0, + "min": 1.0, + "units": "m/s", + "decimalPlaces": 2 +}, +{ + "name": "OfflineEditingHoverSpeed", + "shortDescription": "Offline editing hover speed", + "longDescription": "This value defines the cruising speed for multi-rotor vehicles for use in calculating mission duration when not connected to a vehicle.", + "type": "double", + "defaultValue": 4.0, + "min": 1.0, + "units": "m/s", + "decimalPlaces": 2 +}, +{ + "name": "batteryPercentRemainingAnnounce", + "shortDescription": "Announce battery remaining percent", + "longDescription": "QGroundControl will announce the remaining battery percent when it falls below the specified percentage.", + "type": "uint32", + "defaultValue": 30, + "units": "%", + "min": 0, + "max": 100 +}, +{ + "name": "DefaultMissionItemAltitude", + "shortDescription": "Default value for altitude", + "longDescription": "This value specifies the default altitude for new items added to a mission.", + "type": "double", + "defaultValue": 50.0, + "min": 0.0, + "units": "meters", + "decimalPlaces": 2 +}, +{ + "name": "MissionAutoLoadDir", + "shortDescription": "Mission auto load directory", + "longDescription": "The directory from which missions will be automatically loaded onto a vehicle when it connects. The mission file must be named AutoLoad#.mission where the # is replaced with the vehicle id.", + "type": "string", + "defaultValue": "" +}, +{ + "name": "PromptFLightDataSave", + "shortDescription": "Prompt to save Flight Data Log after each flight", + "longDescription": "If this option is enabled you will be prompted to save Flight Data Log after each flight completes.", + "type": "bool", + "defaultValue": true +}, +{ + "name": "PromptFLightDataSaveNotArmed", + "shortDescription": "Prompt to save Flight Data Log even if vehicle was not armed", + "longDescription": "If this option is enabled you will be prompted to save Flight Data Log even if vehicle was never armed.", + "type": "bool", + "defaultValue": false +}, +{ + "name": "AudioMuted", + "shortDescription": "Mute audio output", + "longDescription": "If this option is enabled all audio output will be muted.", + "type": "bool", + "defaultValue": false +}, +{ + "name": "VirtualTabletJoystick", + "shortDescription": "Show virtual joystick", + "longDescription": "If this option is enabled the virtual joystick will be shown on the Fly view.", + "type": "bool", + "defaultValue": false +}, +{ + "name": "BaseDeviceFontPointSize", + "shortDescription": "QGroundControl font size", + "longDescription": "The point size for the default font used in QGroundControl.", + "type": "uint32", + "units": "pt", + "min": 6, + "max": 48, + "defaultValue": 0 +}, +{ + "name": "StyleIsDark", + "shortDescription": "QGroundControl color scheme", + "longDescription": "The color scheme for the QGroundControl user interface.", + "type": "uint32", + "enumStrings": "Indoor,Outdoor", + "enumValues": "1,0" +} +] diff --git a/src/Settings/AppSettings.cc b/src/Settings/AppSettings.cc new file mode 100644 index 0000000000000000000000000000000000000000..e30ca2c05c1209311df0a22e5cf1532d421da95a --- /dev/null +++ b/src/Settings/AppSettings.cc @@ -0,0 +1,173 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "AppSettings.h" +#include "QGCPalette.h" +#include "QGCApplication.h" + +#include +#include + +const char* AppSettings::appSettingsGroupName = "App"; +const char* AppSettings::offlineEditingFirmwareTypeSettingsName = "OfflineEditingFirmwareType"; +const char* AppSettings::offlineEditingVehicleTypeSettingsName = "OfflineEditingVehicleType"; +const char* AppSettings::offlineEditingCruiseSpeedSettingsName = "OfflineEditingCruiseSpeed"; +const char* AppSettings::offlineEditingHoverSpeedSettingsName = "OfflineEditingHoverSpeed"; +const char* AppSettings::batteryPercentRemainingAnnounceSettingsName = "batteryPercentRemainingAnnounce"; +const char* AppSettings::defaultMissionItemAltitudeSettingsName = "DefaultMissionItemAltitude"; +const char* AppSettings::missionAutoLoadDirSettingsName = "MissionAutoLoadDir"; +const char* AppSettings::promptFlightTelemetrySaveName = "PromptFLightDataSave"; +const char* AppSettings::promptFlightTelemetrySaveNotArmedName = "PromptFLightDataSaveNotArmed"; +const char* AppSettings::audioMutedName = "AudioMuted"; +const char* AppSettings::virtualJoystickName = "VirtualTabletJoystick"; +const char* AppSettings::appFontPointSizeName = "BaseDeviceFontPointSize"; +const char* AppSettings::indoorPaletteName = "StyleIsDark"; + +AppSettings::AppSettings(QObject* parent) + : SettingsGroup(appSettingsGroupName, QString() /* root settings group */, parent) + , _offlineEditingFirmwareTypeFact(NULL) + , _offlineEditingVehicleTypeFact(NULL) + , _offlineEditingCruiseSpeedFact(NULL) + , _offlineEditingHoverSpeedFact(NULL) + , _batteryPercentRemainingAnnounceFact(NULL) + , _defaultMissionItemAltitudeFact(NULL) + , _missionAutoLoadDirFact(NULL) + , _promptFlightTelemetrySaveFact(NULL) + , _promptFlightTelemetrySaveNotArmedFact(NULL) + , _audioMutedFact(NULL) + , _virtualJoystickFact(NULL) + , _appFontPointSizeFact(NULL) + , _indoorPaletteFact(NULL) +{ + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + qmlRegisterUncreatableType("QGroundControl.SettingsManager", 1, 0, "AppSettings", "Reference only"); + QGCPalette::setGlobalTheme(indoorPalette()->rawValue().toBool() ? QGCPalette::Dark : QGCPalette::Light); +} + +Fact* AppSettings::offlineEditingFirmwareType(void) +{ + if (!_offlineEditingFirmwareTypeFact) { + _offlineEditingFirmwareTypeFact = _createSettingsFact(offlineEditingFirmwareTypeSettingsName); + } + + return _offlineEditingFirmwareTypeFact; +} + +Fact* AppSettings::offlineEditingVehicleType(void) +{ + if (!_offlineEditingVehicleTypeFact) { + _offlineEditingVehicleTypeFact = _createSettingsFact(offlineEditingVehicleTypeSettingsName); + } + + return _offlineEditingVehicleTypeFact; +} + +Fact* AppSettings::offlineEditingCruiseSpeed(void) +{ + if (!_offlineEditingCruiseSpeedFact) { + _offlineEditingCruiseSpeedFact = _createSettingsFact(offlineEditingCruiseSpeedSettingsName); + } + return _offlineEditingCruiseSpeedFact; +} + +Fact* AppSettings::offlineEditingHoverSpeed(void) +{ + if (!_offlineEditingHoverSpeedFact) { + _offlineEditingHoverSpeedFact = _createSettingsFact(offlineEditingHoverSpeedSettingsName); + } + return _offlineEditingHoverSpeedFact; +} + +Fact* AppSettings::batteryPercentRemainingAnnounce(void) +{ + if (!_batteryPercentRemainingAnnounceFact) { + _batteryPercentRemainingAnnounceFact = _createSettingsFact(batteryPercentRemainingAnnounceSettingsName); + } + + return _batteryPercentRemainingAnnounceFact; +} + +Fact* AppSettings::defaultMissionItemAltitude(void) +{ + if (!_defaultMissionItemAltitudeFact) { + _defaultMissionItemAltitudeFact = _createSettingsFact(defaultMissionItemAltitudeSettingsName); + } + + return _defaultMissionItemAltitudeFact; +} + +Fact* AppSettings::missionAutoLoadDir(void) +{ + if (!_missionAutoLoadDirFact) { + _missionAutoLoadDirFact = _createSettingsFact(missionAutoLoadDirSettingsName); + } + + return _missionAutoLoadDirFact; +} + +Fact* AppSettings::promptFlightTelemetrySave(void) +{ + if (!_promptFlightTelemetrySaveFact) { + _promptFlightTelemetrySaveFact = _createSettingsFact(promptFlightTelemetrySaveName); + } + + return _promptFlightTelemetrySaveFact; +} + +Fact* AppSettings::promptFlightTelemetrySaveNotArmed(void) +{ + if (!_promptFlightTelemetrySaveNotArmedFact) { + _promptFlightTelemetrySaveNotArmedFact = _createSettingsFact(promptFlightTelemetrySaveNotArmedName); + } + + return _promptFlightTelemetrySaveNotArmedFact; +} + +Fact* AppSettings::audioMuted(void) +{ + if (!_audioMutedFact) { + _audioMutedFact = _createSettingsFact(audioMutedName); + } + + return _audioMutedFact; +} + +Fact* AppSettings::appFontPointSize(void) +{ + if (!_appFontPointSizeFact) { + _appFontPointSizeFact = _createSettingsFact(appFontPointSizeName); + } + + return _appFontPointSizeFact; +} + +Fact* AppSettings::virtualJoystick(void) +{ + if (!_virtualJoystickFact) { + _virtualJoystickFact = _createSettingsFact(virtualJoystickName); + } + + return _virtualJoystickFact; +} + +Fact* AppSettings::indoorPalette(void) +{ + if (!_indoorPaletteFact) { + _indoorPaletteFact = _createSettingsFact(indoorPaletteName); + connect(_indoorPaletteFact, &Fact::rawValueChanged, this, &AppSettings::_indoorPaletteChanged); + } + + return _indoorPaletteFact; +} + +void AppSettings::_indoorPaletteChanged(void) +{ + qgcApp()->_loadCurrentStyleSheet(); + QGCPalette::setGlobalTheme(indoorPalette()->rawValue().toBool() ? QGCPalette::Dark : QGCPalette::Light); +} diff --git a/src/Settings/AppSettings.h b/src/Settings/AppSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..7e39514cab3f651ea39b15e94fb7e7e776205313 --- /dev/null +++ b/src/Settings/AppSettings.h @@ -0,0 +1,85 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef AppSettings_H +#define AppSettings_H + +#include "SettingsGroup.h" + +class AppSettings : public SettingsGroup +{ + Q_OBJECT + +public: + AppSettings(QObject* parent = NULL); + + Q_PROPERTY(Fact* offlineEditingFirmwareType READ offlineEditingFirmwareType CONSTANT) + Q_PROPERTY(Fact* offlineEditingVehicleType READ offlineEditingVehicleType CONSTANT) + Q_PROPERTY(Fact* offlineEditingCruiseSpeed READ offlineEditingCruiseSpeed CONSTANT) + Q_PROPERTY(Fact* offlineEditingHoverSpeed READ offlineEditingHoverSpeed CONSTANT) + Q_PROPERTY(Fact* batteryPercentRemainingAnnounce READ batteryPercentRemainingAnnounce CONSTANT) + Q_PROPERTY(Fact* defaultMissionItemAltitude READ defaultMissionItemAltitude CONSTANT) + Q_PROPERTY(Fact* missionAutoLoadDir READ missionAutoLoadDir CONSTANT) + Q_PROPERTY(Fact* promptFlightTelemetrySave READ promptFlightTelemetrySave CONSTANT) + Q_PROPERTY(Fact* promptFlightTelemetrySaveNotArmed READ promptFlightTelemetrySaveNotArmed CONSTANT) + Q_PROPERTY(Fact* audioMuted READ audioMuted CONSTANT) + Q_PROPERTY(Fact* virtualJoystick READ virtualJoystick CONSTANT) + Q_PROPERTY(Fact* appFontPointSize READ appFontPointSize CONSTANT) + Q_PROPERTY(Fact* indoorPalette READ indoorPalette CONSTANT) + + Fact* offlineEditingFirmwareType (void); + Fact* offlineEditingVehicleType (void); + Fact* offlineEditingCruiseSpeed (void); + Fact* offlineEditingHoverSpeed (void); + Fact* batteryPercentRemainingAnnounce (void); + Fact* defaultMissionItemAltitude (void); + Fact* missionAutoLoadDir (void); + Fact* promptFlightTelemetrySave (void); + Fact* promptFlightTelemetrySaveNotArmed (void); + Fact* audioMuted (void); + Fact* virtualJoystick (void); + Fact* appFontPointSize (void); + Fact* indoorPalette (void); + + static const char* appSettingsGroupName; + + static const char* offlineEditingFirmwareTypeSettingsName; + static const char* offlineEditingVehicleTypeSettingsName; + static const char* offlineEditingCruiseSpeedSettingsName; + static const char* offlineEditingHoverSpeedSettingsName; + static const char* batteryPercentRemainingAnnounceSettingsName; + static const char* defaultMissionItemAltitudeSettingsName; + static const char* missionAutoLoadDirSettingsName; + static const char* promptFlightTelemetrySaveName; + static const char* promptFlightTelemetrySaveNotArmedName; + static const char* audioMutedName; + static const char* virtualJoystickName; + static const char* appFontPointSizeName; + static const char* indoorPaletteName; + +private slots: + void _indoorPaletteChanged(void); + +private: + SettingsFact* _offlineEditingFirmwareTypeFact; + SettingsFact* _offlineEditingVehicleTypeFact; + SettingsFact* _offlineEditingCruiseSpeedFact; + SettingsFact* _offlineEditingHoverSpeedFact; + SettingsFact* _batteryPercentRemainingAnnounceFact; + SettingsFact* _defaultMissionItemAltitudeFact; + SettingsFact* _missionAutoLoadDirFact; + SettingsFact* _promptFlightTelemetrySaveFact; + SettingsFact* _promptFlightTelemetrySaveNotArmedFact; + SettingsFact* _audioMutedFact; + SettingsFact* _virtualJoystickFact; + SettingsFact* _appFontPointSizeFact; + SettingsFact* _indoorPaletteFact; +}; + +#endif diff --git a/src/Settings/AutoConnect.SettingsGroup.json b/src/Settings/AutoConnect.SettingsGroup.json new file mode 100644 index 0000000000000000000000000000000000000000..afce2047f2e95fc4a98a91fad72c13af54c61ccd --- /dev/null +++ b/src/Settings/AutoConnect.SettingsGroup.json @@ -0,0 +1,44 @@ +[ +{ + "name": "AutoconnectUDP", + "shortDescription": "Automatically open a connection over UDP", + "longDescription": "If this option is enabled GroundControl will automatically connect to a vehicle which is detected on a UDP communication link.", + "type": "bool", + "defaultValue": true +}, +{ + "name": "AutoconnectPixhawk", + "shortDescription": "Automatically connect to a Pixhawk board", + "longDescription": "If this option is enabled GroundControl will automatically connect to a Pixhawk board which is connected via USB.", + "type": "bool", + "defaultValue": true +}, +{ + "name": "Autoconnect3DRRadio", + "shortDescription": "Automatically connect to a SiK Radio", + "longDescription": "If this option is enabled GroundControl will automatically connect to a vehicle which is detected on a SiK Radio communication link.", + "type": "bool", + "defaultValue": true +}, +{ + "name": "AutoconnectPX4Flow", + "shortDescription": "Automatically connect to a P4 Flow", + "longDescription": "If this option is enabled GroundControl will automatically connect to a PX4 Flow board which is connected via USB.", + "type": "bool", + "defaultValue": true +}, +{ + "name": "AutoconnectRTKGPS", + "shortDescription": "Automatically connect to an RTK GPS", + "longDescription": "If this option is enabled GroundControl will automatically connect to an RTK GPS which is connected via USB.", + "type": "bool", + "defaultValue": true +}, +{ + "name": "AutoconnectLibrePilot", + "shortDescription": "Automatically connect to a LibrePilot", + "longDescription": "If this option is enabled GroundControl will automatically connect to a LibrePilot board which is connected via USB.", + "type": "bool", + "defaultValue": true +} +] diff --git a/src/Settings/AutoConnectSettings.cc b/src/Settings/AutoConnectSettings.cc new file mode 100644 index 0000000000000000000000000000000000000000..fc1247f84c289394c062b872b0d92ec4882a86fe --- /dev/null +++ b/src/Settings/AutoConnectSettings.cc @@ -0,0 +1,92 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "AutoConnectSettings.h" +#include "LinkManager.h" + +#include +#include + +const char* AutoConnectSettings::_settingsGroup = "LinkManager"; + +const char* AutoConnectSettings:: autoConnectUDPSettingsName = "AutoconnectUDP"; +const char* AutoConnectSettings:: autoConnectPixhawkSettingsName = "AutoconnectPixhawk"; +const char* AutoConnectSettings:: autoConnectSiKRadioSettingsName = "Autoconnect3DRRadio"; +const char* AutoConnectSettings:: autoConnectPX4FlowSettingsName = "AutoconnectPX4Flow"; +const char* AutoConnectSettings:: autoConnectRTKGPSSettingsName = "AutoconnectRTKGPS"; +const char* AutoConnectSettings:: autoConnectLibrePilotSettingsName = "AutoconnectLibrePilot"; + +const char* AutoConnectSettings::autoConnectSettingsGroupName = "AutoConnect"; + +AutoConnectSettings::AutoConnectSettings(QObject* parent) + : SettingsGroup(autoConnectSettingsGroupName, _settingsGroup, parent) + , _autoConnectUDPFact(NULL) + , _autoConnectPixhawkFact(NULL) + , _autoConnectSiKRadioFact(NULL) + , _autoConnectPX4FlowFact(NULL) + , _autoConnectRTKGPSFact(NULL) + , _autoConnectLibrePilotFact(NULL) +{ + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + qmlRegisterUncreatableType("QGroundControl.SettingsManager", 1, 0, "AutoConnectSettings", "Reference only"); +} + +Fact* AutoConnectSettings::autoConnectUDP(void) +{ + if (!_autoConnectUDPFact) { + _autoConnectUDPFact = _createSettingsFact(autoConnectUDPSettingsName); + } + + return _autoConnectUDPFact; +} + +Fact* AutoConnectSettings::autoConnectPixhawk(void) +{ + if (!_autoConnectPixhawkFact) { + _autoConnectPixhawkFact = _createSettingsFact(autoConnectPixhawkSettingsName); + } + + return _autoConnectPixhawkFact; +} + +Fact* AutoConnectSettings::autoConnectSiKRadio(void) +{ + if (!_autoConnectSiKRadioFact) { + _autoConnectSiKRadioFact = _createSettingsFact(autoConnectSiKRadioSettingsName); + } + + return _autoConnectSiKRadioFact; +} + +Fact* AutoConnectSettings::autoConnectPX4Flow(void) +{ + if (!_autoConnectPX4FlowFact) { + _autoConnectPX4FlowFact = _createSettingsFact(autoConnectPX4FlowSettingsName); + } + + return _autoConnectPX4FlowFact; +} + +Fact* AutoConnectSettings::autoConnectRTKGPS(void) +{ + if (!_autoConnectRTKGPSFact) { + _autoConnectRTKGPSFact = _createSettingsFact(autoConnectRTKGPSSettingsName); + } + + return _autoConnectRTKGPSFact; +} + +Fact* AutoConnectSettings::autoConnectLibrePilot(void) +{ + if (!_autoConnectLibrePilotFact) { + _autoConnectLibrePilotFact = _createSettingsFact(autoConnectLibrePilotSettingsName); + } + + return _autoConnectLibrePilotFact; +} diff --git a/src/Settings/AutoConnectSettings.h b/src/Settings/AutoConnectSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..83829fdfe15694428ac019d91e5391c8ad86d759 --- /dev/null +++ b/src/Settings/AutoConnectSettings.h @@ -0,0 +1,56 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef AutoConnectSettings_H +#define AutoConnectSettings_H + +#include "SettingsGroup.h" + +class AutoConnectSettings : public SettingsGroup +{ + Q_OBJECT + +public: + AutoConnectSettings(QObject* parent = NULL); + + Q_PROPERTY(Fact* autoConnectUDP READ autoConnectUDP CONSTANT) + Q_PROPERTY(Fact* autoConnectPixhawk READ autoConnectPixhawk CONSTANT) + Q_PROPERTY(Fact* autoConnectSiKRadio READ autoConnectSiKRadio CONSTANT) + Q_PROPERTY(Fact* autoConnectPX4Flow READ autoConnectPX4Flow CONSTANT) + Q_PROPERTY(Fact* autoConnectRTKGPS READ autoConnectRTKGPS CONSTANT) + Q_PROPERTY(Fact* autoConnectLibrePilot READ autoConnectLibrePilot CONSTANT) + + Fact* autoConnectUDP (void); + Fact* autoConnectPixhawk (void); + Fact* autoConnectSiKRadio (void); + Fact* autoConnectPX4Flow (void); + Fact* autoConnectRTKGPS (void); + Fact* autoConnectLibrePilot (void); + + static const char* autoConnectSettingsGroupName; + + static const char* autoConnectUDPSettingsName; + static const char* autoConnectPixhawkSettingsName; + static const char* autoConnectSiKRadioSettingsName; + static const char* autoConnectPX4FlowSettingsName; + static const char* autoConnectRTKGPSSettingsName; + static const char* autoConnectLibrePilotSettingsName; + +private: + SettingsFact* _autoConnectUDPFact; + SettingsFact* _autoConnectPixhawkFact; + SettingsFact* _autoConnectSiKRadioFact; + SettingsFact* _autoConnectPX4FlowFact; + SettingsFact* _autoConnectRTKGPSFact; + SettingsFact* _autoConnectLibrePilotFact; + + static const char* _settingsGroup; +}; + +#endif diff --git a/src/Settings/SettingsGroup.cc b/src/Settings/SettingsGroup.cc new file mode 100644 index 0000000000000000000000000000000000000000..e0f1ac231397146c46dbd31c3be6b44158b2d272 --- /dev/null +++ b/src/Settings/SettingsGroup.cc @@ -0,0 +1,29 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "SettingsGroup.h" +#include "QGCCorePlugin.h" +#include "QGCApplication.h" + +SettingsGroup::SettingsGroup(const QString& name, const QString& settingsGroup, QObject* parent) + : QObject(parent) + , _name(name) + , _settingsGroup(settingsGroup) + , _visible(qgcApp()->toolbox()->corePlugin()->overrideSettingsGroupVisibility(name)) +{ + QString jsonNameFormat(":/json/%1.SettingsGroup.json"); + + _nameToMetaDataMap = FactMetaData::createMapFromJsonFile(jsonNameFormat.arg(name), this); +} + +SettingsFact* SettingsGroup::_createSettingsFact(const QString& name) +{ + return new SettingsFact(_settingsGroup, _nameToMetaDataMap[name], this); +} + diff --git a/src/Settings/SettingsGroup.h b/src/Settings/SettingsGroup.h new file mode 100644 index 0000000000000000000000000000000000000000..048c0b1132fdb721cb48c5f962ad505776f2c934 --- /dev/null +++ b/src/Settings/SettingsGroup.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef SettingsGroup_H +#define SettingsGroup_H + +#include "QGCLoggingCategory.h" +#include "Joystick.h" +#include "MultiVehicleManager.h" +#include "QGCToolbox.h" + +#include + +/// Provides access to group of settings. The group is named and has a visible property associated with which can control whether the group +/// is shows in the ui. +class SettingsGroup : public QObject +{ + Q_OBJECT + +public: + /// @param name Name for this Settings group + /// @param settingsGroup Group to place settings in for QSettings::setGroup + SettingsGroup(const QString& name, const QString& settingsGroup, QObject* parent = NULL); + + Q_PROPERTY(bool visible MEMBER _visible CONSTANT) + +protected: + SettingsFact* _createSettingsFact(const QString& name); + + QString _name; + QString _settingsGroup; + bool _visible; + + QMap _nameToMetaDataMap; +}; + +#endif diff --git a/src/Settings/SettingsManager.cc b/src/Settings/SettingsManager.cc new file mode 100644 index 0000000000000000000000000000000000000000..226976f28e2d7b9ca33940b211a483fa2739d4f9 --- /dev/null +++ b/src/Settings/SettingsManager.cc @@ -0,0 +1,35 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "SettingsManager.h" + +#include +#include + +SettingsManager::SettingsManager(QGCApplication* app) + : QGCTool(app) + , _appSettings(NULL) + , _unitsSettings(NULL) + , _autoConnectSettings(NULL) + , _videoSettings(NULL) +{ + +} + +void SettingsManager::setToolbox(QGCToolbox *toolbox) +{ + QGCTool::setToolbox(toolbox); + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + qmlRegisterUncreatableType("QGroundControl.SettingsManager", 1, 0, "SettingsManager", "Reference only"); + + _unitsSettings = new UnitsSettings(this); // Must be first since AppSettings references it + _appSettings = new AppSettings(this); + _autoConnectSettings = new AutoConnectSettings(this); + _videoSettings = new VideoSettings(this); +} diff --git a/src/Settings/SettingsManager.h b/src/Settings/SettingsManager.h new file mode 100644 index 0000000000000000000000000000000000000000..40e67555c4a1881ec96c3a2b2a8de5c1e2c690ff --- /dev/null +++ b/src/Settings/SettingsManager.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef SettingsManager_H +#define SettingsManager_H + +#include "QGCLoggingCategory.h" +#include "Joystick.h" +#include "MultiVehicleManager.h" +#include "QGCToolbox.h" +#include "AppSettings.h" +#include "UnitsSettings.h" +#include "AutoConnectSettings.h" +#include "VideoSettings.h" + +#include + +/// Provides access to all app settings +class SettingsManager : public QGCTool +{ + Q_OBJECT + +public: + SettingsManager(QGCApplication* app); + + Q_PROPERTY(QObject* appSettings READ appSettings CONSTANT) + Q_PROPERTY(QObject* unitsSettings READ unitsSettings CONSTANT) + Q_PROPERTY(QObject* autoConnectSettings READ autoConnectSettings CONSTANT) + Q_PROPERTY(QObject* videoSettings READ videoSettings CONSTANT) + + // Override from QGCTool + virtual void setToolbox(QGCToolbox *toolbox); + + AppSettings* appSettings (void) { return _appSettings; } + UnitsSettings* unitsSettings (void) { return _unitsSettings; } + AutoConnectSettings* autoConnectSettings (void) { return _autoConnectSettings; } + VideoSettings* videoSettings (void) { return _videoSettings; } + +private: + AppSettings* _appSettings; + UnitsSettings* _unitsSettings; + AutoConnectSettings* _autoConnectSettings; + VideoSettings* _videoSettings; +}; + +#endif diff --git a/src/Settings/Units.SettingsGroup.json b/src/Settings/Units.SettingsGroup.json new file mode 100644 index 0000000000000000000000000000000000000000..0d4f101c7a37a4c875e6999bee1a287fdb733380 --- /dev/null +++ b/src/Settings/Units.SettingsGroup.json @@ -0,0 +1,2 @@ +[ +] diff --git a/src/Settings/UnitsSettings.cc b/src/Settings/UnitsSettings.cc new file mode 100644 index 0000000000000000000000000000000000000000..0d5c6e0d6df29fd8ecaf43ea5839bb286874866b --- /dev/null +++ b/src/Settings/UnitsSettings.cc @@ -0,0 +1,94 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "UnitsSettings.h" + +#include +#include + +const char* UnitsSettings::unitsSettingsGroupName = "Units"; +const char* UnitsSettings::distanceUnitsSettingsName = "DistanceUnits"; +const char* UnitsSettings::areaUnitsSettingsName = "AreaUnits"; +const char* UnitsSettings::speedUnitsSettingsName = "SpeedUnits"; + +UnitsSettings::UnitsSettings(QObject* parent) + : SettingsGroup(unitsSettingsGroupName, QString() /* root settings group */, parent) + , _distanceUnitsFact(NULL) + , _areaUnitsFact(NULL) + , _speedUnitsFact(NULL) +{ + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + qmlRegisterUncreatableType("QGroundControl.SettingsManager", 1, 0, "UnitsSettings", "Reference only"); +} + +Fact* UnitsSettings::distanceUnits(void) +{ + if (!_distanceUnitsFact) { + // Distance/Area/Speed units settings can't be loaded from json since it creates an infinite loop of meta data loading. + QStringList enumStrings; + QVariantList enumValues; + + enumStrings << "Feet" << "Meters"; + enumValues << QVariant::fromValue((uint32_t)DistanceUnitsFeet) << QVariant::fromValue((uint32_t)DistanceUnitsMeters); + + FactMetaData* metaData = new FactMetaData(FactMetaData::valueTypeUint32, this); + metaData->setName(distanceUnitsSettingsName); + metaData->setEnumInfo(enumStrings, enumValues); + metaData->setRawDefaultValue(DistanceUnitsMeters); + + _distanceUnitsFact = new SettingsFact(QString() /* no settings group */, metaData, this); + + } + + return _distanceUnitsFact; + +} + +Fact* UnitsSettings::areaUnits(void) +{ + if (!_areaUnitsFact) { + // Distance/Area/Speed units settings can't be loaded from json since it creates an infinite loop of meta data loading. + QStringList enumStrings; + QVariantList enumValues; + + enumStrings << "SquareFeet" << "SquareMeters" << "SquareKilometers" << "Hectares" << "Acres" << "SquareMiles"; + enumValues << QVariant::fromValue((uint32_t)AreaUnitsSquareFeet) << QVariant::fromValue((uint32_t)AreaUnitsSquareMeters) << QVariant::fromValue((uint32_t)AreaUnitsSquareKilometers) << QVariant::fromValue((uint32_t)AreaUnitsHectares) << QVariant::fromValue((uint32_t)AreaUnitsAcres) << QVariant::fromValue((uint32_t)AreaUnitsSquareMiles); + + FactMetaData* metaData = new FactMetaData(FactMetaData::valueTypeUint32, this); + metaData->setName(areaUnitsSettingsName); + metaData->setEnumInfo(enumStrings, enumValues); + metaData->setRawDefaultValue(AreaUnitsSquareMeters); + + _areaUnitsFact = new SettingsFact(QString() /* no settings group */, metaData, this); + } + + return _areaUnitsFact; + +} + +Fact* UnitsSettings::speedUnits(void) +{ + if (!_speedUnitsFact) { + // Distance/Area/Speed units settings can't be loaded from json since it creates an infinite loop of meta data loading. + QStringList enumStrings; + QVariantList enumValues; + + enumStrings << "Feet/second" << "Meters/second" << "Miles/hour" << "Kilometers/hour" << "Knots"; + enumValues << QVariant::fromValue((uint32_t)SpeedUnitsFeetPerSecond) << QVariant::fromValue((uint32_t)SpeedUnitsMetersPerSecond) << QVariant::fromValue((uint32_t)SpeedUnitsMilesPerHour) << QVariant::fromValue((uint32_t)SpeedUnitsKilometersPerHour) << QVariant::fromValue((uint32_t)SpeedUnitsKnots); + + FactMetaData* metaData = new FactMetaData(FactMetaData::valueTypeUint32, this); + metaData->setName(speedUnitsSettingsName); + metaData->setEnumInfo(enumStrings, enumValues); + metaData->setRawDefaultValue(SpeedUnitsMetersPerSecond); + + _speedUnitsFact = new SettingsFact(QString() /* no settings group */, metaData, this); + } + + return _speedUnitsFact; +} diff --git a/src/Settings/UnitsSettings.h b/src/Settings/UnitsSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..3ede8765a39cd7bd0bdd929ae9a7aec3d377c953 --- /dev/null +++ b/src/Settings/UnitsSettings.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef UnitsSettings_H +#define UnitsSettings_H + +#include "SettingsGroup.h" + +class UnitsSettings : public SettingsGroup +{ + Q_OBJECT + +public: + UnitsSettings(QObject* parent = NULL); + + enum DistanceUnits { + DistanceUnitsFeet = 0, + DistanceUnitsMeters + }; + + enum AreaUnits { + AreaUnitsSquareFeet = 0, + AreaUnitsSquareMeters, + AreaUnitsSquareKilometers, + AreaUnitsHectares, + AreaUnitsAcres, + AreaUnitsSquareMiles, + }; + + enum SpeedUnits { + SpeedUnitsFeetPerSecond = 0, + SpeedUnitsMetersPerSecond, + SpeedUnitsMilesPerHour, + SpeedUnitsKilometersPerHour, + SpeedUnitsKnots, + }; + + Q_ENUMS(DistanceUnits) + Q_ENUMS(AreaUnits) + Q_ENUMS(SpeedUnits) + + Q_PROPERTY(Fact* distanceUnits READ distanceUnits CONSTANT) + Q_PROPERTY(Fact* areaUnits READ areaUnits CONSTANT) + Q_PROPERTY(Fact* speedUnits READ speedUnits CONSTANT) + + Fact* distanceUnits (void); + Fact* areaUnits (void); + Fact* speedUnits (void); + + static const char* unitsSettingsGroupName; + + static const char* distanceUnitsSettingsName; + static const char* areaUnitsSettingsName; + static const char* speedUnitsSettingsName; + +private: + SettingsFact* _distanceUnitsFact; + SettingsFact* _areaUnitsFact; + SettingsFact* _speedUnitsFact; +}; + +#endif diff --git a/src/Settings/Video.SettingsGroup.json b/src/Settings/Video.SettingsGroup.json new file mode 100644 index 0000000000000000000000000000000000000000..457a519c274f87171d725a012a2097ee175eabb9 --- /dev/null +++ b/src/Settings/Video.SettingsGroup.json @@ -0,0 +1,48 @@ +[ +{ + "name": "VideoSource", + "shortDescription": "Video source", + "longDescription": "Source for video. UDP, RTSP and UVC Cameras may be supported supported depending on Vehicle and QGroundControl version.", + "type": "string", + "defaultValue": "" +}, +{ + "name": "VideoUDPPort", + "shortDescription": "Video UDP Port", + "longDescription": "UDP port to bind to for video stream.", + "type": "uint16", + "min": 1025, + "defaultValue": 5600 +}, +{ + "name": "VideoRTSPUrl", + "shortDescription": "Video RTSP Url", + "longDescription": "RTSP url address and port to bind to for video stream. Example: rtsp://192.168.42.1:554/live", + "type": "string", + "defaultValue": "" +}, +{ + "name": "VideoSavePath", + "shortDescription": "Video save directory", + "longDescription": "Directory to save videos to.", + "type": "string", + "defaultValue": "" +}, +{ + "name": "VideoAspectRatio", + "shortDescription": "Video Aspect Ratio", + "longDescription": "Video Aspect Ratio (width / height). Use 0.0 to ignore it.", + "type": "float", + "decimalPlaces": 6, + "defaultValue": 1.777777 +}, +{ + "name": "VideoGridLines", + "shortDescription": "Video Grid Lines", + "longDescription": "Displays a grid overlayed over the video view.", + "type": "uint32", + "enumStrings": "Hide,Show", + "enumValues": "1,0", + "defaultValue": 0 +} +] diff --git a/src/Settings/VideoSettings.cc b/src/Settings/VideoSettings.cc new file mode 100644 index 0000000000000000000000000000000000000000..52cf5961587d209565a7d96047b5adf758122567 --- /dev/null +++ b/src/Settings/VideoSettings.cc @@ -0,0 +1,128 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "VideoSettings.h" + +#include +#include +#include + +#ifndef QGC_DISABLE_UVC +#include +#endif + +const char* VideoSettings::videoSettingsGroupName = "Video"; + +const char* VideoSettings::videoSourceName = "VideoSource"; +const char* VideoSettings::udpPortName = "VideoUDPPort"; +const char* VideoSettings::rtspUrlName = "VideoRTSPUrl"; +const char* VideoSettings::videoSavePathName = "VideoSavePath"; +const char* VideoSettings::videoAspectRatioName = "VideoAspectRatio"; +const char* VideoSettings::videoGridLinesName = "VideoGridLines"; + +const char* VideoSettings::videoSourceNoVideo = "No Video Available"; +const char* VideoSettings::videoSourceUDP = "UDP Video Stream"; +const char* VideoSettings::videoSourceRTSP = "RTSP Video Stream"; + +VideoSettings::VideoSettings(QObject* parent) + : SettingsGroup(videoSettingsGroupName, QString() /* root settings group */, parent) + , _videoSourceFact(NULL) + , _udpPortFact(NULL) + , _rtspUrlFact(NULL) + , _videoSavePathFact(NULL) + , _videoAspectRatioFact(NULL) + , _gridLinesFact(NULL) +{ + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + qmlRegisterUncreatableType("QGroundControl.SettingsManager", 1, 0, "VideoSettings", "Reference only"); + + // Setup enum values for videoSource settings into meta data + QStringList videoSourceList; +#ifdef QGC_GST_STREAMING +#ifndef NO_UDP_VIDEO + videoSourceList.append(videoSourceUDP); +#endif + videoSourceList.append(videoSourceRTSP); +#endif +#ifndef QGC_DISABLE_UVC + QList cameras = QCameraInfo::availableCameras(); + foreach (const QCameraInfo &cameraInfo, cameras) { + videoSourceList.append(cameraInfo.description()); + } +#endif + if (videoSourceList.count() == 0) { + videoSourceList.append(videoSourceNoVideo); + } + QVariantList videoSourceVarList; + foreach (const QString& videoSource, videoSourceList) { + videoSourceVarList.append(QVariant::fromValue(videoSource)); + } + _nameToMetaDataMap[videoSourceName]->setEnumInfo(videoSourceList, videoSourceVarList); + + // Set default value for videoSource +#if defined(NO_UDP_VIDEO) + _nameToMetaDataMap[videoSourceName]->setRawDefaultValue(videoSourceRTSP); +#else + _nameToMetaDataMap[videoSourceName]->setRawDefaultValue(videoSourceUDP); +#endif +} + +Fact* VideoSettings::videoSource(void) +{ + if (!_videoSourceFact) { + _videoSourceFact = _createSettingsFact(videoSourceName); + } + + return _videoSourceFact; +} + +Fact* VideoSettings::udpPort(void) +{ + if (!_udpPortFact) { + _udpPortFact = _createSettingsFact(udpPortName); + } + + return _udpPortFact; +} + +Fact* VideoSettings::rtspUrl(void) +{ + if (!_rtspUrlFact) { + _rtspUrlFact = _createSettingsFact(rtspUrlName); + } + + return _rtspUrlFact; +} + +Fact* VideoSettings::videoSavePath(void) +{ + if (!_videoSavePathFact) { + _videoSavePathFact = _createSettingsFact(videoSavePathName); + } + + return _videoSavePathFact; +} + +Fact* VideoSettings::aspectRatio(void) +{ + if (!_videoAspectRatioFact) { + _videoAspectRatioFact = _createSettingsFact(videoAspectRatioName); + } + + return _videoAspectRatioFact; +} + +Fact* VideoSettings::gridLines(void) +{ + if (!_gridLinesFact) { + _gridLinesFact = _createSettingsFact(videoGridLinesName); + } + + return _gridLinesFact; +} diff --git a/src/Settings/VideoSettings.h b/src/Settings/VideoSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..48eb53dfc9844de55d3823561282da80658ffd1e --- /dev/null +++ b/src/Settings/VideoSettings.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#ifndef VideoSettings_H +#define VideoSettings_H + +#include "SettingsGroup.h" + +class VideoSettings : public SettingsGroup +{ + Q_OBJECT + +public: + VideoSettings(QObject* parent = NULL); + + Q_PROPERTY(Fact* videoSource READ videoSource CONSTANT) + Q_PROPERTY(Fact* udpPort READ udpPort CONSTANT) + Q_PROPERTY(Fact* rtspUrl READ rtspUrl CONSTANT) + Q_PROPERTY(Fact* videoSavePath READ videoSavePath CONSTANT) + Q_PROPERTY(Fact* aspectRatio READ aspectRatio CONSTANT) + Q_PROPERTY(Fact* gridLines READ gridLines CONSTANT) + + Fact* videoSource (void); + Fact* udpPort (void); + Fact* rtspUrl (void); + Fact* videoSavePath (void); + Fact* aspectRatio (void); + Fact* gridLines (void); + + static const char* videoSettingsGroupName; + + static const char* videoSourceName; + static const char* udpPortName; + static const char* rtspUrlName; + static const char* videoSavePathName; + static const char* videoAspectRatioName; + static const char* videoGridLinesName; + + static const char* videoSourceNoVideo; + static const char* videoSourceUDP; + static const char* videoSourceRTSP; + +private: + SettingsFact* _videoSourceFact; + SettingsFact* _udpPortFact; + SettingsFact* _rtspUrlFact; + SettingsFact* _videoSavePathFact; + SettingsFact* _videoAspectRatioFact; + SettingsFact* _gridLinesFact; +}; + +#endif diff --git a/src/Vehicle/BatteryFact.json b/src/Vehicle/BatteryFact.json index b915bc4b27270e5dea01413c857ba51df114f712..f6ca0c9b05b774492f50f353af31c407adf4f15c 100644 --- a/src/Vehicle/BatteryFact.json +++ b/src/Vehicle/BatteryFact.json @@ -23,9 +23,9 @@ { "name": "current", "shortDescription": "Current", - "type": "int32", - "decimalPlaces": 0, - "units": "mA" + "type": "float", + "decimalPlaces": 2, + "units": "A" }, { "name": "temperature", diff --git a/src/Vehicle/GPSFact.json b/src/Vehicle/GPSFact.json index 938e3dd37e7b1832a658ff478176afe264471737..9b018b4598044d8adf2bd31849b10488c2dced4c 100644 --- a/src/Vehicle/GPSFact.json +++ b/src/Vehicle/GPSFact.json @@ -22,14 +22,13 @@ "name": "lock", "shortDescription": "GPS Lock", "type": "uint32", - "enumStrings": "None,None,2D Lock,3D Lock,3D DGPS Lock,3D RTK GPS Lock (float),3D RTK GPS Lock (fixed)", - "enumValues": "0,1,2,3,4,5,6", + "enumStrings": "None,None,2D Lock,3D Lock,3D DGPS Lock,3D RTK GPS Lock (float),3D RTK GPS Lock (fixed),Static (fixed)", + "enumValues": "0,1,2,3,4,5,6,7", "decimalPlaces": 0 }, { "name": "count", "shortDescription": "Sat Count", - "type": "double", - "decimalPlaces": 0 + "type": "uint32" } ] diff --git a/src/Vehicle/MAVLinkLogManager.cc b/src/Vehicle/MAVLinkLogManager.cc new file mode 100644 index 0000000000000000000000000000000000000000..8a1a64c376009631090fa841bf1bd7e6b6dff83f --- /dev/null +++ b/src/Vehicle/MAVLinkLogManager.cc @@ -0,0 +1,952 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "MAVLinkLogManager.h" +#include "QGCApplication.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QGC_LOGGING_CATEGORY(MAVLinkLogManagerLog, "MAVLinkLogManagerLog") + +static const char* kMAVLinkLogGroup = "MAVLinkLogGroup"; +static const char* kEmailAddressKey = "Email"; +static const char* kDescriptionsKey = "Description"; +static const char* kDefaultDescr = "QGroundControl Session"; +static const char* kPx4URLKey = "LogURL"; +static const char* kDefaultPx4URL = "http://logs.px4.io/upload"; +static const char* kEnableAutoUploadKey = "EnableAutoUpload"; +static const char* kEnableAutoStartKey = "EnableAutoStart"; +static const char* kEnableDeletetKey = "EnableDelete"; +static const char* kUlogExtension = ".ulg"; +static const char* kSidecarExtension = ".uploaded"; +static const char* kVideoURLKey = "VideoURL"; +static const char* kWindSpeedKey = "WindSpeed"; +static const char* kRateKey = "RateKey"; +static const char* kPublicLogKey = "PublicLog"; +static const char* kFeedback = "feedback"; +static const char* kVideoURL = "videoUrl"; + +//----------------------------------------------------------------------------- +MAVLinkLogFiles::MAVLinkLogFiles(MAVLinkLogManager* manager, const QString& filePath, bool newFile) + : _manager(manager) + , _size(0) + , _selected(false) + , _uploading(false) + , _progress(0) + , _writing(false) + , _uploaded(false) +{ + QFileInfo fi(filePath); + _name = fi.baseName(); + if(!newFile) { + _size = (quint32)fi.size(); + QString sideCar = filePath; + sideCar.replace(kUlogExtension, kSidecarExtension); + QFileInfo sc(sideCar); + _uploaded = sc.exists(); + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogFiles::setSize(quint32 size) +{ + _size = size; + emit sizeChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogFiles::setSelected(bool selected) +{ + _selected = selected; + emit selectedChanged(); + emit _manager->selectedCountChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogFiles::setUploading(bool uploading) +{ + _uploading = uploading; + emit uploadingChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogFiles::setProgress(qreal progress) +{ + _progress = progress; + emit progressChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogFiles::setWriting(bool writing) +{ + _writing = writing; + emit writingChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogFiles::setUploaded(bool uploaded) +{ + _uploaded = uploaded; + emit uploadedChanged(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +MAVLinkLogProcessor::MAVLinkLogProcessor() + : _fd(NULL) + , _written(0) + , _sequence(-1) + , _numDrops(0) + , _gotHeader(false) + , _error(false) + , _record(NULL) +{ +} + +//----------------------------------------------------------------------------- +MAVLinkLogProcessor::~MAVLinkLogProcessor() +{ + close(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogProcessor::close() +{ + if(_fd) { + fclose(_fd); + _fd = NULL; + } +} + +//----------------------------------------------------------------------------- +bool +MAVLinkLogProcessor::valid() +{ + return (_fd != NULL) && (_record != NULL); +} + +//----------------------------------------------------------------------------- +bool +MAVLinkLogProcessor::create(MAVLinkLogManager* manager, const QString path, uint8_t id) +{ + _fileName.sprintf("%s/%03d-%s%s", + path.toLatin1().data(), + id, + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz").toLatin1().data(), + kUlogExtension); + _fd = fopen(_fileName.toLatin1().data(), "wb"); + if(_fd) { + _record = new MAVLinkLogFiles(manager, _fileName, true); + _record->setWriting(true); + _sequence = -1; + return true; + } + return false; +} + +//----------------------------------------------------------------------------- +bool +MAVLinkLogProcessor::_checkSequence(uint16_t seq, int& num_drops) +{ + num_drops = 0; + //-- Check if a sequence is newer than the one previously received and if + // there were dropped messages between the last one and this. + if(_sequence == -1) { + _sequence = seq; + return true; + } + if((uint16_t)_sequence == seq) { + return false; + } + if(seq > (uint16_t)_sequence) { + // Account for wrap-arounds, sequence is 2 bytes + if((seq - _sequence) > (1 << 15)) { // Assume reordered + return false; + } + num_drops = seq - _sequence - 1; + _numDrops += num_drops; + _sequence = seq; + return true; + } else { + if((_sequence - seq) > (1 << 15)) { + num_drops = (1 << 16) - _sequence - 1 + seq; + _numDrops += num_drops; + _sequence = seq; + return true; + } + return false; + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogProcessor::_writeData(void* data, int len) +{ + if(!_error) { + _error = fwrite(data, 1, len, _fd) != (size_t)len; + if(!_error) { + _written += len; + if(_record) { + _record->setSize(_written); + } + } else { + qCDebug(MAVLinkLogManagerLog) << "File IO error:" << len << "bytes into" << _fileName; + } + } +} + +//----------------------------------------------------------------------------- +QByteArray +MAVLinkLogProcessor::_writeUlogMessage(QByteArray& data) +{ + //-- Write ulog data w/o integrity checking, assuming data starts with a + // valid ulog message. returns the remaining data at the end. + while(data.length() > 2) { + uint8_t* ptr = (uint8_t*)data.data(); + int message_length = ptr[0] + (ptr[1] * 256) + 3; // 3 = ULog msg header + if(message_length > data.length()) + break; + _writeData(data.data(), message_length); + data.remove(0, message_length); + } + return data; +} + +//----------------------------------------------------------------------------- +bool +MAVLinkLogProcessor::processStreamData(uint16_t sequence, uint8_t first_message, QByteArray data) +{ + int num_drops = 0; + _error = false; + while(_checkSequence(sequence, num_drops)) { + //-- The first 16 bytes need special treatment (this sounds awfully brittle) + if(!_gotHeader) { + if(data.size() < 16) { + //-- Shouldn't happen but if it does, we might as well close shop. + qCWarning(MAVLinkLogManagerLog) << "Corrupt log header. Canceling log download."; + return false; + } + //-- Write header + _writeData(data.data(), 16); + data.remove(0, 16); + _gotHeader = true; + // What about data start offset now that we removed 16 bytes off the start? + } + if(_gotHeader && num_drops > 0) { + if(num_drops > 25) num_drops = 25; + //-- Hocus Pocus + // Write a dropout message. We don't really know the actual duration, + // so just use the number of drops * 10 ms + uint8_t bogus[] = {2, 0, 79, 0, 0}; + bogus[3] = num_drops * 10; + _writeData(bogus, sizeof(bogus)); + } + if(num_drops > 0) { + _writeUlogMessage(_ulogMessage); + _ulogMessage.clear(); + //-- If no usefull information in this message. Drop it. + if(first_message == 255) { + break; + } + if(first_message > 0) { + data.remove(0, first_message); + first_message = 0; + } + } + if(first_message == 255 && _ulogMessage.length() > 0) { + _ulogMessage.append(data); + break; + } + if(_ulogMessage.length()) { + _writeData(_ulogMessage.data(), _ulogMessage.length()); + if(first_message) { + _writeData(data.left(first_message).data(), first_message); + } + _ulogMessage.clear(); + } + if(first_message) { + data.remove(0, first_message); + } + _ulogMessage = _writeUlogMessage(data); + break; + } + return !_error; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +MAVLinkLogManager::MAVLinkLogManager(QGCApplication* app) + : QGCTool(app) + , _enableAutoUpload(true) + , _enableAutoStart(false) + , _nam(NULL) + , _currentLogfile(NULL) + , _vehicle(NULL) + , _logRunning(false) + , _loggingDisabled(false) + , _logProcessor(NULL) + , _deleteAfterUpload(false) + , _windSpeed(-1) + , _publicLog(false) +{ + //-- Get saved settings + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + setEmailAddress(settings.value(kEmailAddressKey, QString()).toString()); + setDescription(settings.value(kDescriptionsKey, QString(kDefaultDescr)).toString()); + setUploadURL(settings.value(kPx4URLKey, QString(kDefaultPx4URL)).toString()); + setVideoURL(settings.value(kVideoURLKey, QString()).toString()); + setEnableAutoUpload(settings.value(kEnableAutoUploadKey, true).toBool()); + setEnableAutoStart(settings.value(kEnableAutoStartKey, false).toBool()); + setDeleteAfterUpload(settings.value(kEnableDeletetKey, false).toBool()); + setWindSpeed(settings.value(kWindSpeedKey, -1).toInt()); + setRating(settings.value(kRateKey, "notset").toString()); + setPublicLog(settings.value(kPublicLogKey, true).toBool()); + //-- Logging location + _logPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + _logPath += "/MAVLinkLogs"; + if(!QDir(_logPath).exists()) { + if(!QDir().mkpath(_logPath)) { + qCWarning(MAVLinkLogManagerLog) << "Could not create MAVLink log download path:" << _logPath; + _loggingDisabled = true; + } + } + if(!_loggingDisabled) { + //-- Load current list of logs + QString filter = "*"; + filter += kUlogExtension; + QDirIterator it(_logPath, QStringList() << filter, QDir::Files); + while(it.hasNext()) { + _insertNewLog(new MAVLinkLogFiles(this, it.next())); + } + qCDebug(MAVLinkLogManagerLog) << "MAVLink logs directory:" << _logPath; + } +} + +//----------------------------------------------------------------------------- +MAVLinkLogManager::~MAVLinkLogManager() +{ + _logFiles.clear(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setToolbox(QGCToolbox* toolbox) +{ + QGCTool::setToolbox(toolbox); + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + qmlRegisterUncreatableType("QGroundControl.MAVLinkLogManager", 1, 0, "MAVLinkLogManager", "Reference only"); + if(!_loggingDisabled) { + connect(toolbox->multiVehicleManager(), &MultiVehicleManager::activeVehicleChanged, this, &MAVLinkLogManager::_activeVehicleChanged); + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setEmailAddress(QString email) +{ + _emailAddress = email; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kEmailAddressKey, email); + emit emailAddressChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setDescription(QString description) +{ + _description = description; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kDescriptionsKey, description); + emit descriptionChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setUploadURL(QString url) +{ + _uploadURL = url; + if(_uploadURL.isEmpty()) { + _uploadURL = kDefaultPx4URL; + } + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kPx4URLKey, _uploadURL); + emit uploadURLChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setFeedback(QString fb) +{ + _feedback = fb; + emit feedbackChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setVideoURL(QString url) +{ + _videoURL = url; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kVideoURLKey, url); + emit videoURLChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setEnableAutoUpload(bool enable) +{ + _enableAutoUpload = enable; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kEnableAutoUploadKey, enable); + emit enableAutoUploadChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setEnableAutoStart(bool enable) +{ + _enableAutoStart = enable; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kEnableAutoStartKey, enable); + emit enableAutoStartChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setDeleteAfterUpload(bool enable) +{ + _deleteAfterUpload = enable; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kEnableDeletetKey, enable); + emit deleteAfterUploadChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setWindSpeed(int speed) +{ + _windSpeed = speed; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kWindSpeedKey, speed); + emit windSpeedChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setRating(QString rate) +{ + _rating = rate; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kRateKey, rate); + emit ratingChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::setPublicLog(bool pub) +{ + _publicLog = pub; + QSettings settings; + settings.beginGroup(kMAVLinkLogGroup); + settings.setValue(kPublicLogKey, pub); + emit publicLogChanged(); +} + +//----------------------------------------------------------------------------- +bool +MAVLinkLogManager::uploading() +{ + return _currentLogfile != NULL; +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::uploadLog() +{ + if(_currentLogfile) { + _currentLogfile->setUploading(false); + } + for(int i = 0; i < _logFiles.count(); i++) { + _currentLogfile = qobject_cast(_logFiles.get(i)); + Q_ASSERT(_currentLogfile); + if(_currentLogfile->selected()) { + _currentLogfile->setSelected(false); + if(!_currentLogfile->uploaded() && !_emailAddress.isEmpty() && !_uploadURL.isEmpty()) { + _currentLogfile->setUploading(true); + _currentLogfile->setProgress(0.0); + QString filePath = _makeFilename(_currentLogfile->name()); + _sendLog(filePath); + emit uploadingChanged(); + return; + } + } + } + _currentLogfile = NULL; + emit uploadingChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_insertNewLog(MAVLinkLogFiles* newLog) +{ + //-- Simpler than trying to sort this thing + int count = _logFiles.count(); + if(!count) { + _logFiles.append(newLog); + } else { + for(int i = 0; i < count; i++) { + MAVLinkLogFiles* f = qobject_cast(_logFiles.get(i)); + if(newLog->name() < f->name()) { + _logFiles.insert(i, newLog); + return; + } + } + _logFiles.append(newLog); + } +} + +//----------------------------------------------------------------------------- +int +MAVLinkLogManager::_getFirstSelected() +{ + for(int i = 0; i < _logFiles.count(); i++) { + MAVLinkLogFiles* f = qobject_cast(_logFiles.get(i)); + Q_ASSERT(f); + if(f->selected()) { + return i; + } + } + return -1; +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::deleteLog() +{ + while (true) { + int idx = _getFirstSelected(); + if(idx < 0) { + break; + } + MAVLinkLogFiles* log = qobject_cast(_logFiles.get(idx)); + _deleteLog(log); + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_deleteLog(MAVLinkLogFiles* log) +{ + QString filePath = _makeFilename(log->name()); + QFile gone(filePath); + if(!gone.remove()) { + qCWarning(MAVLinkLogManagerLog) << "Could not delete MAVLink log file:" << _logPath; + } + //-- Remove sidecar file (if any) + filePath.replace(kUlogExtension, kSidecarExtension); + QFile sgone(filePath); + if(sgone.exists()) { + sgone.remove(); + } + //-- Remove file from list and delete record + _logFiles.removeOne(log); + delete log; + emit logFilesChanged(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::cancelUpload() +{ + for(int i = 0; i < _logFiles.count(); i++) { + MAVLinkLogFiles* pLogFile = qobject_cast(_logFiles.get(i)); + Q_ASSERT(pLogFile); + if(pLogFile->selected() && pLogFile != _currentLogfile) { + pLogFile->setSelected(false); + } + } + if(_currentLogfile) { + emit abortUpload(); + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::startLogging() +{ + if(_vehicle && _vehicle->px4Firmware()) { + if(_createNewLog()) { + _vehicle->startMavlinkLog(); + _logRunning = true; + emit logRunningChanged(); + } + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::stopLogging() +{ + if(_vehicle && _vehicle->px4Firmware()) { + //-- Tell vehicle to stop sending logs + _vehicle->stopMavlinkLog(); + } + if(_logProcessor) { + _logProcessor->close(); + if(_logProcessor->record()) { + _logProcessor->record()->setWriting(false); + if(_enableAutoUpload) { + //-- Queue log for auto upload (set selected flag) + _logProcessor->record()->setSelected(true); + if(!uploading()) { + uploadLog(); + } + } + } + delete _logProcessor; + _logProcessor = NULL; + _logRunning = false; + emit logRunningChanged(); + } +} + +//----------------------------------------------------------------------------- +QHttpPart +create_form_part(const QString& name, const QString& value) +{ + QHttpPart formPart; + formPart.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(name)); + formPart.setBody(value.toUtf8()); + return formPart; +} + +//----------------------------------------------------------------------------- +bool +MAVLinkLogManager::_sendLog(const QString& logFile) +{ + QString defaultDescription = _description; + if(_description.isEmpty()) { + qCWarning(MAVLinkLogManagerLog) << "Log description missing. Using defaults."; + defaultDescription = kDefaultDescr; + } + if(_emailAddress.isEmpty()) { + qCWarning(MAVLinkLogManagerLog) << "User email missing."; + return false; + } + if(_uploadURL.isEmpty()) { + qCWarning(MAVLinkLogManagerLog) << "Upload URL missing."; + return false; + } + QFileInfo fi(logFile); + if(!fi.exists()) { + qCWarning(MAVLinkLogManagerLog) << "Log file missing:" << logFile; + return false; + } + QFile* file = new QFile(logFile); + if(!file || !file->open(QIODevice::ReadOnly)) { + if(file) { + delete file; + } + qCWarning(MAVLinkLogManagerLog) << "Could not open log file:" << logFile; + return false; + } + if(!_nam) { + _nam = new QNetworkAccessManager(this); + } + QNetworkProxy savedProxy = _nam->proxy(); + QNetworkProxy tempProxy; + tempProxy.setType(QNetworkProxy::DefaultProxy); + _nam->setProxy(tempProxy); + //-- Build POST request + QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + QHttpPart emailPart = create_form_part("email", _emailAddress); + QHttpPart descriptionPart = create_form_part("description", _description); + QHttpPart sourcePart = create_form_part("source", "QGroundControl"); + QHttpPart versionPart = create_form_part("version", _app->applicationVersion()); + QHttpPart typePart = create_form_part("type", "flightreport"); + QHttpPart windPart = create_form_part("windSpeed", QString::number(_windSpeed)); + QHttpPart ratingPart = create_form_part("rating", _rating); + QHttpPart publicPart = create_form_part("public", _publicLog ? "true" : "false"); + //-- Assemble request and POST it + multiPart->append(emailPart); + multiPart->append(descriptionPart); + multiPart->append(sourcePart); + multiPart->append(versionPart); + multiPart->append(typePart); + multiPart->append(windPart); + multiPart->append(ratingPart); + multiPart->append(publicPart); + //-- Optional + QHttpPart feedbackPart; + if(_feedback.isEmpty()) { + feedbackPart = create_form_part(kFeedback, "None Given"); + } else { + feedbackPart = create_form_part(kFeedback, _feedback); + } + multiPart->append(feedbackPart); + QHttpPart videoPart; + if(_videoURL.isEmpty()) { + videoPart = create_form_part(kVideoURL, "None"); + } else { + videoPart = create_form_part(kVideoURL, _videoURL); + } + multiPart->append(videoPart); + //-- Actual Log File + QHttpPart logPart; + logPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream"); + logPart.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"filearg\"; filename=\"%1\"").arg(fi.fileName())); + logPart.setBodyDevice(file); + multiPart->append(logPart); + file->setParent(multiPart); + QNetworkRequest request(_uploadURL); +#if QT_VERSION > 0x050600 + request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); +#endif + QNetworkReply* reply = _nam->post(request, multiPart); + connect(reply, &QNetworkReply::finished, this, &MAVLinkLogManager::_uploadFinished); + connect(this, &MAVLinkLogManager::abortUpload, reply, &QNetworkReply::abort); + //connect(reply, &QNetworkReply::readyRead, this, &MAVLinkLogManager::_dataAvailable); + connect(reply, &QNetworkReply::uploadProgress, this, &MAVLinkLogManager::_uploadProgress); + multiPart->setParent(reply); + qCDebug(MAVLinkLogManagerLog) << "Log" << fi.baseName() << "Uploading." << fi.size() << "bytes."; + _nam->setProxy(savedProxy); + return true; +} + +//----------------------------------------------------------------------------- +bool +MAVLinkLogManager::_processUploadResponse(int http_code, QByteArray& data) +{ + qCDebug(MAVLinkLogManagerLog) << "Uploaded response:" << QString::fromUtf8(data); + emit readyRead(data); + return http_code == 200; +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_dataAvailable() +{ + QNetworkReply* reply = qobject_cast(sender()); + if(!reply) { + return; + } + QByteArray data = reply->readAll(); + qCDebug(MAVLinkLogManagerLog) << "Uploaded response data:" << QString::fromUtf8(data); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_uploadFinished() +{ + QNetworkReply* reply = qobject_cast(sender()); + if(!reply) { + return; + } + const int http_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QByteArray data = reply->readAll(); + if(_processUploadResponse(http_code, data)) { + qCDebug(MAVLinkLogManagerLog) << "Log uploaded."; + emit succeed(); + if(_deleteAfterUpload) { + if(_currentLogfile) { + _deleteLog(_currentLogfile); + _currentLogfile = NULL; + } + } else { + if(_currentLogfile) { + _currentLogfile->setUploaded(true); + //-- Write side-car file to flag it as uploaded + QString sideCar = _makeFilename(_currentLogfile->name()); + sideCar.replace(kUlogExtension, kSidecarExtension); + FILE* f = fopen(sideCar.toLatin1().data(), "wb"); + if(f) { + fclose(f); + } + } + } + } else { + qCWarning(MAVLinkLogManagerLog) << QString("Log Upload Error: %1 status: %2").arg(reply->errorString(), reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString()); + emit failed(); + } + reply->deleteLater(); + //-- Next (if any) + uploadLog(); +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_uploadProgress(qint64 bytesSent, qint64 bytesTotal) +{ + if(bytesTotal) { + qreal progress = (qreal)bytesSent / (qreal)bytesTotal; + if(_currentLogfile) { + _currentLogfile->setProgress(progress); + } + } + qCDebug(MAVLinkLogManagerLog) << bytesSent << "of" << bytesTotal; +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_activeVehicleChanged(Vehicle* vehicle) +{ + //-- TODO: This is not quite right. This is being used to detect when a vehicle + // connects/disconnects. In reality, if QGC is connected to multiple vehicles, + // this is called each time the user switches from one vehicle to another. So + // far, I'm working on the assumption that multiple vehicles is a rare exception. + // For now, we only handle one log download at a time. + // Disconnect the previous one (if any) + if(_vehicle && _vehicle->px4Firmware()) { + disconnect(_vehicle, &Vehicle::armedChanged, this, &MAVLinkLogManager::_armedChanged); + disconnect(_vehicle, &Vehicle::mavlinkLogData, this, &MAVLinkLogManager::_mavlinkLogData); + disconnect(_vehicle, &Vehicle::mavCommandResult, this, &MAVLinkLogManager::_mavCommandResult); + _vehicle = NULL; + //-- Stop logging (if that's the case) + stopLogging(); + emit canStartLogChanged(); + } + // Connect new system + if(vehicle && vehicle->px4Firmware()) { + _vehicle = vehicle; + connect(_vehicle, &Vehicle::armedChanged, this, &MAVLinkLogManager::_armedChanged); + connect(_vehicle, &Vehicle::mavlinkLogData, this, &MAVLinkLogManager::_mavlinkLogData); + connect(_vehicle, &Vehicle::mavCommandResult, this, &MAVLinkLogManager::_mavCommandResult); + emit canStartLogChanged(); + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_mavlinkLogData(Vehicle* /*vehicle*/, uint8_t /*target_system*/, uint8_t /*target_component*/, uint16_t sequence, uint8_t first_message, QByteArray data, bool /*acked*/) +{ + if(_logProcessor && _logProcessor->valid()) { + if(!_logProcessor->processStreamData(sequence, first_message, data)) { + qCWarning(MAVLinkLogManagerLog) << "Error writing MAVLink log file:" << _logProcessor->fileName(); + delete _logProcessor; + _logProcessor = NULL; + _logRunning = false; + _vehicle->stopMavlinkLog(); + emit logRunningChanged(); + } + } else { + qCWarning(MAVLinkLogManagerLog) << "MAVLink log data received when not expected."; + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_mavCommandResult(int vehicleId, int component, int command, int result, bool noReponseFromVehicle) +{ + Q_UNUSED(vehicleId); + Q_UNUSED(component); + Q_UNUSED(noReponseFromVehicle) + + if(command == MAV_CMD_LOGGING_START || command == MAV_CMD_LOGGING_STOP) { + //-- Did it fail? + if(result != MAV_RESULT_ACCEPTED) { + if(command == MAV_CMD_LOGGING_STOP) { + //-- Not that it could happen but... + qCWarning(MAVLinkLogManagerLog) << "Stop MAVLink log command failed."; + } else { + //-- Could not start logging for some reason. + qCWarning(MAVLinkLogManagerLog) << "Start MAVLink log command failed."; + _discardLog(); + } + } + } +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_discardLog() +{ + //-- Delete (empty) log file (and record) + if(_logProcessor) { + _logProcessor->close(); + if(_logProcessor->record()) { + _deleteLog(_logProcessor->record()); + } + delete _logProcessor; + _logProcessor = NULL; + } + _logRunning = false; + emit logRunningChanged(); +} + +//----------------------------------------------------------------------------- +bool +MAVLinkLogManager::_createNewLog() +{ + if(_logProcessor) { + delete _logProcessor; + _logProcessor = NULL; + } + _logProcessor = new MAVLinkLogProcessor; + if(_logProcessor->create(this, _logPath, _vehicle->id())) { + _insertNewLog(_logProcessor->record()); + emit logFilesChanged(); + } else { + qCWarning(MAVLinkLogManagerLog) << "Could not create MAVLink log file:" << _logProcessor->fileName(); + delete _logProcessor; + _logProcessor = NULL; + } + return _logProcessor != NULL; +} + +//----------------------------------------------------------------------------- +void +MAVLinkLogManager::_armedChanged(bool armed) +{ + if(_vehicle && _vehicle->px4Firmware()) { + if(armed) { + if(_enableAutoStart) { + startLogging(); + } + } else { + if(_logRunning && _enableAutoStart) { + stopLogging(); + } + } + } +} + +//----------------------------------------------------------------------------- +QString +MAVLinkLogManager::_makeFilename(const QString& baseName) +{ + QString filePath = _logPath; + filePath += "/"; + filePath += baseName; + filePath += kUlogExtension; + return filePath; +} diff --git a/src/Vehicle/MAVLinkLogManager.h b/src/Vehicle/MAVLinkLogManager.h new file mode 100644 index 0000000000000000000000000000000000000000..a64b8998f724403405ad8241edc0cf0c6f4e5ba6 --- /dev/null +++ b/src/Vehicle/MAVLinkLogManager.h @@ -0,0 +1,229 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +#ifndef MAVLinkLogManager_H +#define MAVLinkLogManager_H + +#include + +#include "QmlObjectListModel.h" +#include "QGCLoggingCategory.h" +#include "QGCToolbox.h" +#include "Vehicle.h" + +Q_DECLARE_LOGGING_CATEGORY(MAVLinkLogManagerLog) + +class QNetworkAccessManager; +class MAVLinkLogManager; + +//----------------------------------------------------------------------------- +class MAVLinkLogFiles : public QObject +{ + Q_OBJECT +public: + MAVLinkLogFiles (MAVLinkLogManager* manager, const QString& filePath, bool newFile = false); + + Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(quint32 size READ size NOTIFY sizeChanged) + Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged) + Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged) + Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) + Q_PROPERTY(bool writing READ writing NOTIFY writingChanged) + Q_PROPERTY(bool uploaded READ uploaded NOTIFY uploadedChanged) + + QString name () { return _name; } + quint32 size () { return _size; } + bool selected () { return _selected; } + bool uploading () { return _uploading; } + qreal progress () { return _progress; } + bool writing () { return _writing; } + bool uploaded () { return _uploaded; } + + void setSelected (bool selected); + void setUploading (bool uploading); + void setProgress (qreal progress); + void setWriting (bool writing); + void setSize (quint32 size); + void setUploaded (bool uploaded); + +signals: + void sizeChanged (); + void selectedChanged (); + void uploadingChanged (); + void progressChanged (); + void writingChanged (); + void uploadedChanged (); + +private: + MAVLinkLogManager* _manager; + QString _name; + quint32 _size; + bool _selected; + bool _uploading; + qreal _progress; + bool _writing; + bool _uploaded; +}; + +//----------------------------------------------------------------------------- +class MAVLinkLogProcessor +{ +public: + MAVLinkLogProcessor(); + ~MAVLinkLogProcessor(); + void close (); + bool valid (); + bool create (MAVLinkLogManager *manager, const QString path, uint8_t id); + MAVLinkLogFiles* record () { return _record; } + QString fileName () { return _fileName; } + bool processStreamData(uint16_t _sequence, uint8_t first_message, QByteArray data); +private: + bool _checkSequence(uint16_t seq, int &num_drops); + QByteArray _writeUlogMessage(QByteArray &data); + void _writeData(void* data, int len); +private: + FILE* _fd; + quint32 _written; + int _sequence; + int _numDrops; + bool _gotHeader; + bool _error; + QByteArray _ulogMessage; + QString _fileName; + MAVLinkLogFiles* _record; +}; + +//----------------------------------------------------------------------------- +class MAVLinkLogManager : public QGCTool +{ + Q_OBJECT + +public: + MAVLinkLogManager (QGCApplication* app); + ~MAVLinkLogManager (); + + Q_PROPERTY(QString emailAddress READ emailAddress WRITE setEmailAddress NOTIFY emailAddressChanged) + Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) + Q_PROPERTY(QString uploadURL READ uploadURL WRITE setUploadURL NOTIFY uploadURLChanged) + Q_PROPERTY(QString feedback READ feedback WRITE setFeedback NOTIFY feedbackChanged) + Q_PROPERTY(QString videoURL READ videoURL WRITE setVideoURL NOTIFY videoURLChanged) + Q_PROPERTY(bool enableAutoUpload READ enableAutoUpload WRITE setEnableAutoUpload NOTIFY enableAutoUploadChanged) + Q_PROPERTY(bool enableAutoStart READ enableAutoStart WRITE setEnableAutoStart NOTIFY enableAutoStartChanged) + Q_PROPERTY(bool deleteAfterUpload READ deleteAfterUpload WRITE setDeleteAfterUpload NOTIFY deleteAfterUploadChanged) + Q_PROPERTY(bool publicLog READ publicLog WRITE setPublicLog NOTIFY publicLogChanged) + Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged) + Q_PROPERTY(bool logRunning READ logRunning NOTIFY logRunningChanged) + Q_PROPERTY(bool canStartLog READ canStartLog NOTIFY canStartLogChanged) + Q_PROPERTY(QmlObjectListModel* logFiles READ logFiles NOTIFY logFilesChanged) + Q_PROPERTY(int windSpeed READ windSpeed WRITE setWindSpeed NOTIFY windSpeedChanged) + Q_PROPERTY(QString rating READ rating WRITE setRating NOTIFY ratingChanged) + + Q_INVOKABLE void uploadLog (); + Q_INVOKABLE void deleteLog (); + Q_INVOKABLE void cancelUpload (); + Q_INVOKABLE void startLogging (); + Q_INVOKABLE void stopLogging (); + + QString emailAddress () { return _emailAddress; } + QString description () { return _description; } + QString uploadURL () { return _uploadURL; } + QString feedback () { return _feedback; } + QString videoURL () { return _videoURL; } + bool enableAutoUpload () { return _enableAutoUpload; } + bool enableAutoStart () { return _enableAutoStart; } + bool uploading (); + bool logRunning () { return _logRunning; } + bool canStartLog () { return _vehicle != NULL; } + bool deleteAfterUpload () { return _deleteAfterUpload; } + bool publicLog () { return _publicLog; } + int windSpeed () { return _windSpeed; } + QString rating () { return _rating; } + + QmlObjectListModel* logFiles () { return &_logFiles; } + + void setEmailAddress (QString email); + void setDescription (QString description); + void setUploadURL (QString url); + void setFeedback (QString feedback); + void setVideoURL (QString url); + void setEnableAutoUpload (bool enable); + void setEnableAutoStart (bool enable); + void setDeleteAfterUpload(bool enable); + void setWindSpeed (int speed); + void setRating (QString rate); + void setPublicLog (bool publicLog); + + // Override from QGCTool + void setToolbox (QGCToolbox *toolbox); + +signals: + void emailAddressChanged (); + void descriptionChanged (); + void uploadURLChanged (); + void feedbackChanged (); + void enableAutoUploadChanged (); + void enableAutoStartChanged (); + void logFilesChanged (); + void selectedCountChanged (); + void uploadingChanged (); + void readyRead (QByteArray data); + void failed (); + void succeed (); + void abortUpload (); + void logRunningChanged (); + void canStartLogChanged (); + void deleteAfterUploadChanged (); + void windSpeedChanged (); + void ratingChanged (); + void videoURLChanged (); + void publicLogChanged (); + +private slots: + void _uploadFinished (); + void _dataAvailable (); + void _uploadProgress (qint64 bytesSent, qint64 bytesTotal); + void _activeVehicleChanged (Vehicle* vehicle); + void _mavlinkLogData (Vehicle* vehicle, uint8_t target_system, uint8_t target_component, uint16_t sequence, uint8_t first_message, QByteArray data, bool acked); + void _armedChanged (bool armed); + void _mavCommandResult (int vehicleId, int component, int command, int result, bool noReponseFromVehicle); + +private: + bool _sendLog (const QString& logFile); + bool _processUploadResponse (int http_code, QByteArray &data); + bool _createNewLog (); + int _getFirstSelected (); + void _insertNewLog (MAVLinkLogFiles* newLog); + void _deleteLog (MAVLinkLogFiles* log); + void _discardLog (); + QString _makeFilename (const QString& baseName); + +private: + QString _description; + QString _emailAddress; + QString _uploadURL; + QString _feedback; + QString _logPath; + QString _videoURL; + bool _enableAutoUpload; + bool _enableAutoStart; + QNetworkAccessManager* _nam; + QmlObjectListModel _logFiles; + MAVLinkLogFiles* _currentLogfile; + Vehicle* _vehicle; + bool _logRunning; + bool _loggingDisabled; + MAVLinkLogProcessor* _logProcessor; + bool _deleteAfterUpload; + int _windSpeed; + QString _rating; + bool _publicLog; +}; + +#endif diff --git a/src/Vehicle/MultiVehicleManager.cc b/src/Vehicle/MultiVehicleManager.cc index 139955c62d1b4e52569a11ac326e81e3d4c752ae..105da0786d8ba8696aa1e5dc67b87b56737f8120 100644 --- a/src/Vehicle/MultiVehicleManager.cc +++ b/src/Vehicle/MultiVehicleManager.cc @@ -15,8 +15,9 @@ #include "FollowMe.h" #include "QGroundControlQmlGlobal.h" #include "ParameterManager.h" +#include "SettingsManager.h" -#ifdef __mobile__ +#if defined (__ios__) || defined(__android__) #include "MobileScreenMgr.h" #endif @@ -33,7 +34,6 @@ MultiVehicleManager::MultiVehicleManager(QGCApplication* app) , _activeVehicle(NULL) , _offlineEditingVehicle(NULL) , _firmwarePluginManager(NULL) - , _autopilotPluginManager(NULL) , _joystickManager(NULL) , _mavlinkProtocol(NULL) , _gcsHeartbeatEnabled(true) @@ -55,7 +55,6 @@ void MultiVehicleManager::setToolbox(QGCToolbox *toolbox) QGCTool::setToolbox(toolbox); _firmwarePluginManager = _toolbox->firmwarePluginManager(); - _autopilotPluginManager = _toolbox->autopilotPluginManager(); _joystickManager = _toolbox->joystickManager(); _mavlinkProtocol = _toolbox->mavlinkProtocol(); @@ -64,22 +63,35 @@ void MultiVehicleManager::setToolbox(QGCToolbox *toolbox) connect(_mavlinkProtocol, &MAVLinkProtocol::vehicleHeartbeatInfo, this, &MultiVehicleManager::_vehicleHeartbeatInfo); - _offlineEditingVehicle = new Vehicle(static_cast(QGroundControlQmlGlobal::offlineEditingFirmwareType()->rawValue().toInt()), - static_cast(QGroundControlQmlGlobal::offlineEditingVehicleType()->rawValue().toInt()), + SettingsManager* settingsManager = toolbox->settingsManager(); + _offlineEditingVehicle = new Vehicle(static_cast(settingsManager->appSettings()->offlineEditingFirmwareType()->rawValue().toInt()), + static_cast(settingsManager->appSettings()->offlineEditingVehicleType()->rawValue().toInt()), _firmwarePluginManager, this); } -void MultiVehicleManager::_vehicleHeartbeatInfo(LinkInterface* link, int vehicleId, int vehicleMavlinkVersion, int vehicleFirmwareType, int vehicleType) +void MultiVehicleManager::_vehicleHeartbeatInfo(LinkInterface* link, int vehicleId, int componentId, int vehicleMavlinkVersion, int vehicleFirmwareType, int vehicleType) { - if (_ignoreVehicleIds.contains(vehicleId) || getVehicleById(vehicleId) - || vehicleId == 0) { + if (_ignoreVehicleIds.contains(vehicleId) || getVehicleById(vehicleId) || vehicleId == 0) { return; } - qCDebug(MultiVehicleManagerLog()) << "Adding new vehicle link:vehicleId:vehicleMavlinkVersion:vehicleFirmwareType:vehicleType " + switch (vehicleType) { + case MAV_TYPE_GCS: + case MAV_TYPE_ONBOARD_CONTROLLER: + case MAV_TYPE_GIMBAL: + case MAV_TYPE_ADSB: + // These are not vehicles, so don't create a vehicle for them + return; + default: + // All other MAV_TYPEs create vehicles + break; + } + + qCDebug(MultiVehicleManagerLog()) << "Adding new vehicle link:vehicleId:componentId:vehicleMavlinkVersion:vehicleFirmwareType:vehicleType " << link->getName() << vehicleId + << componentId << vehicleMavlinkVersion << vehicleFirmwareType << vehicleType; @@ -98,7 +110,7 @@ void MultiVehicleManager::_vehicleHeartbeatInfo(LinkInterface* link, int vehicle // return; // } - Vehicle* vehicle = new Vehicle(link, vehicleId, (MAV_AUTOPILOT)vehicleFirmwareType, (MAV_TYPE)vehicleType, _firmwarePluginManager, _autopilotPluginManager, _joystickManager); + Vehicle* vehicle = new Vehicle(link, vehicleId, componentId, (MAV_AUTOPILOT)vehicleFirmwareType, (MAV_TYPE)vehicleType, _firmwarePluginManager, _joystickManager); connect(vehicle, &Vehicle::allLinksInactive, this, &MultiVehicleManager::_deleteVehiclePhase1); connect(vehicle->parameterManager(), &ParameterManager::parametersReadyChanged, this, &MultiVehicleManager::_vehicleParametersReadyChanged); @@ -109,12 +121,16 @@ void MultiVehicleManager::_vehicleHeartbeatInfo(LinkInterface* link, int vehicle emit vehicleAdded(vehicle); - setActiveVehicle(vehicle); + if (_vehicles.count() > 1) { + qgcApp()->showMessage(tr("Connected to Vehicle %1").arg(vehicleId)); + } else { + setActiveVehicle(vehicle); + } // Mark link as active link->setActive(true); -#ifdef __mobile__ +#if defined (__ios__) || defined(__android__) if(_vehicles.count() == 1) { //-- Once a vehicle is connected, keep screen from going off qCDebug(MultiVehicleManagerLog) << "QAndroidJniObject::keepScreenOn"; @@ -155,7 +171,7 @@ void MultiVehicleManager::_deleteVehiclePhase1(Vehicle* vehicle) emit parameterReadyVehicleAvailableChanged(false); emit vehicleRemoved(vehicle); -#ifdef __mobile__ +#if defined (__ios__) || defined(__android__) if(_vehicles.count() == 0) { //-- Once no vehicles are connected, we no longer need to keep screen from going off qCDebug(MultiVehicleManagerLog) << "QAndroidJniObject::restoreScreenOn"; @@ -303,20 +319,27 @@ void MultiVehicleManager::setGcsHeartbeatEnabled(bool gcsHeartBeatEnabled) void MultiVehicleManager::_sendGCSHeartbeat(void) { - for (int i=0; i< _vehicles.count(); i++) { - Vehicle* vehicle = qobject_cast(_vehicles[i]); - - mavlink_message_t message; - mavlink_msg_heartbeat_pack_chan(_mavlinkProtocol->getSystemId(), - _mavlinkProtocol->getComponentId(), - vehicle->priorityLink()->mavlinkChannel(), - &message, - MAV_TYPE_GCS, // MAV_TYPE - MAV_AUTOPILOT_INVALID, // MAV_AUTOPILOT - MAV_MODE_MANUAL_ARMED, // MAV_MODE - 0, // custom mode - MAV_STATE_ACTIVE); // MAV_STATE - vehicle->sendMessageOnLink(vehicle->priorityLink(), message); + // Send a heartbeat out on each link + LinkManager* linkMgr = _toolbox->linkManager(); + for (int i=0; ilinks().count(); i++) { + LinkInterface* link = linkMgr->links()[i]; + if (link->isConnected()) { + mavlink_message_t message; + mavlink_msg_heartbeat_pack_chan(_mavlinkProtocol->getSystemId(), + _mavlinkProtocol->getComponentId(), + link->mavlinkChannel(), + &message, + MAV_TYPE_GCS, // MAV_TYPE + MAV_AUTOPILOT_INVALID, // MAV_AUTOPILOT + MAV_MODE_MANUAL_ARMED, // MAV_MODE + 0, // custom mode + MAV_STATE_ACTIVE); // MAV_STATE + + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + int len = mavlink_msg_to_send_buffer(buffer, &message); + + link->writeBytesSafe((const char*)buffer, len); + } } } diff --git a/src/Vehicle/MultiVehicleManager.h b/src/Vehicle/MultiVehicleManager.h index 5c6a8e3ee563c628dda14c13566a524cd1121e7f..c8d5e31349a4aa2b512c54f0ae0026adc6c5d4c9 100644 --- a/src/Vehicle/MultiVehicleManager.h +++ b/src/Vehicle/MultiVehicleManager.h @@ -21,7 +21,6 @@ #include "QGCLoggingCategory.h" class FirmwarePluginManager; -class AutoPilotPluginManager; class FollowMe; class JoystickManager; class QGCApplication; @@ -95,7 +94,7 @@ private slots: void _setActiveVehiclePhase2(void); void _vehicleParametersReadyChanged(bool parametersReady); void _sendGCSHeartbeat(void); - void _vehicleHeartbeatInfo(LinkInterface* link, int vehicleId, int vehicleMavlinkVersion, int vehicleFirmwareType, int vehicleType); + void _vehicleHeartbeatInfo(LinkInterface* link, int vehicleId, int componentId, int vehicleMavlinkVersion, int vehicleFirmwareType, int vehicleType); private: bool _vehicleExists(int vehicleId); @@ -113,7 +112,6 @@ private: QmlObjectListModel _vehicles; FirmwarePluginManager* _firmwarePluginManager; - AutoPilotPluginManager* _autopilotPluginManager; JoystickManager* _joystickManager; MAVLinkProtocol* _mavlinkProtocol; diff --git a/src/Vehicle/SendMavCommandTest.cc b/src/Vehicle/SendMavCommandTest.cc new file mode 100644 index 0000000000000000000000000000000000000000..de4a8c7ad7b08d67ac3809c2bcc84e9f981eccd2 --- /dev/null +++ b/src/Vehicle/SendMavCommandTest.cc @@ -0,0 +1,151 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +#include "SendMavCommandTest.h" +#include "MultiVehicleManager.h" +#include "QGCApplication.h" + +void SendMavCommandTest::_noFailure(void) +{ + _connectMockLink(MAV_AUTOPILOT_ARDUPILOTMEGA); + + MultiVehicleManager* vehicleMgr = qgcApp()->toolbox()->multiVehicleManager(); + Vehicle* vehicle = vehicleMgr->activeVehicle(); + QVERIFY(vehicle); + + vehicle->sendMavCommand(MAV_COMP_ID_ALL, MAV_CMD_USER_1, true /* showError */); + + QSignalSpy spyResult(vehicle, SIGNAL(mavCommandResult(int, int, int, int, bool))); + QCOMPARE(spyResult.wait(10000), true); + QList arguments = spyResult.takeFirst(); + QCOMPARE(arguments.count(), 5); + QCOMPARE(arguments.at(0).toInt(), vehicle->id()); + QCOMPARE(arguments.at(2).toInt(), (int)MAV_CMD_USER_1); + QCOMPARE(arguments.at(3).toInt(), (int)MAV_RESULT_ACCEPTED); + QCOMPARE(arguments.at(4).toBool(), false); +} + +void SendMavCommandTest::_failureShowError(void) +{ + // Will pop error about request failure + setExpectedMessageBox(QMessageBox::Ok); + + _connectMockLink(MAV_AUTOPILOT_ARDUPILOTMEGA); + + MultiVehicleManager* vehicleMgr = qgcApp()->toolbox()->multiVehicleManager(); + Vehicle* vehicle = vehicleMgr->activeVehicle(); + QVERIFY(vehicle); + + vehicle->sendMavCommand(MAV_COMP_ID_ALL, MAV_CMD_USER_2, true /* showError */); + + QSignalSpy spyResult(vehicle, SIGNAL(mavCommandResult(int, int, int, int, bool))); + QCOMPARE(spyResult.wait(10000), true); + QList arguments = spyResult.takeFirst(); + QCOMPARE(arguments.count(), 5); + QCOMPARE(arguments.at(0).toInt(), vehicle->id()); + QCOMPARE(arguments.at(2).toInt(), (int)MAV_CMD_USER_2); + QCOMPARE(arguments.at(3).toInt(), (int)MAV_RESULT_FAILED); + QCOMPARE(arguments.at(4).toBool(), false); + + // User should have been notified + checkExpectedMessageBox(); +} + +void SendMavCommandTest::_failureNoShowError(void) +{ + _connectMockLink(MAV_AUTOPILOT_ARDUPILOTMEGA); + + MultiVehicleManager* vehicleMgr = qgcApp()->toolbox()->multiVehicleManager(); + Vehicle* vehicle = vehicleMgr->activeVehicle(); + QVERIFY(vehicle); + + vehicle->sendMavCommand(MAV_COMP_ID_ALL, MAV_CMD_USER_2, false /* showError */); + + QSignalSpy spyResult(vehicle, SIGNAL(mavCommandResult(int, int, int, int, bool))); + QCOMPARE(spyResult.wait(10000), true); + QList arguments = spyResult.takeFirst(); + QCOMPARE(arguments.count(), 5); + QCOMPARE(arguments.at(0).toInt(), vehicle->id()); + QCOMPARE(arguments.at(2).toInt(), (int)MAV_CMD_USER_2); + QCOMPARE(arguments.at(3).toInt(), (int)MAV_RESULT_FAILED); + QCOMPARE(arguments.at(4).toBool(), false); +} + +void SendMavCommandTest::_noFailureAfterRetry(void) +{ + _connectMockLink(MAV_AUTOPILOT_ARDUPILOTMEGA); + + MultiVehicleManager* vehicleMgr = qgcApp()->toolbox()->multiVehicleManager(); + Vehicle* vehicle = vehicleMgr->activeVehicle(); + QVERIFY(vehicle); + + vehicle->sendMavCommand(MAV_COMP_ID_ALL, MAV_CMD_USER_3, true /* showError */); + + QSignalSpy spyResult(vehicle, SIGNAL(mavCommandResult(int, int, int, int, bool))); + QCOMPARE(spyResult.wait(10000), true); + QList arguments = spyResult.takeFirst(); + QCOMPARE(arguments.count(), 5); + QCOMPARE(arguments.at(0).toInt(), vehicle->id()); + QCOMPARE(arguments.at(2).toInt(), (int)MAV_CMD_USER_3); + QCOMPARE(arguments.at(3).toInt(), (int)MAV_RESULT_ACCEPTED); + QCOMPARE(arguments.at(4).toBool(), false); +} + +void SendMavCommandTest::_failureAfterRetry(void) +{ + // Will pop error about request failure + setExpectedMessageBox(QMessageBox::Ok); + + _connectMockLink(MAV_AUTOPILOT_ARDUPILOTMEGA); + + MultiVehicleManager* vehicleMgr = qgcApp()->toolbox()->multiVehicleManager(); + Vehicle* vehicle = vehicleMgr->activeVehicle(); + QVERIFY(vehicle); + + vehicle->sendMavCommand(MAV_COMP_ID_ALL, MAV_CMD_USER_4, true /* showError */); + + QSignalSpy spyResult(vehicle, SIGNAL(mavCommandResult(int, int, int, int, bool))); + QCOMPARE(spyResult.wait(10000), true); + QList arguments = spyResult.takeFirst(); + QCOMPARE(arguments.count(), 5); + QCOMPARE(arguments.at(0).toInt(), vehicle->id()); + QCOMPARE(arguments.at(2).toInt(), (int)MAV_CMD_USER_4); + QCOMPARE(arguments.at(3).toInt(), (int)MAV_RESULT_FAILED); + QCOMPARE(arguments.at(4).toBool(), false); + + // User should have been notified + checkExpectedMessageBox(); +} + +void SendMavCommandTest::_failureAfterNoReponse(void) +{ + // Will pop error about request failure + setExpectedMessageBox(QMessageBox::Ok); + + _connectMockLink(MAV_AUTOPILOT_ARDUPILOTMEGA); + + MultiVehicleManager* vehicleMgr = qgcApp()->toolbox()->multiVehicleManager(); + Vehicle* vehicle = vehicleMgr->activeVehicle(); + QVERIFY(vehicle); + + vehicle->sendMavCommand(MAV_COMP_ID_ALL, MAV_CMD_USER_5, true /* showError */); + + QSignalSpy spyResult(vehicle, SIGNAL(mavCommandResult(int, int, int, int, bool))); + QCOMPARE(spyResult.wait(20000), true); + QList arguments = spyResult.takeFirst(); + QCOMPARE(arguments.count(), 5); + QCOMPARE(arguments.at(0).toInt(), vehicle->id()); + QCOMPARE(arguments.at(2).toInt(), (int)MAV_CMD_USER_5); + QCOMPARE(arguments.at(3).toInt(), (int)MAV_RESULT_FAILED); + QCOMPARE(arguments.at(4).toBool(), true); + + // User should have been notified + checkExpectedMessageBox(); +} diff --git a/src/Vehicle/SendMavCommandTest.h b/src/Vehicle/SendMavCommandTest.h new file mode 100644 index 0000000000000000000000000000000000000000..28624573ba0c9ee6a3706753e65617a52fd82924 --- /dev/null +++ b/src/Vehicle/SendMavCommandTest.h @@ -0,0 +1,31 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +#ifndef SendMavCommandTest_H +#define SendMavCommandTest_H + +#include "UnitTest.h" + +class SendMavCommandTest : public UnitTest +{ + Q_OBJECT + +private slots: + void _noFailure(void); + void _failureShowError(void); + void _failureNoShowError(void); + void _noFailureAfterRetry(void); + void _failureAfterRetry(void); + void _failureAfterNoReponse(void); + +private: +}; + +#endif diff --git a/src/Vehicle/TemperatureFact.json b/src/Vehicle/TemperatureFact.json new file mode 100644 index 0000000000000000000000000000000000000000..01cfb25e7702b34dc28111e250374286cc3b9ae8 --- /dev/null +++ b/src/Vehicle/TemperatureFact.json @@ -0,0 +1,23 @@ +[ +{ + "name": "temperature1", + "shortDescription": "Temperature (1)", + "type": "double", + "decimalPlaces": 2, + "units": "C" +}, +{ + "name": "temperature2", + "shortDescription": "Temperature (2)", + "type": "double", + "decimalPlaces": 2, + "units": "C" +}, +{ + "name": "temperature3", + "shortDescription": "Temperature (3)", + "type": "double", + "decimalPlaces": 2, + "units": "C" +} +] diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index 09480d7bdbe047dc33ef6df9e96f45923e4e4f14..adf4ace24f9bb2c4c9fc61e16386e3603ac41b53 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -13,10 +13,10 @@ #include "FirmwarePluginManager.h" #include "LinkManager.h" #include "FirmwarePlugin.h" -#include "AutoPilotPluginManager.h" #include "UAS.h" #include "JoystickManager.h" #include "MissionManager.h" +#include "MissionController.h" #include "GeoFenceManager.h" #include "RallyPointManager.h" #include "CoordinateVector.h" @@ -27,6 +27,7 @@ #include "FollowMe.h" #include "MissionCommandTree.h" #include "QGroundControlQmlGlobal.h" +#include "SettingsManager.h" QGC_LOGGING_CATEGORY(VehicleLog, "VehicleLog") @@ -53,26 +54,30 @@ const char* Vehicle::_gpsFactGroupName = "gps"; const char* Vehicle::_batteryFactGroupName = "battery"; const char* Vehicle::_windFactGroupName = "wind"; const char* Vehicle::_vibrationFactGroupName = "vibration"; +const char* Vehicle::_temperatureFactGroupName = "temperature"; const int Vehicle::_lowBatteryAnnounceRepeatMSecs = 30 * 1000; Vehicle::Vehicle(LinkInterface* link, int vehicleId, + int defaultComponentId, MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType, FirmwarePluginManager* firmwarePluginManager, - AutoPilotPluginManager* autopilotPluginManager, JoystickManager* joystickManager) : FactGroup(_vehicleUIUpdateRateMSecs, ":/json/Vehicle/VehicleFact.json") , _id(vehicleId) + , _defaultComponentId(defaultComponentId) , _active(false) , _offlineEditingVehicle(false) , _firmwareType(firmwareType) , _vehicleType(vehicleType) , _firmwarePlugin(NULL) + , _firmwarePluginInstanceData(NULL) , _autopilotPlugin(NULL) , _mavlink(NULL) , _soloFirmware(false) + , _settingsManager(qgcApp()->toolbox()->settingsManager()) , _joystickMode(JoystickModeRC) , _joystickEnabled(false) , _uas(NULL) @@ -86,16 +91,26 @@ Vehicle::Vehicle(LinkInterface* link, , _currentWarningCount(0) , _currentNormalCount(0) , _currentMessageType(MessageNone) - , _navigationAltitudeError(0.0f) - , _navigationSpeedError(0.0f) - , _navigationCrosstrackError(0.0f) - , _navigationTargetBearing(0.0f) - , _refreshTimer(new QTimer(this)) , _updateCount(0) , _rcRSSI(255) , _rcRSSIstore(255) , _autoDisconnect(false) , _flying(false) + , _onboardControlSensorsPresent(0) + , _onboardControlSensorsEnabled(0) + , _onboardControlSensorsHealth(0) + , _onboardControlSensorsUnhealthy(0) + , _gpsRawIntMessageAvailable(false) + , _globalPositionIntMessageAvailable(false) + , _cruiseSpeed(_settingsManager->appSettings()->offlineEditingCruiseSpeed()->rawValue().toDouble()) + , _hoverSpeed(_settingsManager->appSettings()->offlineEditingHoverSpeed()->rawValue().toDouble()) + , _telemetryRRSSI(0) + , _telemetryLRSSI(0) + , _telemetryRXErrors(0) + , _telemetryFixed(0) + , _telemetryTXBuffer(0) + , _telemetryLNoise(0) + , _telemetryRNoise(0) , _connectionLost(false) , _connectionLostEnabled(true) , _missionManager(NULL) @@ -110,7 +125,6 @@ Vehicle::Vehicle(LinkInterface* link, , _custom_mode(0) , _nextSendMessageMultipleIndex(0) , _firmwarePluginManager(firmwarePluginManager) - , _autopilotPluginManager(autopilotPluginManager) , _joystickManager(joystickManager) , _flowImageIndex(0) , _allLinksInactiveSent(false) @@ -136,48 +150,47 @@ Vehicle::Vehicle(LinkInterface* link, , _batteryFactGroup(this) , _windFactGroup(this) , _vibrationFactGroup(this) + , _temperatureFactGroup(this) { _addLink(link); + connect(_joystickManager, &JoystickManager::activeJoystickChanged, this, &Vehicle::_activeJoystickChanged); + _mavlink = qgcApp()->toolbox()->mavlinkProtocol(); connect(_mavlink, &MAVLinkProtocol::messageReceived, this, &Vehicle::_mavlinkMessageReceived); + connect(_mavlink, &MAVLinkProtocol::radioStatusChanged, this, &Vehicle::_telemetryChanged); connect(this, &Vehicle::_sendMessageOnLinkOnThread, this, &Vehicle::_sendMessageOnLink, Qt::QueuedConnection); connect(this, &Vehicle::flightModeChanged, this, &Vehicle::_handleFlightModeChanged); connect(this, &Vehicle::armedChanged, this, &Vehicle::_announceArmedChanged); _uas = new UAS(_mavlink, this, _firmwarePluginManager); - setLatitude(_uas->getLatitude()); - setLongitude(_uas->getLongitude()); - - connect(_uas, &UAS::latitudeChanged, this, &Vehicle::setLatitude); - connect(_uas, &UAS::longitudeChanged, this, &Vehicle::setLongitude); connect(_uas, &UAS::imageReady, this, &Vehicle::_imageReady); connect(this, &Vehicle::remoteControlRSSIChanged, this, &Vehicle::_remoteControlRSSIChanged); - _firmwarePlugin = _firmwarePluginManager->firmwarePluginForAutopilot(_firmwareType, _vehicleType); - _autopilotPlugin = _autopilotPluginManager->newAutopilotPluginForVehicle(this); + _commonInit(); + _autopilotPlugin = _firmwarePlugin->autopilotPlugin(this); // connect this vehicle to the follow me handle manager connect(this, &Vehicle::flightModeChanged,qgcApp()->toolbox()->followMe(), &FollowMe::followMeHandleManager); - // Refresh timer - connect(_refreshTimer, &QTimer::timeout, this, &Vehicle::_checkUpdate); - _refreshTimer->setInterval(UPDATE_TIMER); - _refreshTimer->start(UPDATE_TIMER); - // PreArm Error self-destruct timer connect(&_prearmErrorTimer, &QTimer::timeout, this, &Vehicle::_prearmErrorTimeout); _prearmErrorTimer.setInterval(_prearmErrorTimeoutMSecs); _prearmErrorTimer.setSingleShot(true); - // Connection Lost time - _connectionLostTimer.setInterval(Vehicle::_connectionLostTimeoutMSecs); + // Connection Lost timer + _connectionLostTimer.setInterval(_connectionLostTimeoutMSecs); _connectionLostTimer.setSingleShot(false); _connectionLostTimer.start(); connect(&_connectionLostTimer, &QTimer::timeout, this, &Vehicle::_connectionLostTimeout); + // Send MAV_CMD ack timer + _mavCommandAckTimer.setSingleShot(true); + _mavCommandAckTimer.setInterval(_mavCommandAckTimeoutMSecs); + connect(&_mavCommandAckTimer, &QTimer::timeout, this, &Vehicle::_sendMavCommandAgain); + _mav = uas(); // Listen for system messages @@ -186,47 +199,14 @@ Vehicle::Vehicle(LinkInterface* link, // Now connect the new UAS connect(_mav, SIGNAL(attitudeChanged (UASInterface*,double,double,double,quint64)), this, SLOT(_updateAttitude(UASInterface*, double, double, double, quint64))); connect(_mav, SIGNAL(attitudeChanged (UASInterface*,int,double,double,double,quint64)), this, SLOT(_updateAttitude(UASInterface*,int,double, double, double, quint64))); - connect(_mav, SIGNAL(statusChanged (UASInterface*,QString,QString)), this, SLOT(_updateState(UASInterface*, QString,QString))); - - connect(_mav, &UASInterface::speedChanged, this, &Vehicle::_updateSpeed); - connect(_mav, &UASInterface::altitudeChanged, this, &Vehicle::_updateAltitude); - connect(_mav, &UASInterface::navigationControllerErrorsChanged,this, &Vehicle::_updateNavigationControllerErrors); - connect(_mav, &UASInterface::NavigationControllerDataChanged, this, &Vehicle::_updateNavigationControllerData); _loadSettings(); - _missionManager = new MissionManager(this); - connect(_missionManager, &MissionManager::error, this, &Vehicle::_missionManagerError); - connect(_missionManager, &MissionManager::newMissionItemsAvailable, this, &Vehicle::_newMissionItemsAvailable); - - _parameterManager = new ParameterManager(this); - connect(_parameterManager, &ParameterManager::parametersReadyChanged, this, &Vehicle::_parametersReady); - - // GeoFenceManager needs to access ParameterManager so make sure to create after - _geoFenceManager = _firmwarePlugin->newGeoFenceManager(this); - connect(_geoFenceManager, &GeoFenceManager::error, this, &Vehicle::_geoFenceManagerError); - connect(_geoFenceManager, &GeoFenceManager::loadComplete, this, &Vehicle::_newGeoFenceAvailable); - - _rallyPointManager = _firmwarePlugin->newRallyPointManager(this); - connect(_rallyPointManager, &RallyPointManager::error, this, &Vehicle::_rallyPointManagerError); - - // Ask the vehicle for firmware version info. This must be MAV_COMP_ID_ALL since we don't know default component id yet. - - mavlink_message_t versionMsg; - mavlink_command_long_t versionCmd; - - versionCmd.command = MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES; - versionCmd.confirmation = 0; - versionCmd.param1 = 1; // Request firmware version - versionCmd.param2 = versionCmd.param3 = versionCmd.param4 = versionCmd.param5 = versionCmd.param6 = versionCmd.param7 = 0; - versionCmd.target_system = id(); - versionCmd.target_component = MAV_COMP_ID_ALL; - mavlink_msg_command_long_encode_chan(_mavlink->getSystemId(), - _mavlink->getComponentId(), - priorityLink()->mavlinkChannel(), - &versionMsg, - &versionCmd); - sendMessageMultiple(versionMsg); + // Ask the vehicle for firmware version info. + sendMavCommand(MAV_COMP_ID_ALL, // Don't know default component id yet. + MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES, + false, // No error shown if fails + 1); // Request firmware version _firmwarePlugin->initializeVehicle(this); @@ -238,27 +218,6 @@ Vehicle::Vehicle(LinkInterface* link, // Invalidate the timer to signal first announce _lowBatteryAnnounceTimer.invalidate(); - - // Build FactGroup object model - - _addFact(&_rollFact, _rollFactName); - _addFact(&_pitchFact, _pitchFactName); - _addFact(&_headingFact, _headingFactName); - _addFact(&_groundSpeedFact, _groundSpeedFactName); - _addFact(&_airSpeedFact, _airSpeedFactName); - _addFact(&_climbRateFact, _climbRateFactName); - _addFact(&_altitudeRelativeFact, _altitudeRelativeFactName); - _addFact(&_altitudeAMSLFact, _altitudeAMSLFactName); - - _addFactGroup(&_gpsFactGroup, _gpsFactGroupName); - _addFactGroup(&_batteryFactGroup, _batteryFactGroupName); - _addFactGroup(&_windFactGroup, _windFactGroupName); - _addFactGroup(&_vibrationFactGroup, _vibrationFactGroupName); - - _gpsFactGroup.setVehicle(this); - _batteryFactGroup.setVehicle(this); - _windFactGroup.setVehicle(this); - _vibrationFactGroup.setVehicle(this); } // Disconnected Vehicle for offline editing @@ -268,12 +227,17 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, QObject* parent) : FactGroup(_vehicleUIUpdateRateMSecs, ":/json/Vehicle/VehicleFact.json", parent) , _id(0) + , _defaultComponentId(MAV_COMP_ID_ALL) , _active(false) , _offlineEditingVehicle(true) , _firmwareType(firmwareType) , _vehicleType(vehicleType) , _firmwarePlugin(NULL) + , _firmwarePluginInstanceData(NULL) , _autopilotPlugin(NULL) + , _mavlink(NULL) + , _soloFirmware(false) + , _settingsManager(qgcApp()->toolbox()->settingsManager()) , _joystickMode(JoystickModeRC) , _joystickEnabled(false) , _uas(NULL) @@ -287,15 +251,19 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, , _currentWarningCount(0) , _currentNormalCount(0) , _currentMessageType(MessageNone) - , _navigationAltitudeError(0.0f) - , _navigationSpeedError(0.0f) - , _navigationCrosstrackError(0.0f) - , _navigationTargetBearing(0.0f) - , _refreshTimer(new QTimer(this)) , _updateCount(0) , _rcRSSI(255) , _rcRSSIstore(255) , _autoDisconnect(false) + , _flying(false) + , _onboardControlSensorsPresent(0) + , _onboardControlSensorsEnabled(0) + , _onboardControlSensorsHealth(0) + , _onboardControlSensorsUnhealthy(0) + , _gpsRawIntMessageAvailable(false) + , _globalPositionIntMessageAvailable(false) + , _cruiseSpeed(_settingsManager->appSettings()->offlineEditingCruiseSpeed()->rawValue().toDouble()) + , _hoverSpeed(_settingsManager->appSettings()->offlineEditingHoverSpeed()->rawValue().toDouble()) , _connectionLost(false) , _connectionLostEnabled(true) , _missionManager(NULL) @@ -310,7 +278,6 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, , _custom_mode(0) , _nextSendMessageMultipleIndex(0) , _firmwarePluginManager(firmwarePluginManager) - , _autopilotPluginManager(NULL) , _joystickManager(NULL) , _flowImageIndex(0) , _allLinksInactiveSent(false) @@ -323,6 +290,7 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, , _firmwareMajorVersion(versionNotSetValue) , _firmwareMinorVersion(versionNotSetValue) , _firmwarePatchVersion(versionNotSetValue) + , _gitHash(versionNotSetValue) , _rollFact (0, _rollFactName, FactMetaData::valueTypeDouble) , _pitchFact (0, _pitchFactName, FactMetaData::valueTypeDouble) , _headingFact (0, _headingFactName, FactMetaData::valueTypeDouble) @@ -336,13 +304,19 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, , _windFactGroup(this) , _vibrationFactGroup(this) { - _firmwarePlugin = _firmwarePluginManager->firmwarePluginForAutopilot(_firmwareType, _vehicleType); + _commonInit(); _firmwarePlugin->initializeVehicle(this); +} + +void Vehicle::_commonInit(void) +{ + _firmwarePlugin = _firmwarePluginManager->firmwarePluginForAutopilot(_firmwareType, _vehicleType); _missionManager = new MissionManager(this); connect(_missionManager, &MissionManager::error, this, &Vehicle::_missionManagerError); _parameterManager = new ParameterManager(this); + connect(_parameterManager, &ParameterManager::parametersReadyChanged, this, &Vehicle::_parametersReady); // GeoFenceManager needs to access ParameterManager so make sure to create after _geoFenceManager = _firmwarePlugin->newGeoFenceManager(this); @@ -351,6 +325,12 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, _rallyPointManager = _firmwarePlugin->newRallyPointManager(this); connect(_rallyPointManager, &RallyPointManager::error, this, &Vehicle::_rallyPointManagerError); + // Offline editing vehicle tracks settings changes for offline editing settings + connect(_settingsManager->appSettings()->offlineEditingFirmwareType(), &Fact::rawValueChanged, this, &Vehicle::_offlineFirmwareTypeSettingChanged); + connect(_settingsManager->appSettings()->offlineEditingVehicleType(), &Fact::rawValueChanged, this, &Vehicle::_offlineVehicleTypeSettingChanged); + connect(_settingsManager->appSettings()->offlineEditingCruiseSpeed(), &Fact::rawValueChanged, this, &Vehicle::_offlineCruiseSpeedSettingChanged); + connect(_settingsManager->appSettings()->offlineEditingHoverSpeed(), &Fact::rawValueChanged, this, &Vehicle::_offlineHoverSpeedSettingChanged); + // Build FactGroup object model _addFact(&_rollFact, _rollFactName); @@ -366,11 +346,7 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, _addFactGroup(&_batteryFactGroup, _batteryFactGroupName); _addFactGroup(&_windFactGroup, _windFactGroupName); _addFactGroup(&_vibrationFactGroup, _vibrationFactGroupName); - - _gpsFactGroup.setVehicle(NULL); - _batteryFactGroup.setVehicle(NULL); - _windFactGroup.setVehicle(NULL); - _vibrationFactGroup.setVehicle(NULL); + _addFactGroup(&_temperatureFactGroup, _temperatureFactGroupName); } Vehicle::~Vehicle() @@ -388,8 +364,59 @@ Vehicle::~Vehicle() } -void -Vehicle::resetCounters() +void Vehicle::_offlineFirmwareTypeSettingChanged(QVariant value) +{ + _firmwareType = static_cast(value.toInt()); + emit firmwareTypeChanged(); +} + +void Vehicle::_offlineVehicleTypeSettingChanged(QVariant value) +{ + _vehicleType = static_cast(value.toInt()); + emit vehicleTypeChanged(); +} + +void Vehicle::_offlineCruiseSpeedSettingChanged(QVariant value) +{ + _cruiseSpeed = value.toDouble(); + emit cruiseSpeedChanged(_cruiseSpeed); +} + +void Vehicle::_offlineHoverSpeedSettingChanged(QVariant value) +{ + _hoverSpeed = value.toDouble(); + emit hoverSpeedChanged(_hoverSpeed); +} + +QString Vehicle::firmwareTypeString(void) const +{ + if (px4Firmware()) { + return QStringLiteral("PX4 Pro"); + } else if (apmFirmware()) { + return QStringLiteral("ArduPilot"); + } else { + return tr("MAVLink Generic"); + } +} + +QString Vehicle::vehicleTypeString(void) const +{ + if (fixedWing()) { + return tr("Fixed Wing"); + } else if (multiRotor()) { + return tr("Multi-Rotor"); + } else if (vtol()) { + return tr("VTOL"); + } else if (rover()) { + return tr("Rover"); + } else if (sub()) { + return tr("Sub"); + } else { + return tr("Unknown"); + } +} + +void Vehicle::resetCounters() { _messagesReceived = 0; _messagesSent = 0; @@ -398,8 +425,40 @@ Vehicle::resetCounters() _heardFrom = false; } +void Vehicle::_telemetryChanged(LinkInterface*, unsigned rxerrors, unsigned fixed, int rssi, int remrssi, unsigned txbuf, unsigned noise, unsigned remnoise) +{ + if(_telemetryLRSSI != rssi) { + _telemetryLRSSI = rssi; + emit telemetryLRSSIChanged(_telemetryLRSSI); + } + if(_telemetryRRSSI != remrssi) { + _telemetryRRSSI = remrssi; + emit telemetryRRSSIChanged(_telemetryRRSSI); + } + if(_telemetryRXErrors != rxerrors) { + _telemetryRXErrors = rxerrors; + emit telemetryRXErrorsChanged(_telemetryRXErrors); + } + if(_telemetryFixed != fixed) { + _telemetryFixed = fixed; + emit telemetryFixedChanged(_telemetryFixed); + } + if(_telemetryTXBuffer != txbuf) { + _telemetryTXBuffer = txbuf; + emit telemetryTXBufferChanged(_telemetryTXBuffer); + } + if(_telemetryLNoise != noise) { + _telemetryLNoise = noise; + emit telemetryLNoiseChanged(_telemetryLNoise); + } + if(_telemetryRNoise != remnoise) { + _telemetryRNoise = remnoise; + emit telemetryRNoiseChanged(_telemetryRNoise); + } +} void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message) { + if (message.sysid != _id && message.sysid != 0) { return; } @@ -434,6 +493,10 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes } } + + // Mark this vehicle as active + _connectionActive(); + // Give the plugin a change to adjust the message contents if (!_firmwarePlugin->adjustIncomingMavlinkMessage(this, &message)) { return; @@ -480,7 +543,7 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes _handleCommandAck(message); break; case MAVLINK_MSG_ID_AUTOPILOT_VERSION: - _handleAutopilotVersion(message); + _handleAutopilotVersion(link, message); break; case MAVLINK_MSG_ID_WIND_COV: _handleWindCov(message); @@ -488,6 +551,33 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes case MAVLINK_MSG_ID_HIL_ACTUATOR_CONTROLS: _handleHilActuatorControls(message); break; + case MAVLINK_MSG_ID_LOGGING_DATA: + _handleMavlinkLoggingData(message); + break; + case MAVLINK_MSG_ID_LOGGING_DATA_ACKED: + _handleMavlinkLoggingDataAcked(message); + break; + case MAVLINK_MSG_ID_GPS_RAW_INT: + _handleGpsRawInt(message); + break; + case MAVLINK_MSG_ID_GLOBAL_POSITION_INT: + _handleGlobalPositionInt(message); + break; + case MAVLINK_MSG_ID_ALTITUDE: + _handleAltitude(message); + break; + case MAVLINK_MSG_ID_VFR_HUD: + _handleVfrHud(message); + break; + case MAVLINK_MSG_ID_SCALED_PRESSURE: + _handleScaledPressure(message); + break; + case MAVLINK_MSG_ID_SCALED_PRESSURE2: + _handleScaledPressure2(message); + break; + case MAVLINK_MSG_ID_SCALED_PRESSURE3: + _handleScaledPressure3(message); + break; // Following are ArduPilot dialect messages @@ -501,8 +591,78 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes _uas->receiveMessage(message); } -void Vehicle::_handleAutopilotVersion(mavlink_message_t& message) +void Vehicle::_handleVfrHud(mavlink_message_t& message) +{ + mavlink_vfr_hud_t vfrHud; + mavlink_msg_vfr_hud_decode(&message, &vfrHud); + + _airSpeedFact.setRawValue(qIsNaN(vfrHud.airspeed) ? 0 : vfrHud.airspeed); + _groundSpeedFact.setRawValue(qIsNaN(vfrHud.groundspeed) ? 0 : vfrHud.groundspeed); + _climbRateFact.setRawValue(qIsNaN(vfrHud.climb) ? 0 : vfrHud.climb); +} + +void Vehicle::_handleGpsRawInt(mavlink_message_t& message) +{ + mavlink_gps_raw_int_t gpsRawInt; + mavlink_msg_gps_raw_int_decode(&message, &gpsRawInt); + + _gpsRawIntMessageAvailable = true; + + if (gpsRawInt.fix_type >= GPS_FIX_TYPE_3D_FIX) { + if (!_globalPositionIntMessageAvailable) { + //-- Set these here and emit a single signal instead of 3 for the same variable (_coordinate) + _coordinate.setLatitude(gpsRawInt.lat / (double)1E7); + _coordinate.setLongitude(gpsRawInt.lon / (double)1E7); + _coordinate.setAltitude(gpsRawInt.alt / 1000.0); + emit coordinateChanged(_coordinate); + _altitudeAMSLFact.setRawValue(gpsRawInt.alt / 1000.0); + } + } + + _gpsFactGroup.count()->setRawValue(gpsRawInt.satellites_visible == 255 ? 0 : gpsRawInt.satellites_visible); + _gpsFactGroup.hdop()->setRawValue(gpsRawInt.eph == UINT16_MAX ? std::numeric_limits::quiet_NaN() : gpsRawInt.eph / 100.0); + _gpsFactGroup.vdop()->setRawValue(gpsRawInt.epv == UINT16_MAX ? std::numeric_limits::quiet_NaN() : gpsRawInt.epv / 100.0); + _gpsFactGroup.courseOverGround()->setRawValue(gpsRawInt.cog == UINT16_MAX ? std::numeric_limits::quiet_NaN() : gpsRawInt.cog / 100.0); + _gpsFactGroup.lock()->setRawValue(gpsRawInt.fix_type); + + if (gpsRawInt.fix_type >= GPS_FIX_TYPE_3D_FIX) { + _setCoordinateValid(true); + } +} + +void Vehicle::_handleGlobalPositionInt(mavlink_message_t& message) +{ + mavlink_global_position_int_t globalPositionInt; + mavlink_msg_global_position_int_decode(&message, &globalPositionInt); + + _globalPositionIntMessageAvailable = true; + //-- Set these here and emit a single signal instead of 3 for the same variable (_coordinate) + _coordinate.setLatitude(globalPositionInt.lat / (double)1E7); + _coordinate.setLongitude(globalPositionInt.lon / (double)1E7); + _coordinate.setAltitude(globalPositionInt.alt / 1000.0); + emit coordinateChanged(_coordinate); + _altitudeRelativeFact.setRawValue(globalPositionInt.relative_alt / 1000.0); + _altitudeAMSLFact.setRawValue(globalPositionInt.alt / 1000.0); +} + +void Vehicle::_handleAltitude(mavlink_message_t& message) +{ + mavlink_altitude_t altitude; + mavlink_msg_altitude_decode(&message, &altitude); + + // If data from GPS is available it takes precedence over ALTITUDE message + if (!_globalPositionIntMessageAvailable) { + _altitudeRelativeFact.setRawValue(altitude.altitude_relative); + if (!_gpsRawIntMessageAvailable) { + _altitudeAMSLFact.setRawValue(altitude.altitude_amsl); + } + } +} + +void Vehicle::_handleAutopilotVersion(LinkInterface *link, mavlink_message_t& message) { + Q_UNUSED(link); + mavlink_autopilot_version_t autopilotVersion; mavlink_msg_autopilot_version_decode(&message, &autopilotVersion); @@ -516,6 +676,22 @@ void Vehicle::_handleAutopilotVersion(mavlink_message_t& message) versionType = (FIRMWARE_VERSION_TYPE)((autopilotVersion.flight_sw_version >> (8*0)) & 0xFF); setFirmwareVersion(majorVersion, minorVersion, patchVersion, versionType); } + + // Git hash + if (autopilotVersion.flight_custom_version[0] != 0) { + // PX4 Firmware stores the first 16 characters of the git hash as binary, with the individual bytes in reverse order + if (px4Firmware()) { + _gitHash = ""; + QByteArray array((char*)autopilotVersion.flight_custom_version, 8); + for (int i = 7; i >= 0; i--) { + _gitHash.append(QString("%1").arg(autopilotVersion.flight_custom_version[i], 2, 16, QChar('0'))); + } + } else { + // APM Firmware stores the first 8 characters of the git hash as an ASCII character string + _gitHash = QString::fromUtf8((char*)autopilotVersion.flight_custom_version, 8); + } + emit gitHashChanged(_gitHash); + } } void Vehicle::_handleHilActuatorControls(mavlink_message_t &message) @@ -544,35 +720,42 @@ void Vehicle::_handleHilActuatorControls(mavlink_message_t &message) void Vehicle::_handleCommandAck(mavlink_message_t& message) { + bool showError = true; + mavlink_command_ack_t ack; mavlink_msg_command_ack_decode(&message, &ack); - emit commandLongAck(message.compid, ack.command, ack.result); - - if (ack.command == MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES) { - // Disregard failures - return; + if (_mavCommandQueue.count() && ack.command == _mavCommandQueue[0].command) { + _mavCommandAckTimer.stop(); + showError = _mavCommandQueue[0].showError; + _mavCommandQueue.removeFirst(); + } + + emit mavCommandResult(_id, message.compid, ack.command, ack.result, false /* noResponsefromVehicle */); + + if (showError) { + QString commandName = qgcApp()->toolbox()->missionCommandTree()->friendlyName((MAV_CMD)ack.command); + + switch (ack.result) { + case MAV_RESULT_TEMPORARILY_REJECTED: + qgcApp()->showMessage(tr("%1 command temporarily rejected").arg(commandName)); + break; + case MAV_RESULT_DENIED: + qgcApp()->showMessage(tr("%1 command denied").arg(commandName)); + break; + case MAV_RESULT_UNSUPPORTED: + qgcApp()->showMessage(tr("%1 command not supported").arg(commandName)); + break; + case MAV_RESULT_FAILED: + qgcApp()->showMessage(tr("%1 command failed").arg(commandName)); + break; + default: + // Do nothing + break; + } } - QString commandName = qgcApp()->toolbox()->missionCommandTree()->friendlyName((MAV_CMD)ack.command); - - switch (ack.result) { - case MAV_RESULT_TEMPORARILY_REJECTED: - qgcApp()->showMessage(tr("%1 command temporarily rejected").arg(commandName)); - break; - case MAV_RESULT_DENIED: - qgcApp()->showMessage(tr("%1 command denied").arg(commandName)); - break; - case MAV_RESULT_UNSUPPORTED: - qgcApp()->showMessage(tr("%1 command not supported").arg(commandName)); - break; - case MAV_RESULT_FAILED: - qgcApp()->showMessage(tr("%1 command failed").arg(commandName)); - break; - default: - // Do nothing - break; - } + _sendNextQueuedMavCommand(); } void Vehicle::_handleExtendedSysState(mavlink_message_t& message) @@ -636,7 +819,8 @@ void Vehicle::_handleSysStatus(mavlink_message_t& message) if (sysStatus.current_battery == -1) { _batteryFactGroup.current()->setRawValue(VehicleBatteryFactGroup::_currentUnavailable); } else { - _batteryFactGroup.current()->setRawValue((double)sysStatus.current_battery * 10); + // Current is in Amps, current_battery is 10 * milliamperes (1 = 10 milliampere) + _batteryFactGroup.current()->setRawValue((float)sysStatus.current_battery / 100.0f); } if (sysStatus.voltage_battery == UINT16_MAX) { _batteryFactGroup.voltage()->setRawValue(VehicleBatteryFactGroup::_voltageUnavailable); @@ -645,12 +829,22 @@ void Vehicle::_handleSysStatus(mavlink_message_t& message) } _batteryFactGroup.percentRemaining()->setRawValue(sysStatus.battery_remaining); - if (sysStatus.battery_remaining > 0 && sysStatus.battery_remaining < QGroundControlQmlGlobal::batteryPercentRemainingAnnounce()->rawValue().toInt()) { + if (sysStatus.battery_remaining > 0 && sysStatus.battery_remaining < _settingsManager->appSettings()->batteryPercentRemainingAnnounce()->rawValue().toInt()) { if (!_lowBatteryAnnounceTimer.isValid() || _lowBatteryAnnounceTimer.elapsed() > _lowBatteryAnnounceRepeatMSecs) { _lowBatteryAnnounceTimer.restart(); _say(QString("%1 low battery: %2 percent remaining").arg(_vehicleIdSpeech()).arg(sysStatus.battery_remaining)); } } + + _onboardControlSensorsPresent = sysStatus.onboard_control_sensors_present; + _onboardControlSensorsEnabled = sysStatus.onboard_control_sensors_enabled; + _onboardControlSensorsHealth = sysStatus.onboard_control_sensors_health; + + uint32_t newSensorsUnhealthy = _onboardControlSensorsEnabled & ~_onboardControlSensorsHealth; + if (newSensorsUnhealthy != _onboardControlSensorsUnhealthy) { + _onboardControlSensorsUnhealthy = newSensorsUnhealthy; + emit unhealthySensorsChanged(); + } } void Vehicle::_handleBatteryStatus(mavlink_message_t& message) @@ -716,7 +910,9 @@ void Vehicle::_handleHomePosition(mavlink_message_t& message) void Vehicle::_handleHeartbeat(mavlink_message_t& message) { - _connectionActive(); + if (message.compid != _defaultComponentId) { + return; + } mavlink_heartbeat_t heartbeat; @@ -830,6 +1026,24 @@ void Vehicle::_handleRCChannelsRaw(mavlink_message_t& message) emit rcChannelsChanged(channelCount, pwmValues); } +void Vehicle::_handleScaledPressure(mavlink_message_t& message) { + mavlink_scaled_pressure_t pressure; + mavlink_msg_scaled_pressure_decode(&message, &pressure); + _temperatureFactGroup.temperature1()->setRawValue(pressure.temperature / 100.0); +} + +void Vehicle::_handleScaledPressure2(mavlink_message_t& message) { + mavlink_scaled_pressure2_t pressure; + mavlink_msg_scaled_pressure2_decode(&message, &pressure); + _temperatureFactGroup.temperature2()->setRawValue(pressure.temperature / 100.0); +} + +void Vehicle::_handleScaledPressure3(mavlink_message_t& message) { + mavlink_scaled_pressure3_t pressure; + mavlink_msg_scaled_pressure3_decode(&message, &pressure); + _temperatureFactGroup.temperature3()->setRawValue(pressure.temperature / 100.0); +} + bool Vehicle::_containsLink(LinkInterface* link) { return _links.contains(link); @@ -838,8 +1052,9 @@ bool Vehicle::_containsLink(LinkInterface* link) void Vehicle::_addLink(LinkInterface* link) { if (!_containsLink(link)) { - _links += link; qCDebug(VehicleLog) << "_addLink:" << QString("%1").arg((ulong)link, 0, 16); + _links += link; + _updatePriorityLink(); connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkInactive, this, &Vehicle::_linkInactiveOrDeleted); connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkDeleted, this, &Vehicle::_linkInactiveOrDeleted); } @@ -850,6 +1065,7 @@ void Vehicle::_linkInactiveOrDeleted(LinkInterface* link) qCDebug(VehicleLog) << "_linkInactiveOrDeleted linkCount" << _links.count(); _links.removeOne(link); + _updatePriorityLink(); if (_links.count() == 0 && !_allLinksInactiveSent) { qCDebug(VehicleLog) << "All links inactive"; @@ -895,26 +1111,42 @@ void Vehicle::_sendMessageOnLink(LinkInterface* link, mavlink_message_t message) emit messagesSentChanged(); } -/// @return Direct usb connection link to board if one, NULL if none -LinkInterface* Vehicle::priorityLink(void) +void Vehicle::_updatePriorityLink(void) { -#ifndef __ios__ - foreach (LinkInterface* link, _links) { + LinkInterface* newPriorityLink = NULL; + +#ifndef NO_SERIAL_LINK + // Note that this routine specificallty does not clear _priorityLink when there are no links remaining. + // By doing this we hold a reference on the last link as the Vehicle shuts down. Thus preventing shutdown + // ordering NULL pointer crashes where priorityLink() is still called during shutdown sequence. + for (int i=0; i<_links.count(); i++) { + LinkInterface* link = _links[i]; if (link->isConnected()) { SerialLink* pSerialLink = qobject_cast(link); if (pSerialLink) { - LinkConfiguration* pLinkConfig = pSerialLink->getLinkConfiguration(); - if (pLinkConfig) { - SerialConfiguration* pSerialConfig = qobject_cast(pLinkConfig); + LinkConfiguration* config = pSerialLink->getLinkConfiguration(); + if (config) { + SerialConfiguration* pSerialConfig = qobject_cast(config); if (pSerialConfig && pSerialConfig->usbDirect()) { - return link; + if (_priorityLink.data() != link) { + newPriorityLink = link; + break; + } + return; } } } } } #endif - return _links.count() ? _links[0] : NULL; + + if (!newPriorityLink && !_priorityLink.data() && _links.count()) { + newPriorityLink = _links[0]; + } + + if (newPriorityLink) { + _priorityLink = qgcApp()->toolbox()->linkManager()->sharedLinkInterfacePointerForLink(newPriorityLink); + } } void Vehicle::setLatitude(double latitude) @@ -928,6 +1160,11 @@ void Vehicle::setLongitude(double longitude){ emit coordinateChanged(_coordinate); } +void Vehicle::setAltitude(double altitude){ + _coordinate.setAltitude(altitude); + emit coordinateChanged(_coordinate); +} + void Vehicle::_updateAttitude(UASInterface*, double roll, double pitch, double yaw, quint64) { if (qIsInf(roll)) { @@ -954,31 +1191,6 @@ void Vehicle::_updateAttitude(UASInterface* uas, int, double roll, double pitch, _updateAttitude(uas, roll, pitch, yaw, timestamp); } -void Vehicle::_updateSpeed(UASInterface*, double groundSpeed, double airSpeed, quint64) -{ - _groundSpeedFact.setRawValue(groundSpeed); - _airSpeedFact.setRawValue(airSpeed); -} - -void Vehicle::_updateAltitude(UASInterface*, double altitudeAMSL, double altitudeRelative, double climbRate, quint64) -{ - _altitudeAMSLFact.setRawValue(altitudeAMSL); - _altitudeRelativeFact.setRawValue(altitudeRelative); - _climbRateFact.setRawValue(climbRate); -} - -void Vehicle::_updateNavigationControllerErrors(UASInterface*, double altitudeError, double speedError, double xtrackError) { - _navigationAltitudeError = altitudeError; - _navigationSpeedError = speedError; - _navigationCrosstrackError = xtrackError; -} - -void Vehicle::_updateNavigationControllerData(UASInterface *uas, float, float, float, float targetBearing, float) { - if (_mav == uas) { - _navigationTargetBearing = targetBearing; - } -} - int Vehicle::motorCount(void) { switch (_vehicleType) { @@ -1014,19 +1226,6 @@ bool Vehicle::xConfigMotors(void) * Internal */ -void Vehicle::_checkUpdate() -{ - // Update current location - if(_mav) { - if(latitude() != _mav->getLatitude()) { - setLatitude(_mav->getLatitude()); - } - if(longitude() != _mav->getLongitude()) { - setLongitude(_mav->getLongitude()); - } - } -} - QString Vehicle::getMavIconColor() { // TODO: Not using because not only the colors are ghastly, it doesn't respect dark/light palette @@ -1059,14 +1258,6 @@ void Vehicle::_handletextMessageReceived(UASMessage* message) } } -void Vehicle::_updateState(UASInterface*, QString name, QString) -{ - if (_currentState != name) { - _currentState = name; - emit currentStateChanged(); - } -} - void Vehicle::_handleTextMessage(int newCount) { // Reset? @@ -1216,6 +1407,12 @@ QStringList Vehicle::joystickModes(void) return list; } +void Vehicle::_activeJoystickChanged(void) +{ + _loadSettings(); + _startJoystick(true); +} + bool Vehicle::joystickEnabled(void) { return _joystickEnabled; @@ -1268,29 +1465,10 @@ QGeoCoordinate Vehicle::homePosition(void) void Vehicle::setArmed(bool armed) { // We specifically use COMMAND_LONG:MAV_CMD_COMPONENT_ARM_DISARM since it is supported by more flight stacks. - - mavlink_message_t msg; - mavlink_command_long_t cmd; - - cmd.command = (uint16_t)MAV_CMD_COMPONENT_ARM_DISARM; - cmd.confirmation = 0; - cmd.param1 = armed ? 1.0f : 0.0f; - cmd.param2 = 0.0f; - cmd.param3 = 0.0f; - cmd.param4 = 0.0f; - cmd.param5 = 0.0f; - cmd.param6 = 0.0f; - cmd.param7 = 0.0f; - cmd.target_system = id(); - cmd.target_component = defaultComponentId(); - - mavlink_msg_command_long_encode_chan(_mavlink->getSystemId(), - _mavlink->getComponentId(), - priorityLink()->mavlinkChannel(), - &msg, - &cmd); - - sendMessageOnLink(priorityLink(), msg); + sendMavCommand(_defaultComponentId, + MAV_CMD_COMPONENT_ARM_DISARM, + true, // show error if fails + armed ? 1.0f : 0.0f); } bool Vehicle::flightModeSetAvailable(void) @@ -1313,6 +1491,8 @@ void Vehicle::setFlightMode(const QString& flightMode) uint8_t base_mode; uint32_t custom_mode; + qDebug() << flightMode; + if (_firmwarePlugin->setFlightMode(flightMode, &base_mode, &custom_mode)) { // setFlightMode will only set MAV_MODE_FLAG_CUSTOM_MODE_ENABLED in base_mode, we need to move back in the existing // states. @@ -1366,7 +1546,7 @@ void Vehicle::requestDataStream(MAV_DATA_STREAM stream, uint16_t rate, bool send dataStream.req_message_rate = rate; dataStream.start_stop = 1; // start dataStream.target_system = id(); - dataStream.target_component = defaultComponentId(); + dataStream.target_component = _defaultComponentId; mavlink_msg_request_data_stream_encode_chan(_mavlink->getSystemId(), _mavlink->getComponentId(), @@ -1458,7 +1638,18 @@ void Vehicle::_parametersReady(bool parametersReady) { if (parametersReady && !_missionManagerInitialRequestSent) { _missionManagerInitialRequestSent = true; - _missionManager->requestMissionItems(); + QString missionAutoLoadDirPath = _settingsManager->appSettings()->missionAutoLoadDir()->rawValue().toString(); + if (missionAutoLoadDirPath.isEmpty()) { + _missionManager->requestMissionItems(); + } else { + QmlObjectListModel* visualItems = NULL; + QmlObjectListModel* complexItems = NULL; + QDir missionAutoLoadDir(missionAutoLoadDirPath); + QString autoloadFilename = missionAutoLoadDir.absoluteFilePath(tr("AutoLoad%1.mission").arg(_id)); + if (MissionController::loadItemsFromFile(this, autoloadFilename, &visualItems, &complexItems)) { + MissionController::sendItemsToVehicle(this, visualItems); + } + } } if (parametersReady) { @@ -1610,6 +1801,16 @@ bool Vehicle::supportsJSButton(void) const return _firmwarePlugin->supportsJSButton(); } +bool Vehicle::supportsCalibratePressure(void) const +{ + return _firmwarePlugin->supportsCalibratePressure(); +} + +bool Vehicle::supportsMotorInterference(void) const +{ + return _firmwarePlugin->supportsMotorInterference(); +} + void Vehicle::_setCoordinateValid(bool coordinateValid) { if (coordinateValid != _coordinateValid) { @@ -1765,6 +1966,14 @@ void Vehicle::pauseVehicle(void) _firmwarePlugin->pauseVehicle(this); } +void Vehicle::abortLanding(double climbOutAltitude) +{ + sendMavCommand(defaultComponentId(), + MAV_CMD_DO_GO_AROUND, + true, // show error if fails + climbOutAltitude); +} + bool Vehicle::guidedMode(void) const { return _firmwarePlugin->isGuidedMode(this); @@ -1777,27 +1986,11 @@ void Vehicle::setGuidedMode(bool guidedMode) void Vehicle::emergencyStop(void) { - mavlink_message_t msg; - mavlink_command_long_t cmd; - - cmd.command = (uint16_t)MAV_CMD_COMPONENT_ARM_DISARM; - cmd.confirmation = 0; - cmd.param1 = 0.0f; - cmd.param2 = 21196.0f; // Magic number for emergency stop - cmd.param3 = 0.0f; - cmd.param4 = 0.0f; - cmd.param5 = 0.0f; - cmd.param6 = 0.0f; - cmd.param7 = 0.0f; - cmd.target_system = id(); - cmd.target_component = defaultComponentId(); - mavlink_msg_command_long_encode_chan(_mavlink->getSystemId(), - _mavlink->getComponentId(), - priorityLink()->mavlinkChannel(), - &msg, - &cmd); - - sendMessageOnLink(priorityLink(), msg); + sendMavCommand(_defaultComponentId, + MAV_CMD_COMPONENT_ARM_DISARM, + true, // show error if fails + 0.0f, + 21196.0f); // Magic number for emergency stop } void Vehicle::setCurrentMissionSequence(int seq) @@ -1816,22 +2009,89 @@ void Vehicle::setCurrentMissionSequence(int seq) sendMessageOnLink(priorityLink(), msg); } -void Vehicle::doCommandLong(int component, MAV_CMD command, float param1, float param2, float param3, float param4, float param5, float param6, float param7) +void Vehicle::sendMavCommand(int component, MAV_CMD command, bool showError, float param1, float param2, float param3, float param4, float param5, float param6, float param7) { + MavCommandQueueEntry_t entry; + + entry.component = component; + entry.command = command; + entry.showError = showError; + entry.rgParam[0] = param1; + entry.rgParam[1] = param2; + entry.rgParam[2] = param3; + entry.rgParam[3] = param4; + entry.rgParam[4] = param5; + entry.rgParam[5] = param6; + entry.rgParam[6] = param7; + + _mavCommandQueue.append(entry); + + if (_mavCommandQueue.count() == 1) { + _mavCommandRetryCount = 0; + _sendMavCommandAgain(); + } +} + +void Vehicle::_sendMavCommandAgain(void) +{ + if(!_mavCommandQueue.size()) { + qWarning() << "Command resend with no commands in queue"; + _mavCommandAckTimer.stop(); + return; + } + + MavCommandQueueEntry_t& queuedCommand = _mavCommandQueue[0]; + + if (_mavCommandRetryCount++ > _mavCommandMaxRetryCount) { + emit mavCommandResult(_id, queuedCommand.component, queuedCommand.command, MAV_RESULT_FAILED, true /* noResponsefromVehicle */); + if (queuedCommand.showError) { + qgcApp()->showMessage(tr("Vehicle did not respond to command: %1").arg(qgcApp()->toolbox()->missionCommandTree()->friendlyName(queuedCommand.command))); + } + _mavCommandQueue.removeFirst(); + _sendNextQueuedMavCommand(); + return; + } + + if (_mavCommandRetryCount > 1) { + // We always let AUTOPILOT_CAPABILITIES go through multiple times even if we don't get acks. This is because + // we really need to get capabilities and version info back over a lossy link. + if (queuedCommand.command != MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES) { + if (px4Firmware()) { + // Older PX4 firmwares are inconsistent with repect to sending back an Ack from a COMMAND_LONG, hence we can't support retry logic for it. + if (_firmwareMajorVersion != versionNotSetValue) { + // If no version set assume lastest master dev build, so acks are suppored + if (_firmwareMajorVersion <= 1 && _firmwareMinorVersion <= 5 && _firmwarePatchVersion <= 3) { + // Acks not supported in this version + return; + } + } + } else { + if (queuedCommand.command == MAV_CMD_START_RX_PAIR) { + // The implementation of this command comes from the IO layer and is shared across stacks. So for other firmwares + // we aren't really sure whether they are correct or not. + return; + } + } + } + qDebug() << "Vehicle::_sendMavCommandAgain retrying command:_mavCommandRetryCount" << queuedCommand.command << _mavCommandRetryCount; + } + + _mavCommandAckTimer.start(); + mavlink_message_t msg; mavlink_command_long_t cmd; - cmd.command = command; + cmd.command = queuedCommand.command; cmd.confirmation = 0; - cmd.param1 = param1; - cmd.param2 = param2; - cmd.param3 = param3; - cmd.param4 = param4; - cmd.param5 = param5; - cmd.param6 = param6; - cmd.param7 = param7; - cmd.target_system = id(); - cmd.target_component = component; + cmd.param1 = queuedCommand.rgParam[0]; + cmd.param2 = queuedCommand.rgParam[1]; + cmd.param3 = queuedCommand.rgParam[2]; + cmd.param4 = queuedCommand.rgParam[3]; + cmd.param5 = queuedCommand.rgParam[4]; + cmd.param6 = queuedCommand.rgParam[5]; + cmd.param7 = queuedCommand.rgParam[6]; + cmd.target_system = _id; + cmd.target_component = queuedCommand.component; mavlink_msg_command_long_encode_chan(_mavlink->getSystemId(), _mavlink->getComponentId(), priorityLink()->mavlinkChannel(), @@ -1841,6 +2101,15 @@ void Vehicle::doCommandLong(int component, MAV_CMD command, float param1, float sendMessageOnLink(priorityLink(), msg); } +void Vehicle::_sendNextQueuedMavCommand(void) +{ + if (_mavCommandQueue.count()) { + _mavCommandRetryCount = 0; + _sendMavCommandAgain(); + } +} + + void Vehicle::setPrearmError(const QString& prearmError) { _prearmError = prearmError; @@ -1886,12 +2155,7 @@ QString Vehicle::firmwareVersionTypeString(void) const void Vehicle::rebootVehicle() { - doCommandLong(defaultComponentId(), MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); -} - -int Vehicle::defaultComponentId(void) -{ - return _parameterManager->defaultComponentId(); + sendMavCommand(_defaultComponentId, MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, true, 1.0f); } void Vehicle::setSoloFirmware(bool soloFirmware) @@ -1906,13 +2170,13 @@ void Vehicle::setSoloFirmware(bool soloFirmware) // Temporarily removed, waiting for new command implementation void Vehicle::motorTest(int motor, int percent, int timeoutSecs) { - doCommandLong(defaultComponentId(), MAV_CMD_DO_MOTOR_TEST, motor, MOTOR_TEST_THROTTLE_PERCENT, percent, timeoutSecs); + doCommandLongUnverified(_defaultComponentId, MAV_CMD_DO_MOTOR_TEST, motor, MOTOR_TEST_THROTTLE_PERCENT, percent, timeoutSecs); } #endif void Vehicle::_newMissionItemsAvailable(void) { - // After the initial mission request complets we ask for the geofence + // After the initial mission request completes we ask for the geofence if (!_geoFenceManagerInitialRequestSent) { _geoFenceManagerInitialRequestSent = true; _geoFenceManager->loadFromVehicle(); @@ -1921,7 +2185,7 @@ void Vehicle::_newMissionItemsAvailable(void) void Vehicle::_newGeoFenceAvailable(void) { - // After the initial mission request complets we ask for the geofence + // After geofence request completes we ask for the rally points if (!_rallyPointManagerInitialRequestSent) { _rallyPointManagerInitialRequestSent = true; _rallyPointManager->loadFromVehicle(); @@ -1933,6 +2197,71 @@ QString Vehicle::brandImage(void) const return _firmwarePlugin->brandImage(this); } +QStringList Vehicle::unhealthySensors(void) const +{ + QStringList sensorList; + + struct sensorInfo_s { + uint32_t bit; + const char* sensorName; + }; + + static const sensorInfo_s rgSensorInfo[] = { + { MAV_SYS_STATUS_SENSOR_3D_GYRO, "Gyro" }, + { MAV_SYS_STATUS_SENSOR_3D_ACCEL, "Accelerometer" }, + { MAV_SYS_STATUS_SENSOR_3D_MAG, "Magnetometer" }, + { MAV_SYS_STATUS_SENSOR_ABSOLUTE_PRESSURE, "Absolute pressure" }, + { MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE, "Differential pressure" }, + { MAV_SYS_STATUS_SENSOR_GPS, "GPS" }, + { MAV_SYS_STATUS_SENSOR_OPTICAL_FLOW, "Optical flow" }, + { MAV_SYS_STATUS_SENSOR_VISION_POSITION, "Computer vision position" }, + { MAV_SYS_STATUS_SENSOR_LASER_POSITION, "Laser based position" }, + { MAV_SYS_STATUS_SENSOR_EXTERNAL_GROUND_TRUTH, "External ground truth" }, + { MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL, "Angular rate control" }, + { MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION, "Attitude stabilization" }, + { MAV_SYS_STATUS_SENSOR_YAW_POSITION, "Yaw position" }, + { MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL, "Z/altitude control" }, + { MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL, "X/Y position control" }, + { MAV_SYS_STATUS_SENSOR_MOTOR_OUTPUTS, "Motor outputs / control" }, + { MAV_SYS_STATUS_SENSOR_RC_RECEIVER, "RC receiver" }, + { MAV_SYS_STATUS_SENSOR_3D_GYRO2, "Gyro 2" }, + { MAV_SYS_STATUS_SENSOR_3D_ACCEL2, "Accelerometer 2" }, + { MAV_SYS_STATUS_SENSOR_3D_MAG2, "Magnetometer 2" }, + { MAV_SYS_STATUS_GEOFENCE, "GeoFence" }, + { MAV_SYS_STATUS_AHRS, "AHRS" }, + { MAV_SYS_STATUS_TERRAIN, "Terrain" }, + { MAV_SYS_STATUS_REVERSE_MOTOR, "Motors reversed" }, + { MAV_SYS_STATUS_LOGGING, "Logging" }, + }; + + for (size_t i=0; ibit) && !(_onboardControlSensorsHealth & pSensorInfo->bit)) { + sensorList << pSensorInfo->sensorName; + } + } + + return sensorList; +} + +void Vehicle::setOfflineEditingDefaultComponentId(int defaultComponentId) +{ + if (_offlineEditingVehicle) { + _defaultComponentId = defaultComponentId; + } else { + qWarning() << "Call to Vehicle::setOfflineEditingDefaultComponentId on vehicle which is not offline"; + } +} + +void Vehicle::triggerCamera(void) +{ + sendMavCommand(FactSystem::defaultComponentId, + MAV_CMD_DO_DIGICAM_CONTROL, + true, // show errors + 0.0, 0.0, 0.0, 0.0, // param 1-4 unused + 1.0); // trigger camera +} + const char* VehicleGPSFactGroup::_hdopFactName = "hdop"; const char* VehicleGPSFactGroup::_vdopFactName = "vdop"; const char* VehicleGPSFactGroup::_courseOverGroundFactName = "courseOverGround"; @@ -1941,7 +2270,6 @@ const char* VehicleGPSFactGroup::_lockFactName = "lock"; VehicleGPSFactGroup::VehicleGPSFactGroup(QObject* parent) : FactGroup(1000, ":/json/Vehicle/GPSFact.json", parent) - , _vehicle(NULL) , _hdopFact (0, _hdopFactName, FactMetaData::valueTypeDouble) , _vdopFact (0, _vdopFactName, FactMetaData::valueTypeDouble) , _courseOverGroundFact (0, _courseOverGroundFactName, FactMetaData::valueTypeDouble) @@ -1959,58 +2287,97 @@ VehicleGPSFactGroup::VehicleGPSFactGroup(QObject* parent) _courseOverGroundFact.setRawValue(std::numeric_limits::quiet_NaN()); } -void VehicleGPSFactGroup::setVehicle(Vehicle* vehicle) +void Vehicle::startMavlinkLog() { - _vehicle = vehicle; + sendMavCommand(_defaultComponentId, MAV_CMD_LOGGING_START, false /* showError */); +} - if (!vehicle) { - // Disconnected Vehicle - return; - } +void Vehicle::stopMavlinkLog() +{ + sendMavCommand(_defaultComponentId, MAV_CMD_LOGGING_STOP, false /* showError */); +} - connect(_vehicle->uas(), &UASInterface::localizationChanged, this, &VehicleGPSFactGroup::_setSatLoc); +void Vehicle::_ackMavlinkLogData(uint16_t sequence) +{ + mavlink_message_t msg; + mavlink_logging_ack_t ack; + ack.sequence = sequence; + ack.target_component = _defaultComponentId; + ack.target_system = id(); + mavlink_msg_logging_ack_encode_chan( + _mavlink->getSystemId(), + _mavlink->getComponentId(), + priorityLink()->mavlinkChannel(), + &msg, + &ack); + sendMessageOnLink(priorityLink(), msg); +} - UAS* pUas = dynamic_cast(_vehicle->uas()); - connect(pUas, &UAS::satelliteCountChanged, this, &VehicleGPSFactGroup::_setSatelliteCount); - connect(pUas, &UAS::satRawHDOPChanged, this, &VehicleGPSFactGroup::_setSatRawHDOP); - connect(pUas, &UAS::satRawVDOPChanged, this, &VehicleGPSFactGroup::_setSatRawVDOP); - connect(pUas, &UAS::satRawCOGChanged, this, &VehicleGPSFactGroup::_setSatRawCOG); +void Vehicle::_handleMavlinkLoggingData(mavlink_message_t& message) +{ + mavlink_logging_data_t log; + mavlink_msg_logging_data_decode(&message, &log); + emit mavlinkLogData(this, log.target_system, log.target_component, log.sequence, + log.first_message_offset, QByteArray((const char*)log.data, log.length), false); } -void VehicleGPSFactGroup::_setSatelliteCount(double val, QString) +void Vehicle::_handleMavlinkLoggingDataAcked(mavlink_message_t& message) { - // I'm assuming that a negative value or over 99 means there is no GPS - if(val < 0.0) val = -1.0; - if(val > 99.0) val = -1.0; + mavlink_logging_data_acked_t log; + mavlink_msg_logging_data_acked_decode(&message, &log); + _ackMavlinkLogData(log.sequence); + emit mavlinkLogData(this, log.target_system, log.target_component, log.sequence, + log.first_message_offset, QByteArray((const char*)log.data, log.length), true); +} - _countFact.setRawValue(val); +void Vehicle::setFirmwarePluginInstanceData(QObject* firmwarePluginInstanceData) +{ + firmwarePluginInstanceData->setParent(this); + _firmwarePluginInstanceData = firmwarePluginInstanceData; } -void VehicleGPSFactGroup::_setSatRawHDOP(double val) +QString Vehicle::missionFlightMode(void) const { - _hdopFact.setRawValue(val); + return _firmwarePlugin->missionFlightMode(); } -void VehicleGPSFactGroup::_setSatRawVDOP(double val) +QString Vehicle::rtlFlightMode(void) const { - _vdopFact.setRawValue(val); + return _firmwarePlugin->rtlFlightMode(); } -void VehicleGPSFactGroup::_setSatRawCOG(double val) +QString Vehicle::takeControlFlightMode(void) const { - _courseOverGroundFact.setRawValue(val); + return _firmwarePlugin->takeControlFlightMode(); } -void VehicleGPSFactGroup::_setSatLoc(UASInterface*, int fix) +QString Vehicle::vehicleImageOpaque() const { - _lockFact.setRawValue(fix); + if(_firmwarePlugin) + return _firmwarePlugin->vehicleImageOpaque(this); + else + return QString(); +} - // fix 0: lost, 1: at least one satellite, but no GPS fix, 2: 2D lock, 3: 3D lock - if (fix > 2) { - _vehicle->_setCoordinateValid(true); - } +QString Vehicle::vehicleImageOutline() const +{ + if(_firmwarePlugin) + return _firmwarePlugin->vehicleImageOutline(this); + else + return QString(); +} + +QString Vehicle::vehicleImageCompass() const +{ + if(_firmwarePlugin) + return _firmwarePlugin->vehicleImageCompass(this); + else + return QString(); } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + const char* VehicleBatteryFactGroup::_voltageFactName = "voltage"; const char* VehicleBatteryFactGroup::_percentRemainingFactName = "percentRemaining"; const char* VehicleBatteryFactGroup::_mahConsumedFactName = "mahConsumed"; @@ -2029,11 +2396,10 @@ const int VehicleBatteryFactGroup::_cellCountUnavailable = -1.0; VehicleBatteryFactGroup::VehicleBatteryFactGroup(QObject* parent) : FactGroup(1000, ":/json/Vehicle/BatteryFact.json", parent) - , _vehicle(NULL) , _voltageFact (0, _voltageFactName, FactMetaData::valueTypeDouble) , _percentRemainingFact (0, _percentRemainingFactName, FactMetaData::valueTypeInt32) , _mahConsumedFact (0, _mahConsumedFactName, FactMetaData::valueTypeInt32) - , _currentFact (0, _currentFactName, FactMetaData::valueTypeInt32) + , _currentFact (0, _currentFactName, FactMetaData::valueTypeFloat) , _temperatureFact (0, _temperatureFactName, FactMetaData::valueTypeDouble) , _cellCountFact (0, _cellCountFactName, FactMetaData::valueTypeInt32) { @@ -2053,18 +2419,12 @@ VehicleBatteryFactGroup::VehicleBatteryFactGroup(QObject* parent) _cellCountFact.setRawValue (_cellCountUnavailable); } -void VehicleBatteryFactGroup::setVehicle(Vehicle* vehicle) -{ - _vehicle = vehicle; -} - const char* VehicleWindFactGroup::_directionFactName = "direction"; const char* VehicleWindFactGroup::_speedFactName = "speed"; const char* VehicleWindFactGroup::_verticalSpeedFactName = "verticalSpeed"; VehicleWindFactGroup::VehicleWindFactGroup(QObject* parent) : FactGroup(1000, ":/json/Vehicle/WindFact.json", parent) - , _vehicle(NULL) , _directionFact (0, _directionFactName, FactMetaData::valueTypeDouble) , _speedFact (0, _speedFactName, FactMetaData::valueTypeDouble) , _verticalSpeedFact(0, _verticalSpeedFactName, FactMetaData::valueTypeDouble) @@ -2079,11 +2439,6 @@ VehicleWindFactGroup::VehicleWindFactGroup(QObject* parent) _verticalSpeedFact.setRawValue (std::numeric_limits::quiet_NaN()); } -void VehicleWindFactGroup::setVehicle(Vehicle* vehicle) -{ - _vehicle = vehicle; -} - const char* VehicleVibrationFactGroup::_xAxisFactName = "xAxis"; const char* VehicleVibrationFactGroup::_yAxisFactName = "yAxis"; const char* VehicleVibrationFactGroup::_zAxisFactName = "zAxis"; @@ -2093,7 +2448,6 @@ const char* VehicleVibrationFactGroup::_clipCount3FactName = "clipCount3"; VehicleVibrationFactGroup::VehicleVibrationFactGroup(QObject* parent) : FactGroup(1000, ":/json/Vehicle/VibrationFact.json", parent) - , _vehicle(NULL) , _xAxisFact (0, _xAxisFactName, FactMetaData::valueTypeDouble) , _yAxisFact (0, _yAxisFactName, FactMetaData::valueTypeDouble) , _zAxisFact (0, _zAxisFactName, FactMetaData::valueTypeDouble) @@ -2114,7 +2468,23 @@ VehicleVibrationFactGroup::VehicleVibrationFactGroup(QObject* parent) _zAxisFact.setRawValue(std::numeric_limits::quiet_NaN()); } -void VehicleVibrationFactGroup::setVehicle(Vehicle* vehicle) + +const char* VehicleTemperatureFactGroup::_temperature1FactName = "temperature1"; +const char* VehicleTemperatureFactGroup::_temperature2FactName = "temperature2"; +const char* VehicleTemperatureFactGroup::_temperature3FactName = "temperature3"; + +VehicleTemperatureFactGroup::VehicleTemperatureFactGroup(QObject* parent) + : FactGroup(1000, ":/json/Vehicle/TemperatureFact.json", parent) + , _temperature1Fact (0, _temperature1FactName, FactMetaData::valueTypeDouble) + , _temperature2Fact (0, _temperature2FactName, FactMetaData::valueTypeDouble) + , _temperature3Fact (0, _temperature3FactName, FactMetaData::valueTypeDouble) { - _vehicle = vehicle; + _addFact(&_temperature1Fact, _temperature1FactName); + _addFact(&_temperature2Fact, _temperature2FactName); + _addFact(&_temperature3Fact, _temperature3FactName); + + // Start out as not available "--.--" + _temperature1Fact.setRawValue (std::numeric_limits::quiet_NaN()); + _temperature2Fact.setRawValue (std::numeric_limits::quiet_NaN()); + _temperature3Fact.setRawValue (std::numeric_limits::quiet_NaN()); } diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index c2b3bfbed2d9ea30c2a06d5cd4bd19b38202f6c7..4c6c16dcbb567333ad370df0edeebf8b353b9599 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -31,13 +31,13 @@ class UASInterface; class FirmwarePlugin; class FirmwarePluginManager; class AutoPilotPlugin; -class AutoPilotPluginManager; class MissionManager; class GeoFenceManager; class RallyPointManager; class ParameterManager; class JoystickManager; class UASMessage; +class SettingsManager; Q_DECLARE_LOGGING_CATEGORY(VehicleLog) @@ -64,8 +64,6 @@ public: Fact* clipCount2 (void) { return &_clipCount2Fact; } Fact* clipCount3 (void) { return &_clipCount3Fact; } - void setVehicle(Vehicle* vehicle); - static const char* _xAxisFactName; static const char* _yAxisFactName; static const char* _zAxisFactName; @@ -74,7 +72,6 @@ public: static const char* _clipCount3FactName; private: - Vehicle* _vehicle; Fact _xAxisFact; Fact _yAxisFact; Fact _zAxisFact; @@ -98,14 +95,11 @@ public: Fact* speed (void) { return &_speedFact; } Fact* verticalSpeed (void) { return &_verticalSpeedFact; } - void setVehicle(Vehicle* vehicle); - static const char* _directionFactName; static const char* _speedFactName; static const char* _verticalSpeedFactName; private: - Vehicle* _vehicle; Fact _directionFact; Fact _speedFact; Fact _verticalSpeedFact; @@ -130,23 +124,13 @@ public: Fact* count (void) { return &_countFact; } Fact* lock (void) { return &_lockFact; } - void setVehicle(Vehicle* vehicle); - static const char* _hdopFactName; static const char* _vdopFactName; static const char* _courseOverGroundFactName; static const char* _countFactName; static const char* _lockFactName; -private slots: - void _setSatelliteCount(double val, QString); - void _setSatRawHDOP(double val); - void _setSatRawVDOP(double val); - void _setSatRawCOG(double val); - void _setSatLoc(UASInterface*, int fix); - private: - Vehicle* _vehicle; Fact _hdopFact; Fact _vdopFact; Fact _courseOverGroundFact; @@ -176,8 +160,6 @@ public: Fact* cellCount (void) { return &_cellCountFact; } - void setVehicle(Vehicle* vehicle); - static const char* _voltageFactName; static const char* _percentRemainingFactName; static const char* _mahConsumedFactName; @@ -195,7 +177,6 @@ public: static const int _cellCountUnavailable; private: - Vehicle* _vehicle; Fact _voltageFact; Fact _percentRemainingFact; Fact _mahConsumedFact; @@ -204,6 +185,35 @@ private: Fact _cellCountFact; }; +class VehicleTemperatureFactGroup : public FactGroup +{ + Q_OBJECT + +public: + VehicleTemperatureFactGroup(QObject* parent = NULL); + + Q_PROPERTY(Fact* temperature1 READ temperature1 CONSTANT) + Q_PROPERTY(Fact* temperature2 READ temperature2 CONSTANT) + Q_PROPERTY(Fact* temperature3 READ temperature3 CONSTANT) + + Fact* temperature1 (void) { return &_temperature1Fact; } + Fact* temperature2 (void) { return &_temperature2Fact; } + Fact* temperature3 (void) { return &_temperature3Fact; } + + static const char* _temperature1FactName; + static const char* _temperature2FactName; + static const char* _temperature3FactName; + + static const char* _settingsGroup; + + static const double _temperatureUnavailable; + +private: + Fact _temperature1Fact; + Fact _temperature2Fact; + Fact _temperature3Fact; +}; + class Vehicle : public FactGroup { Q_OBJECT @@ -211,10 +221,10 @@ class Vehicle : public FactGroup public: Vehicle(LinkInterface* link, int vehicleId, + int defaultComponentId, MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType, FirmwarePluginManager* firmwarePluginManager, - AutoPilotPluginManager* autopilotPluginManager, JoystickManager* joystickManager); // The following is used to create a disconnected Vehicle for use while offline editing. @@ -239,7 +249,6 @@ public: Q_PROPERTY(QmlObjectListModel* trajectoryPoints READ trajectoryPoints CONSTANT) Q_PROPERTY(float latitude READ latitude NOTIFY coordinateChanged) Q_PROPERTY(float longitude READ longitude NOTIFY coordinateChanged) - Q_PROPERTY(QString currentState READ currentState NOTIFY currentStateChanged) Q_PROPERTY(bool messageTypeNone READ messageTypeNone NOTIFY messageTypeChanged) Q_PROPERTY(bool messageTypeNormal READ messageTypeNormal NOTIFY messageTypeChanged) Q_PROPERTY(bool messageTypeWarning READ messageTypeWarning NOTIFY messageTypeChanged) @@ -255,8 +264,8 @@ public: Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) Q_PROPERTY(int flowImageIndex READ flowImageIndex NOTIFY flowImageIndexChanged) Q_PROPERTY(int rcRSSI READ rcRSSI NOTIFY rcRSSIChanged) - Q_PROPERTY(bool px4Firmware READ px4Firmware CONSTANT) - Q_PROPERTY(bool apmFirmware READ apmFirmware CONSTANT) + Q_PROPERTY(bool px4Firmware READ px4Firmware NOTIFY firmwareTypeChanged) + Q_PROPERTY(bool apmFirmware READ apmFirmware NOTIFY firmwareTypeChanged) Q_PROPERTY(bool soloFirmware READ soloFirmware WRITE setSoloFirmware NOTIFY soloFirmwareChanged) Q_PROPERTY(bool genericFirmware READ genericFirmware CONSTANT) Q_PROPERTY(bool connectionLost READ connectionLost NOTIFY connectionLostChanged) @@ -264,22 +273,40 @@ public: Q_PROPERTY(uint messagesReceived READ messagesReceived NOTIFY messagesReceivedChanged) Q_PROPERTY(uint messagesSent READ messagesSent NOTIFY messagesSentChanged) Q_PROPERTY(uint messagesLost READ messagesLost NOTIFY messagesLostChanged) - Q_PROPERTY(bool fixedWing READ fixedWing CONSTANT) - Q_PROPERTY(bool multiRotor READ multiRotor CONSTANT) - Q_PROPERTY(bool vtol READ vtol CONSTANT) - Q_PROPERTY(bool rover READ rover CONSTANT) + Q_PROPERTY(bool fixedWing READ fixedWing NOTIFY vehicleTypeChanged) + Q_PROPERTY(bool multiRotor READ multiRotor NOTIFY vehicleTypeChanged) + Q_PROPERTY(bool vtol READ vtol NOTIFY vehicleTypeChanged) + Q_PROPERTY(bool rover READ rover NOTIFY vehicleTypeChanged) + Q_PROPERTY(bool sub READ sub NOTIFY vehicleTypeChanged) Q_PROPERTY(bool supportsManualControl READ supportsManualControl CONSTANT) Q_PROPERTY(bool supportsThrottleModeCenterZero READ supportsThrottleModeCenterZero CONSTANT) Q_PROPERTY(bool supportsJSButton READ supportsJSButton CONSTANT) Q_PROPERTY(bool supportsRadio READ supportsRadio CONSTANT) - Q_PROPERTY(bool sub READ sub CONSTANT) + Q_PROPERTY(bool supportsCalibratePressure READ supportsCalibratePressure CONSTANT) + Q_PROPERTY(bool supportsMotorInterference READ supportsMotorInterference CONSTANT) Q_PROPERTY(bool autoDisconnect MEMBER _autoDisconnect NOTIFY autoDisconnectChanged) Q_PROPERTY(QString prearmError READ prearmError WRITE setPrearmError NOTIFY prearmErrorChanged) Q_PROPERTY(int motorCount READ motorCount CONSTANT) Q_PROPERTY(bool coaxialMotors READ coaxialMotors CONSTANT) Q_PROPERTY(bool xConfigMotors READ xConfigMotors CONSTANT) Q_PROPERTY(bool isOfflineEditingVehicle READ isOfflineEditingVehicle CONSTANT) - Q_PROPERTY(QString brandImage READ brandImage CONSTANT) + Q_PROPERTY(QString brandImage READ brandImage NOTIFY firmwareTypeChanged) + Q_PROPERTY(QStringList unhealthySensors READ unhealthySensors NOTIFY unhealthySensorsChanged) + Q_PROPERTY(QString missionFlightMode READ missionFlightMode CONSTANT) + Q_PROPERTY(QString rtlFlightMode READ rtlFlightMode CONSTANT) + Q_PROPERTY(QString takeControlFlightMode READ takeControlFlightMode CONSTANT) + Q_PROPERTY(QString firmwareTypeString READ firmwareTypeString NOTIFY firmwareTypeChanged) + Q_PROPERTY(QString vehicleTypeString READ vehicleTypeString NOTIFY vehicleTypeChanged) + Q_PROPERTY(QString vehicleImageOpaque READ vehicleImageOpaque CONSTANT) + Q_PROPERTY(QString vehicleImageOutline READ vehicleImageOutline CONSTANT) + Q_PROPERTY(QString vehicleImageCompass READ vehicleImageCompass CONSTANT) + Q_PROPERTY(int telemetryRRSSI READ telemetryRRSSI NOTIFY telemetryRRSSIChanged) + Q_PROPERTY(int telemetryLRSSI READ telemetryLRSSI NOTIFY telemetryLRSSIChanged) + Q_PROPERTY(unsigned int telemetryRXErrors READ telemetryRXErrors NOTIFY telemetryRXErrorsChanged) + Q_PROPERTY(unsigned int telemetryFixed READ telemetryFixed NOTIFY telemetryFixedChanged) + Q_PROPERTY(unsigned int telemetryTXBuffer READ telemetryTXBuffer NOTIFY telemetryTXBufferChanged) + Q_PROPERTY(unsigned int telemetryLNoise READ telemetryLNoise NOTIFY telemetryLNoiseChanged) + Q_PROPERTY(unsigned int telemetryRNoise READ telemetryRNoise NOTIFY telemetryRNoiseChanged) /// true: Vehicle is flying, false: Vehicle is on ground Q_PROPERTY(bool flying READ flying WRITE setFlying NOTIFY flyingChanged) @@ -309,16 +336,18 @@ public: Q_PROPERTY(Fact* altitudeRelative READ altitudeRelative CONSTANT) Q_PROPERTY(Fact* altitudeAMSL READ altitudeAMSL CONSTANT) - Q_PROPERTY(FactGroup* gps READ gpsFactGroup CONSTANT) - Q_PROPERTY(FactGroup* battery READ batteryFactGroup CONSTANT) - Q_PROPERTY(FactGroup* wind READ windFactGroup CONSTANT) - Q_PROPERTY(FactGroup* vibration READ vibrationFactGroup CONSTANT) + Q_PROPERTY(FactGroup* gps READ gpsFactGroup CONSTANT) + Q_PROPERTY(FactGroup* battery READ batteryFactGroup CONSTANT) + Q_PROPERTY(FactGroup* wind READ windFactGroup CONSTANT) + Q_PROPERTY(FactGroup* vibration READ vibrationFactGroup CONSTANT) + Q_PROPERTY(FactGroup* temperature READ temperatureFactGroup CONSTANT) Q_PROPERTY(int firmwareMajorVersion READ firmwareMajorVersion NOTIFY firmwareMajorVersionChanged) Q_PROPERTY(int firmwareMinorVersion READ firmwareMinorVersion NOTIFY firmwareMinorVersionChanged) Q_PROPERTY(int firmwarePatchVersion READ firmwarePatchVersion NOTIFY firmwarePatchVersionChanged) Q_PROPERTY(int firmwareVersionType READ firmwareVersionType NOTIFY firmwareVersionTypeChanged) Q_PROPERTY(QString firmwareVersionTypeString READ firmwareVersionTypeString NOTIFY firmwareVersionTypeChanged) + Q_PROPERTY(QString gitHash READ gitHash NOTIFY gitHashChanged) /// Resets link status counters Q_INVOKABLE void resetCounters (); @@ -368,6 +397,9 @@ public: /// Command vehicle to kill all motors no matter what state Q_INVOKABLE void emergencyStop(void); + /// Command vehicle to abort landing + Q_INVOKABLE void abortLanding(double climbOutAltitude); + /// Alter the current mission item on the vehicle Q_INVOKABLE void setCurrentMissionSequence(int seq); @@ -377,6 +409,8 @@ public: /// Clear Messages Q_INVOKABLE void clearMessages(); + Q_INVOKABLE void triggerCamera(void); + #if 0 // Temporarily removed, waiting for new command implementation /// Test motor @@ -424,8 +458,9 @@ public: MAV_TYPE vehicleType(void) const { return _vehicleType; } Q_INVOKABLE QString vehicleTypeName(void) const; - /// Returns the highest quality link available to the Vehicle - LinkInterface* priorityLink(void); + /// Returns the highest quality link available to the Vehicle. If you need to hold a refernce to this link use + /// LinkManager::sharedLinkInterfaceForGet to get QSharedPointer for link. + LinkInterface* priorityLink(void) { return _priorityLink.data(); } /// Sends a message to the specified link /// @return true: message sent, false: Link no longer connected @@ -474,6 +509,8 @@ public: bool supportsThrottleModeCenterZero(void) const; bool supportsRadio(void) const; bool supportsJSButton(void) const; + bool supportsCalibratePressure(void) const; + bool supportsMotorInterference(void) const; void setFlying(bool flying); void setGuidedMode(bool guidedMode); @@ -485,6 +522,10 @@ public: int flowImageIndex() { return _flowImageIndex; } + //-- Mavlink Logging + void startMavlinkLog(); + void stopMavlinkLog(); + /// Requests the specified data stream from the vehicle /// @param stream Stream which is being requested /// @param rate Rate at which to send stream in Hz @@ -510,7 +551,6 @@ public: float latitude () { return _coordinate.latitude(); } float longitude () { return _coordinate.longitude(); } bool mavPresent () { return _mav != NULL; } - QString currentState () { return _currentState; } int rcRSSI () { return _rcRSSI; } bool px4Firmware () const { return _firmwareType == MAV_AUTOPILOT_PX4; } bool apmFirmware () const { return _firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA; } @@ -526,6 +566,21 @@ public: uint32_t customMode () const { return _custom_mode; } bool isOfflineEditingVehicle () const { return _offlineEditingVehicle; } QString brandImage () const; + QStringList unhealthySensors () const; + QString missionFlightMode () const; + QString rtlFlightMode () const; + QString takeControlFlightMode () const; + double cruiseSpeed () const { return _cruiseSpeed; } + double hoverSpeed () const { return _hoverSpeed; } + QString firmwareTypeString () const; + QString vehicleTypeString () const; + int telemetryRRSSI () { return _telemetryRRSSI; } + int telemetryLRSSI () { return _telemetryLRSSI; } + unsigned int telemetryRXErrors () { return _telemetryRXErrors; } + unsigned int telemetryFixed () { return _telemetryFixed; } + unsigned int telemetryTXBuffer () { return _telemetryTXBuffer; } + unsigned int telemetryLNoise () { return _telemetryLNoise; } + unsigned int telemetryRNoise () { return _telemetryRNoise; } Fact* roll (void) { return &_rollFact; } Fact* heading (void) { return &_headingFact; } @@ -540,6 +595,7 @@ public: FactGroup* batteryFactGroup (void) { return &_batteryFactGroup; } FactGroup* windFactGroup (void) { return &_windFactGroup; } FactGroup* vibrationFactGroup (void) { return &_vibrationFactGroup; } + FactGroup* temperatureFactGroup (void) { return &_temperatureFactGroup; } void setConnectionLostEnabled(bool connectionLostEnabled); @@ -549,7 +605,13 @@ public: static const int cMaxRcChannels = 18; bool containsLink(LinkInterface* link) { return _links.contains(link); } - void doCommandLong(int component, MAV_CMD command, float param1 = 0.0f, float param2 = 0.0f, float param3 = 0.0f, float param4 = 0.0f, float param5 = 0.0f, float param6 = 0.0f, float param7 = 0.0f); + + /// Sends the specified MAV_CMD to the vehicle. If no Ack is received command will be retried. If a sendMavCommand is already in progress + /// the command will be queued and sent when the previous command completes. + /// @param component Component to send to + /// @param command MAV_CMD to send + /// @param showError true: Display error to user if command failed, false: no error shown + void sendMavCommand(int component, MAV_CMD command, bool showError, float param1 = 0.0f, float param2 = 0.0f, float param3 = 0.0f, float param4 = 0.0f, float param5 = 0.0f, float param6 = 0.0f, float param7 = 0.0f); int firmwareMajorVersion(void) const { return _firmwareMajorVersion; } int firmwareMinorVersion(void) const { return _firmwareMinorVersion; } @@ -559,10 +621,15 @@ public: void setFirmwareVersion(int majorVersion, int minorVersion, int patchVersion, FIRMWARE_VERSION_TYPE versionType = FIRMWARE_VERSION_TYPE_OFFICIAL); static const int versionNotSetValue = -1; + QString gitHash(void) const { return _gitHash; } + bool soloFirmware(void) const { return _soloFirmware; } void setSoloFirmware(bool soloFirmware); - int defaultComponentId(void); + int defaultComponentId(void) { return _defaultComponentId; } + + /// Sets the default component id for an offline editing vehicle + void setOfflineEditingDefaultComponentId(int defaultComponentId); /// @return -1 = Unknown, Number of motors on vehicle int motorCount(void); @@ -573,9 +640,23 @@ public: /// @return true: X confiuration, false: Plus configuration bool xConfigMotors(void); + /// @return Firmware plugin instance data associated with this Vehicle + QObject* firmwarePluginInstanceData(void) { return _firmwarePluginInstanceData; } + + /// Sets the firmware plugin instance data associated with this Vehicle. This object will be parented to the Vehicle + /// and destroyed when the vehicle goes away. + void setFirmwarePluginInstanceData(QObject* firmwarePluginInstanceData); + + QString vehicleImageOpaque () const; + QString vehicleImageOutline () const; + QString vehicleImageCompass () const; + public slots: - void setLatitude(double latitude); - void setLongitude(double longitude); + /// Sets the firmware plugin instance data associated with this Vehicle. This object will be parented to the Vehicle + /// and destroyed when the vehicle goes away. + void setLatitude (double latitude); + void setLongitude (double longitude); + void setAltitude (double altitude); signals: void allLinksInactive(Vehicle* vehicle); @@ -598,8 +679,12 @@ signals: void flyingChanged(bool flying); void guidedModeChanged(bool guidedMode); void prearmErrorChanged(const QString& prearmError); - void commandLongAck(uint8_t compID, uint16_t command, uint8_t result); void soloFirmwareChanged(bool soloFirmware); + void unhealthySensorsChanged(void); + void cruiseSpeedChanged(double cruiseSpeed); + void hoverSpeedChanged(double hoverSpeed); + void firmwareTypeChanged(void); + void vehicleTypeChanged(void); void messagesReceivedChanged (); void messagesSentChanged (); @@ -608,23 +693,31 @@ signals: /// Used internally to move sendMessage call to main thread void _sendMessageOnLinkOnThread(LinkInterface* link, mavlink_message_t message); - void messageTypeChanged (); - void newMessageCountChanged (); - void messageCountChanged (); - void formatedMessagesChanged(); - void formatedMessageChanged (); - void latestErrorChanged (); - void longitudeChanged (); - void currentConfigChanged (); - void currentStateChanged (); - void flowImageIndexChanged (); - void rcRSSIChanged (int rcRSSI); + void messageTypeChanged (); + void newMessageCountChanged (); + void messageCountChanged (); + void formatedMessagesChanged (); + void formatedMessageChanged (); + void latestErrorChanged (); + void longitudeChanged (); + void currentConfigChanged (); + void flowImageIndexChanged (); + void rcRSSIChanged (int rcRSSI); + void telemetryRRSSIChanged (int value); + void telemetryLRSSIChanged (int value); + void telemetryRXErrorsChanged (unsigned int value); + void telemetryFixedChanged (unsigned int value); + void telemetryTXBufferChanged (unsigned int value); + void telemetryLNoiseChanged (unsigned int value); + void telemetryRNoiseChanged (unsigned int value); void firmwareMajorVersionChanged(int major); void firmwareMinorVersionChanged(int minor); void firmwarePatchVersionChanged(int patch); void firmwareVersionTypeChanged(int type); + void gitHashChanged(QString hash); + /// New RC channel values /// @param channelCount Number of available channels, cMaxRcChannels max /// @param pwmValues -1 signals channel not available @@ -638,8 +731,20 @@ signals: void mavlinkScaledImu2(mavlink_message_t message); void mavlinkScaledImu3(mavlink_message_t message); + // Mavlink Log Download + void mavlinkLogData (Vehicle* vehicle, uint8_t target_system, uint8_t target_component, uint16_t sequence, uint8_t first_message, QByteArray data, bool acked); + + /// Signalled in response to usage of sendMavCommand + /// @param vehicleId Vehicle which command was sent to + /// @param component Component which command was sent to + /// @param command MAV_CMD Command which was sent + /// @param result MAV_RESULT returned in ack + /// @param noResponseFromVehicle true: vehicle did not respond to command, false: vehicle responsed, MAV_RESULT in result + void mavCommandResult(int vehicleId, int component, int command, int result, bool noReponseFromVehicle); + private slots: void _mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message); + void _telemetryChanged(LinkInterface* link, unsigned rxerrors, unsigned fixed, int rssi, int remrssi, unsigned txbuf, unsigned noise, unsigned remnoise); void _linkInactiveOrDeleted(LinkInterface* link); void _sendMessageOnLink(LinkInterface* link, mavlink_message_t message); void _sendMessageMultipleNext(void); @@ -648,6 +753,10 @@ private slots: void _remoteControlRSSIChanged(uint8_t rssi); void _handleFlightModeChanged(const QString& flightMode); void _announceArmedChanged(bool armed); + void _offlineFirmwareTypeSettingChanged(QVariant value); + void _offlineVehicleTypeSettingChanged(QVariant value); + void _offlineCruiseSpeedSettingChanged(QVariant value); + void _offlineHoverSpeedSettingChanged(QVariant value); void _handleTextMessage (int newCount); void _handletextMessageReceived (UASMessage* message); @@ -655,18 +764,15 @@ private slots: void _updateAttitude (UASInterface* uas, double roll, double pitch, double yaw, quint64 timestamp); /** @brief Attitude from one specific component / redundant autopilot */ void _updateAttitude (UASInterface* uas, int component, double roll, double pitch, double yaw, quint64 timestamp); - void _updateSpeed (UASInterface* uas, double _groundSpeed, double _airSpeed, quint64 timestamp); - void _updateAltitude (UASInterface* uas, double _altitudeAMSL, double _altitudeRelative, double _climbRate, quint64 timestamp); - void _updateNavigationControllerErrors (UASInterface* uas, double altitudeError, double speedError, double xtrackError); - void _updateNavigationControllerData (UASInterface *uas, float navRoll, float navPitch, float navBearing, float targetBearing, float targetDistance); - void _checkUpdate (); - void _updateState (UASInterface* system, QString name, QString description); /** @brief A new camera image has arrived */ void _imageReady (UASInterface* uas); void _connectionLostTimeout(void); void _prearmErrorTimeout(void); void _newMissionItemsAvailable(void); void _newGeoFenceAvailable(void); + void _sendMavCommandAgain(void); + + void _activeJoystickChanged(void); private: bool _containsLink(LinkInterface* link); @@ -685,8 +791,15 @@ private: void _handleVibration(mavlink_message_t& message); void _handleExtendedSysState(mavlink_message_t& message); void _handleCommandAck(mavlink_message_t& message); - void _handleAutopilotVersion(mavlink_message_t& message); + void _handleAutopilotVersion(LinkInterface* link, mavlink_message_t& message); void _handleHilActuatorControls(mavlink_message_t& message); + void _handleGpsRawInt(mavlink_message_t& message); + void _handleGlobalPositionInt(mavlink_message_t& message); + void _handleAltitude(mavlink_message_t& message); + void _handleVfrHud(mavlink_message_t& message); + void _handleScaledPressure(mavlink_message_t& message); + void _handleScaledPressure2(mavlink_message_t& message); + void _handleScaledPressure3(mavlink_message_t& message); void _missionManagerError(int errorCode, const QString& errorMsg); void _geoFenceManagerError(int errorCode, const QString& errorMsg); void _rallyPointManagerError(int errorCode, const QString& errorMsg); @@ -695,18 +808,26 @@ private: void _connectionActive(void); void _say(const QString& text); QString _vehicleIdSpeech(void); + void _handleMavlinkLoggingData(mavlink_message_t& message); + void _handleMavlinkLoggingDataAcked(mavlink_message_t& message); + void _ackMavlinkLogData(uint16_t sequence); + void _sendNextQueuedMavCommand(void); + void _updatePriorityLink(void); + void _commonInit(void); -private: int _id; ///< Mavlink system id + int _defaultComponentId; bool _active; bool _offlineEditingVehicle; ///< This Vehicle is a "disconnected" vehicle for ui use while offline editing MAV_AUTOPILOT _firmwareType; MAV_TYPE _vehicleType; FirmwarePlugin* _firmwarePlugin; + QObject* _firmwarePluginInstanceData; AutoPilotPlugin* _autopilotPlugin; MAVLinkProtocol* _mavlink; bool _soloFirmware; + SettingsManager* _settingsManager; QList _links; @@ -729,18 +850,40 @@ private: int _currentNormalCount; MessageType_t _currentMessageType; QString _latestError; - float _navigationAltitudeError; - float _navigationSpeedError; - float _navigationCrosstrackError; - float _navigationTargetBearing; - QTimer* _refreshTimer; - QString _currentState; int _updateCount; QString _formatedMessage; int _rcRSSI; double _rcRSSIstore; bool _autoDisconnect; ///< true: Automatically disconnect vehicle when last connection goes away or lost heartbeat bool _flying; + uint32_t _onboardControlSensorsPresent; + uint32_t _onboardControlSensorsEnabled; + uint32_t _onboardControlSensorsHealth; + uint32_t _onboardControlSensorsUnhealthy; + bool _gpsRawIntMessageAvailable; + bool _globalPositionIntMessageAvailable; + double _cruiseSpeed; + double _hoverSpeed; + int _telemetryRRSSI; + int _telemetryLRSSI; + uint32_t _telemetryRXErrors; + uint32_t _telemetryFixed; + uint32_t _telemetryTXBuffer; + uint32_t _telemetryLNoise; + uint32_t _telemetryRNoise; + + typedef struct { + int component; + MAV_CMD command; + float rgParam[7]; + bool showError; + } MavCommandQueueEntry_t; + + QList _mavCommandQueue; + QTimer _mavCommandAckTimer; + int _mavCommandRetryCount; + static const int _mavCommandMaxRetryCount = 3; + static const int _mavCommandAckTimeoutMSecs = 3000; QString _prearmError; QTimer _prearmErrorTimer; @@ -789,7 +932,6 @@ private: // Toolbox references FirmwarePluginManager* _firmwarePluginManager; - AutoPilotPluginManager* _autopilotPluginManager; JoystickManager* _joystickManager; int _flowImageIndex; @@ -808,9 +950,13 @@ private: int _firmwarePatchVersion; FIRMWARE_VERSION_TYPE _firmwareVersionType; + QString _gitHash; + static const int _lowBatteryAnnounceRepeatMSecs; // Amount of time in between each low battery announcement QElapsedTimer _lowBatteryAnnounceTimer; + SharedLinkInterfacePointer _priorityLink; // We always keep a reference to the priority link to manage shutdown ordering + // FactGroup facts Fact _rollFact; @@ -826,6 +972,7 @@ private: VehicleBatteryFactGroup _batteryFactGroup; VehicleWindFactGroup _windFactGroup; VehicleVibrationFactGroup _vibrationFactGroup; + VehicleTemperatureFactGroup _temperatureFactGroup; static const char* _rollFactName; static const char* _pitchFactName; @@ -840,6 +987,7 @@ private: static const char* _batteryFactGroupName; static const char* _windFactGroupName; static const char* _vibrationFactGroupName; + static const char* _temperatureFactGroupName; static const int _vehicleUIUpdateRateMSecs = 100; diff --git a/src/VehicleSetup/Bootloader.h b/src/VehicleSetup/Bootloader.h index 522f528b89195ef6cae3edee4347c8373c8b48f3..268132483a720f95d148e8856ee4ba2c16606147 100644 --- a/src/VehicleSetup/Bootloader.h +++ b/src/VehicleSetup/Bootloader.h @@ -61,15 +61,16 @@ public: bool reboot(QextSerialPort* port); // Supported bootloader board ids - static const int boardIDPX4FMUV1 = 5; ///< PX4 V1 board, as from USB PID - static const int boardIDPX4FMUV2 = 9; ///< PX4 V2 board, as from USB PID - static const int boardIDPX4FMUV4 = 11; ///< PX4 V4 board, as from USB PID - static const int boardIDPX4Flow = 6; ///< PX4 Flow board, as from USB PID - static const int boardIDAeroCore = 98; ///< Gumstix AeroCore board, as from USB PID - static const int boardID3DRRadio = 78; ///< 3DR Radio. This is an arbitrary value unrelated to the PID - static const int boardIDMINDPXFMUV2 = 88; ///< MindPX V2 board, as from USB PID - static const int boardIDTAPV1 = 64; ///< TAP V1 board, as from USB PID - static const int boardIDASCV1 = 65; ///< ASC V1 board, as from USB PID + static const int boardIDPX4FMUV1 = 5; ///< PX4 V1 board, as from USB PID + static const int boardIDPX4FMUV2 = 9; ///< PX4 V2 board, as from USB PID + static const int boardIDPX4FMUV4 = 11; ///< PX4 V4 board, as from USB PID + static const int boardIDPX4Flow = 6; ///< PX4 Flow board, as from USB PID + static const int boardIDAeroCore = 98; ///< Gumstix AeroCore board, as from USB PID + static const int boardIDAUAVX2_1 = 33; ///< AUAV X2.1 board, as from USB PID + static const int boardID3DRRadio = 78; ///< 3DR Radio. This is an arbitrary value unrelated to the PID + static const int boardIDMINDPXFMUV2 = 88; ///< MindPX V2 board, as from USB PID + static const int boardIDTAPV1 = 64; ///< TAP V1 board, as from USB PID + static const int boardIDASCV1 = 65; ///< ASC V1 board, as from USB PID signals: /// @brief Signals progress indicator for long running bootloader utility routines diff --git a/src/VehicleSetup/FirmwareImage.cc b/src/VehicleSetup/FirmwareImage.cc index d947991e0efd49f30796348829fe1c9fdff780fe..20841df74e4396e57be06bedef1443446df03bf4 100644 --- a/src/VehicleSetup/FirmwareImage.cc +++ b/src/VehicleSetup/FirmwareImage.cc @@ -51,9 +51,8 @@ bool FirmwareImage::load(const QString& imageFilename, uint32_t boardId) _boardId = boardId; if (imageFilename.endsWith(".bin")) { - return _binLoad(imageFilename); _binFormat = true; - return true; + return _binLoad(imageFilename); } else if (imageFilename.endsWith(".px4")) { _binFormat = true; return _px4Load(imageFilename); diff --git a/src/VehicleSetup/FirmwareUpgrade.qml b/src/VehicleSetup/FirmwareUpgrade.qml index 55df893480a96c51c2e7842ed6363d2e7b91dc0f..8ab41ccf210cdde6fdc97423ccd7cb95b2162b75 100644 --- a/src/VehicleSetup/FirmwareUpgrade.qml +++ b/src/VehicleSetup/FirmwareUpgrade.qml @@ -97,7 +97,7 @@ QGCView { } else { // We end up here when we detect a board plugged in after we've started upgrade statusTextArea.append(highlightPrefix + qsTr("Found device") + highlightSuffix + ": " + controller.boardType) - if (controller.boardType == "Pixhawk" || controller.boardType == "AeroCore" || controller.boardType == "PX4 Flow" || controller.boardType == "PX4 FMU V1" || controller.boardType == "MindPX" || controller.boardType == "TAP V1" || controller.boardType == "ASC V1") { + if (controller.pixhawkBoard || controller.px4FlowBoard) { showDialog(pixhawkFirmwareSelectDialogComponent, title, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel) } } @@ -124,7 +124,7 @@ QGCView { anchors.fill: parent property bool showFirmwareTypeSelection: _advanced.checked - property bool px4Flow: controller.boardType == "PX4 Flow" + property bool px4Flow: controller.px4FlowBoard function updatePX4VersionDisplay() { var versionString = "" diff --git a/src/VehicleSetup/FirmwareUpgradeController.cc b/src/VehicleSetup/FirmwareUpgradeController.cc index ef24f1de4a5c2e1cecf238df0e7e04b9e5d7e1f1..bf83ef8cc5ee9e36ee052464eb3268279211b202 100644 --- a/src/VehicleSetup/FirmwareUpgradeController.cc +++ b/src/VehicleSetup/FirmwareUpgradeController.cc @@ -116,43 +116,14 @@ void FirmwareUpgradeController::cancel(void) _threadController->cancel(); } -void FirmwareUpgradeController::_foundBoard(bool firstAttempt, const QSerialPortInfo& info, int boardType) +void FirmwareUpgradeController::_foundBoard(bool firstAttempt, const QSerialPortInfo& info, int boardType, QString boardName) { _foundBoardInfo = info; _foundBoardType = (QGCSerialPortInfo::BoardType_t)boardType; + _foundBoardTypeName = boardName; + _startFlashWhenBootloaderFound = false; - switch (boardType) { - case QGCSerialPortInfo::BoardTypePX4FMUV1: - _foundBoardTypeName = "PX4 FMU V1"; - _startFlashWhenBootloaderFound = false; - break; - case QGCSerialPortInfo::BoardTypePX4FMUV2: - case QGCSerialPortInfo::BoardTypePX4FMUV4: - _foundBoardTypeName = "Pixhawk"; - _startFlashWhenBootloaderFound = false; - break; - case QGCSerialPortInfo::BoardTypeAeroCore: - _foundBoardTypeName = "AeroCore"; - _startFlashWhenBootloaderFound = false; - break; - case QGCSerialPortInfo::BoardTypeMINDPXFMUV2: - _foundBoardTypeName = "MindPX"; - _startFlashWhenBootloaderFound = false; - break; - case QGCSerialPortInfo::BoardTypeTAPV1: - _foundBoardTypeName = "TAP V1"; - _startFlashWhenBootloaderFound = false; - break; - case QGCSerialPortInfo::BoardTypeASCV1: - _foundBoardTypeName = "ASC V1"; - _startFlashWhenBootloaderFound = false; - break; - case QGCSerialPortInfo::BoardTypePX4Flow: - _foundBoardTypeName = "PX4 Flow"; - _startFlashWhenBootloaderFound = false; - break; - case QGCSerialPortInfo::BoardTypeSikRadio: - _foundBoardTypeName = "SiK Radio"; + if (_foundBoardType == QGCSerialPortInfo::BoardTypeSiKRadio) { if (!firstAttempt) { // Radio always flashes latest firmware, so we can start right away without // any further user input. @@ -161,12 +132,10 @@ void FirmwareUpgradeController::_foundBoard(bool firstAttempt, const QSerialPort StableFirmware, DefaultVehicleFirmware); } - break; } - qCDebug(FirmwareUpgradeLog) << _foundBoardType; + qCDebug(FirmwareUpgradeLog) << _foundBoardType << _foundBoardTypeName; emit boardFound(); - _loadAPMVersions(_foundBoardType); } @@ -197,6 +166,8 @@ void FirmwareUpgradeController::_foundBootloader(int bootloaderVersion, int boar if (_startFlashWhenBootloaderFound) { flash(_startFlashWhenBootloaderFoundFirmwareIdentity); } + + _loadAPMVersions(_bootloaderBoardID); } @@ -224,21 +195,11 @@ void FirmwareUpgradeController::_initFirmwareHash() { AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v4.px4"}, { AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v4.px4"}, { AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v4.px4"}, - { AutoPilotStackAPM, BetaFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-quad/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, BetaFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa-quad/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, BetaFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-hexa/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, BetaFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, BetaFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-tri/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, BetaFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-y6/ArduCopter-v4.px4"}, + { AutoPilotStackAPM, BetaFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4/ArduCopter-v4.px4"}, { AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-heli/ArduCopter-v4.px4"}, { AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/beta/PX4/ArduPlane-v4.px4"}, { AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/beta/PX4/APMrover2-v4.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-quad/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa-quad/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-hexa/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-tri/ArduCopter-v4.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-y6/ArduCopter-v4.px4"}, + { AutoPilotStackAPM, DeveloperFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4/ArduCopter-v4.px4"}, { AutoPilotStackAPM, DeveloperFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-heli/ArduCopter-v4.px4"}, { AutoPilotStackAPM, DeveloperFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/latest/PX4/ArduPlane-v4.px4"}, { AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/latest/PX4/APMrover2-v4.px4"} @@ -258,24 +219,15 @@ void FirmwareUpgradeController::_initFirmwareHash() { AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v2.px4"}, { AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v2.px4"}, { AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-quad/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa-quad/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-hexa/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-tri/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-y6/ArduCopter-v2.px4"}, + { AutoPilotStackAPM, BetaFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4/ArduCopter-v2.px4"}, { AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-heli/ArduCopter-v2.px4"}, { AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/beta/PX4/ArduPlane-v2.px4"}, { AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/beta/PX4/APMrover2-v2.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-quad/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa-quad/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-hexa/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-tri/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-y6/ArduCopter-v2.px4"}, + { AutoPilotStackAPM, DeveloperFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4/ArduCopter-v2.px4"}, { AutoPilotStackAPM, DeveloperFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-heli/ArduCopter-v2.px4"}, { AutoPilotStackAPM, DeveloperFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/latest/PX4/ArduPlane-v2.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/latest/PX4/APMrover2-v2.px4"} + { AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/latest/PX4/APMrover2-v2.px4"}, + { AutoPilotStackAPM, DeveloperFirmware, SubFirmware, "http://firmware.ardupilot.org/Sub/latest/PX4/ArduSub-v2.px4"}, }; //////////////////////////////////// PX4FMU aerocore firmwares ////////////////////////////////////////////////// @@ -292,15 +244,10 @@ void FirmwareUpgradeController::_initFirmwareHash() { AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/stable/PX4-heli/ArduCopter-v2.px4"}, { AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Plane/stable/PX4/ArduPlane-v2.px4"}, { AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Rover/stable/PX4/APMrover2-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, QuadFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-quad/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, X8Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-octa-quad/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, HexaFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-hexa/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, OctoFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-octa/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, YFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-tri/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, Y6Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-y6/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-heli/ArduCopter-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Plane/beta/PX4/ArduPlane-v2.px4"}, - { AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Rover/beta/PX4/APMrover2-v2.px4"}, + { AutoPilotStackAPM, BetaFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4/ArduCopter-v2.px4"}, + { AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-heli/ArduCopter-v2.px4"}, + { AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/beta/PX4/ArduPlane-v2.px4"}, + { AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/beta/PX4/APMrover2-v2.px4"}, { AutoPilotStackAPM, DeveloperFirmware, QuadFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-quad/ArduCopter-v2.px4"}, { AutoPilotStackAPM, DeveloperFirmware, X8Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-octa-quad/ArduCopter-v2.px4"}, { AutoPilotStackAPM, DeveloperFirmware, HexaFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-hexa/ArduCopter-v2.px4"}, @@ -326,26 +273,21 @@ void FirmwareUpgradeController::_initFirmwareHash() { AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v1.px4"}, { AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v1.px4"}, { AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v1.px4"}, - { AutoPilotStackAPM, BetaFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-quad/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, BetaFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa-quad/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, BetaFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-hexa/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, BetaFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, BetaFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-tri/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, BetaFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-y6/ArduCopter-v1.px4"}, + { AutoPilotStackAPM, BetaFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4/ArduCopter-v1.px4"}, { AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-heli/ArduCopter-v1.px4"}, { AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/beta/PX4/ArduPlane-v1.px4"}, { AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/beta/PX4/APMrover2-v1.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-quad/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa-quad/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-hexa/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-tri/ArduCopter-v1.px4"}, - { AutoPilotStackAPM, DeveloperFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-y6/ArduCopter-v1.px4"}, + { AutoPilotStackAPM, DeveloperFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4/ArduCopter-v1.px4"}, { AutoPilotStackAPM, DeveloperFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-heli/ArduCopter-v1.px4"}, { AutoPilotStackAPM, DeveloperFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/latest/PX4/ArduPlane-v1.px4"}, { AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/latest/PX4/APMrover2-v1.px4"} }; - + //////////////////////////////////// AUAVX2_1 firmwares ////////////////////////////////////////////////// + FirmwareToUrlElement_t rgAUAVX2_1FirmwareArray[] = { + { AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/auav-x21_default.px4"}, + { AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/auav-x21_default.px4"}, + { AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/auav-x21_default.px4"}, + }; //////////////////////////////////// MindPXFMUV2 firmwares ////////////////////////////////////////////////// FirmwareToUrlElement_t rgMindPXFMUV2FirmwareArray[] = { { AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/mindpx-v2_default.px4"}, @@ -399,6 +341,12 @@ void FirmwareUpgradeController::_initFirmwareHash() _rgPX4FMUV1Firmware.insert(FirmwareIdentifier(element.stackType, element.firmwareType, element.vehicleType), element.url); } + size = sizeof(rgAUAVX2_1FirmwareArray)/sizeof(rgAUAVX2_1FirmwareArray[0]); + for (int i = 0; i < size; i++) { + const FirmwareToUrlElement_t& element = rgAUAVX2_1FirmwareArray[i]; + _rgAUAVX2_1Firmware.insert(FirmwareIdentifier(element.stackType, element.firmwareType, element.vehicleType), element.url); + } + size = sizeof(rgMindPXFMUV2FirmwareArray)/sizeof(rgMindPXFMUV2FirmwareArray[0]); for (int i = 0; i < size; i++) { const FirmwareToUrlElement_t& element = rgMindPXFMUV2FirmwareArray[i]; @@ -450,6 +398,8 @@ QHash* FirmwareUpgradeCo return &_rgPX4FMUV4Firmware; case Bootloader::boardIDAeroCore: return &_rgAeroCoreFirmware; + case Bootloader::boardIDAUAVX2_1: + return &_rgAUAVX2_1Firmware; case Bootloader::boardIDMINDPXFMUV2: return &_rgMindPXFMUV2Firmware; case Bootloader::boardIDTAPV1: @@ -463,48 +413,6 @@ QHash* FirmwareUpgradeCo } } -QHash* FirmwareUpgradeController::_firmwareHashForBoardType(QGCSerialPortInfo::BoardType_t boardType) -{ - int boardId = Bootloader::boardIDPX4FMUV2; - - switch (boardType) { - case QGCSerialPortInfo::BoardTypePX4FMUV1: - boardId = Bootloader::boardIDPX4FMUV1; - break; - case QGCSerialPortInfo::BoardTypePX4FMUV2: - boardId = Bootloader::boardIDPX4FMUV2; - break; - case QGCSerialPortInfo::BoardTypePX4FMUV4: - boardId = Bootloader::boardIDPX4FMUV4; - break; - case QGCSerialPortInfo::BoardTypeAeroCore: - boardId = Bootloader::boardIDAeroCore; - break; - case QGCSerialPortInfo::BoardTypeMINDPXFMUV2: - boardId = Bootloader::boardIDMINDPXFMUV2; - break; - case QGCSerialPortInfo::BoardTypeTAPV1: - boardId = Bootloader::boardIDTAPV1; - break; - case QGCSerialPortInfo::BoardTypeASCV1: - boardId = Bootloader::boardIDASCV1; - break; - case QGCSerialPortInfo::BoardTypePX4Flow: - boardId = Bootloader::boardIDPX4Flow; - break; - case QGCSerialPortInfo::BoardTypeSikRadio: - boardId = Bootloader::boardID3DRRadio; - break; - default: - qWarning() << "Internal error: invalid board type for flashing" << boardType; - boardId = Bootloader::boardIDPX4FMUV2; - break; - } - - return _firmwareHashForBoardId(boardId); -} - - /// @brief Prompts the user to select a firmware file if needed and moves the state machine to the next state. void FirmwareUpgradeController::_getFirmwareFile(FirmwareIdentifier firmwareId) { @@ -697,11 +605,11 @@ void FirmwareUpgradeController::_eraseComplete(void) _eraseTimer.stop(); } -void FirmwareUpgradeController::_loadAPMVersions(QGCSerialPortInfo::BoardType_t boardType) +void FirmwareUpgradeController::_loadAPMVersions(uint32_t bootloaderBoardID) { _apmVersionMap.clear(); - QHash* prgFirmware = _firmwareHashForBoardType(boardType); + QHash* prgFirmware = _firmwareHashForBoardId(bootloaderBoardID); foreach (FirmwareIdentifier firmwareId, prgFirmware->keys()) { if (firmwareId.autopilotStackType == AutoPilotStackAPM) { @@ -740,7 +648,7 @@ void FirmwareUpgradeController::_apmVersionDownloadFinished(QString remoteFile, // In order to determine the firmware and vehicle type for this file we find the matching entry in the firmware list - QHash* prgFirmware = _firmwareHashForBoardType(_foundBoardType); + QHash* prgFirmware = _firmwareHashForBoardId(_bootloaderBoardID); QString remotePath = QFileInfo(remoteFile).path(); foreach (FirmwareIdentifier firmwareId, prgFirmware->keys()) { @@ -791,6 +699,12 @@ QStringList FirmwareUpgradeController::apmAvailableVersions(void) case HeliFirmware: version = "Heli - "; break; + case CopterFirmware: + version = "MultiRotor - "; + break; + case SubFirmware: + version = "Sub - "; + break; case PlaneFirmware: case RoverFirmware: case DefaultVehicleFirmware: diff --git a/src/VehicleSetup/FirmwareUpgradeController.h b/src/VehicleSetup/FirmwareUpgradeController.h index 29b4f7d24c63e7db0ab7fba4c4c262df0f4261d0..1209135dfd51ec4d374dd42d00eaba2588e4f361 100644 --- a/src/VehicleSetup/FirmwareUpgradeController.h +++ b/src/VehicleSetup/FirmwareUpgradeController.h @@ -60,8 +60,10 @@ public: YFirmware, Y6Firmware, HeliFirmware, + CopterFirmware, PlaneFirmware, RoverFirmware, + SubFirmware, DefaultVehicleFirmware } FirmwareVehicleType_t; @@ -96,6 +98,8 @@ public: Q_PROPERTY(QString boardPort READ boardPort NOTIFY boardFound) Q_PROPERTY(QString boardDescription READ boardDescription NOTIFY boardFound) Q_PROPERTY(QString boardType MEMBER _foundBoardTypeName NOTIFY boardFound) + Q_PROPERTY(bool pixhawkBoard READ pixhawkBoard NOTIFY boardFound) + Q_PROPERTY(bool px4FlowBoard READ px4FlowBoard NOTIFY boardFound) Q_PROPERTY(FirmwareType_t selectedFirmwareType READ selectedFirmwareType WRITE setSelectedFirmwareType NOTIFY selectedFirmwareTypeChanged) Q_PROPERTY(QStringList apmAvailableVersions READ apmAvailableVersions NOTIFY apmAvailableVersionsChanged) Q_PROPERTY(QString px4StableVersion READ px4StableVersion NOTIFY px4StableVersionChanged) @@ -142,6 +146,9 @@ public: QString px4StableVersion(void) { return _px4StableVersion; } QString px4BetaVersion(void) { return _px4BetaVersion; } + bool pixhawkBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePixhawk; } + bool px4FlowBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePX4Flow; } + signals: void boardFound(void); void noBoardFound(void); @@ -158,7 +165,7 @@ private slots: void _firmwareDownloadProgress(qint64 curr, qint64 total); void _firmwareDownloadFinished(QString remoteFile, QString localFile); void _firmwareDownloadError(QString errorMsg); - void _foundBoard(bool firstAttempt, const QSerialPortInfo& portInfo, int boardType); + void _foundBoard(bool firstAttempt, const QSerialPortInfo& portInfo, int boardType, QString boardName); void _noBoardFound(void); void _boardGone(); void _foundBootloader(int bootloaderVersion, int boardID, int flashSize); @@ -180,9 +187,8 @@ private: void _downloadFirmware(void); void _appendStatusLog(const QString& text, bool critical = false); void _errorCancel(const QString& msg); - void _loadAPMVersions(QGCSerialPortInfo::BoardType_t boardType); + void _loadAPMVersions(uint32_t bootloaderBoardID); QHash* _firmwareHashForBoardId(int boardId); - QHash* _firmwareHashForBoardType(QGCSerialPortInfo::BoardType_t boardType); void _determinePX4StableVersion(void); QString _portName; @@ -193,6 +199,7 @@ private: QHash _rgPX4FMUV2Firmware; QHash _rgAeroCoreFirmware; QHash _rgPX4FMUV1Firmware; + QHash _rgAUAVX2_1Firmware; QHash _rgMindPXFMUV2Firmware; QHash _rgTAPV1Firmware; QHash _rgASCV1Firmware; diff --git a/src/VehicleSetup/JoystickConfig.qml b/src/VehicleSetup/JoystickConfig.qml index 503c6be53598527acd296f3b319db50ffa7afe3c..066146b298c4158a830ebb63b8ea76214554a18c 100644 --- a/src/VehicleSetup/JoystickConfig.qml +++ b/src/VehicleSetup/JoystickConfig.qml @@ -27,6 +27,16 @@ SetupPage { pageName: qsTr("Joystick") pageDescription: qsTr("Joystick Setup is used to configure a calibrate joysticks.") + Connections { + target: joystickManager + onAvailableJoysticksChanged: { + if( joystickManager.joysticks.length == 0 ) { + summaryButton.checked = true + setupView.showSummaryPanel() + } + } + } + Component { id: pageComponent @@ -176,7 +186,7 @@ SetupPage { QGCLabel { id: rollLabel width: defaultTextWidth * 10 - text: qsTr("Roll") + text: _activeVehicle.sub ? qsTr("Lateral") : qsTr("Roll") } Loader { @@ -208,7 +218,7 @@ SetupPage { QGCLabel { id: pitchLabel width: defaultTextWidth * 10 - text: qsTr("Pitch") + text: _activeVehicle.sub ? qsTr("Forward") : qsTr("Pitch") } Loader { @@ -302,6 +312,7 @@ SetupPage { // Command Buttons Row { spacing: 10 + visible: _activeJoystick.requiresCalibration QGCButton { id: skipButton @@ -358,11 +369,22 @@ SetupPage { QGCCheckBox { - enabled: checked || _activeJoystick.calibrated - text: _activeJoystick.calibrated ? qsTr("Enable joystick input") : qsTr("Enable not allowed (Calibrate First)") + id: enabledCheckBox + enabled: _activeJoystick ? _activeJoystick.calibrated : false + text: _activeJoystick ? _activeJoystick.calibrated ? qsTr("Enable joystick input") : qsTr("Enable not allowed (Calibrate First)") : "" checked: _activeVehicle.joystickEnabled onClicked: _activeVehicle.joystickEnabled = checked + + Connections { + target: joystickManager + + onActiveJoystickChanged: { + if(_activeJoystick) { + enabledCheckBox.checked = Qt.binding(function() { return _activeJoystick.calibrated && _activeVehicle.joystickEnabled }) + } + } + } } Row { @@ -390,6 +412,16 @@ SetupPage { joystickCombo.currentIndex = index } } + + Connections { + target: joystickManager + onAvailableJoysticksChanged: { + var index = joystickCombo.find(joystickManager.activeJoystickName) + if (index >= 0) { + joystickCombo.currentIndex = index + } + } + } } } @@ -402,7 +434,7 @@ SetupPage { QGCRadioButton { exclusiveGroup: throttleModeExclusiveGroup text: qsTr("Center stick is zero throttle") - checked: _activeJoystick.throttleMode == 0 + checked: _activeJoystick ? _activeJoystick.throttleMode == 0 : false onClicked: _activeJoystick.throttleMode = 0 } @@ -411,11 +443,11 @@ SetupPage { x: 20 width: parent.width spacing: ScreenTools.defaultFontPixelWidth - visible: _activeJoystick.throttleMode == 0 + visible: _activeJoystick ? _activeJoystick.throttleMode == 0 : false QGCCheckBox { id: accumulator - checked: _activeJoystick.accumulator + checked: _activeJoystick ? _activeJoystick.accumulator : false text: qsTr("Spring loaded throttle smoothing") onClicked: _activeJoystick.accumulator = checked @@ -425,7 +457,7 @@ SetupPage { QGCRadioButton { exclusiveGroup: throttleModeExclusiveGroup text: qsTr("Full down stick is zero throttle") - checked: _activeJoystick.throttleMode == 1 + checked: _activeJoystick ? _activeJoystick.throttleMode == 1 : false onClicked: _activeJoystick.throttleMode = 1 } @@ -436,7 +468,7 @@ SetupPage { QGCCheckBox { id: exponential - checked: _activeJoystick.exponential + checked: _activeJoystick ? _activeJoystick.exponential : false text: qsTr("Use exponential curve on roll, pitch, yaw") onClicked: _activeJoystick.exponential = checked @@ -525,7 +557,7 @@ SetupPage { Repeater { id: buttonActionRepeater - model: _activeJoystick.totalButtonCount + model: _activeJoystick ? _activeJoystick.totalButtonCount : 0 Row { spacing: ScreenTools.defaultFontPixelWidth @@ -535,7 +567,7 @@ SetupPage { QGCCheckBox { anchors.verticalCenter: parent.verticalCenter - checked: _activeJoystick.buttonActions[modelData] != "" + checked: _activeJoystick ? _activeJoystick.buttonActions[modelData] != "" : false onClicked: _activeJoystick.setButtonAction(modelData, checked ? buttonActionCombo.textAt(buttonActionCombo.currentIndex) : "") } @@ -561,7 +593,7 @@ SetupPage { QGCComboBox { id: buttonActionCombo width: ScreenTools.defaultFontPixelWidth * 20 - model: _activeJoystick.actions + model: _activeJoystick ? _activeJoystick.actions : 0 onActivated: _activeJoystick.setButtonAction(modelData, textAt(index)) Component.onCompleted: currentIndex = find(_activeJoystick.buttonActions[modelData]) @@ -592,7 +624,7 @@ SetupPage { Repeater { id: jsButtonActionRepeater - model: _activeJoystick.totalButtonCount + model: _activeJoystick ? _activeJoystick.totalButtonCount : 0 Row { spacing: ScreenTools.defaultFontPixelWidth @@ -643,12 +675,57 @@ SetupPage { id: rightColumn anchors.top: parent.top anchors.right: parent.right - width: defaultTextWidth * 35 - spacing: 10 + width: Math.min(joystickPage.defaultTextWidth * 35, availableWidth * 0.4) + spacing: ScreenTools.defaultFontPixelHeight / 2 + + Row { + spacing: ScreenTools.defaultFontPixelWidth + + ExclusiveGroup { id: modeGroup } + + QGCLabel { + text: "TX Mode:" + } + + QGCRadioButton { + exclusiveGroup: modeGroup + text: "1" + checked: controller.transmitterMode == 1 + enabled: !controller.calibrating + + onClicked: controller.transmitterMode = 1 + } + + QGCRadioButton { + exclusiveGroup: modeGroup + text: "2" + checked: controller.transmitterMode == 2 + enabled: !controller.calibrating + + onClicked: controller.transmitterMode = 2 + } + + QGCRadioButton { + exclusiveGroup: modeGroup + text: "3" + checked: controller.transmitterMode == 3 + enabled: !controller.calibrating + + onClicked: controller.transmitterMode = 3 + } + + QGCRadioButton { + exclusiveGroup: modeGroup + text: "4" + checked: controller.transmitterMode == 4 + enabled: !controller.calibrating + + onClicked: controller.transmitterMode = 4 + } + } Image { - //width: parent.width - height: defaultTextHeight * 15 + width: parent.width fillMode: Image.PreserveAspectFit smooth: true source: controller.imageHelp @@ -673,7 +750,7 @@ SetupPage { Repeater { id: axisMonitorRepeater - model: _activeJoystick.axisCount + model: _activeJoystick ? _activeJoystick.axisCount : 0 width: parent.width Row { @@ -725,7 +802,7 @@ SetupPage { Repeater { id: buttonMonitorRepeater - model: _activeJoystick.totalButtonCount + model: _activeJoystick ? _activeJoystick.totalButtonCount : 0 Rectangle { width: ScreenTools.defaultFontPixelHeight * 1.2 diff --git a/src/VehicleSetup/JoystickConfigController.cc b/src/VehicleSetup/JoystickConfigController.cc index 505478bd73107da3be0fe2dba60b4ea689a059d8..0c4446b52b2f1980400603a780263f50e5de657f 100644 --- a/src/VehicleSetup/JoystickConfigController.cc +++ b/src/VehicleSetup/JoystickConfigController.cc @@ -29,8 +29,11 @@ const int JoystickConfigController::_calMinDelta = 1000; ///< Amo const int JoystickConfigController::_stickDetectSettleMSecs = 500; -const char* JoystickConfigController::_imageFilePrefix = "calibration/"; -const char* JoystickConfigController::_imageFileMode2Dir = "joystick/"; +const char* JoystickConfigController::_imageFilePrefix = "calibration/joystick/"; +const char* JoystickConfigController::_imageFileMode1Dir = "mode1/"; +const char* JoystickConfigController::_imageFileMode2Dir = "mode2/"; +const char* JoystickConfigController::_imageFileMode3Dir = "mode3/"; +const char* JoystickConfigController::_imageFileMode4Dir = "mode4/"; const char* JoystickConfigController::_imageCenter = "joystickCenter.png"; const char* JoystickConfigController::_imageThrottleUp = "joystickThrottleUp.png"; const char* JoystickConfigController::_imageThrottleDown = "joystickThrottleDown.png"; @@ -43,6 +46,7 @@ const char* JoystickConfigController::_imagePitchDown = "joystickPitchDown.p JoystickConfigController::JoystickConfigController(void) : _activeJoystick(NULL) + , _transmitterMode(2) , _currentStep(-1) , _axisCount(0) , _rgAxisInfo(NULL) @@ -69,7 +73,9 @@ void JoystickConfigController::start(void) JoystickConfigController::~JoystickConfigController() { - _activeJoystick->stopCalibrationMode(Joystick::CalibrationModeMonitor); + if(_activeJoystick) { + _activeJoystick->stopCalibrationMode(Joystick::CalibrationModeMonitor); + } } /// @brief Returns the state machine entry for the specified state. @@ -491,10 +497,13 @@ void JoystickConfigController::_setInternalCalibrationValuesFromSettings(void) int paramAxis; paramAxis = joystick->getFunctionAxis((Joystick::AxisFunction_t)function); - - _rgFunctionAxisMapping[function] = paramAxis; - _rgAxisInfo[paramAxis].function = (Joystick::AxisFunction_t)function; + if(paramAxis >= 0) { + _rgFunctionAxisMapping[function] = paramAxis; + _rgAxisInfo[paramAxis].function = (Joystick::AxisFunction_t)function; + } } + + _transmitterMode = joystick->getTXMode(); _signalAllAttiudeValueChanges(); } @@ -591,6 +600,7 @@ void JoystickConfigController::_startCalibration(void) _currentStep = 0; _setupCurrentState(); + emit calibratingChanged(); } /// @brief Cancels the calibration process, setting things back to initial state. @@ -609,6 +619,7 @@ void JoystickConfigController::_stopCalibration(void) _skipButton->setEnabled(false); _setHelpImage(_imageCenter); + emit calibratingChanged(); } /// @brief Saves the current axis values, so that we can detect when the use moves an input. @@ -642,7 +653,23 @@ void JoystickConfigController::_setHelpImage(const char* imageFile) { QString file = _imageFilePrefix; - file += _imageFileMode2Dir; + switch(_transmitterMode) { + case 1: + file += _imageFileMode1Dir; + break; + case 2: + file += _imageFileMode2Dir; + break; + case 3: + file += _imageFileMode3Dir; + break; + case 4: + file += _imageFileMode4Dir; + break; + default: + Q_ASSERT(false); + } + file += imageFile; qCDebug(JoystickConfigControllerLog) << "_setHelpImage" << file; @@ -784,6 +811,20 @@ bool JoystickConfigController::throttleAxisReversed(void) } } +void JoystickConfigController::setTransmitterMode(int mode) +{ + if (mode > 0 && mode <= 4) { + _transmitterMode = mode; + if (_currentStep != -1) { // This should never be true, mode selection is disabled during calibration + const stateMachineEntry* state = _getStateMachineEntry(_currentStep); + _setHelpImage(state->image); + } else { + _activeJoystick->setTXMode(mode); + _setInternalCalibrationValuesFromSettings(); + } + } +} + void JoystickConfigController::_signalAllAttiudeValueChanges(void) { emit rollAxisMappedChanged(rollAxisMapped()); @@ -800,6 +841,8 @@ void JoystickConfigController::_signalAllAttiudeValueChanges(void) emit pitchAxisDeadbandChanged(pitchAxisDeadband()); emit yawAxisDeadbandChanged(yawAxisDeadband()); emit throttleAxisDeadbandChanged(throttleAxisDeadband()); + + emit transmitterModeChanged(_transmitterMode); } void JoystickConfigController::_activeJoystickChanged(Joystick* joystick) @@ -809,9 +852,11 @@ void JoystickConfigController::_activeJoystickChanged(Joystick* joystick) if (_activeJoystick) { joystickTransition = true; disconnect(_activeJoystick, &Joystick::rawAxisValueChanged, this, &JoystickConfigController::_axisValueChanged); - delete _rgAxisInfo; - delete _axisValueSave; - delete _axisRawValue; + // This will reset _rgFunctionAxis values to -1 to prevent out-of-bounds accesses + _resetInternalCalibrationValues(); + delete[] _rgAxisInfo; + delete[] _axisValueSave; + delete[] _axisRawValue; _axisCount = 0; _activeJoystick = NULL; } @@ -826,6 +871,7 @@ void JoystickConfigController::_activeJoystickChanged(Joystick* joystick) _rgAxisInfo = new struct AxisInfo[_axisCount]; _axisValueSave = new int[_axisCount]; _axisRawValue = new int[_axisCount]; + _setInternalCalibrationValuesFromSettings(); connect(_activeJoystick, &Joystick::rawAxisValueChanged, this, &JoystickConfigController::_axisValueChanged); } } diff --git a/src/VehicleSetup/JoystickConfigController.h b/src/VehicleSetup/JoystickConfigController.h index 9b0a8c8795a502a0021138d8eb97724eee298939..c0c709c724a3ef53e30cb50962780c7b240a7e5f 100644 --- a/src/VehicleSetup/JoystickConfigController.h +++ b/src/VehicleSetup/JoystickConfigController.h @@ -69,7 +69,9 @@ public: Q_PROPERTY(bool deadbandToggle READ getDeadbandToggle WRITE setDeadbandToggle NOTIFY deadbandToggled) + Q_PROPERTY(int transmitterMode READ transmitterMode WRITE setTransmitterMode NOTIFY transmitterModeChanged) Q_PROPERTY(QString imageHelp MEMBER _imageHelp NOTIFY imageHelpChanged) + Q_PROPERTY(bool calibrating READ calibrating NOTIFY calibratingChanged) Q_INVOKABLE void cancelButtonClicked(void); Q_INVOKABLE void skipButtonClicked(void); @@ -100,6 +102,11 @@ public: void setDeadbandToggle(bool); int axisCount(void); + + int transmitterMode(void) { return _transmitterMode; } + void setTransmitterMode(int mode); + + bool calibrating(void) { return _currentStep != -1; } signals: void axisValueChanged(int axis, int value); @@ -127,6 +134,8 @@ signals: void deadbandToggled(bool value); void imageHelpChanged(QString source); + void transmitterModeChanged(int mode); + void calibratingChanged(void); // @brief Signalled when in unit test mode and a message box should be displayed by the next button void nextButtonMessageBoxDisplayed(void); @@ -172,6 +181,7 @@ private: Joystick* _activeJoystick; + int _transmitterMode; int _currentStep; ///< Current step of state machine const struct stateMachineEntry* _getStateMachineEntry(int step); @@ -211,7 +221,10 @@ private: // Member variables + static const char* _imageFileMode1Dir; static const char* _imageFileMode2Dir; + static const char* _imageFileMode3Dir; + static const char* _imageFileMode4Dir; static const char* _imageFilePrefix; static const char* _imageCenter; static const char* _imageThrottleUp; diff --git a/src/VehicleSetup/PX4FirmwareUpgradeThread.cc b/src/VehicleSetup/PX4FirmwareUpgradeThread.cc index 532ca38df28f7b698aab59742808a8d35020240a..28797e1493ed208fb508b54f682be5d0defde201 100644 --- a/src/VehicleSetup/PX4FirmwareUpgradeThread.cc +++ b/src/VehicleSetup/PX4FirmwareUpgradeThread.cc @@ -86,14 +86,15 @@ void PX4FirmwareUpgradeThreadWorker::_findBoardOnce(void) QGCSerialPortInfo portInfo; QGCSerialPortInfo::BoardType_t boardType; + QString boardName; - if (_findBoardFromPorts(portInfo, boardType)) { + if (_findBoardFromPorts(portInfo, boardType, boardName)) { if (!_foundBoard) { _foundBoard = true; _foundBoardPortInfo = portInfo; - emit foundBoard(_findBoardFirstAttempt, portInfo, boardType); + emit foundBoard(_findBoardFirstAttempt, portInfo, boardType, boardName); if (!_findBoardFirstAttempt) { - if (boardType == QGCSerialPortInfo::BoardTypeSikRadio) { + if (boardType == QGCSerialPortInfo::BoardTypeSiKRadio) { _3drRadioForceBootloader(portInfo); return; } else { @@ -116,18 +117,20 @@ void PX4FirmwareUpgradeThreadWorker::_findBoardOnce(void) _timerRetry->start(); } -bool PX4FirmwareUpgradeThreadWorker::_findBoardFromPorts(QGCSerialPortInfo& portInfo, QGCSerialPortInfo::BoardType_t& boardType) +bool PX4FirmwareUpgradeThreadWorker::_findBoardFromPorts(QGCSerialPortInfo& portInfo, QGCSerialPortInfo::BoardType_t& boardType, QString& boardName) { foreach (QGCSerialPortInfo info, QGCSerialPortInfo::availablePorts()) { + info.getBoardInfo(boardType, boardName); + qCDebug(FirmwareUpgradeVerboseLog) << "Serial Port --------------"; - qCDebug(FirmwareUpgradeVerboseLog) << "\tboard type" << info.boardType(); + qCDebug(FirmwareUpgradeVerboseLog) << "\tboard type" << boardType; + qCDebug(FirmwareUpgradeVerboseLog) << "\tboard name" << boardName; qCDebug(FirmwareUpgradeVerboseLog) << "\tport name:" << info.portName(); qCDebug(FirmwareUpgradeVerboseLog) << "\tdescription:" << info.description(); qCDebug(FirmwareUpgradeVerboseLog) << "\tsystem location:" << info.systemLocation(); qCDebug(FirmwareUpgradeVerboseLog) << "\tvendor ID:" << info.vendorIdentifier(); qCDebug(FirmwareUpgradeVerboseLog) << "\tproduct ID:" << info.productIdentifier(); - boardType = info.boardType(); if (info.canFlash()) { portInfo = info; return true; diff --git a/src/VehicleSetup/PX4FirmwareUpgradeThread.h b/src/VehicleSetup/PX4FirmwareUpgradeThread.h index cff613019a3a9275f2db41a05895493b39d7ff18..018249cbc07a6c4f1cd608fc9b48fedf53841d24 100644 --- a/src/VehicleSetup/PX4FirmwareUpgradeThread.h +++ b/src/VehicleSetup/PX4FirmwareUpgradeThread.h @@ -43,7 +43,7 @@ public: signals: void updateProgress(int curr, int total); - void foundBoard(bool firstAttempt, const QGCSerialPortInfo& portInfo, int type); + void foundBoard(bool firstAttempt, const QGCSerialPortInfo& portInfo, int type, QString boardName); void noBoardFound(void); void boardGone(void); void foundBootloader(int bootloaderVersion, int boardID, int flashSize); @@ -64,7 +64,7 @@ private slots: void _cancel(void); private: - bool _findBoardFromPorts(QGCSerialPortInfo& portInfo, QGCSerialPortInfo::BoardType_t& boardType); + bool _findBoardFromPorts(QGCSerialPortInfo& portInfo, QGCSerialPortInfo::BoardType_t& boardType, QString& boardName); bool _findBootloader(const QGCSerialPortInfo& portInfo, bool radioMode, bool errorOnNotFound); void _3drRadioForceBootloader(const QGCSerialPortInfo& portInfo); bool _erase(void); @@ -107,7 +107,7 @@ public: signals: /// @brief Emitted by the find board process when it finds a board. - void foundBoard(bool firstAttempt, const QGCSerialPortInfo &portInfo, int boardType); + void foundBoard(bool firstAttempt, const QGCSerialPortInfo &portInfo, int boardType, QString boardName); void noBoardFound(void); @@ -142,7 +142,7 @@ signals: void _cancel(void); private slots: - void _foundBoard(bool firstAttempt, const QGCSerialPortInfo& portInfo, int type) { emit foundBoard(firstAttempt, portInfo, type); } + void _foundBoard(bool firstAttempt, const QGCSerialPortInfo& portInfo, int type, QString name) { emit foundBoard(firstAttempt, portInfo, type, name); } void _noBoardFound(void) { emit noBoardFound(); } void _boardGone(void) { emit boardGone(); } void _foundBootloader(int bootloaderVersion, int boardID, int flashSize) { emit foundBootloader(bootloaderVersion, boardID, flashSize); } diff --git a/src/VehicleSetup/SetupView.qml b/src/VehicleSetup/SetupView.qml index 77b6781790a3b921bb61f14d0854d47fd82cd830..ac1156397cb78ccee0f1f832a597d2e21b20ae6a 100644 --- a/src/VehicleSetup/SetupView.qml +++ b/src/VehicleSetup/SetupView.qml @@ -233,8 +233,8 @@ Rectangle { // I don't know why this does not work Connections { - target: QGroundControl - onBaseFontPointSizeChanged: buttonColumn.reflowWidths() + target: QGroundControl.settingsManager.appSettings.appFontPointSize + onValueChanged: buttonColumn.reflowWidths() } function reflowWidths() { @@ -256,6 +256,19 @@ Rectangle { visible: !ScreenTools.isShortScreen } + Repeater { + model: QGroundControl.corePlugin.settings + visible: QGroundControl.corePlugin.options.combineSettingsAndSetup + SubMenuButton { + imageResource: modelData.icon + setupIndicator: false + exclusiveGroup: setupButtonGroup + text: modelData.title + visible: QGroundControl.corePlugin.options.combineSettingsAndSetup + onClicked: panelLoader.setSource(modelData.url) + } + } + SubMenuButton { id: summaryButton imageResource: "/qmlimages/VehicleSummaryIcon.png" diff --git a/src/VideoStreaming/VideoReceiver.cc b/src/VideoStreaming/VideoReceiver.cc index 520aa48b279351f84ad9fec61a9be0d7711136a4..81c8f56284198559983313109c8bffcba8862a17 100644 --- a/src/VideoStreaming/VideoReceiver.cc +++ b/src/VideoStreaming/VideoReceiver.cc @@ -15,23 +15,50 @@ */ #include "VideoReceiver.h" +#include "SettingsManager.h" +#include "QGCApplication.h" + #include +#include +#include +#include +#include + +QGC_LOGGING_CATEGORY(VideoReceiverLog, "VideoReceiverLog") VideoReceiver::VideoReceiver(QObject* parent) : QObject(parent) #if defined(QGC_GST_STREAMING) + , _running(false) + , _recording(false) + , _streaming(false) + , _starting(false) + , _stopping(false) + , _sink(NULL) + , _tee(NULL) , _pipeline(NULL) + , _pipelineStopRec(NULL) , _videoSink(NULL) + , _socket(NULL) + , _serverPresent(false) #endif { - +#if defined(QGC_GST_STREAMING) + _timer.setSingleShot(true); + connect(&_timer, &QTimer::timeout, this, &VideoReceiver::_timeout); + connect(this, &VideoReceiver::msgErrorReceived, this, &VideoReceiver::_handleError); + connect(this, &VideoReceiver::msgEOSReceived, this, &VideoReceiver::_handleEOS); + connect(this, &VideoReceiver::msgStateChangedReceived, this, &VideoReceiver::_handleStateChanged); +#endif } VideoReceiver::~VideoReceiver() { #if defined(QGC_GST_STREAMING) stop(); - setVideoSink(NULL); + if(_socket) { + delete _socket; + } #endif } @@ -50,25 +77,81 @@ void VideoReceiver::setVideoSink(GstElement* sink) #endif #if defined(QGC_GST_STREAMING) -static void newPadCB(GstElement * element, GstPad* pad, gpointer data) +static void newPadCB(GstElement* element, GstPad* pad, gpointer data) { - gchar *name; + gchar* name; name = gst_pad_get_name(pad); g_print("A new pad %s was created\n", name); - GstCaps * p_caps = gst_pad_get_pad_template_caps (pad); - gchar * description = gst_caps_to_string(p_caps); - qDebug() << p_caps << ", " << description; + GstCaps* p_caps = gst_pad_get_pad_template_caps (pad); + gchar* description = gst_caps_to_string(p_caps); + qCDebug(VideoReceiverLog) << p_caps << ", " << description; g_free(description); - GstElement * p_rtph264depay = GST_ELEMENT(data); + GstElement* p_rtph264depay = GST_ELEMENT(data); if(gst_element_link_pads(element, name, p_rtph264depay, "sink") == false) qCritical() << "newPadCB : failed to link elements\n"; g_free(name); } #endif +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_connected() +{ + //-- Server showed up. Now we start the stream. + _timer.stop(); + _socket->deleteLater(); + _socket = NULL; + _serverPresent = true; + start(); +} +#endif + +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_socketError(QAbstractSocket::SocketError socketError) +{ + Q_UNUSED(socketError); + _socket->deleteLater(); + _socket = NULL; + //-- Try again in 5 seconds + _timer.start(5000); +} +#endif + +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_timeout() +{ + //-- If socket is live, we got no connection nor a socket error + if(_socket) { + delete _socket; + _socket = NULL; + } + //-- RTSP will try to connect to the server. If it cannot connect, + // it will simply give up and never try again. Instead, we keep + // attempting a connection on this timer. Once a connection is + // found to be working, only then we actually start the stream. + QUrl url(_uri); + _socket = new QTcpSocket; + connect(_socket, static_cast(&QTcpSocket::error), this, &VideoReceiver::_socketError); + connect(_socket, &QTcpSocket::connected, this, &VideoReceiver::_connected); + //qCDebug(VideoReceiverLog) << "Trying to connect to:" << url.host() << url.port(); + _socket->connectToHost(url.host(), url.port()); + _timer.start(5000); +} +#endif + +// When we finish our pipeline will look like this: +// +// +-->queue-->decoder-->_videosink +// | +// datasource-->demux-->parser-->tee +// +// ^ +// | +// +-Here we will later link elements for recording void VideoReceiver::start() { #if defined(QGC_GST_STREAMING) + qCDebug(VideoReceiverLog) << "start()"; + if (_uri.isEmpty()) { qCritical() << "VideoReceiver::start() failed because URI is not specified"; return; @@ -77,8 +160,20 @@ void VideoReceiver::start() qCritical() << "VideoReceiver::start() failed because video sink is not set"; return; } + if(_running) { + qCDebug(VideoReceiverLog) << "Already running!"; + return; + } - stop(); + _starting = true; + + bool isUdp = _uri.contains("udp://"); + + //-- For RTSP, check to see if server is there first + if(!_serverPresent && !isUdp) { + _timer.start(100); + return; + } bool running = false; @@ -86,10 +181,9 @@ void VideoReceiver::start() GstCaps* caps = NULL; GstElement* demux = NULL; GstElement* parser = NULL; + GstElement* queue = NULL; GstElement* decoder = NULL; - bool isUdp = _uri.contains("udp://"); - do { if ((_pipeline = gst_pipeline_new("receiver")) == NULL) { qCritical() << "VideoReceiver::start() failed. Error with gst_pipeline_new()"; @@ -114,7 +208,7 @@ void VideoReceiver::start() } g_object_set(G_OBJECT(dataSource), "uri", qPrintable(_uri), "caps", caps, NULL); } else { - g_object_set(G_OBJECT(dataSource), "location", qPrintable(_uri), "latency", 0, NULL); + g_object_set(G_OBJECT(dataSource), "location", qPrintable(_uri), "latency", 17, "udp-reconnect", 1, "timeout", static_cast(5000000), NULL); } if ((demux = gst_element_factory_make("rtph264depay", "rtp-h264-depacketizer")) == NULL) { @@ -136,27 +230,38 @@ void VideoReceiver::start() break; } - gst_bin_add_many(GST_BIN(_pipeline), dataSource, demux, parser, decoder, _videoSink, NULL); + if((_tee = gst_element_factory_make("tee", NULL)) == NULL) { + qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('tee')"; + break; + } - gboolean res = FALSE; + if((queue = gst_element_factory_make("queue", NULL)) == NULL) { + qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('queue')"; + break; + } + + gst_bin_add_many(GST_BIN(_pipeline), dataSource, demux, parser, _tee, queue, decoder, _videoSink, NULL); if(isUdp) { - res = gst_element_link_many(dataSource, demux, parser, decoder, _videoSink, NULL); + // Link the pipeline in front of the tee + if(!gst_element_link_many(dataSource, demux, parser, _tee, queue, decoder, _videoSink, NULL)) { + qCritical() << "Unable to link elements."; + break; + } } else { - res = gst_element_link_many(demux, parser, decoder, _videoSink, NULL); - } - - if (!res) { - qCritical() << "VideoReceiver::start() failed. Error with gst_element_link_many()"; - break; + if(!gst_element_link_many(demux, parser, _tee, queue, decoder, _videoSink, NULL)) { + qCritical() << "Unable to link elements."; + break; + } } - dataSource = demux = parser = decoder = NULL; + dataSource = demux = parser = queue = decoder = NULL; GstBus* bus = NULL; if ((bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline))) != NULL) { - gst_bus_add_watch(bus, _onBusMessage, this); + gst_bus_enable_sync_message_emission(bus); + g_signal_connect(bus, "sync-message", G_CALLBACK(_onBusMessage), this); gst_object_unref(bus); bus = NULL; } @@ -193,62 +298,311 @@ void VideoReceiver::start() dataSource = NULL; } + if (_tee != NULL) { + gst_object_unref(_tee); + dataSource = NULL; + } + + if (queue != NULL) { + gst_object_unref(queue); + dataSource = NULL; + } + if (_pipeline != NULL) { gst_object_unref(_pipeline); _pipeline = NULL; } + + _running = false; + } else { + _running = true; + qCDebug(VideoReceiverLog) << "Running"; } + _starting = false; #endif } void VideoReceiver::stop() { #if defined(QGC_GST_STREAMING) - if (_pipeline != NULL) { - gst_element_set_state(_pipeline, GST_STATE_NULL); - gst_object_unref(_pipeline); - _pipeline = NULL; + qCDebug(VideoReceiverLog) << "stop()"; + if(!_streaming) { + _shutdownPipeline(); + } else if (_pipeline != NULL && !_stopping) { + qCDebug(VideoReceiverLog) << "Stopping _pipeline"; + gst_element_send_event(_pipeline, gst_event_new_eos()); + _stopping = true; + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline)); + GstMessage* message = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_EOS|GST_MESSAGE_ERROR)); + gst_object_unref(bus); + if(GST_MESSAGE_TYPE(message) == GST_MESSAGE_ERROR) { + _shutdownPipeline(); + qCritical() << "Error stopping pipeline!"; + } else if(GST_MESSAGE_TYPE(message) == GST_MESSAGE_EOS) { + _handleEOS(); + } + gst_message_unref(message); } #endif } void VideoReceiver::setUri(const QString & uri) { - stop(); _uri = uri; } #if defined(QGC_GST_STREAMING) -void VideoReceiver::_onBusMessage(GstMessage* msg) -{ - switch (GST_MESSAGE_TYPE(msg)) { - case GST_MESSAGE_EOS: - stop(); - break; - case GST_MESSAGE_ERROR: - do { - gchar* debug; - GError* error; - gst_message_parse_error(msg, &error, &debug); - g_free(debug); - qCritical() << error->message; - g_error_free(error); - } while(0); - stop(); - break; - default: - break; +void VideoReceiver::_shutdownPipeline() { + if(!_pipeline) { + qCDebug(VideoReceiverLog) << "No pipeline"; + return; + } + GstBus* bus = NULL; + if ((bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline))) != NULL) { + gst_bus_disable_sync_message_emission(bus); + gst_object_unref(bus); + bus = NULL; + } + gst_element_set_state(_pipeline, GST_STATE_NULL); + gst_bin_remove(GST_BIN(_pipeline), _videoSink); + gst_object_unref(_pipeline); + _pipeline = NULL; + delete _sink; + _sink = NULL; + _serverPresent = false; + _streaming = false; + _recording = false; + _stopping = false; + _running = false; + emit recordingChanged(); +} +#endif + +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_handleError() { + qCDebug(VideoReceiverLog) << "Gstreamer error!"; + _shutdownPipeline(); +} +#endif + +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_handleEOS() { + if(_stopping) { + _shutdownPipeline(); + qCDebug(VideoReceiverLog) << "Stopped"; + } else if(_recording && _sink->removing) { + _shutdownRecordingBranch(); + } else { + qCritical() << "VideoReceiver: Unexpected EOS!"; + _shutdownPipeline(); } } #endif +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_handleStateChanged() { + _streaming = GST_STATE(_pipeline) == GST_STATE_PLAYING; + qCDebug(VideoReceiverLog) << "State changed, _streaming:" << _streaming; +} +#endif + #if defined(QGC_GST_STREAMING) gboolean VideoReceiver::_onBusMessage(GstBus* bus, GstMessage* msg, gpointer data) { Q_UNUSED(bus) Q_ASSERT(msg != NULL && data != NULL); VideoReceiver* pThis = (VideoReceiver*)data; - pThis->_onBusMessage(msg); + + switch(GST_MESSAGE_TYPE(msg)) { + case(GST_MESSAGE_ERROR): { + gchar* debug; + GError* error; + gst_message_parse_error(msg, &error, &debug); + g_free(debug); + qCritical() << error->message; + g_error_free(error); + pThis->msgErrorReceived(); + } + break; + case(GST_MESSAGE_EOS): + pThis->msgEOSReceived(); + break; + case(GST_MESSAGE_STATE_CHANGED): + pThis->msgStateChangedReceived(); + break; + default: + break; + } + return TRUE; } #endif + +// When we finish our pipeline will look like this: +// +// +-->queue-->decoder-->_videosink +// | +// datasource-->demux-->parser-->tee +// | +// | +--------------_sink-------------------+ +// | | | +// we are adding these elements-> +->teepad-->queue-->matroskamux-->_filesink | +// | | +// +--------------------------------------+ +void VideoReceiver::startRecording(void) +{ +#if defined(QGC_GST_STREAMING) && defined(QGC_ENABLE_VIDEORECORDING) + + qCDebug(VideoReceiverLog) << "startRecording()"; + // exit immediately if we are already recording + if(_pipeline == NULL || _recording) { + qCDebug(VideoReceiverLog) << "Already recording!"; + return; + } + + QString savePath = qgcApp()->toolbox()->settingsManager()->videoSettings()->videoSavePath()->rawValue().toString(); + if(savePath.isEmpty()) { + qgcApp()->showMessage("Unabled to record video. Video save path must be specified in Settings."); + return; + } + + _sink = new Sink(); + _sink->teepad = gst_element_get_request_pad(_tee, "src_%u"); + _sink->queue = gst_element_factory_make("queue", NULL); + _sink->mux = gst_element_factory_make("matroskamux", NULL); + _sink->filesink = gst_element_factory_make("filesink", NULL); + _sink->removing = false; + + if(!_sink->teepad || !_sink->queue || !_sink->mux || !_sink->filesink) { + qCritical() << "VideoReceiver::startRecording() failed to make _sink elements"; + return; + } + + QString videoFile; + videoFile = savePath + "/QGC-" + QDateTime::currentDateTime().toString("yyyy-MM-dd_hh.mm.ss") + ".mkv"; + + g_object_set(G_OBJECT(_sink->filesink), "location", qPrintable(videoFile), NULL); + qCDebug(VideoReceiverLog) << "New video file:" << videoFile; + + gst_object_ref(_sink->queue); + gst_object_ref(_sink->mux); + gst_object_ref(_sink->filesink); + + gst_bin_add_many(GST_BIN(_pipeline), _sink->queue, _sink->mux, _sink->filesink, NULL); + gst_element_link_many(_sink->queue, _sink->mux, _sink->filesink, NULL); + + gst_element_sync_state_with_parent(_sink->queue); + gst_element_sync_state_with_parent(_sink->mux); + gst_element_sync_state_with_parent(_sink->filesink); + + GstPad* sinkpad = gst_element_get_static_pad(_sink->queue, "sink"); + gst_pad_link(_sink->teepad, sinkpad); + gst_object_unref(sinkpad); + + _recording = true; + emit recordingChanged(); + qCDebug(VideoReceiverLog) << "Recording started"; +#endif +} + +void VideoReceiver::stopRecording(void) +{ +#if defined(QGC_GST_STREAMING) && defined(QGC_ENABLE_VIDEORECORDING) + qCDebug(VideoReceiverLog) << "stopRecording()"; + // exit immediately if we are not recording + if(_pipeline == NULL || !_recording) { + qCDebug(VideoReceiverLog) << "Not recording!"; + return; + } + // Wait for data block before unlinking + gst_pad_add_probe(_sink->teepad, GST_PAD_PROBE_TYPE_IDLE, _unlinkCallBack, this, NULL); +#endif +} + +// This is only installed on the transient _pipelineStopRec in order +// to finalize a video file. It is not used for the main _pipeline. +// -EOS has appeared on the bus of the temporary pipeline +// -At this point all of the recoring elements have been flushed, and the video file has been finalized +// -Now we can remove the temporary pipeline and its elements +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_shutdownRecordingBranch() +{ + gst_bin_remove(GST_BIN(_pipelineStopRec), _sink->queue); + gst_bin_remove(GST_BIN(_pipelineStopRec), _sink->mux); + gst_bin_remove(GST_BIN(_pipelineStopRec), _sink->filesink); + + gst_element_set_state(_pipelineStopRec, GST_STATE_NULL); + gst_object_unref(_pipelineStopRec); + _pipelineStopRec = NULL; + + gst_element_set_state(_sink->filesink, GST_STATE_NULL); + gst_element_set_state(_sink->mux, GST_STATE_NULL); + gst_element_set_state(_sink->queue, GST_STATE_NULL); + + gst_object_unref(_sink->queue); + gst_object_unref(_sink->mux); + gst_object_unref(_sink->filesink); + + delete _sink; + _sink = NULL; + _recording = false; + + emit recordingChanged(); + qCDebug(VideoReceiverLog) << "Recording Stopped"; +} +#endif + +// -Unlink the recording branch from the tee in the main _pipeline +// -Create a second temporary pipeline, and place the recording branch elements into that pipeline +// -Setup watch and handler for EOS event on the temporary pipeline's bus +// -Send an EOS event at the beginning of that pipeline +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_detachRecordingBranch(GstPadProbeInfo* info) +{ + Q_UNUSED(info) + + // Also unlinks and unrefs + gst_bin_remove_many(GST_BIN(_pipeline), _sink->queue, _sink->mux, _sink->filesink, NULL); + + // Give tee its pad back + gst_element_release_request_pad(_tee, _sink->teepad); + gst_object_unref(_sink->teepad); + + // Create temporary pipeline + _pipelineStopRec = gst_pipeline_new("pipeStopRec"); + + // Put our elements from the recording branch into the temporary pipeline + gst_bin_add_many(GST_BIN(_pipelineStopRec), _sink->queue, _sink->mux, _sink->filesink, NULL); + gst_element_link_many(_sink->queue, _sink->mux, _sink->filesink, NULL); + + // Add handler for EOS event + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(_pipelineStopRec)); + gst_bus_enable_sync_message_emission(bus); + g_signal_connect(bus, "sync-message", G_CALLBACK(_onBusMessage), this); + gst_object_unref(bus); + + if(gst_element_set_state(_pipelineStopRec, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + qCDebug(VideoReceiverLog) << "problem starting _pipelineStopRec"; + } + + // Send EOS at the beginning of the pipeline + GstPad* sinkpad = gst_element_get_static_pad(_sink->queue, "sink"); + gst_pad_send_event(sinkpad, gst_event_new_eos()); + gst_object_unref(sinkpad); + qCDebug(VideoReceiverLog) << "Recording branch unlinked"; +} +#endif + +#if defined(QGC_GST_STREAMING) +GstPadProbeReturn VideoReceiver::_unlinkCallBack(GstPad* pad, GstPadProbeInfo* info, gpointer user_data) +{ + Q_UNUSED(pad); + Q_ASSERT(info != NULL && user_data != NULL); + VideoReceiver* pThis = (VideoReceiver*)user_data; + // We will only act once + if(g_atomic_int_compare_and_exchange(&pThis->_sink->removing, FALSE, TRUE)) + pThis->_detachRecordingBranch(info); + + return GST_PAD_PROBE_REMOVE; +} +#endif diff --git a/src/VideoStreaming/VideoReceiver.h b/src/VideoStreaming/VideoReceiver.h index 0faa58864b804c62a16a4ec256b6fa99644cc862..2c294cf2444cb10b348d885a9ad11ed9af2cf6c4 100644 --- a/src/VideoStreaming/VideoReceiver.h +++ b/src/VideoStreaming/VideoReceiver.h @@ -17,41 +17,106 @@ #ifndef VIDEORECEIVER_H #define VIDEORECEIVER_H +#include "QGCLoggingCategory.h" #include +#include +#include + #if defined(QGC_GST_STREAMING) #include #endif +Q_DECLARE_LOGGING_CATEGORY(VideoReceiverLog) + class VideoReceiver : public QObject { Q_OBJECT public: +#if defined(QGC_GST_STREAMING) + Q_PROPERTY(bool recording READ recording NOTIFY recordingChanged) +#endif + explicit VideoReceiver(QObject* parent = 0); ~VideoReceiver(); #if defined(QGC_GST_STREAMING) void setVideoSink(GstElement* sink); + + bool running() { return _running; } + bool recording() { return _recording; } + bool streaming() { return _streaming; } + bool starting() { return _starting; } + bool stopping() { return _stopping; } #endif -public Q_SLOTS: - void start (); - void stop (); - void setUri (const QString& uri); -private: +signals: +#if defined(QGC_GST_STREAMING) + void recordingChanged(); + void msgErrorReceived(); + void msgEOSReceived(); + void msgStateChangedReceived(); +#endif + +public slots: + void start (); + void stop (); + void setUri (const QString& uri); + void stopRecording (); + void startRecording (); + +private slots: +#if defined(QGC_GST_STREAMING) + void _timeout (); + void _connected (); + void _socketError (QAbstractSocket::SocketError socketError); + void _handleError(); + void _handleEOS(); + void _handleStateChanged(); +#endif + +private: #if defined(QGC_GST_STREAMING) - void _onBusMessage(GstMessage* message); - static gboolean _onBusMessage(GstBus* bus, GstMessage* msg, gpointer data); + typedef struct + { + GstPad* teepad; + GstElement* queue; + GstElement* mux; + GstElement* filesink; + gboolean removing; + } Sink; + + bool _running; + bool _recording; + bool _streaming; + bool _starting; + bool _stopping; + Sink* _sink; + GstElement* _tee; + + static gboolean _onBusMessage(GstBus* bus, GstMessage* message, gpointer user_data); + static GstPadProbeReturn _unlinkCallBack(GstPad* pad, GstPadProbeInfo* info, gpointer user_data); + void _detachRecordingBranch(GstPadProbeInfo* info); + void _shutdownRecordingBranch(); + void _shutdownPipeline(); + #endif QString _uri; #if defined(QGC_GST_STREAMING) - GstElement* _pipeline; - GstElement* _videoSink; + GstElement* _pipeline; + GstElement* _pipelineStopRec; + GstElement* _videoSink; #endif + //-- Wait for Video Server to show up before starting +#if defined(QGC_GST_STREAMING) + QTimer _timer; + QTcpSocket* _socket; + bool _serverPresent; +#endif }; #endif // VIDEORECEIVER_H diff --git a/src/VideoStreaming/VideoStreaming.cc b/src/VideoStreaming/VideoStreaming.cc index f70ddd60bdeee01e9f7347b8c3468f2d7081e509..48c0527d997d8a4e09c57f21c0f771af7d1c6b53 100644 --- a/src/VideoStreaming/VideoStreaming.cc +++ b/src/VideoStreaming/VideoStreaming.cc @@ -131,7 +131,7 @@ void initializeVideoStreaming(int &argc, char* argv[]) // Our own plugin GST_PLUGIN_STATIC_REGISTER(QGC_VIDEOSINK_PLUGIN); // The static plugins we use - #if defined(__mobile__) + #if defined(__mobile__) && !defined(__macos__) GST_PLUGIN_STATIC_REGISTER(coreelements); GST_PLUGIN_STATIC_REGISTER(libav); GST_PLUGIN_STATIC_REGISTER(rtp); diff --git a/src/VideoStreaming/VideoStreaming.pri b/src/VideoStreaming/VideoStreaming.pri index 762a608f599074314d2f94ac2fced008e6e5f395..fb1e58206b449defdd5924b935c7327d5bbff325 100644 --- a/src/VideoStreaming/VideoStreaming.pri +++ b/src/VideoStreaming/VideoStreaming.pri @@ -120,6 +120,15 @@ VideoEnabled { message("Including support for video streaming") + contains (CONFIG, DISABLE_VIDEORECORDING) { + message("Skipping support for video recording (manual override from command line)") + # Otherwise the user can still disable this feature in the user_config.pri file. + } else:exists($$BASEDIR/user_config.pri):infile($$BASEDIR/user_config.pri, DEFINES, DISABLE_VIDEORECORDING) { + message("Skipping support for video recording (manual override from user_config.pri)") + } else { + DEFINES += QGC_ENABLE_VIDEORECORDING + } + DEFINES += \ QGC_GST_STREAMING \ GST_PLUGIN_BUILD_STATIC \ diff --git a/src/VideoStreaming/gstqtvideosink/utils/glutils.h b/src/VideoStreaming/gstqtvideosink/utils/glutils.h index 002b1aa54ad0d2b8112bf961b7e778b0778138b6..f7de1882b3ca8e604ecb536e2cf9a1b4869679fc 100644 --- a/src/VideoStreaming/gstqtvideosink/utils/glutils.h +++ b/src/VideoStreaming/gstqtvideosink/utils/glutils.h @@ -17,7 +17,7 @@ #ifndef GLUTILS_H #define GLUTILS_H -#ifdef __mobile__ +#if defined(__mobile__) && !defined(__macos__) #include #define getQOpenGLFunctions() QOpenGLContext::currentContext()->functions() #define QOpenGLFunctionsDef QOpenGLFunctions diff --git a/src/ViewWidgets/CustomCommandWidgetController.cc b/src/ViewWidgets/CustomCommandWidgetController.cc index cfefb1ae9a4561271c6a82d80c8ab40667ce7708..b8791a5dc8f1f1bde6ab80518e7f3067826dc3f8 100644 --- a/src/ViewWidgets/CustomCommandWidgetController.cc +++ b/src/ViewWidgets/CustomCommandWidgetController.cc @@ -21,10 +21,10 @@ const char* CustomCommandWidgetController::_settingsKey = "CustomCommand.QmlFile"; CustomCommandWidgetController::CustomCommandWidgetController(void) : - _uas(NULL) + _vehicle(NULL) { if(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()) { - _uas = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()->uas(); + _vehicle = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle(); } QSettings settings; _customQmlFile = settings.value(_settingsKey).toString(); @@ -33,15 +33,21 @@ CustomCommandWidgetController::CustomCommandWidgetController(void) : void CustomCommandWidgetController::sendCommand(int commandId, QVariant componentId, QVariant confirm, QVariant param1, QVariant param2, QVariant param3, QVariant param4, QVariant param5, QVariant param6, QVariant param7) { - if(_uas) { - _uas->executeCommand((MAV_CMD)commandId, confirm.toInt(), param1.toFloat(), param2.toFloat(), param3.toFloat(), param4.toFloat(), param5.toFloat(), param6.toFloat(), param7.toFloat(), componentId.toInt()); + Q_UNUSED(confirm); + + if(_vehicle) { + _vehicle->sendMavCommand(componentId.toInt(), + (MAV_CMD)commandId, + true, // show error if fails + param1.toFloat(), param2.toFloat(), param3.toFloat(), param4.toFloat(), param5.toFloat(), param6.toFloat(), param7.toFloat()); } } void CustomCommandWidgetController::_activeVehicleChanged(Vehicle* activeVehicle) { - if(activeVehicle) - _uas = activeVehicle->uas(); + if (activeVehicle) { + _vehicle = activeVehicle; + } } void CustomCommandWidgetController::selectQmlFile(void) diff --git a/src/ViewWidgets/CustomCommandWidgetController.h b/src/ViewWidgets/CustomCommandWidgetController.h index 81f018e80395e1b5a5a9e8c588eb75c607e8eb31..514e7a69225c2290d06b250c82d11839a9c7813b 100644 --- a/src/ViewWidgets/CustomCommandWidgetController.h +++ b/src/ViewWidgets/CustomCommandWidgetController.h @@ -13,7 +13,6 @@ #include -#include "UASInterface.h" #include "AutoPilotPlugin.h" #include "FactPanelController.h" @@ -37,7 +36,7 @@ private slots: void _activeVehicleChanged (Vehicle* activeVehicle); private: - UASInterface* _uas; + Vehicle* _vehicle; QString _customQmlFile; static const char* _settingsKey; }; diff --git a/src/api/QGCCorePlugin.cc b/src/api/QGCCorePlugin.cc new file mode 100644 index 0000000000000000000000000000000000000000..3d7ff10987e9f15c999900734be5f8fa4329515f --- /dev/null +++ b/src/api/QGCCorePlugin.cc @@ -0,0 +1,180 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "QGCCorePlugin.h" +#include "QGCOptions.h" +#include "QGCSettings.h" +#include "FactMetaData.h" +#include "SettingsManager.h" + +#include +#include + +/// @file +/// @brief Core Plugin Interface for QGroundControl - Default Implementation +/// @author Gus Grubba + +class QGCCorePlugin_p +{ +public: + QGCCorePlugin_p() + : pGeneral(NULL) + , pCommLinks(NULL) + , pOfflineMaps(NULL) + , pMAVLink(NULL) + , pConsole(NULL) +#if defined(QT_DEBUG) + , pMockLink(NULL) + , pDebug(NULL) +#endif + , defaultOptions(NULL) + { + } + ~QGCCorePlugin_p() + { + if(pGeneral) + delete pGeneral; + if(pCommLinks) + delete pCommLinks; + if(pOfflineMaps) + delete pOfflineMaps; + if(pMAVLink) + delete pMAVLink; + if(pConsole) + delete pConsole; +#if defined(QT_DEBUG) + if(pMockLink) + delete pMockLink; + if(pDebug) + delete pDebug; +#endif + if(defaultOptions) + delete defaultOptions; + } + QGCSettings* pGeneral; + QGCSettings* pCommLinks; + QGCSettings* pOfflineMaps; + QGCSettings* pMAVLink; + QGCSettings* pConsole; +#if defined(QT_DEBUG) + QGCSettings* pMockLink; + QGCSettings* pDebug; +#endif + QVariantList settingsList; + QVariantList toolBarIndicatorList; + QGCOptions* defaultOptions; +}; + +QGCCorePlugin::~QGCCorePlugin() +{ + if(_p) { + delete _p; + } +} + +QGCCorePlugin::QGCCorePlugin(QGCApplication *app) + : QGCTool(app) +{ + _p = new QGCCorePlugin_p; +} + +void QGCCorePlugin::setToolbox(QGCToolbox *toolbox) +{ + QGCTool::setToolbox(toolbox); + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + qmlRegisterUncreatableType("QGroundControl.QGCCorePlugin", 1, 0, "QGCCorePlugin", "Reference only"); + qmlRegisterUncreatableType("QGroundControl.QGCOptions", 1, 0, "QGCOptions", "Reference only"); +} + +QVariantList &QGCCorePlugin::settings() +{ + //-- If this hasn't been overridden, create default set of settings + if(!_p->pGeneral) { + //-- Default Settings + _p->pGeneral = new QGCSettings(tr("General"), + QUrl::fromUserInput("qrc:/qml/GeneralSettings.qml"), + QUrl::fromUserInput("qrc:/res/gear-white.svg")); + _p->settingsList.append(QVariant::fromValue((QGCSettings*)_p->pGeneral)); + _p->pCommLinks = new QGCSettings(tr("Comm Links"), + QUrl::fromUserInput("qrc:/qml/LinkSettings.qml"), + QUrl::fromUserInput("qrc:/res/waves.svg")); + _p->settingsList.append(QVariant::fromValue((QGCSettings*)_p->pCommLinks)); + _p->pOfflineMaps = new QGCSettings(tr("Offline Maps"), + QUrl::fromUserInput("qrc:/qml/OfflineMap.qml"), + QUrl::fromUserInput("qrc:/res/waves.svg")); + _p->settingsList.append(QVariant::fromValue((QGCSettings*)_p->pOfflineMaps)); + _p->pMAVLink = new QGCSettings(tr("MAVLink"), + QUrl::fromUserInput("qrc:/qml/MavlinkSettings.qml"), + QUrl::fromUserInput("qrc:/res/waves.svg")); + _p->settingsList.append(QVariant::fromValue((QGCSettings*)_p->pMAVLink)); + _p->pConsole = new QGCSettings(tr("Console"), + QUrl::fromUserInput("qrc:/qml/QGroundControl/Controls/AppMessages.qml")); + _p->settingsList.append(QVariant::fromValue((QGCSettings*)_p->pConsole)); + #if defined(QT_DEBUG) + //-- These are always present on Debug builds + _p->pMockLink = new QGCSettings(tr("Mock Link"), + QUrl::fromUserInput("qrc:/qml/MockLink.qml")); + _p->settingsList.append(QVariant::fromValue((QGCSettings*)_p->pMockLink)); + _p->pDebug = new QGCSettings(tr("Debug"), + QUrl::fromUserInput("qrc:/qml/DebugWindow.qml")); + _p->settingsList.append(QVariant::fromValue((QGCSettings*)_p->pDebug)); + #endif + } + return _p->settingsList; +} + +int QGCCorePlugin::defaultSettings() +{ + return 0; +} + +QGCOptions* QGCCorePlugin::options() +{ + if(!_p->defaultOptions) { + _p->defaultOptions = new QGCOptions(); + } + return _p->defaultOptions; +} + +QVariantList& QGCCorePlugin::toolBarIndicators() +{ + if(_p->toolBarIndicatorList.size() == 0) { + _p->toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/MessageIndicator.qml"))); + _p->toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/GPSIndicator.qml"))); + _p->toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/TelemetryRSSIIndicator.qml"))); + _p->toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/RCRSSIIndicator.qml"))); + _p->toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/BatteryIndicator.qml"))); + _p->toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/ModeIndicator.qml"))); + } + return _p->toolBarIndicatorList; +} + +bool QGCCorePlugin::overrideSettingsGroupVisibility(QString name) +{ + Q_UNUSED(name); + + // Always show all + return true; +} + +bool QGCCorePlugin::adjustSettingMetaData(FactMetaData& metaData) +{ + if (metaData.name() == AppSettings::indoorPaletteName) { + // Set up correct default for palette setting + QVariant outdoorPalette; +#if defined (__mobile__) + outdoorPalette = 0; +#else + outdoorPalette = 1; +#endif + metaData.setRawDefaultValue(outdoorPalette); + } + + return true; // Show setting in ui +} diff --git a/src/api/QGCCorePlugin.h b/src/api/QGCCorePlugin.h new file mode 100644 index 0000000000000000000000000000000000000000..e9f1a0a9f3cd82e2c8fedcd9a5b36616c4c5c18e --- /dev/null +++ b/src/api/QGCCorePlugin.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#pragma once + +#include "QGCToolbox.h" + +#include +#include + +/// @file +/// @brief Core Plugin Interface for QGroundControl +/// @author Gus Grubba + +// Work In Progress + +class QGCApplication; +class QGCOptions; +class QGCSettings; +class QGCCorePlugin_p; +class FactMetaData; + +class QGCCorePlugin : public QGCTool +{ + Q_OBJECT +public: + QGCCorePlugin(QGCApplication* app); + ~QGCCorePlugin(); + + Q_PROPERTY(QVariantList settings READ settings CONSTANT) + Q_PROPERTY(int defaultSettings READ defaultSettings CONSTANT) + Q_PROPERTY(QGCOptions* options READ options CONSTANT) + Q_PROPERTY(QVariantList toolBarIndicators READ toolBarIndicators CONSTANT) + + /// The list of settings under the Settings Menu + /// @return A list of QGCSettings + virtual QVariantList& settings (); + + /// Allows the core plugin to override the toolbar indicators + /// @return A list of QUrl with the indicators (see MainToolBarIndicators.qml) + virtual QVariantList& toolBarIndicators (); + + /// The default settings panel to show + /// @return The settings index + virtual int defaultSettings (); + + /// Global options + /// @return An instance of QGCOptions + virtual QGCOptions* options (); + + /// Allows the core plugin to override the visibility for a settings group + /// @param name - Setting group name + /// @return true: Show settings ui, false: Hide settings ui + virtual bool overrideSettingsGroupVisibility (QString name); + + /// Allows the core plugin to override the setting meta data before the setting fact is created. + /// @param metaData - MetaData for setting fact + /// @return true: Setting should be visible in ui, false: Setting should not be shown in ui + virtual bool adjustSettingMetaData (FactMetaData& metaData); + + // Override from QGCTool + void setToolbox (QGCToolbox *toolbox); +private: + QGCCorePlugin_p* _p; +}; diff --git a/src/api/QGCOptions.cc b/src/api/QGCOptions.cc new file mode 100644 index 0000000000000000000000000000000000000000..0955cec12d1e46520cf663d8d759ebd24ef45479 --- /dev/null +++ b/src/api/QGCOptions.cc @@ -0,0 +1,38 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "QGCOptions.h" +#include + +/// @file +/// @brief Core Plugin Interface for QGroundControl - Application Options +/// @author Gus Grubba + +QGCOptions::QGCOptions(QObject* parent) + : QObject(parent) + , _defaultInstrumentWidget(NULL) +{ + qmlRegisterUncreatableType("QGroundControl", 1, 0, "CustomInstrumentWidget", "Reference only"); +} + +CustomInstrumentWidget* +QGCOptions::instrumentWidget() +{ + if(!_defaultInstrumentWidget) { + _defaultInstrumentWidget = new CustomInstrumentWidget(this); + } + return _defaultInstrumentWidget; +} + +CustomInstrumentWidget::CustomInstrumentWidget(QObject* parent) + : QObject(parent) +{ +} + + diff --git a/src/api/QGCOptions.h b/src/api/QGCOptions.h new file mode 100644 index 0000000000000000000000000000000000000000..cfccc4dbc256fbd0648f751c14dd819f676624ea --- /dev/null +++ b/src/api/QGCOptions.h @@ -0,0 +1,72 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#pragma once + +#include +#include +#include + +/// @file +/// @brief Core Plugin Interface for QGroundControl - Application Options +/// @author Gus Grubba + +class CustomInstrumentWidget; +class QGCOptions : public QObject +{ + Q_OBJECT +public: + QGCOptions(QObject* parent = NULL); + + Q_PROPERTY(bool combineSettingsAndSetup READ combineSettingsAndSetup CONSTANT) + Q_PROPERTY(double toolbarHeightMultiplier READ toolbarHeightMultiplier CONSTANT) + Q_PROPERTY(bool enablePlanViewSelector READ enablePlanViewSelector CONSTANT) + Q_PROPERTY(CustomInstrumentWidget* instrumentWidget READ instrumentWidget CONSTANT) + + + /// Should QGC hide its settings menu and colapse it into one single menu (Settings and Vehicle Setup)? + /// @return true if QGC should consolidate both menus into one. + virtual bool combineSettingsAndSetup () { return false; } + + /// Main ToolBar Multiplier. + /// @return Factor to use when computing toolbar height + virtual double toolbarHeightMultiplier () { return 1.0; } + + /// Enable Plan View Selector (Mission, Fence or Rally) + /// @return True or false + virtual bool enablePlanViewSelector () { return true; } + + /// Provides an alternate instrument widget for the Fly View + /// @return An alternate widget (see QGCInstrumentWidget.qml, the default widget) + virtual CustomInstrumentWidget* instrumentWidget(); + +private: + CustomInstrumentWidget* _defaultInstrumentWidget; +}; + +//----------------------------------------------------------------------------- +class CustomInstrumentWidget : public QObject +{ + Q_OBJECT +public: + //-- Widget Position + enum Pos { + POS_TOP_RIGHT = 0, + POS_CENTER_RIGHT = 1, + POS_BOTTOM_RIGHT = 2, + }; + Q_ENUMS(Pos) + CustomInstrumentWidget(QObject* parent = NULL); + Q_PROPERTY(QUrl source READ source CONSTANT) + Q_PROPERTY(Pos widgetPosition READ widgetPosition NOTIFY widgetPositionChanged) + virtual QUrl source () { return QUrl(); } + virtual Pos widgetPosition () { return POS_CENTER_RIGHT; } +signals: + void widgetPositionChanged (); +}; diff --git a/src/api/QGCSettings.cc b/src/api/QGCSettings.cc new file mode 100644 index 0000000000000000000000000000000000000000..6fbe9dbe336b6bda84e2913a817ff6356382ba0c --- /dev/null +++ b/src/api/QGCSettings.cc @@ -0,0 +1,21 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "QGCSettings.h" + +/// @file +/// @brief Core Plugin Interface for QGroundControl. Settings element. +/// @author Gus Grubba + +QGCSettings::QGCSettings(QString title, QUrl url, QUrl icon) + : _title(title) + , _url(url) + , _icon(icon) +{ +} diff --git a/src/api/QGCSettings.h b/src/api/QGCSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..682364cb20b796167f8a787e341001c26ebd6991 --- /dev/null +++ b/src/api/QGCSettings.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#pragma once + +#include +#include + +/// @file +/// @brief Core Plugin Interface for QGroundControl. Settings element. +/// @author Gus Grubba + +class QGCSettings : public QObject +{ + Q_OBJECT +public: + QGCSettings(QString title, QUrl url, QUrl icon = QUrl()); + + Q_PROPERTY(QString title READ title CONSTANT) + Q_PROPERTY(QUrl url READ url CONSTANT) + Q_PROPERTY(QUrl icon READ icon CONSTANT) + + virtual QString title () { return _title; } + virtual QUrl url () { return _url; } + virtual QUrl icon () { return _icon; } + +protected: + QString _title; + QUrl _url; + QUrl _icon; +}; diff --git a/src/audio/QGCAudioWorker.cpp b/src/audio/QGCAudioWorker.cpp index 5e79774f6e2b6d8117ee7b4c5485e9338495f10e..8a19f0db537dbf599034b91e2117cca45983b070 100644 --- a/src/audio/QGCAudioWorker.cpp +++ b/src/audio/QGCAudioWorker.cpp @@ -10,47 +10,27 @@ #if (defined __macos__) && defined QGC_SPEECH_ENABLED #include +#include -static SpeechChannel sc; -static Fixed volume; +void macSpeak(const char* words) +{ + static SpeechChannel sc = NULL; -static void speechDone(SpeechChannel sc2, void *) { - if (sc2 == sc) - { - DisposeSpeechChannel(sc); + while (SpeechBusy()) { + QGC::SLEEP::msleep(100); } -} + if (sc == NULL) { + Float32 volume = 1.0; -class MacSpeech -{ -public: - MacSpeech() - { - setVolume(100); - } - ~MacSpeech() - { - } - void say(const char* words) - { - while (SpeechBusy()) { - QGC::SLEEP::msleep(100); - } NewSpeechChannel(NULL, &sc); - SetSpeechInfo(sc, soVolume, &volume); - SetSpeechInfo(sc, soSpeechDoneCallBack, reinterpret_cast(speechDone)); - CFStringRef cfstr = CFStringCreateWithCString(NULL, words, kCFStringEncodingUTF8); - SpeakCFString(sc, cfstr, NULL); - } - void setVolume(int v) - { - volume = FixRatio(v, 100); + CFNumberRef volumeRef = CFNumberCreate(NULL, kCFNumberFloat32Type, &volume); + SetSpeechProperty(sc, kSpeechVolumeProperty, volumeRef); + CFRelease(volumeRef); } -}; - -//-- Singleton -MacSpeech macSpeech; - + CFStringRef strRef = CFStringCreateWithCString(NULL, words, kCFStringEncodingUTF8); + SpeakCFString(sc, strRef, NULL); + CFRelease(strRef); +} #endif #if (defined __ios__) && defined QGC_SPEECH_ENABLED @@ -154,7 +134,7 @@ void QGCAudioWorker::say(QString inText) espeak_Synth(text.toStdString().c_str(), espeak_size, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL); espeak_Synchronize(); #elif (defined __macos__) && defined QGC_SPEECH_ENABLED - macSpeech.say(text.toStdString().c_str()); + macSpeak(text.toStdString().c_str()); #elif (defined __ios__) && defined QGC_SPEECH_ENABLED iOSSpeak(text); #else @@ -172,7 +152,7 @@ void QGCAudioWorker::mute(bool mute) this->muted = mute; QSettings settings; settings.setValue(QGC_GAUDIOOUTPUT_KEY + "muted", this->muted); -// emit mutedChanged(muted); + // emit mutedChanged(muted); } } diff --git a/src/comm/APMArduSubMockLink.params b/src/comm/APMArduSubMockLink.params old mode 100755 new mode 100644 index 8c935cf03932024b3c8fce91b6b173a93edae8b1..6866b517e7272de365d76ca41fa75b75650aa007 --- a/src/comm/APMArduSubMockLink.params +++ b/src/comm/APMArduSubMockLink.params @@ -1,605 +1,620 @@ -# Onboard parameters for vehicle 128 +# Onboard parameters for vehicle 1 # # MAV ID COMPONENT ID PARAM NAME VALUE (FLOAT) -128 1 ACCEL_Z_D 0.000000000000000000 9 -128 1 ACCEL_Z_FILT 20.000000000000000000 9 -128 1 ACCEL_Z_I 1.000000000000000000 9 -128 1 ACCEL_Z_IMAX 800.000000000000000000 9 -128 1 ACCEL_Z_P 0.500000000000000000 9 -128 1 ACRO_BAL_PITCH 1.000000000000000000 9 -128 1 ACRO_BAL_ROLL 1.000000000000000000 9 -128 1 ACRO_EXPO 0.300000011920928955 9 -128 1 ACRO_RP_P 4.500000000000000000 9 -128 1 ACRO_TRAINER 2 2 -128 1 ACRO_YAW_P 4.500000000000000000 9 -128 1 AHRS_COMP_BETA 0.100000001490116119 9 -128 1 AHRS_EKF_TYPE 2 2 -128 1 AHRS_GPS_GAIN 1.000000000000000000 9 -128 1 AHRS_GPS_MINSATS 6 2 -128 1 AHRS_GPS_USE 1 2 -128 1 AHRS_ORIENTATION 16 2 -128 1 AHRS_RP_P 0.200000002980232239 9 -128 1 AHRS_TRIM_X -0.017862198874354362 9 -128 1 AHRS_TRIM_Y -0.001083165174350142 9 -128 1 AHRS_TRIM_Z 0.000000000000000000 9 -128 1 AHRS_WIND_MAX 0 2 -128 1 AHRS_YAW_P 0.200000002980232239 9 -128 1 ANGLE_MAX 4500 4 -128 1 ARMING_CHECK 0 2 -128 1 ATC_ACCEL_P_MAX 110000.000000000000000000 9 -128 1 ATC_ACCEL_R_MAX 110000.000000000000000000 9 -128 1 ATC_ACCEL_Y_MAX 0.000000000000000000 9 -128 1 ATC_ANGLE_BOOST 1 2 -128 1 ATC_ANG_LIM_TC 1.000000000000000000 9 -128 1 ATC_ANG_PIT_P 6.000000000000000000 9 -128 1 ATC_ANG_RLL_P 6.000000000000000000 9 -128 1 ATC_ANG_YAW_P 6.000000000000000000 9 -128 1 ATC_RATE_FF_ENAB 1 2 -128 1 ATC_RAT_PIT_D 0.003599999938160181 9 -128 1 ATC_RAT_PIT_FILT 20.000000000000000000 9 -128 1 ATC_RAT_PIT_I 0.090000003576278687 9 -128 1 ATC_RAT_PIT_IMAX 0.444000005722045898 9 -128 1 ATC_RAT_PIT_P 0.135000005364418030 9 -128 1 ATC_RAT_RLL_D 0.000000000000000000 9 -128 1 ATC_RAT_RLL_FILT 20.000000000000000000 9 -128 1 ATC_RAT_RLL_I 0.000000000000000000 9 -128 1 ATC_RAT_RLL_IMAX 0.444000005722045898 9 -128 1 ATC_RAT_RLL_P 0.000000000000000000 9 -128 1 ATC_RAT_YAW_D 0.000000000000000000 9 -128 1 ATC_RAT_YAW_FILT 30.000000000000000000 9 -128 1 ATC_RAT_YAW_I 0.019999999552965164 9 -128 1 ATC_RAT_YAW_IMAX 0.222000002861022949 9 -128 1 ATC_RAT_YAW_P 0.180000007152557373 9 -128 1 ATC_SLEW_YAW 6000.000000000000000000 9 -128 1 ATC_THR_MIX_MAX 0.500000000000000000 9 -128 1 ATC_THR_MIX_MIN 0.100000001490116119 9 -128 1 AUTOTUNE_AGGR 0.100000001490116119 9 -128 1 AUTOTUNE_AXES 7 2 -128 1 AUTOTUNE_MIN_D 0.001000000047497451 9 -128 1 AVOID_ENABLE 1 2 -128 1 BATT2_AMP_OFFSET 0.000000000000000000 9 -128 1 BATT2_AMP_PERVOL 17.000000000000000000 9 -128 1 BATT2_CAPACITY 3300 6 -128 1 BATT2_CURR_PIN 3 2 -128 1 BATT2_MONITOR 0 2 -128 1 BATT2_VOLT_MULT 10.100000381469726562 9 -128 1 BATT2_VOLT_PIN 2 2 -128 1 BATT_AMP_OFFSET 0.000000000000000000 9 -128 1 BATT_AMP_PERVOLT 17.000000000000000000 9 -128 1 BATT_CAPACITY 18000 6 -128 1 BATT_CURR_PIN 3 2 -128 1 BATT_MONITOR 4 2 -128 1 BATT_VOLT_MULT 10.100000381469726562 9 -128 1 BATT_VOLT_PIN 2 2 -128 1 BRD_CAN_ENABLE 0 2 -128 1 BRD_IMU_TARGTEMP 0 2 -128 1 BRD_PWM_COUNT 4 2 -128 1 BRD_SAFETYENABLE 0 2 -128 1 BRD_SAFETY_MASK 0 6 -128 1 BRD_SBUS_OUT 0 2 -128 1 BRD_SER1_RTSCTS 2 2 -128 1 BRD_SER2_RTSCTS 2 2 -128 1 BRD_SERIAL_NUM 0 4 -128 1 BTN0_FUNCTION 0 2 -128 1 BTN0_SFUNCTION 0 2 -128 1 BTN10_FUNCTION 48 2 -128 1 BTN10_SFUNCTION 0 2 -128 1 BTN11_FUNCTION 42 2 -128 1 BTN11_SFUNCTION 0 2 -128 1 BTN12_FUNCTION 43 2 -128 1 BTN12_SFUNCTION 0 2 -128 1 BTN13_FUNCTION 33 2 -128 1 BTN13_SFUNCTION 45 2 -128 1 BTN14_FUNCTION 32 2 -128 1 BTN14_SFUNCTION 44 2 -128 1 BTN15_FUNCTION 0 2 -128 1 BTN15_SFUNCTION 0 2 -128 1 BTN1_FUNCTION 6 2 -128 1 BTN1_SFUNCTION 0 2 -128 1 BTN2_FUNCTION 8 2 -128 1 BTN2_SFUNCTION 0 2 -128 1 BTN3_FUNCTION 7 2 -128 1 BTN3_SFUNCTION 0 2 -128 1 BTN4_FUNCTION 22 2 -128 1 BTN4_SFUNCTION 0 2 -128 1 BTN5_FUNCTION 23 2 -128 1 BTN5_SFUNCTION 0 2 -128 1 BTN6_FUNCTION 4 2 -128 1 BTN6_SFUNCTION 0 2 -128 1 BTN7_FUNCTION 3 2 -128 1 BTN7_SFUNCTION 0 2 -128 1 BTN8_FUNCTION 1 2 -128 1 BTN8_SFUNCTION 0 2 -128 1 BTN9_FUNCTION 21 2 -128 1 BTN9_SFUNCTION 0 2 -128 1 CAM_DURATION 10 2 -128 1 CAM_FEEDBACK_PIN 0 2 -128 1 CAM_FEEDBACK_POL 1 2 -128 1 CAM_MAX_ROLL 0 4 -128 1 CAM_MIN_INTERVAL 0 4 -128 1 CAM_RELAY_ON 1 2 -128 1 CAM_SERVO_OFF 1100 4 -128 1 CAM_SERVO_ON 1300 4 -128 1 CAM_TRIGG_DIST 0.000000000000000000 9 -128 1 CAM_TRIGG_TYPE 0 2 -128 1 CH10_OPT 0 2 -128 1 CH11_OPT 0 2 -128 1 CH12_OPT 0 2 -128 1 CH7_OPT 0 2 -128 1 CH8_OPT 0 2 -128 1 CH9_OPT 0 2 -128 1 CIRCLE_RADIUS 1000.000000000000000000 9 -128 1 CIRCLE_RATE 20.000000000000000000 9 -128 1 CLI_ENABLED 0 2 -128 1 COMPASS_AUTODEC 1 2 -128 1 COMPASS_CAL_FIT 8.000000000000000000 9 -128 1 COMPASS_DEC 0.000000000000000000 9 -128 1 COMPASS_DEV_ID 131594 6 -128 1 COMPASS_DEV_ID2 0 6 -128 1 COMPASS_DEV_ID3 0 6 -128 1 COMPASS_DIA2_X 0.000000000000000000 9 -128 1 COMPASS_DIA2_Y 0.000000000000000000 9 -128 1 COMPASS_DIA2_Z 0.000000000000000000 9 -128 1 COMPASS_DIA3_X 0.000000000000000000 9 -128 1 COMPASS_DIA3_Y 0.000000000000000000 9 -128 1 COMPASS_DIA3_Z 0.000000000000000000 9 -128 1 COMPASS_DIA_X 1.000000000000000000 9 -128 1 COMPASS_DIA_Y 1.000000000000000000 9 -128 1 COMPASS_DIA_Z 1.000000000000000000 9 -128 1 COMPASS_EXTERN2 0 2 -128 1 COMPASS_EXTERN3 0 2 -128 1 COMPASS_EXTERNAL 0 2 -128 1 COMPASS_LEARN 1 2 -128 1 COMPASS_MOT2_X 0.000000000000000000 9 -128 1 COMPASS_MOT2_Y 0.000000000000000000 9 -128 1 COMPASS_MOT2_Z 0.000000000000000000 9 -128 1 COMPASS_MOT3_X 0.000000000000000000 9 -128 1 COMPASS_MOT3_Y 0.000000000000000000 9 -128 1 COMPASS_MOT3_Z 0.000000000000000000 9 -128 1 COMPASS_MOTCT 0 2 -128 1 COMPASS_MOT_X 0.000000000000000000 9 -128 1 COMPASS_MOT_Y 0.000000000000000000 9 -128 1 COMPASS_MOT_Z 0.000000000000000000 9 -128 1 COMPASS_ODI2_X 0.000000000000000000 9 -128 1 COMPASS_ODI2_Y 0.000000000000000000 9 -128 1 COMPASS_ODI2_Z 0.000000000000000000 9 -128 1 COMPASS_ODI3_X 0.000000000000000000 9 -128 1 COMPASS_ODI3_Y 0.000000000000000000 9 -128 1 COMPASS_ODI3_Z 0.000000000000000000 9 -128 1 COMPASS_ODI_X 0.000000000000000000 9 -128 1 COMPASS_ODI_Y 0.000000000000000000 9 -128 1 COMPASS_ODI_Z 0.000000000000000000 9 -128 1 COMPASS_OFS2_X 0.000000000000000000 9 -128 1 COMPASS_OFS2_Y 0.000000000000000000 9 -128 1 COMPASS_OFS2_Z 0.000000000000000000 9 -128 1 COMPASS_OFS3_X 0.000000000000000000 9 -128 1 COMPASS_OFS3_Y 0.000000000000000000 9 -128 1 COMPASS_OFS3_Z 0.000000000000000000 9 -128 1 COMPASS_OFS_X -68.000000000000000000 9 -128 1 COMPASS_OFS_Y 166.000000000000000000 9 -128 1 COMPASS_OFS_Z -435.000000000000000000 9 -128 1 COMPASS_ORIENT 0 2 -128 1 COMPASS_ORIENT2 0 2 -128 1 COMPASS_ORIENT3 0 2 -128 1 COMPASS_PRIMARY 0 2 -128 1 COMPASS_USE 1 2 -128 1 COMPASS_USE2 1 2 -128 1 COMPASS_USE3 1 2 -128 1 DISARM_DELAY 0 2 -128 1 EK2_ABIAS_P_NSE 0.004999999888241291 9 -128 1 EK2_ACC_P_NSE 0.600000023841857910 9 -128 1 EK2_ALT_M_NSE 0.100000001490116119 9 -128 1 EK2_ALT_SOURCE 0 2 -128 1 EK2_CHECK_SCALE 100 4 -128 1 EK2_EAS_I_GATE 400 4 -128 1 EK2_EAS_M_NSE 1.399999976158142090 9 -128 1 EK2_ENABLE 1 2 -128 1 EK2_FLOW_DELAY 10 2 -128 1 EK2_FLOW_I_GATE 300 4 -128 1 EK2_FLOW_M_NSE 0.250000000000000000 9 -128 1 EK2_GBIAS_P_NSE 0.000099999997473788 9 -128 1 EK2_GLITCH_RAD 25 2 -128 1 EK2_GPS_CHECK 31 2 -128 1 EK2_GPS_DELAY 220 4 -128 1 EK2_GPS_TYPE 0 2 -128 1 EK2_GSCL_P_NSE 0.000500000023748726 9 -128 1 EK2_GYRO_P_NSE 0.029999999329447746 9 -128 1 EK2_HGT_DELAY 60 4 -128 1 EK2_HGT_I_GATE 500 4 -128 1 EK2_IMU_MASK 3 2 -128 1 EK2_LOG_MASK 1 2 -128 1 EK2_MAGB_P_NSE 0.000099999997473788 9 -128 1 EK2_MAGE_P_NSE 0.001000000047497451 9 -128 1 EK2_MAG_CAL 3 2 -128 1 EK2_MAG_I_GATE 300 4 -128 1 EK2_MAG_M_NSE 0.050000000745058060 9 -128 1 EK2_MAX_FLOW 2.500000000000000000 9 -128 1 EK2_NOAID_M_NSE 10.000000000000000000 9 -128 1 EK2_POSNE_M_NSE 1.000000000000000000 9 -128 1 EK2_POS_I_GATE 500 4 -128 1 EK2_RNG_I_GATE 500 4 -128 1 EK2_RNG_M_NSE 0.500000000000000000 9 -128 1 EK2_TAU_OUTPUT 25 2 -128 1 EK2_VELD_M_NSE 0.699999988079071045 9 -128 1 EK2_VELNE_M_NSE 0.500000000000000000 9 -128 1 EK2_VEL_I_GATE 500 4 -128 1 EK2_WIND_PSCALE 0.500000000000000000 9 -128 1 EK2_WIND_P_NSE 0.100000001490116119 9 -128 1 EK2_YAW_I_GATE 300 4 -128 1 EK2_YAW_M_NSE 0.500000000000000000 9 -128 1 EKF_ENABLE 0 2 -128 1 EPM_ENABLE 0 2 -128 1 EPM_GRAB 1900 4 -128 1 EPM_NEUTRAL 1500 4 -128 1 EPM_REGRAB 0 2 -128 1 EPM_RELEASE 1100 4 -128 1 ESC_CALIBRATION 0 2 -128 1 FENCE_ACTION 1 2 -128 1 FENCE_ALT_MAX 100.000000000000000000 9 -128 1 FENCE_DEPTH_MAX -10.000000000000000000 9 -128 1 FENCE_ENABLE 0 2 -128 1 FENCE_MARGIN 2.000000000000000000 9 -128 1 FENCE_RADIUS 300.000000000000000000 9 -128 1 FENCE_TOTAL 0 2 -128 1 FENCE_TYPE 7 2 -128 1 FLOW_ENABLE 0 2 -128 1 FLOW_FXSCALER 0 4 -128 1 FLOW_FYSCALER 0 4 -128 1 FLOW_ORIENT_YAW 0 4 -128 1 FLTMODE1 19 2 -128 1 FLTMODE2 0 2 -128 1 FLTMODE3 2 2 -128 1 FLTMODE4 0 2 -128 1 FLTMODE5 0 2 -128 1 FLTMODE6 0 2 -128 1 FRAME 1 2 -128 1 FS_BATT_ENABLE 0 2 -128 1 FS_BATT_MAH 0.000000000000000000 9 -128 1 FS_BATT_VOLTAGE 10.500000000000000000 9 -128 1 FS_CRASH_CHECK 0 2 -128 1 FS_EKF_ACTION 1 2 -128 1 FS_EKF_THRESH 0.800000011920928955 9 -128 1 FS_GCS_ENABLE 1 2 -128 1 FS_THR_ENABLE 0 2 -128 1 FS_THR_VALUE 975 4 -128 1 GCS_PID_MASK 0 4 -128 1 GND_ABS_PRESS 100721.140625000000000000 9 -128 1 GND_ALT_OFFSET 0.000000000000000000 9 -128 1 GND_BASE_PRESS 98975.476562500000000000 9 -128 1 GND_BASE_RESET 0 2 -128 1 GND_PRIMARY 1 2 -128 1 GND_SPEC_GRAV 1.000000000000000000 9 -128 1 GND_TEMP 26.966283798217773438 9 -128 1 GPS_AUTO_CONFIG 1 2 -128 1 GPS_AUTO_SWITCH 1 2 -128 1 GPS_GNSS_MODE 0 2 -128 1 GPS_GNSS_MODE2 0 2 -128 1 GPS_HDOP_GOOD 140 4 -128 1 GPS_INJECT_TO 127 2 -128 1 GPS_MIN_DGPS 100 2 -128 1 GPS_MIN_ELEV 0 2 -128 1 GPS_NAVFILTER 8 2 -128 1 GPS_RAW_DATA 0 2 -128 1 GPS_SAVE_CFG 0 2 -128 1 GPS_SBAS_MODE 2 2 -128 1 GPS_SBP_LOGMASK -256 4 -128 1 GPS_TYPE 1 2 -128 1 GPS_TYPE2 0 2 -128 1 INS_ACC2OFFS_X 0.663968503475189209 9 -128 1 INS_ACC2OFFS_Y 0.732862293720245361 9 -128 1 INS_ACC2OFFS_Z 0.392130941152572632 9 -128 1 INS_ACC2SCAL_X 1.044255375862121582 9 -128 1 INS_ACC2SCAL_Y 1.021702170372009277 9 -128 1 INS_ACC2SCAL_Z 1.012331962585449219 9 -128 1 INS_ACC3OFFS_X 0.000000000000000000 9 -128 1 INS_ACC3OFFS_Y 0.000000000000000000 9 -128 1 INS_ACC3OFFS_Z 0.000000000000000000 9 -128 1 INS_ACC3SCAL_X 0.000000000000000000 9 -128 1 INS_ACC3SCAL_Y 0.000000000000000000 9 -128 1 INS_ACC3SCAL_Z 0.000000000000000000 9 -128 1 INS_ACCEL_FILTER 20 2 -128 1 INS_ACCOFFS_X -0.093796379864215851 9 -128 1 INS_ACCOFFS_Y -0.100834839046001434 9 -128 1 INS_ACCOFFS_Z 0.410744011402130127 9 -128 1 INS_ACCSCAL_X 0.995854496955871582 9 -128 1 INS_ACCSCAL_Y 1.006878376007080078 9 -128 1 INS_ACCSCAL_Z 0.992123425006866455 9 -128 1 INS_ACC_BODYFIX 2 2 -128 1 INS_GYR2OFFS_X 0.027385253459215164 9 -128 1 INS_GYR2OFFS_Y 0.030301291495561600 9 -128 1 INS_GYR2OFFS_Z -0.016768395900726318 9 -128 1 INS_GYR3OFFS_X 0.000000000000000000 9 -128 1 INS_GYR3OFFS_Y 0.000000000000000000 9 -128 1 INS_GYR3OFFS_Z 0.000000000000000000 9 -128 1 INS_GYROFFS_X 0.015457602217793465 9 -128 1 INS_GYROFFS_Y 0.038951616734266281 9 -128 1 INS_GYROFFS_Z -0.008368885144591331 9 -128 1 INS_GYRO_FILTER 20 2 -128 1 INS_GYR_CAL 1 2 -128 1 INS_PRODUCT_ID 5 4 -128 1 INS_STILL_THRESH 0.100000001490116119 9 -128 1 INS_TRIM_OPTION 1 2 -128 1 INS_USE 1 2 -128 1 INS_USE2 1 2 -128 1 INS_USE3 0 2 -128 1 LAND_REPOSITION 1 2 -128 1 LAND_SPEED 50 4 -128 1 LAND_SPEED_HIGH 0 4 -128 1 LGR_SERVO_DEPLOY 1750 4 -128 1 LGR_SERVO_RTRACT 1250 4 -128 1 LOG_BACKEND_TYPE 1 2 -128 1 LOG_BITMASK 176126 6 -128 1 LOG_DISARMED 0 2 -128 1 LOG_FILE_BUFSIZE 16 2 -128 1 LOG_REPLAY 0 2 -128 1 MAG_ENABLE 1 2 -128 1 MIS_RESTART 0 2 -128 1 MIS_TOTAL 0 4 -128 1 MNT_ANGMAX_PAN 4500 4 -128 1 MNT_ANGMAX_ROL 4500 4 -128 1 MNT_ANGMAX_TIL 4500 4 -128 1 MNT_ANGMIN_PAN -4500 4 -128 1 MNT_ANGMIN_ROL -4500 4 -128 1 MNT_ANGMIN_TIL -4500 4 -128 1 MNT_DEFLT_MODE 3 2 -128 1 MNT_JSTICK_SPD 0 2 -128 1 MNT_LEAD_PTCH 0.000000000000000000 9 -128 1 MNT_LEAD_RLL 0.000000000000000000 9 -128 1 MNT_NEUTRAL_X 0.000000000000000000 9 -128 1 MNT_NEUTRAL_Y 0.000000000000000000 9 -128 1 MNT_NEUTRAL_Z 0.000000000000000000 9 -128 1 MNT_RC_IN_PAN 0 2 -128 1 MNT_RC_IN_ROLL 0 2 -128 1 MNT_RC_IN_TILT 8 2 -128 1 MNT_RETRACT_X 0.000000000000000000 9 -128 1 MNT_RETRACT_Y 0.000000000000000000 9 -128 1 MNT_RETRACT_Z 0.000000000000000000 9 -128 1 MNT_STAB_PAN 0 2 -128 1 MNT_STAB_ROLL 0 2 -128 1 MNT_STAB_TILT 0 2 -128 1 MNT_TYPE 1 2 -128 1 MOT_1_DIRECTION 0 2 -128 1 MOT_2_DIRECTION 0 2 -128 1 MOT_3_DIRECTION 1 2 -128 1 MOT_4_DIRECTION 1 2 -128 1 MOT_5_DIRECTION 0 2 -128 1 MOT_6_DIRECTION 1 2 -128 1 MOT_7_DIRECTION 1 2 -128 1 MOT_8_DIRECTION 1 2 -128 1 MOT_FV_CPLNG_K 1.000000000000000000 9 -128 1 NTF_BUZZ_ENABLE 1 2 -128 1 NTF_LED_BRIGHT 3 2 -128 1 NTF_LED_OVERRIDE 0 2 -128 1 PILOT_ACCEL_Z 50 4 -128 1 PILOT_THR_BHV 0 4 -128 1 PILOT_THR_FILT 0.000000000000000000 9 -128 1 PILOT_TKOFF_ALT 0.000000000000000000 9 -128 1 PILOT_TKOFF_DZ 100 4 -128 1 PILOT_VELZ_MAX 50 4 -128 1 POS_XY_P 1.000000000000000000 9 -128 1 POS_Z_P 1.000000000000000000 9 -128 1 PSC_ACC_XY_FILT 2.000000000000000000 9 -128 1 RC10_DZ 0 4 -128 1 RC10_FUNCTION 0 2 -128 1 RC10_MAX 2000 4 -128 1 RC10_MIN 1000 4 -128 1 RC10_REV 1 2 -128 1 RC10_TRIM 1500 4 -128 1 RC11_DZ 0 4 -128 1 RC11_FUNCTION 0 2 -128 1 RC11_MAX 2000 4 -128 1 RC11_MIN 1000 4 -128 1 RC11_REV 1 2 -128 1 RC11_TRIM 1500 4 -128 1 RC12_DZ 0 4 -128 1 RC12_FUNCTION 0 2 -128 1 RC12_MAX 2000 4 -128 1 RC12_MIN 1000 4 -128 1 RC12_REV 1 2 -128 1 RC12_TRIM 1500 4 -128 1 RC13_DZ 0 4 -128 1 RC13_FUNCTION 0 2 -128 1 RC13_MAX 2000 4 -128 1 RC13_MIN 1000 4 -128 1 RC13_REV 1 2 -128 1 RC13_TRIM 1500 4 -128 1 RC14_DZ 0 4 -128 1 RC14_FUNCTION 0 2 -128 1 RC14_MAX 2000 4 -128 1 RC14_MIN 1000 4 -128 1 RC14_REV 1 2 -128 1 RC14_TRIM 1500 4 -128 1 RC1_DZ 30 4 -128 1 RC1_MAX 2000 4 -128 1 RC1_MIN 1000 4 -128 1 RC1_REV 1 2 -128 1 RC1_TRIM 1500 4 -128 1 RC2_DZ 30 4 -128 1 RC2_MAX 2000 4 -128 1 RC2_MIN 1000 4 -128 1 RC2_REV 1 2 -128 1 RC2_TRIM 1500 4 -128 1 RC3_DZ 30 4 -128 1 RC3_MAX 1900 4 -128 1 RC3_MIN 1100 4 -128 1 RC3_REV 1 2 -128 1 RC3_TRIM 1100 4 -128 1 RC4_DZ 40 4 -128 1 RC4_MAX 1900 4 -128 1 RC4_MIN 1100 4 -128 1 RC4_REV 1 2 -128 1 RC4_TRIM 1500 4 -128 1 RC5_DZ 0 4 -128 1 RC5_FUNCTION 0 2 -128 1 RC5_MAX 2000 4 -128 1 RC5_MIN 1000 4 -128 1 RC5_REV 1 2 -128 1 RC5_TRIM 1500 4 -128 1 RC6_DZ 30 4 -128 1 RC6_FUNCTION 0 2 -128 1 RC6_MAX 1900 4 -128 1 RC6_MIN 1100 4 -128 1 RC6_REV 1 2 -128 1 RC6_TRIM 1500 4 -128 1 RC7_DZ 30 4 -128 1 RC7_FUNCTION 59 2 -128 1 RC7_MAX 1900 4 -128 1 RC7_MIN 1100 4 -128 1 RC7_REV 0 2 -128 1 RC7_TRIM 1500 4 -128 1 RC8_DZ 0 4 -128 1 RC8_FUNCTION 7 2 -128 1 RC8_MAX 2000 4 -128 1 RC8_MIN 1000 4 -128 1 RC8_REV 0 2 -128 1 RC8_TRIM 1500 4 -128 1 RC9_DZ 0 4 -128 1 RC9_FUNCTION 0 2 -128 1 RC9_MAX 2000 4 -128 1 RC9_MIN 1000 4 -128 1 RC9_REV 1 2 -128 1 RC9_TRIM 1500 4 -128 1 RCMAP_FORWARD 6 2 -128 1 RCMAP_LATERAL 7 2 -128 1 RCMAP_PITCH 1 2 -128 1 RCMAP_ROLL 2 2 -128 1 RCMAP_THROTTLE 3 2 -128 1 RCMAP_YAW 4 2 -128 1 RC_FEEL_RP 50 2 -128 1 RC_SPEED 490 4 -128 1 RELAY_DEFAULT 0 2 -128 1 RELAY_PIN 54 2 -128 1 RELAY_PIN2 55 2 -128 1 RELAY_PIN3 0 2 -128 1 RELAY_PIN4 0 2 -128 1 RNGFND2_ADDR 0 2 -128 1 RNGFND2_FUNCTION 0 2 -128 1 RNGFND2_GNDCLEAR 10 2 -128 1 RNGFND2_MAX_CM 700 4 -128 1 RNGFND2_MIN_CM 20 4 -128 1 RNGFND2_OFFSET 0.000000000000000000 9 -128 1 RNGFND2_PIN 0 2 -128 1 RNGFND2_RMETRIC 1 2 -128 1 RNGFND2_SCALING 3.000000000000000000 9 -128 1 RNGFND2_SETTLE 0 4 -128 1 RNGFND2_STOP_PIN 0 2 -128 1 RNGFND2_TYPE 0 2 -128 1 RNGFND_ADDR 0 2 -128 1 RNGFND_FUNCTION 0 2 -128 1 RNGFND_GAIN 0.800000011920928955 9 -128 1 RNGFND_GNDCLEAR 10 2 -128 1 RNGFND_MAX_CM 700 4 -128 1 RNGFND_MIN_CM 20 4 -128 1 RNGFND_OFFSET 0.000000000000000000 9 -128 1 RNGFND_PIN 0 2 -128 1 RNGFND_PWRRNG 0 4 -128 1 RNGFND_RMETRIC 1 2 -128 1 RNGFND_SCALING 3.000000000000000000 9 -128 1 RNGFND_SETTLE 0 4 -128 1 RNGFND_STOP_PIN 0 2 -128 1 RNGFND_TYPE 0 2 -128 1 RPM2_SCALING 1.000000000000000000 9 -128 1 RPM2_TYPE 0 2 -128 1 RPM_MAX 100000.000000000000000000 9 -128 1 RPM_MIN 10.000000000000000000 9 -128 1 RPM_MIN_QUAL 0.500000000000000000 9 -128 1 RPM_SCALING 1.000000000000000000 9 -128 1 RPM_TYPE 0 2 -128 1 RSSI_ANA_PIN 0 2 -128 1 RSSI_CHANNEL 0 2 -128 1 RSSI_CHAN_HIGH 2000 4 -128 1 RSSI_CHAN_LOW 1000 4 -128 1 RSSI_PIN_HIGH 5.000000000000000000 9 -128 1 RSSI_PIN_LOW 0.000000000000000000 9 -128 1 RSSI_TYPE 0 2 -128 1 RTL_ALT 1500 4 -128 1 RTL_ALT_FINAL 0 4 -128 1 RTL_CLIMB_MIN 0 4 -128 1 RTL_CONE_SLOPE 3.000000000000000000 9 -128 1 RTL_LOIT_TIME 5000 6 -128 1 RTL_SPEED 0 4 -128 1 SCHED_DEBUG 0 2 -128 1 SCHED_LOOP_RATE 400 4 -128 1 SERIAL0_BAUD 115 6 -128 1 SERIAL0_PROTOCOL 1 2 -128 1 SERIAL1_BAUD 57 6 -128 1 SERIAL1_PROTOCOL 1 2 -128 1 SERIAL2_BAUD 57 6 -128 1 SERIAL2_PROTOCOL 1 2 -128 1 SERIAL3_BAUD 38 6 -128 1 SERIAL3_PROTOCOL 5 2 -128 1 SERIAL4_BAUD 38 6 -128 1 SERIAL4_PROTOCOL 5 2 -128 1 SERIAL5_BAUD 57 6 -128 1 SERIAL5_PROTOCOL 0 2 -128 1 SIMPLE 0 2 -128 1 SR0_ADSB 5 4 -128 1 SR0_EXTRA1 4 4 -128 1 SR0_EXTRA2 4 4 -128 1 SR0_EXTRA3 4 4 -128 1 SR0_EXT_STAT 4 4 -128 1 SR0_PARAMS 10 4 -128 1 SR0_POSITION 4 4 -128 1 SR0_RAW_CTRL 4 4 -128 1 SR0_RAW_SENS 4 4 -128 1 SR0_RC_CHAN 4 4 -128 1 SR1_ADSB 5 4 -128 1 SR1_EXTRA1 0 4 -128 1 SR1_EXTRA2 0 4 -128 1 SR1_EXTRA3 0 4 -128 1 SR1_EXT_STAT 0 4 -128 1 SR1_PARAMS 0 4 -128 1 SR1_POSITION 0 4 -128 1 SR1_RAW_CTRL 0 4 -128 1 SR1_RAW_SENS 0 4 -128 1 SR1_RC_CHAN 0 4 -128 1 SR2_ADSB 5 4 -128 1 SR2_EXTRA1 0 4 -128 1 SR2_EXTRA2 0 4 -128 1 SR2_EXTRA3 0 4 -128 1 SR2_EXT_STAT 0 4 -128 1 SR2_PARAMS 0 4 -128 1 SR2_POSITION 0 4 -128 1 SR2_RAW_CTRL 0 4 -128 1 SR2_RAW_SENS 0 4 -128 1 SR2_RC_CHAN 0 4 -128 1 SR3_ADSB 5 4 -128 1 SR3_EXTRA1 0 4 -128 1 SR3_EXTRA2 0 4 -128 1 SR3_EXTRA3 0 4 -128 1 SR3_EXT_STAT 0 4 -128 1 SR3_PARAMS 0 4 -128 1 SR3_POSITION 0 4 -128 1 SR3_RAW_CTRL 0 4 -128 1 SR3_RAW_SENS 0 4 -128 1 SR3_RC_CHAN 0 4 -128 1 SUPER_SIMPLE 0 2 -128 1 SURFACE_DEPTH -10.000000000000000000 9 -128 1 SYSID_MYGCS 255 4 -128 1 SYSID_SW_MREV 120 4 -128 1 SYSID_SW_TYPE 10 2 -128 1 SYSID_THISMAV 1 4 -128 1 TELEM_DELAY 0 2 -128 1 TERRAIN_FOLLOW 0 2 -128 1 THROW_MOT_START 0 2 -128 1 THR_DZ 100 4 -128 1 TUNE 0 2 -128 1 TUNE_HIGH 1000 4 -128 1 TUNE_LOW 0 4 -128 1 VEL_XY_FILT_HZ 5.000000000000000000 9 -128 1 VEL_XY_I 0.500000000000000000 9 -128 1 VEL_XY_IMAX 1000.000000000000000000 9 -128 1 VEL_XY_P 1.000000000000000000 9 -128 1 VEL_Z_P 5.000000000000000000 9 -128 1 WPNAV_ACCEL 100.000000000000000000 9 -128 1 WPNAV_ACCEL_Z 100.000000000000000000 9 -128 1 WPNAV_LOIT_JERK 1000.000000000000000000 9 -128 1 WPNAV_LOIT_MAXA 250.000000000000000000 9 -128 1 WPNAV_LOIT_MINA 25.000000000000000000 9 -128 1 WPNAV_LOIT_SPEED 500.000000000000000000 9 -128 1 WPNAV_RADIUS 200.000000000000000000 9 -128 1 WPNAV_SPEED 500.000000000000000000 9 -128 1 WPNAV_SPEED_DN 150.000000000000000000 9 -128 1 WPNAV_SPEED_UP 250.000000000000000000 9 -128 1 WP_TKOFF_NAV_ALT 0.000000000000000000 9 -128 1 WP_YAW_BEHAVIOR 2 2 +1 1 ACCEL_Z_D 0.000000000000000000 9 +1 1 ACCEL_Z_FILT 20.000000000000000000 9 +1 1 ACCEL_Z_I 1.000000000000000000 9 +1 1 ACCEL_Z_IMAX 800.000000000000000000 9 +1 1 ACCEL_Z_P 0.500000000000000000 9 +1 1 ACRO_BAL_PITCH 1.000000000000000000 9 +1 1 ACRO_BAL_ROLL 1.000000000000000000 9 +1 1 ACRO_EXPO 0.300000011920928955 9 +1 1 ACRO_RP_P 4.500000000000000000 9 +1 1 ACRO_TRAINER 2 2 +1 1 ACRO_YAW_P 4.500000000000000000 9 +1 1 AHRS_COMP_BETA 0.100000001490116119 9 +1 1 AHRS_EKF_TYPE 2 2 +1 1 AHRS_GPS_GAIN 1.000000000000000000 9 +1 1 AHRS_GPS_MINSATS 6 2 +1 1 AHRS_GPS_USE 1 2 +1 1 AHRS_ORIENTATION 16 2 +1 1 AHRS_RP_P 0.200000002980232239 9 +1 1 AHRS_TRIM_X 0.000000000000000000 9 +1 1 AHRS_TRIM_Y 0.007748094387352467 9 +1 1 AHRS_TRIM_Z 0.000000000000000000 9 +1 1 AHRS_WIND_MAX 0 2 +1 1 AHRS_YAW_P 0.200000002980232239 9 +1 1 ANGLE_MAX 4500 4 +1 1 ARMING_CHECK 0 2 +1 1 ATC_ACCEL_P_MAX 110000.000000000000000000 9 +1 1 ATC_ACCEL_R_MAX 110000.000000000000000000 9 +1 1 ATC_ACCEL_Y_MAX 110000.000000000000000000 9 +1 1 ATC_ANGLE_BOOST 1 2 +1 1 ATC_ANG_LIM_TC 1.000000000000000000 9 +1 1 ATC_ANG_PIT_P 6.000000000000000000 9 +1 1 ATC_ANG_RLL_P 0.000000000000000000 9 +1 1 ATC_ANG_YAW_P 6.000000000000000000 9 +1 1 ATC_RATE_FF_ENAB 1 2 +1 1 ATC_RAT_PIT_D 0.003599999938160181 9 +1 1 ATC_RAT_PIT_FILT 20.000000000000000000 9 +1 1 ATC_RAT_PIT_I 0.090000003576278687 9 +1 1 ATC_RAT_PIT_IMAX 0.444000005722045898 9 +1 1 ATC_RAT_PIT_P 0.135000005364418030 9 +1 1 ATC_RAT_RLL_D 0.004000000189989805 9 +1 1 ATC_RAT_RLL_FILT 20.000000000000000000 9 +1 1 ATC_RAT_RLL_I 0.000000000000000000 9 +1 1 ATC_RAT_RLL_IMAX 0.444000005722045898 9 +1 1 ATC_RAT_RLL_P 0.140000000596046448 9 +1 1 ATC_RAT_YAW_D 0.000000000000000000 9 +1 1 ATC_RAT_YAW_FILT 30.000000000000000000 9 +1 1 ATC_RAT_YAW_I 0.019999999552965164 9 +1 1 ATC_RAT_YAW_IMAX 0.222000002861022949 9 +1 1 ATC_RAT_YAW_P 0.180000007152557373 9 +1 1 ATC_SLEW_YAW 6000.000000000000000000 9 +1 1 ATC_THR_MIX_MAX 0.500000000000000000 9 +1 1 ATC_THR_MIX_MIN 0.100000001490116119 9 +1 1 AUTOTUNE_AGGR 0.100000001490116119 9 +1 1 AUTOTUNE_AXES 7 2 +1 1 AUTOTUNE_MIN_D 0.001000000047497451 9 +1 1 AVOID_ENABLE 1 2 +1 1 BATT2_AMP_OFFSET 0.000000000000000000 9 +1 1 BATT2_AMP_PERVOL 17.000000000000000000 9 +1 1 BATT2_CAPACITY 3300 6 +1 1 BATT2_CURR_PIN 3 2 +1 1 BATT2_MONITOR 0 2 +1 1 BATT2_VOLT_MULT 10.100000381469726562 9 +1 1 BATT2_VOLT_PIN 2 2 +1 1 BATT_AMP_OFFSET 0.000000000000000000 9 +1 1 BATT_AMP_PERVOLT 17.000000000000000000 9 +1 1 BATT_CAPACITY 10000 6 +1 1 BATT_CURR_PIN 3 2 +1 1 BATT_MONITOR 4 2 +1 1 BATT_VOLT_MULT 10.100000381469726562 9 +1 1 BATT_VOLT_PIN 2 2 +1 1 BRD_CAN_ENABLE 0 2 +1 1 BRD_IMU_TARGTEMP 0 2 +1 1 BRD_PWM_COUNT 4 2 +1 1 BRD_SAFETYENABLE 0 2 +1 1 BRD_SAFETY_MASK 0 6 +1 1 BRD_SBUS_OUT 0 2 +1 1 BRD_SER1_RTSCTS 2 2 +1 1 BRD_SER2_RTSCTS 2 2 +1 1 BRD_SERIAL_NUM 0 4 +1 1 BTN0_FUNCTION 0 2 +1 1 BTN0_SFUNCTION 0 2 +1 1 BTN10_FUNCTION 22 2 +1 1 BTN10_SFUNCTION 0 2 +1 1 BTN11_FUNCTION 42 2 +1 1 BTN11_SFUNCTION 47 2 +1 1 BTN12_FUNCTION 43 2 +1 1 BTN12_SFUNCTION 46 2 +1 1 BTN13_FUNCTION 33 2 +1 1 BTN13_SFUNCTION 45 2 +1 1 BTN14_FUNCTION 32 2 +1 1 BTN14_SFUNCTION 44 2 +1 1 BTN15_FUNCTION 0 2 +1 1 BTN15_SFUNCTION 0 2 +1 1 BTN1_FUNCTION 6 2 +1 1 BTN1_SFUNCTION 0 2 +1 1 BTN2_FUNCTION 8 2 +1 1 BTN2_SFUNCTION 0 2 +1 1 BTN3_FUNCTION 7 2 +1 1 BTN3_SFUNCTION 0 2 +1 1 BTN4_FUNCTION 4 2 +1 1 BTN4_SFUNCTION 0 2 +1 1 BTN5_FUNCTION 1 2 +1 1 BTN5_SFUNCTION 0 2 +1 1 BTN6_FUNCTION 3 2 +1 1 BTN6_SFUNCTION 0 2 +1 1 BTN7_FUNCTION 21 2 +1 1 BTN7_SFUNCTION 0 2 +1 1 BTN8_FUNCTION 48 2 +1 1 BTN8_SFUNCTION 0 2 +1 1 BTN9_FUNCTION 23 2 +1 1 BTN9_SFUNCTION 0 2 +1 1 CAM_DURATION 10 2 +1 1 CAM_FEEDBACK_PIN 0 2 +1 1 CAM_FEEDBACK_POL 1 2 +1 1 CAM_MAX_ROLL 0 4 +1 1 CAM_MIN_INTERVAL 0 4 +1 1 CAM_RELAY_ON 1 2 +1 1 CAM_SERVO_OFF 1100 4 +1 1 CAM_SERVO_ON 1300 4 +1 1 CAM_TRIGG_DIST 0.000000000000000000 9 +1 1 CAM_TRIGG_TYPE 0 2 +1 1 CH10_OPT 0 2 +1 1 CH11_OPT 0 2 +1 1 CH12_OPT 0 2 +1 1 CH7_OPT 0 2 +1 1 CH8_OPT 0 2 +1 1 CH9_OPT 0 2 +1 1 CIRCLE_RADIUS 1000.000000000000000000 9 +1 1 CIRCLE_RATE 20.000000000000000000 9 +1 1 CLI_ENABLED 0 2 +1 1 COMPASS_AUTODEC 1 2 +1 1 COMPASS_CAL_FIT 8.000000000000000000 9 +1 1 COMPASS_DEC 0.000000000000000000 9 +1 1 COMPASS_DEV_ID 131594 6 +1 1 COMPASS_DEV_ID2 0 6 +1 1 COMPASS_DEV_ID3 0 6 +1 1 COMPASS_DIA2_X 0.000000000000000000 9 +1 1 COMPASS_DIA2_Y 0.000000000000000000 9 +1 1 COMPASS_DIA2_Z 0.000000000000000000 9 +1 1 COMPASS_DIA3_X 0.000000000000000000 9 +1 1 COMPASS_DIA3_Y 0.000000000000000000 9 +1 1 COMPASS_DIA3_Z 0.000000000000000000 9 +1 1 COMPASS_DIA_X 1.000000000000000000 9 +1 1 COMPASS_DIA_Y 1.000000000000000000 9 +1 1 COMPASS_DIA_Z 1.000000000000000000 9 +1 1 COMPASS_EXTERN2 0 2 +1 1 COMPASS_EXTERN3 0 2 +1 1 COMPASS_EXTERNAL 0 2 +1 1 COMPASS_LEARN 1 2 +1 1 COMPASS_MOT2_X 0.000000000000000000 9 +1 1 COMPASS_MOT2_Y 0.000000000000000000 9 +1 1 COMPASS_MOT2_Z 0.000000000000000000 9 +1 1 COMPASS_MOT3_X 0.000000000000000000 9 +1 1 COMPASS_MOT3_Y 0.000000000000000000 9 +1 1 COMPASS_MOT3_Z 0.000000000000000000 9 +1 1 COMPASS_MOTCT 0 2 +1 1 COMPASS_MOT_X 0.000000000000000000 9 +1 1 COMPASS_MOT_Y 0.000000000000000000 9 +1 1 COMPASS_MOT_Z 0.000000000000000000 9 +1 1 COMPASS_ODI2_X 0.000000000000000000 9 +1 1 COMPASS_ODI2_Y 0.000000000000000000 9 +1 1 COMPASS_ODI2_Z 0.000000000000000000 9 +1 1 COMPASS_ODI3_X 0.000000000000000000 9 +1 1 COMPASS_ODI3_Y 0.000000000000000000 9 +1 1 COMPASS_ODI3_Z 0.000000000000000000 9 +1 1 COMPASS_ODI_X 0.000000000000000000 9 +1 1 COMPASS_ODI_Y 0.000000000000000000 9 +1 1 COMPASS_ODI_Z 0.000000000000000000 9 +1 1 COMPASS_OFS2_X 0.000000000000000000 9 +1 1 COMPASS_OFS2_Y 0.000000000000000000 9 +1 1 COMPASS_OFS2_Z 0.000000000000000000 9 +1 1 COMPASS_OFS3_X 0.000000000000000000 9 +1 1 COMPASS_OFS3_Y 0.000000000000000000 9 +1 1 COMPASS_OFS3_Z 0.000000000000000000 9 +1 1 COMPASS_OFS_X -17.000000000000000000 9 +1 1 COMPASS_OFS_Y 389.000000000000000000 9 +1 1 COMPASS_OFS_Z 128.000000000000000000 9 +1 1 COMPASS_ORIENT 16 2 +1 1 COMPASS_ORIENT2 0 2 +1 1 COMPASS_ORIENT3 0 2 +1 1 COMPASS_PRIMARY 0 2 +1 1 COMPASS_USE 1 2 +1 1 COMPASS_USE2 1 2 +1 1 COMPASS_USE3 1 2 +1 1 DISARM_DELAY 0 2 +1 1 EK2_ABIAS_P_NSE 0.004999999888241291 9 +1 1 EK2_ACC_P_NSE 0.600000023841857910 9 +1 1 EK2_ALT_M_NSE 0.100000001490116119 9 +1 1 EK2_ALT_SOURCE 0 2 +1 1 EK2_CHECK_SCALE 100 4 +1 1 EK2_EAS_I_GATE 400 4 +1 1 EK2_EAS_M_NSE 1.399999976158142090 9 +1 1 EK2_ENABLE 1 2 +1 1 EK2_FLOW_DELAY 10 2 +1 1 EK2_FLOW_I_GATE 300 4 +1 1 EK2_FLOW_M_NSE 0.250000000000000000 9 +1 1 EK2_GBIAS_P_NSE 0.000099999997473788 9 +1 1 EK2_GLITCH_RAD 25 2 +1 1 EK2_GPS_CHECK 31 2 +1 1 EK2_GPS_DELAY 220 4 +1 1 EK2_GPS_TYPE 0 2 +1 1 EK2_GSCL_P_NSE 0.000500000023748726 9 +1 1 EK2_GYRO_P_NSE 0.029999999329447746 9 +1 1 EK2_HGT_DELAY 60 4 +1 1 EK2_HGT_I_GATE 500 4 +1 1 EK2_IMU_MASK 3 2 +1 1 EK2_LOG_MASK 1 2 +1 1 EK2_MAGB_P_NSE 0.000099999997473788 9 +1 1 EK2_MAGE_P_NSE 0.001000000047497451 9 +1 1 EK2_MAG_CAL 3 2 +1 1 EK2_MAG_I_GATE 300 4 +1 1 EK2_MAG_M_NSE 0.050000000745058060 9 +1 1 EK2_MAX_FLOW 2.500000000000000000 9 +1 1 EK2_NOAID_M_NSE 10.000000000000000000 9 +1 1 EK2_POSNE_M_NSE 1.000000000000000000 9 +1 1 EK2_POS_I_GATE 500 4 +1 1 EK2_RNG_I_GATE 500 4 +1 1 EK2_RNG_M_NSE 0.500000000000000000 9 +1 1 EK2_TAU_OUTPUT 25 2 +1 1 EK2_VELD_M_NSE 0.699999988079071045 9 +1 1 EK2_VELNE_M_NSE 0.500000000000000000 9 +1 1 EK2_VEL_I_GATE 500 4 +1 1 EK2_WIND_PSCALE 0.500000000000000000 9 +1 1 EK2_WIND_P_NSE 0.100000001490116119 9 +1 1 EK2_YAW_I_GATE 300 4 +1 1 EK2_YAW_M_NSE 0.500000000000000000 9 +1 1 EKF_ENABLE 0 2 +1 1 EPM_ENABLE 0 2 +1 1 EPM_GRAB 1900 4 +1 1 EPM_NEUTRAL 1500 4 +1 1 EPM_REGRAB 0 2 +1 1 EPM_RELEASE 1100 4 +1 1 ESC_CALIBRATION 0 2 +1 1 FENCE_ACTION 1 2 +1 1 FENCE_ALT_MAX 100.000000000000000000 9 +1 1 FENCE_DEPTH_MAX -10.000000000000000000 9 +1 1 FENCE_ENABLE 0 2 +1 1 FENCE_MARGIN 2.000000000000000000 9 +1 1 FENCE_RADIUS 300.000000000000000000 9 +1 1 FENCE_TOTAL 0 2 +1 1 FENCE_TYPE 7 2 +1 1 FLOW_ENABLE 0 2 +1 1 FLOW_FXSCALER 0 4 +1 1 FLOW_FYSCALER 0 4 +1 1 FLOW_ORIENT_YAW 0 4 +1 1 FLTMODE1 19 2 +1 1 FLTMODE2 0 2 +1 1 FLTMODE3 2 2 +1 1 FLTMODE4 0 2 +1 1 FLTMODE5 0 2 +1 1 FLTMODE6 0 2 +1 1 FRAME 1 2 +1 1 FS_BATT_ENABLE 0 2 +1 1 FS_BATT_MAH 0.000000000000000000 9 +1 1 FS_BATT_VOLTAGE 10.500000000000000000 9 +1 1 FS_CRASH_CHECK 0 2 +1 1 FS_EKF_ACTION 1 2 +1 1 FS_EKF_THRESH 0.800000011920928955 9 +1 1 FS_GCS_ENABLE 1 2 +1 1 FS_LEAK_ENABLE 1 2 +1 1 FS_PRESS_ENABLE 0 2 +1 1 FS_PRESS_MAX 105000 6 +1 1 FS_TEMP_ENABLE 0 2 +1 1 FS_TEMP_MAX 62 2 +1 1 FS_TERRAIN_ENAB 0 2 +1 1 FS_THR_ENABLE 0 2 +1 1 FS_THR_VALUE 975 4 +1 1 GCS_PID_MASK 0 4 +1 1 GND_ABS_PRESS 102237.296875000000000000 9 +1 1 GND_ALT_OFFSET 0.000000000000000000 9 +1 1 GND_BASE_PRESS 98975.476562500000000000 9 +1 1 GND_BASE_RESET 0 2 +1 1 GND_PRIMARY 1 2 +1 1 GND_SPEC_GRAV 1.000000000000000000 9 +1 1 GND_TEMP 37.426425933837890625 9 +1 1 GPS_AUTO_CONFIG 1 2 +1 1 GPS_AUTO_SWITCH 1 2 +1 1 GPS_GNSS_MODE 0 2 +1 1 GPS_GNSS_MODE2 0 2 +1 1 GPS_HDOP_GOOD 140 4 +1 1 GPS_INJECT_TO 127 2 +1 1 GPS_MIN_DGPS 100 2 +1 1 GPS_MIN_ELEV 0 2 +1 1 GPS_NAVFILTER 8 2 +1 1 GPS_RAW_DATA 0 2 +1 1 GPS_SAVE_CFG 0 2 +1 1 GPS_SBAS_MODE 2 2 +1 1 GPS_SBP_LOGMASK -256 4 +1 1 GPS_TYPE 1 2 +1 1 GPS_TYPE2 0 2 +1 1 INS_ACC2OFFS_X 0.649672329425811768 9 +1 1 INS_ACC2OFFS_Y 0.710507631301879883 9 +1 1 INS_ACC2OFFS_Z 0.387798368930816650 9 +1 1 INS_ACC2SCAL_X 1.043415188789367676 9 +1 1 INS_ACC2SCAL_Y 1.020669221878051758 9 +1 1 INS_ACC2SCAL_Z 1.008688688278198242 9 +1 1 INS_ACC3OFFS_X 0.000000000000000000 9 +1 1 INS_ACC3OFFS_Y 0.000000000000000000 9 +1 1 INS_ACC3OFFS_Z 0.000000000000000000 9 +1 1 INS_ACC3SCAL_X 0.000000000000000000 9 +1 1 INS_ACC3SCAL_Y 0.000000000000000000 9 +1 1 INS_ACC3SCAL_Z 0.000000000000000000 9 +1 1 INS_ACCEL_FILTER 20 2 +1 1 INS_ACCOFFS_X -0.088626168668270111 9 +1 1 INS_ACCOFFS_Y -0.112697608768939972 9 +1 1 INS_ACCOFFS_Z 0.440824359655380249 9 +1 1 INS_ACCSCAL_X 0.996031224727630615 9 +1 1 INS_ACCSCAL_Y 1.005982160568237305 9 +1 1 INS_ACCSCAL_Z 0.992506563663482666 9 +1 1 INS_ACC_BODYFIX 2 2 +1 1 INS_GYR2OFFS_X 0.017705552279949188 9 +1 1 INS_GYR2OFFS_Y 0.022531248629093170 9 +1 1 INS_GYR2OFFS_Z -0.017156355082988739 9 +1 1 INS_GYR3OFFS_X 0.000000000000000000 9 +1 1 INS_GYR3OFFS_Y 0.000000000000000000 9 +1 1 INS_GYR3OFFS_Z 0.000000000000000000 9 +1 1 INS_GYROFFS_X 0.015944827347993851 9 +1 1 INS_GYROFFS_Y 0.044509842991828918 9 +1 1 INS_GYROFFS_Z -0.004005374852567911 9 +1 1 INS_GYRO_FILTER 20 2 +1 1 INS_GYR_CAL 1 2 +1 1 INS_PRODUCT_ID 5 4 +1 1 INS_STILL_THRESH 0.100000001490116119 9 +1 1 INS_TRIM_OPTION 1 2 +1 1 INS_USE 1 2 +1 1 INS_USE2 1 2 +1 1 INS_USE3 0 2 +1 1 LAND_REPOSITION 1 2 +1 1 LAND_SPEED 50 4 +1 1 LAND_SPEED_HIGH 0 4 +1 1 LEAK1_LOGIC 0 2 +1 1 LEAK1_PIN -1 2 +1 1 LEAK2_LOGIC 0 2 +1 1 LEAK2_PIN -1 2 +1 1 LEAK3_LOGIC 0 2 +1 1 LEAK3_PIN -1 2 +1 1 LGR_SERVO_DEPLOY 1750 4 +1 1 LGR_SERVO_RTRACT 1250 4 +1 1 LOG_BACKEND_TYPE 1 2 +1 1 LOG_BITMASK 176126 6 +1 1 LOG_DISARMED 0 2 +1 1 LOG_FILE_BUFSIZE 16 2 +1 1 LOG_REPLAY 0 2 +1 1 MAG_ENABLE 1 2 +1 1 MIS_RESTART 0 2 +1 1 MIS_TOTAL 0 4 +1 1 MNT_ANGMAX_PAN 4500 4 +1 1 MNT_ANGMAX_ROL 4500 4 +1 1 MNT_ANGMAX_TIL 4500 4 +1 1 MNT_ANGMIN_PAN -4500 4 +1 1 MNT_ANGMIN_ROL -4500 4 +1 1 MNT_ANGMIN_TIL -4500 4 +1 1 MNT_DEFLT_MODE 3 2 +1 1 MNT_JSTICK_SPD 0 2 +1 1 MNT_LEAD_PTCH 0.000000000000000000 9 +1 1 MNT_LEAD_RLL 0.000000000000000000 9 +1 1 MNT_NEUTRAL_X 0.000000000000000000 9 +1 1 MNT_NEUTRAL_Y 0.000000000000000000 9 +1 1 MNT_NEUTRAL_Z 0.000000000000000000 9 +1 1 MNT_RC_IN_PAN 0 2 +1 1 MNT_RC_IN_ROLL 0 2 +1 1 MNT_RC_IN_TILT 8 2 +1 1 MNT_RETRACT_X 0.000000000000000000 9 +1 1 MNT_RETRACT_Y 0.000000000000000000 9 +1 1 MNT_RETRACT_Z 0.000000000000000000 9 +1 1 MNT_STAB_PAN 0 2 +1 1 MNT_STAB_ROLL 0 2 +1 1 MNT_STAB_TILT 0 2 +1 1 MNT_TYPE 1 2 +1 1 MOT_1_DIRECTION 1 2 +1 1 MOT_2_DIRECTION -1 2 +1 1 MOT_3_DIRECTION 1 2 +1 1 MOT_4_DIRECTION 1 2 +1 1 MOT_5_DIRECTION -1 2 +1 1 MOT_6_DIRECTION 1 2 +1 1 MOT_7_DIRECTION 1 2 +1 1 MOT_8_DIRECTION 1 2 +1 1 MOT_FV_CPLNG_K 1.000000000000000000 9 +1 1 NTF_BUZZ_ENABLE 1 2 +1 1 NTF_LED_BRIGHT 3 2 +1 1 NTF_LED_OVERRIDE 0 2 +1 1 PHLD_BRAKE_ANGLE 3000 4 +1 1 PHLD_BRAKE_RATE 8 4 +1 1 PILOT_ACCEL_Z 50 4 +1 1 PILOT_THR_BHV 0 4 +1 1 PILOT_THR_FILT 0.000000000000000000 9 +1 1 PILOT_TKOFF_ALT 0.000000000000000000 9 +1 1 PILOT_TKOFF_DZ 100 4 +1 1 PILOT_VELZ_MAX 50 4 +1 1 POS_XY_P 1.000000000000000000 9 +1 1 POS_Z_P 1.000000000000000000 9 +1 1 PSC_ACC_XY_FILT 2.000000000000000000 9 +1 1 RC10_DZ 0 4 +1 1 RC10_FUNCTION 0 2 +1 1 RC10_MAX 2000 4 +1 1 RC10_MIN 1000 4 +1 1 RC10_REV 1 2 +1 1 RC10_TRIM 1500 4 +1 1 RC11_DZ 0 4 +1 1 RC11_FUNCTION 0 2 +1 1 RC11_MAX 2000 4 +1 1 RC11_MIN 1000 4 +1 1 RC11_REV 1 2 +1 1 RC11_TRIM 1500 4 +1 1 RC12_DZ 0 4 +1 1 RC12_FUNCTION 0 2 +1 1 RC12_MAX 2000 4 +1 1 RC12_MIN 1000 4 +1 1 RC12_REV 1 2 +1 1 RC12_TRIM 1500 4 +1 1 RC13_DZ 0 4 +1 1 RC13_FUNCTION 0 2 +1 1 RC13_MAX 2000 4 +1 1 RC13_MIN 1000 4 +1 1 RC13_REV 1 2 +1 1 RC13_TRIM 1500 4 +1 1 RC14_DZ 0 4 +1 1 RC14_FUNCTION 0 2 +1 1 RC14_MAX 2000 4 +1 1 RC14_MIN 1000 4 +1 1 RC14_REV 1 2 +1 1 RC14_TRIM 1500 4 +1 1 RC1_DZ 30 4 +1 1 RC1_MAX 2000 4 +1 1 RC1_MIN 1000 4 +1 1 RC1_REV 1 2 +1 1 RC1_TRIM 1500 4 +1 1 RC2_DZ 30 4 +1 1 RC2_MAX 2000 4 +1 1 RC2_MIN 1000 4 +1 1 RC2_REV 1 2 +1 1 RC2_TRIM 1500 4 +1 1 RC3_DZ 30 4 +1 1 RC3_MAX 1900 4 +1 1 RC3_MIN 1100 4 +1 1 RC3_REV 1 2 +1 1 RC3_TRIM 1100 4 +1 1 RC4_DZ 40 4 +1 1 RC4_MAX 1900 4 +1 1 RC4_MIN 1100 4 +1 1 RC4_REV 1 2 +1 1 RC4_TRIM 1500 4 +1 1 RC5_DZ 0 4 +1 1 RC5_FUNCTION 0 2 +1 1 RC5_MAX 2000 4 +1 1 RC5_MIN 1000 4 +1 1 RC5_REV 1 2 +1 1 RC5_TRIM 1500 4 +1 1 RC6_DZ 30 4 +1 1 RC6_FUNCTION 0 2 +1 1 RC6_MAX 1900 4 +1 1 RC6_MIN 1100 4 +1 1 RC6_REV 1 2 +1 1 RC6_TRIM 1500 4 +1 1 RC7_DZ 30 4 +1 1 RC7_FUNCTION 59 2 +1 1 RC7_MAX 1900 4 +1 1 RC7_MIN 1100 4 +1 1 RC7_REV 0 2 +1 1 RC7_TRIM 1500 4 +1 1 RC8_DZ 0 4 +1 1 RC8_FUNCTION 7 2 +1 1 RC8_MAX 2000 4 +1 1 RC8_MIN 1000 4 +1 1 RC8_REV 0 2 +1 1 RC8_TRIM 1500 4 +1 1 RC9_DZ 0 4 +1 1 RC9_FUNCTION 0 2 +1 1 RC9_MAX 2000 4 +1 1 RC9_MIN 1000 4 +1 1 RC9_REV 1 2 +1 1 RC9_TRIM 1500 4 +1 1 RCMAP_FORWARD 6 2 +1 1 RCMAP_LATERAL 7 2 +1 1 RCMAP_PITCH 1 2 +1 1 RCMAP_ROLL 2 2 +1 1 RCMAP_THROTTLE 3 2 +1 1 RCMAP_YAW 4 2 +1 1 RC_FEEL_RP 50 2 +1 1 RC_SPEED 100 4 +1 1 RELAY_DEFAULT 0 2 +1 1 RELAY_PIN 54 2 +1 1 RELAY_PIN2 55 2 +1 1 RELAY_PIN3 0 2 +1 1 RELAY_PIN4 0 2 +1 1 RNGFND2_ADDR 0 2 +1 1 RNGFND2_FUNCTION 0 2 +1 1 RNGFND2_GNDCLEAR 10 2 +1 1 RNGFND2_MAX_CM 700 4 +1 1 RNGFND2_MIN_CM 20 4 +1 1 RNGFND2_OFFSET 0.000000000000000000 9 +1 1 RNGFND2_PIN 0 2 +1 1 RNGFND2_RMETRIC 1 2 +1 1 RNGFND2_SCALING 3.000000000000000000 9 +1 1 RNGFND2_SETTLE 0 4 +1 1 RNGFND2_STOP_PIN 0 2 +1 1 RNGFND2_TYPE 0 2 +1 1 RNGFND_ADDR 0 2 +1 1 RNGFND_FUNCTION 0 2 +1 1 RNGFND_GAIN 0.800000011920928955 9 +1 1 RNGFND_GNDCLEAR 10 2 +1 1 RNGFND_MAX_CM 700 4 +1 1 RNGFND_MIN_CM 20 4 +1 1 RNGFND_OFFSET 0.000000000000000000 9 +1 1 RNGFND_PIN 0 2 +1 1 RNGFND_PWRRNG 0 4 +1 1 RNGFND_RMETRIC 1 2 +1 1 RNGFND_SCALING 3.000000000000000000 9 +1 1 RNGFND_SETTLE 0 4 +1 1 RNGFND_STOP_PIN 0 2 +1 1 RNGFND_TYPE 0 2 +1 1 RPM2_SCALING 1.000000000000000000 9 +1 1 RPM2_TYPE 0 2 +1 1 RPM_MAX 100000.000000000000000000 9 +1 1 RPM_MIN 10.000000000000000000 9 +1 1 RPM_MIN_QUAL 0.500000000000000000 9 +1 1 RPM_SCALING 1.000000000000000000 9 +1 1 RPM_TYPE 0 2 +1 1 RSSI_ANA_PIN 0 2 +1 1 RSSI_CHANNEL 0 2 +1 1 RSSI_CHAN_HIGH 2000 4 +1 1 RSSI_CHAN_LOW 1000 4 +1 1 RSSI_PIN_HIGH 5.000000000000000000 9 +1 1 RSSI_PIN_LOW 0.000000000000000000 9 +1 1 RSSI_TYPE 0 2 +1 1 RTL_ALT 1500 4 +1 1 RTL_ALT_FINAL 0 4 +1 1 RTL_CLIMB_MIN 0 4 +1 1 RTL_CONE_SLOPE 3.000000000000000000 9 +1 1 RTL_LOIT_TIME 5000 6 +1 1 RTL_SPEED 0 4 +1 1 SCHED_DEBUG 0 2 +1 1 SCHED_LOOP_RATE 400 4 +1 1 SERIAL0_BAUD 115 6 +1 1 SERIAL0_PROTOCOL 1 2 +1 1 SERIAL1_BAUD 57 6 +1 1 SERIAL1_PROTOCOL 1 2 +1 1 SERIAL2_BAUD 57 6 +1 1 SERIAL2_PROTOCOL 1 2 +1 1 SERIAL3_BAUD 38 6 +1 1 SERIAL3_PROTOCOL 5 2 +1 1 SERIAL4_BAUD 38 6 +1 1 SERIAL4_PROTOCOL 5 2 +1 1 SERIAL5_BAUD 57 6 +1 1 SERIAL5_PROTOCOL 0 2 +1 1 SIMPLE 0 2 +1 1 SR0_ADSB 5 4 +1 1 SR0_EXTRA1 4 4 +1 1 SR0_EXTRA2 4 4 +1 1 SR0_EXTRA3 4 4 +1 1 SR0_EXT_STAT 4 4 +1 1 SR0_PARAMS 10 4 +1 1 SR0_POSITION 4 4 +1 1 SR0_RAW_CTRL 4 4 +1 1 SR0_RAW_SENS 4 4 +1 1 SR0_RC_CHAN 4 4 +1 1 SR1_ADSB 5 4 +1 1 SR1_EXTRA1 0 4 +1 1 SR1_EXTRA2 0 4 +1 1 SR1_EXTRA3 0 4 +1 1 SR1_EXT_STAT 0 4 +1 1 SR1_PARAMS 0 4 +1 1 SR1_POSITION 0 4 +1 1 SR1_RAW_CTRL 0 4 +1 1 SR1_RAW_SENS 0 4 +1 1 SR1_RC_CHAN 0 4 +1 1 SR2_ADSB 5 4 +1 1 SR2_EXTRA1 0 4 +1 1 SR2_EXTRA2 0 4 +1 1 SR2_EXTRA3 0 4 +1 1 SR2_EXT_STAT 0 4 +1 1 SR2_PARAMS 0 4 +1 1 SR2_POSITION 0 4 +1 1 SR2_RAW_CTRL 0 4 +1 1 SR2_RAW_SENS 0 4 +1 1 SR2_RC_CHAN 0 4 +1 1 SR3_ADSB 5 4 +1 1 SR3_EXTRA1 0 4 +1 1 SR3_EXTRA2 0 4 +1 1 SR3_EXTRA3 0 4 +1 1 SR3_EXT_STAT 0 4 +1 1 SR3_PARAMS 0 4 +1 1 SR3_POSITION 0 4 +1 1 SR3_RAW_CTRL 0 4 +1 1 SR3_RAW_SENS 0 4 +1 1 SR3_RC_CHAN 0 4 +1 1 SUPER_SIMPLE 0 2 +1 1 SURFACE_DEPTH -10.000000000000000000 9 +1 1 SYSID_MYGCS 255 4 +1 1 SYSID_SW_MREV 120 4 +1 1 SYSID_SW_TYPE 10 2 +1 1 SYSID_THISMAV 1 4 +1 1 TELEM_DELAY 0 2 +1 1 TERRAIN_FOLLOW 0 2 +1 1 THROW_MOT_START 0 2 +1 1 THR_DZ 100 4 +1 1 TUNE 0 2 +1 1 TUNE_HIGH 1000 4 +1 1 TUNE_LOW 0 4 +1 1 VEL_XY_FILT_HZ 5.000000000000000000 9 +1 1 VEL_XY_I 0.500000000000000000 9 +1 1 VEL_XY_IMAX 1000.000000000000000000 9 +1 1 VEL_XY_P 1.000000000000000000 9 +1 1 VEL_Z_P 5.000000000000000000 9 +1 1 WPNAV_ACCEL 100.000000000000000000 9 +1 1 WPNAV_ACCEL_Z 100.000000000000000000 9 +1 1 WPNAV_LOIT_JERK 1000.000000000000000000 9 +1 1 WPNAV_LOIT_MAXA 250.000000000000000000 9 +1 1 WPNAV_LOIT_MINA 25.000000000000000000 9 +1 1 WPNAV_LOIT_SPEED 500.000000000000000000 9 +1 1 WPNAV_RADIUS 200.000000000000000000 9 +1 1 WPNAV_SPEED 500.000000000000000000 9 +1 1 WPNAV_SPEED_DN 150.000000000000000000 9 +1 1 WPNAV_SPEED_UP 250.000000000000000000 9 +1 1 WP_TKOFF_NAV_ALT 0.000000000000000000 9 +1 1 WP_YAW_BEHAVIOR 2 2 +1 1 XTRACK_ANG_LIM 45 2 diff --git a/src/comm/BluetoothLink.cc b/src/comm/BluetoothLink.cc index 9ed804ed2b73dbabcbc4b46369569cd66d5beadd..2ffe1e7258637458732bf6879ffe0c7774605c94 100644 --- a/src/comm/BluetoothLink.cc +++ b/src/comm/BluetoothLink.cc @@ -29,24 +29,21 @@ #include "BluetoothLink.h" #include "QGC.h" -BluetoothLink::BluetoothLink(BluetoothConfiguration* config) - : _connectState(false) +BluetoothLink::BluetoothLink(SharedLinkConfigurationPointer& config) + : LinkInterface(config) + , _config(qobject_cast(config.data())) + , _connectState(false) , _targetSocket(NULL) #ifdef __ios__ , _discoveryAgent(NULL) #endif , _shutDown(false) { - Q_ASSERT(config != NULL); - _config = config; - _config->setLink(this); - //moveToThread(this); + } BluetoothLink::~BluetoothLink() { - // Disconnect link from configuration - _config->setLink(NULL); _disconnect(); #ifdef __ios__ if(_discoveryAgent) { @@ -150,7 +147,7 @@ bool BluetoothLink::_hardwareConnect() _discoveryAgent->start(); #else _createSocket(); - _targetSocket->connectToService(QBluetoothAddress(_config->device().address), QBluetoothUuid(QBluetoothUuid::Rfcomm)); + _targetSocket->connectToService(QBluetoothAddress(_config->device().address), QBluetoothUuid(QBluetoothUuid::SerialPort)); #endif return true; } @@ -352,9 +349,17 @@ void BluetoothConfiguration::startScan() void BluetoothConfiguration::deviceDiscovered(QBluetoothDeviceInfo info) { - //print_device_info(info); if(!info.name().isEmpty() && info.isValid()) { +#if 0 + qDebug() << "Name: " << info.name(); + qDebug() << "Address: " << info.address().toString(); + qDebug() << "Service Classes:" << info.serviceClasses(); + QList uuids = info.serviceUuids(); + foreach (QBluetoothUuid uuid, uuids) { + qDebug() << "Service UUID: " << uuid.toString(); + } +#endif BluetoothData data; data.name = info.name(); #ifdef __ios__ diff --git a/src/comm/BluetoothLink.h b/src/comm/BluetoothLink.h index 2a2b98144dde866c2aaa10ad5521f0e1a08d6b73..e639ac37db98421c5a4fd7cc77a7b4ed31d558e4 100644 --- a/src/comm/BluetoothLink.h +++ b/src/comm/BluetoothLink.h @@ -104,7 +104,6 @@ public: void loadSettings (QSettings& settings, const QString& root); void saveSettings (QSettings& settings, const QString& root); void updateSettings (); - bool isAutoConnectAllowed () { return false; } QString settingsURL () { return "BluetoothSettings.qml"; } public slots: @@ -169,7 +168,7 @@ protected: private: // Links are only created/destroyed by LinkManager so constructor/destructor is not public - BluetoothLink(BluetoothConfiguration* config); + BluetoothLink(SharedLinkConfigurationPointer& config); ~BluetoothLink(); // From LinkInterface diff --git a/src/comm/HexSpinBox.cpp b/src/comm/HexSpinBox.cpp deleted file mode 100644 index 878e9409e6ca56e11b27fcc3bb6e4bdc2350ff9e..0000000000000000000000000000000000000000 --- a/src/comm/HexSpinBox.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "HexSpinBox.h" - -#include - -HexSpinBox::HexSpinBox(QWidget *parent) - : QSpinBox(parent), validator(NULL) -{ - setRange(0, 0x7fffffff); - validator = new QRegExpValidator(QRegExp("[0-9A-Fa-f]{1,8}"), this); -} - -HexSpinBox::~HexSpinBox(void) -{ - if(this->validator) - { - delete this->validator; - this->validator = NULL; - } -} - -QValidator::State HexSpinBox::validate(QString &text, int &pos) const -{ - return validator->validate(text, pos); -} - -QString HexSpinBox::textFromValue(int value) const -{ - return QString::number(value, 16).toUpper(); -} - -int HexSpinBox::valueFromText(const QString &text) const -{ - bool ok; - return text.toInt(&ok, 16); -} \ No newline at end of file diff --git a/src/comm/HexSpinBox.h b/src/comm/HexSpinBox.h deleted file mode 100644 index 84703c95c79e94c931a850a3e64c2bd1cc7a0060..0000000000000000000000000000000000000000 --- a/src/comm/HexSpinBox.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef HEXSPINBOX_H_ -#define HEXSPINBOX_H_ - -#include - -class QRegExpValidator; - -class HexSpinBox : public QSpinBox -{ - Q_OBJECT -public: - HexSpinBox(QWidget *parent = 0); - ~HexSpinBox(void); - -protected: - QValidator::State validate(QString &text, int &pos) const; - int valueFromText(const QString &text) const; - QString textFromValue(int value) const; - -private: - QRegExpValidator *validator; -}; - -#endif // HEXSPINBOX_H_ - diff --git a/src/comm/LinkConfiguration.cc b/src/comm/LinkConfiguration.cc index 367051b73b325befa918480a0cf27b327e2f7908..915c20cda6217c6c3fe51a135a4c7e4c95590651 100644 --- a/src/comm/LinkConfiguration.cc +++ b/src/comm/LinkConfiguration.cc @@ -15,12 +15,12 @@ */ #include "LinkConfiguration.h" -#ifndef __ios__ +#ifndef NO_SERIAL_LINK #include "SerialLink.h" #endif #include "UDPLink.h" #include "TCPLink.h" -#ifndef __mobile__ +#if !defined(__mobile__) #include "LogReplayLink.h" #endif #ifdef QGC_ENABLE_BLUETOOTH @@ -79,7 +79,7 @@ LinkConfiguration* LinkConfiguration::createSettings(int type, const QString& na { LinkConfiguration* config = NULL; switch(type) { -#ifndef __ios__ +#ifndef NO_SERIAL_LINK case LinkConfiguration::TypeSerial: config = new SerialConfiguration(name); break; @@ -117,7 +117,7 @@ LinkConfiguration* LinkConfiguration::duplicateSettings(LinkConfiguration* sourc { LinkConfiguration* dupe = NULL; switch(source->type()) { -#ifndef __ios__ +#ifndef NO_SERIAL_LINK case TypeSerial: dupe = new SerialConfiguration(dynamic_cast(source)); break; diff --git a/src/comm/LinkConfiguration.h b/src/comm/LinkConfiguration.h index 0158cc4a5d449f376393a16d8fde22da17f937d1..76a4bed125f3d3f5f67d1c39c3731ce264a3a26a 100644 --- a/src/comm/LinkConfiguration.h +++ b/src/comm/LinkConfiguration.h @@ -7,7 +7,6 @@ * ****************************************************************************/ - #ifndef LINKCONFIGURATION_H #define LINKCONFIGURATION_H @@ -37,7 +36,7 @@ public: // Property accessors - const QString name(void) { return _name; } + QString name(void) const { return _name; } LinkInterface* link(void) { return _link; } void setName(const QString name); @@ -46,7 +45,7 @@ public: /// The link types supported by QGC /// Any changes here MUST be reflected in LinkManager::linkTypeStrings() enum LinkType { -#ifndef __ios__ +#ifndef NO_SERIAL_LINK TypeSerial, ///< Serial Link #endif TypeUdp, ///< UDP Link @@ -54,12 +53,6 @@ public: #ifdef QGC_ENABLE_BLUETOOTH TypeBluetooth, ///< Bluetooth Link #endif -#if 0 - // TODO Below is not yet implemented - TypeForwarding, ///< Forwarding Link - TypeXbee, ///< XBee Proprietary Link - TypeOpal, ///< Opal-RT Link -#endif #ifdef QT_DEBUG TypeMock, ///< Mock Link for Unitesting #endif @@ -100,7 +93,7 @@ public: * Is Auto Connect allowed for this type? * @return True if this type can be set as an Auto Connect configuration */ - virtual bool isAutoConnectAllowed() { return true; } + virtual bool isAutoConnectAllowed() { return false; } /*! * @brief Connection type @@ -190,4 +183,6 @@ private: bool _autoConnect; ///< This connection is started automatically at boot }; +typedef QSharedPointer SharedLinkConfigurationPointer; + #endif // LINKCONFIGURATION_H diff --git a/src/comm/LinkInterface.cc b/src/comm/LinkInterface.cc new file mode 100644 index 0000000000000000000000000000000000000000..9361fb2b77faf1421d56d9db874a19e6d4d61aa7 --- /dev/null +++ b/src/comm/LinkInterface.cc @@ -0,0 +1,158 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "LinkInterface.h" +#include "QGCApplication.h" + +/// mavlink channel to use for this link, as used by mavlink_parse_char. The mavlink channel is only +/// set into the link when it is added to LinkManager +uint8_t LinkInterface::mavlinkChannel(void) const +{ + if (!_mavlinkChannelSet) { + qWarning() << "Call to LinkInterface::mavlinkChannel with _mavlinkChannelSet == false"; + } + return _mavlinkChannel; +} +// Links are only created by LinkManager so constructor is not public +LinkInterface::LinkInterface(SharedLinkConfigurationPointer& config) + : QThread(0) + , _config(config) + , _mavlinkChannelSet(false) + , _active(false) + , _enableRateCollection(false) + , _decodedFirstMavlinkPacket(false) +{ + _config->setLink(this); + + // Initialize everything for the data rate calculation buffers. + _inDataIndex = 0; + _outDataIndex = 0; + + // Initialize our data rate buffers. + memset(_inDataWriteAmounts, 0, sizeof(_inDataWriteAmounts)); + memset(_inDataWriteTimes, 0, sizeof(_inDataWriteTimes)); + memset(_outDataWriteAmounts,0, sizeof(_outDataWriteAmounts)); + memset(_outDataWriteTimes, 0, sizeof(_outDataWriteTimes)); + + QObject::connect(this, &LinkInterface::_invokeWriteBytes, this, &LinkInterface::_writeBytes); + qRegisterMetaType("LinkInterface*"); +} + +/// This function logs the send times and amounts of datas for input. Data is used for calculating +/// the transmission rate. +/// @param byteCount Number of bytes received +/// @param time Time in ms send occurred +void LinkInterface::_logInputDataRate(quint64 byteCount, qint64 time) { + if(_enableRateCollection) + _logDataRateToBuffer(_inDataWriteAmounts, _inDataWriteTimes, &_inDataIndex, byteCount, time); +} + +/// This function logs the send times and amounts of datas for output. Data is used for calculating +/// the transmission rate. +/// @param byteCount Number of bytes sent +/// @param time Time in ms receive occurred +void LinkInterface::_logOutputDataRate(quint64 byteCount, qint64 time) { + if(_enableRateCollection) + _logDataRateToBuffer(_outDataWriteAmounts, _outDataWriteTimes, &_outDataIndex, byteCount, time); +} + +/** + * @brief logDataRateToBuffer Stores transmission times/amounts for statistics + * + * This function logs the send times and amounts of datas to the given circular buffers. + * This data is used for calculating the transmission rate. + * + * @param bytesBuffer[out] The buffer to write the bytes value into. + * @param timeBuffer[out] The buffer to write the time value into + * @param writeIndex[out] The write index used for this buffer. + * @param bytes The amount of bytes transmit. + * @param time The time (in ms) this transmission occurred. + */ +void LinkInterface::_logDataRateToBuffer(quint64 *bytesBuffer, qint64 *timeBuffer, int *writeIndex, quint64 bytes, qint64 time) +{ + QMutexLocker dataRateLocker(&_dataRateMutex); + + int i = *writeIndex; + + // Now write into the buffer, if there's no room, we just overwrite the first data point. + bytesBuffer[i] = bytes; + timeBuffer[i] = time; + + // Increment and wrap the write index + ++i; + if (i == _dataRateBufferSize) + { + i = 0; + } + *writeIndex = i; +} + +/** + * @brief getCurrentDataRate Get the current data rate given a data rate buffer. + * + * This function attempts to use the times and number of bytes transmit into a current data rate + * estimation. Since it needs to use timestamps to get the timeperiods over when the data was sent, + * this is effectively a global data rate over the last _dataRateBufferSize - 1 data points. Also note + * that data points older than NOW - dataRateCurrentTimespan are ignored. + * + * @param index The first valid sample in the data rate buffer. Refers to the oldest time sample. + * @param dataWriteTimes The time, in ms since epoch, that each data sample took place. + * @param dataWriteAmounts The amount of data (in bits) that was transferred. + * @return The bits per second of data transferrence of the interface over the last [-statsCurrentTimespan, 0] timespan. + */ +qint64 LinkInterface::_getCurrentDataRate(int index, const qint64 dataWriteTimes[], const quint64 dataWriteAmounts[]) const +{ + const qint64 now = QDateTime::currentMSecsSinceEpoch(); + + // Limit the time we calculate to the recent past + const qint64 cutoff = now - _dataRateCurrentTimespan; + + // Grab the mutex for working with the stats variables + QMutexLocker dataRateLocker(&_dataRateMutex); + + // Now iterate through the buffer of all received data packets adding up all values + // within now and our cutof. + qint64 totalBytes = 0; + qint64 totalTime = 0; + qint64 lastTime = 0; + int size = _dataRateBufferSize; + while (size-- > 0) + { + // If this data is within our cutoff time, include it in our calculations. + // This also accounts for when the buffer is empty and filled with 0-times. + if (dataWriteTimes[index] > cutoff && lastTime > 0) { + // Track the total time, using the previous time as our timeperiod. + totalTime += dataWriteTimes[index] - lastTime; + totalBytes += dataWriteAmounts[index]; + } + + // Track the last time sample for doing timespan calculations + lastTime = dataWriteTimes[index]; + + // Increment and wrap the index if necessary. + if (++index == _dataRateBufferSize) + { + index = 0; + } + } + + // Return the final calculated value in bits / s, converted from bytes/ms. + qint64 dataRate = (totalTime != 0)?(qint64)((float)totalBytes * 8.0f / ((float)totalTime / 1000.0f)):0; + + // Finally return our calculated data rate. + return dataRate; +} + +/// Sets the mavlink channel to use for this link +void LinkInterface::_setMavlinkChannel(uint8_t channel) +{ + Q_ASSERT(!_mavlinkChannelSet); + _mavlinkChannelSet = true; + _mavlinkChannel = channel; +} diff --git a/src/comm/LinkInterface.h b/src/comm/LinkInterface.h index ecb8947406e07b8ad0d8a2cdaaac0a14df26969e..477b8a9e49593afcc8d0bb2da52b0fea823058eb 100644 --- a/src/comm/LinkInterface.h +++ b/src/comm/LinkInterface.h @@ -19,9 +19,9 @@ #include #include "QGCMAVLink.h" +#include "LinkConfiguration.h" class LinkManager; -class LinkConfiguration; /** * The link interface defines the interface for all links used to communicate @@ -35,18 +35,16 @@ class LinkInterface : public QThread // Only LinkManager is allowed to create/delete or _connect/_disconnect a link friend class LinkManager; -public: +public: + ~LinkInterface() { _config->setLink(NULL); } + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) // Property accessors - bool active(void) { return _active; } - void setActive(bool active) { _active = active; emit activeChanged(active); } + bool active(void) { return _active; } + void setActive(bool active) { _active = active; emit activeChanged(active); } - /** - * @brief Get link configuration - * @return A pointer to the instance of LinkConfiguration - **/ - virtual LinkConfiguration* getLinkConfiguration() = 0; + LinkConfiguration* getLinkConfiguration(void) { return _config.data(); } /* Connection management */ @@ -116,13 +114,10 @@ public: /// mavlink channel to use for this link, as used by mavlink_parse_char. The mavlink channel is only /// set into the link when it is added to LinkManager - uint8_t mavlinkChannel(void) const - { - if (!_mavlinkChannelSet) { - qWarning() << "Call to LinkInterface::mavlinkChannel with _mavlinkChannelSet == false"; - } - return _mavlinkChannel; - } + uint8_t mavlinkChannel(void) const; + + bool decodedFirstMavlinkPacket(void) const { return _decodedFirstMavlinkPacket; } + bool setDecodedFirstMavlinkPacket(bool decodedFirstMavlinkPacket) { return _decodedFirstMavlinkPacket = decodedFirstMavlinkPacket; } // These are left unimplemented in order to cause linker errors which indicate incorrect usage of // connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager. @@ -192,43 +187,21 @@ signals: protected: // Links are only created by LinkManager so constructor is not public - LinkInterface() : - QThread(0) - , _mavlinkChannelSet(false) - , _active(false) - , _enableRateCollection(false) - { - // Initialize everything for the data rate calculation buffers. - _inDataIndex = 0; - _outDataIndex = 0; - - // Initialize our data rate buffers. - memset(_inDataWriteAmounts, 0, sizeof(_inDataWriteAmounts)); - memset(_inDataWriteTimes, 0, sizeof(_inDataWriteTimes)); - memset(_outDataWriteAmounts,0, sizeof(_outDataWriteAmounts)); - memset(_outDataWriteTimes, 0, sizeof(_outDataWriteTimes)); - - QObject::connect(this, &LinkInterface::_invokeWriteBytes, this, &LinkInterface::_writeBytes); - qRegisterMetaType("LinkInterface*"); - } + LinkInterface(SharedLinkConfigurationPointer& config); /// This function logs the send times and amounts of datas for input. Data is used for calculating /// the transmission rate. /// @param byteCount Number of bytes received /// @param time Time in ms send occurred - void _logInputDataRate(quint64 byteCount, qint64 time) { - if(_enableRateCollection) - _logDataRateToBuffer(_inDataWriteAmounts, _inDataWriteTimes, &_inDataIndex, byteCount, time); - } + void _logInputDataRate(quint64 byteCount, qint64 time); /// This function logs the send times and amounts of datas for output. Data is used for calculating /// the transmission rate. /// @param byteCount Number of bytes sent /// @param time Time in ms receive occurred - void _logOutputDataRate(quint64 byteCount, qint64 time) { - if(_enableRateCollection) - _logDataRateToBuffer(_outDataWriteAmounts, _outDataWriteTimes, &_outDataIndex, byteCount, time); - } + void _logOutputDataRate(quint64 byteCount, qint64 time); + + SharedLinkConfigurationPointer _config; private: /** @@ -243,24 +216,7 @@ private: * @param bytes The amount of bytes transmit. * @param time The time (in ms) this transmission occurred. */ - void _logDataRateToBuffer(quint64 *bytesBuffer, qint64 *timeBuffer, int *writeIndex, quint64 bytes, qint64 time) - { - QMutexLocker dataRateLocker(&_dataRateMutex); - - int i = *writeIndex; - - // Now write into the buffer, if there's no room, we just overwrite the first data point. - bytesBuffer[i] = bytes; - timeBuffer[i] = time; - - // Increment and wrap the write index - ++i; - if (i == _dataRateBufferSize) - { - i = 0; - } - *writeIndex = i; - } + void _logDataRateToBuffer(quint64 *bytesBuffer, qint64 *timeBuffer, int *writeIndex, quint64 bytes, qint64 time); /** * @brief getCurrentDataRate Get the current data rate given a data rate buffer. @@ -275,48 +231,7 @@ private: * @param dataWriteAmounts The amount of data (in bits) that was transferred. * @return The bits per second of data transferrence of the interface over the last [-statsCurrentTimespan, 0] timespan. */ - qint64 _getCurrentDataRate(int index, const qint64 dataWriteTimes[], const quint64 dataWriteAmounts[]) const - { - const qint64 now = QDateTime::currentMSecsSinceEpoch(); - - // Limit the time we calculate to the recent past - const qint64 cutoff = now - _dataRateCurrentTimespan; - - // Grab the mutex for working with the stats variables - QMutexLocker dataRateLocker(&_dataRateMutex); - - // Now iterate through the buffer of all received data packets adding up all values - // within now and our cutof. - qint64 totalBytes = 0; - qint64 totalTime = 0; - qint64 lastTime = 0; - int size = _dataRateBufferSize; - while (size-- > 0) - { - // If this data is within our cutoff time, include it in our calculations. - // This also accounts for when the buffer is empty and filled with 0-times. - if (dataWriteTimes[index] > cutoff && lastTime > 0) { - // Track the total time, using the previous time as our timeperiod. - totalTime += dataWriteTimes[index] - lastTime; - totalBytes += dataWriteAmounts[index]; - } - - // Track the last time sample for doing timespan calculations - lastTime = dataWriteTimes[index]; - - // Increment and wrap the index if necessary. - if (++index == _dataRateBufferSize) - { - index = 0; - } - } - - // Return the final calculated value in bits / s, converted from bytes/ms. - qint64 dataRate = (totalTime != 0)?(qint64)((float)totalBytes * 8.0f / ((float)totalTime / 1000.0f)):0; - - // Finally return our calculated data rate. - return dataRate; - } + qint64 _getCurrentDataRate(int index, const qint64 dataWriteTimes[], const quint64 dataWriteAmounts[]) const; /** * @brief Connect this interface logically @@ -328,7 +243,7 @@ private: virtual void _disconnect(void) = 0; /// Sets the mavlink channel to use for this link - void _setMavlinkChannel(uint8_t channel) { Q_ASSERT(!_mavlinkChannelSet); _mavlinkChannelSet = true; _mavlinkChannel = channel; } + void _setMavlinkChannel(uint8_t channel); bool _mavlinkChannelSet; ///< true: _mavlinkChannel has been set uint8_t _mavlinkChannel; ///< mavlink channel to use for this link, as used by mavlink_parse_char @@ -351,10 +266,11 @@ private: mutable QMutex _dataRateMutex; // Mutex for accessing the data rate member variables - bool _active; ///< true: link is actively receiving mavlink messages + bool _active; ///< true: link is actively receiving mavlink messages bool _enableRateCollection; + bool _decodedFirstMavlinkPacket; ///< true: link has correctly decoded it's first mavlink packet }; -typedef QSharedPointer SharedLinkInterface; +typedef QSharedPointer SharedLinkInterfacePointer; #endif // _LINKINTERFACE_H_ diff --git a/src/comm/LinkManager.cc b/src/comm/LinkManager.cc index 7aef4cad9f358d5a47461b18ead2c9dfda92ec7f..0f6868495a4083d97693986175058ed7cc571a65 100644 --- a/src/comm/LinkManager.cc +++ b/src/comm/LinkManager.cc @@ -7,21 +7,12 @@ * ****************************************************************************/ - -/** - * @file - * @brief Brief Description - * - * @author Lorenz Meier - * - */ - #include #include #include #include -#ifndef __ios__ +#ifndef NO_SERIAL_LINK #include "QGCSerialPortInfo.h" #endif @@ -29,6 +20,7 @@ #include "QGCApplication.h" #include "UDPLink.h" #include "TCPLink.h" +#include "SettingsManager.h" #ifdef QGC_ENABLE_BLUETOOTH #include "BluetoothLink.h" #endif @@ -40,14 +32,7 @@ QGC_LOGGING_CATEGORY(LinkManagerLog, "LinkManagerLog") QGC_LOGGING_CATEGORY(LinkManagerVerboseLog, "LinkManagerVerboseLog") -const char* LinkManager::_settingsGroup = "LinkManager"; -const char* LinkManager::_autoconnectUDPKey = "AutoconnectUDP"; -const char* LinkManager::_autoconnectPixhawkKey = "AutoconnectPixhawk"; -const char* LinkManager::_autoconnect3DRRadioKey = "Autoconnect3DRRadio"; -const char* LinkManager::_autoconnectPX4FlowKey = "AutoconnectPX4Flow"; -const char* LinkManager::_autoconnectRTKGPSKey = "AutoconnectRTKGPS"; -const char* LinkManager::_autoconnectLibrePilotKey = "AutoconnectLibrePilot"; -const char* LinkManager::_defaultUPDLinkName = "Default UDP Link"; +const char* LinkManager::_defaultUPDLinkName = "UDP Link (AutoConnect)"; const int LinkManager::_autoconnectUpdateTimerMSecs = 1000; #ifdef Q_OS_WIN @@ -58,34 +43,19 @@ const int LinkManager::_autoconnectConnectDelayMSecs = 1000; #endif LinkManager::LinkManager(QGCApplication* app) - : QGCTool(app) + : QGCTool(app) , _configUpdateSuspended(false) , _configurationsLoaded(false) , _connectionsSuspended(false) , _mavlinkChannelsUsedBitMask(1) // We never use channel 0 to avoid sequence numbering problems + , _autoConnectSettings(NULL) , _mavlinkProtocol(NULL) - , _autoconnectUDP(true) - , _autoconnectPixhawk(true) - , _autoconnect3DRRadio(true) - , _autoconnectPX4Flow(true) - , _autoconnectRTKGPS(true) - , _autoconnectLibrePilot(true) { qmlRegisterUncreatableType ("QGroundControl", 1, 0, "LinkManager", "Reference only"); qmlRegisterUncreatableType ("QGroundControl", 1, 0, "LinkConfiguration", "Reference only"); qmlRegisterUncreatableType ("QGroundControl", 1, 0, "LinkInterface", "Reference only"); - QSettings settings; - - settings.beginGroup(_settingsGroup); - _autoconnectUDP = settings.value(_autoconnectUDPKey, true).toBool(); - _autoconnectPixhawk = settings.value(_autoconnectPixhawkKey, true).toBool(); - _autoconnect3DRRadio = settings.value(_autoconnect3DRRadioKey, true).toBool(); - _autoconnectPX4Flow = settings.value(_autoconnectPX4FlowKey, true).toBool(); - _autoconnectRTKGPS = settings.value(_autoconnectRTKGPSKey, true).toBool(); - _autoconnectLibrePilot = settings.value(_autoconnectLibrePilotKey, true).toBool(); - -#ifndef __ios__ +#ifndef NO_SERIAL_LINK _activeLinkCheckTimer.setInterval(_activeLinkCheckTimeoutMSecs); _activeLinkCheckTimer.setSingleShot(false); connect(&_activeLinkCheckTimer, &QTimer::timeout, this, &LinkManager::_activeLinkCheck); @@ -101,6 +71,7 @@ void LinkManager::setToolbox(QGCToolbox *toolbox) { QGCTool::setToolbox(toolbox); + _autoConnectSettings = toolbox->settingsManager()->autoConnectSettings(); _mavlinkProtocol = _toolbox->mavlinkProtocol(); connect(&_portListTimer, &QTimer::timeout, this, &LinkManager::_updateAutoConnectLinks); @@ -108,17 +79,31 @@ void LinkManager::setToolbox(QGCToolbox *toolbox) } -LinkInterface* LinkManager::createConnectedLink(LinkConfiguration* config) +// This should only be used by Qml code +void LinkManager::createConnectedLink(LinkConfiguration* config) { - Q_ASSERT(config); + for(int i = 0; i < _sharedConfigurations.count(); i++) { + SharedLinkConfigurationPointer& sharedConf = _sharedConfigurations[i]; + if (sharedConf->name() == config->name()) + createConnectedLink(sharedConf); + } +} + +LinkInterface* LinkManager::createConnectedLink(SharedLinkConfigurationPointer& config) +{ + if (!config) { + qWarning() << "LinkManager::createConnectedLink called with NULL config"; + return NULL; + } + LinkInterface* pLink = NULL; switch(config->type()) { -#ifndef __ios__ +#ifndef NO_SERIAL_LINK case LinkConfiguration::TypeSerial: { - SerialConfiguration* serialConfig = dynamic_cast(config); + SerialConfiguration* serialConfig = dynamic_cast(config.data()); if (serialConfig) { - pLink = new SerialLink(serialConfig); + pLink = new SerialLink(config); if (serialConfig->usbDirect()) { _activeLinkCheckList.append((SerialLink*)pLink); if (!_activeLinkCheckTimer.isActive()) { @@ -130,43 +115,45 @@ LinkInterface* LinkManager::createConnectedLink(LinkConfiguration* config) break; #endif case LinkConfiguration::TypeUdp: - pLink = new UDPLink(dynamic_cast(config)); + pLink = new UDPLink(config); break; case LinkConfiguration::TypeTcp: - pLink = new TCPLink(dynamic_cast(config)); + pLink = new TCPLink(config); break; #ifdef QGC_ENABLE_BLUETOOTH case LinkConfiguration::TypeBluetooth: - pLink = new BluetoothLink(dynamic_cast(config)); + pLink = new BluetoothLink(config); break; #endif #ifndef __mobile__ case LinkConfiguration::TypeLogReplay: - pLink = new LogReplayLink(dynamic_cast(config)); + pLink = new LogReplayLink(config); break; #endif #ifdef QT_DEBUG case LinkConfiguration::TypeMock: - pLink = new MockLink(dynamic_cast(config)); + pLink = new MockLink(config); break; #endif case LinkConfiguration::TypeLast: default: break; } - if(pLink) { + + if (pLink) { _addLink(pLink); connectLink(pLink); } + return pLink; } LinkInterface* LinkManager::createConnectedLink(const QString& name) { Q_ASSERT(name.isEmpty() == false); - for(int i = 0; i < _linkConfigurations.count(); i++) { - LinkConfiguration* conf = _linkConfigurations.value(i); - if(conf && conf->name() == name) + for(int i = 0; i < _sharedConfigurations.count(); i++) { + SharedLinkConfigurationPointer& conf = _sharedConfigurations[i]; + if (conf->name() == name) return createConnectedLink(conf); } return NULL; @@ -183,7 +170,7 @@ void LinkManager::_addLink(LinkInterface* link) return; } - if (!_links.contains(link)) { + if (!containsLink(link)) { bool channelSet = false; // Find a mavlink channel to use for this link, Channel 0 is reserved for internal use. @@ -194,7 +181,7 @@ void LinkManager::_addLink(LinkInterface* link) // Start the channel on Mav 1 protocol mavlink_status_t* mavlinkStatus = mavlink_get_channel_status(i); mavlinkStatus->flags = mavlink_get_channel_status(i)->flags | MAVLINK_STATUS_FLAG_OUT_MAVLINK1; - qDebug() << "LinkManager mavlinkStatus" << mavlinkStatus << i << mavlinkStatus->flags; + qDebug() << "LinkManager mavlinkStatus:channel:flags" << mavlinkStatus << i << mavlinkStatus->flags; _mavlinkChannelsUsedBitMask |= 1 << i; channelSet = true; break; @@ -205,7 +192,7 @@ void LinkManager::_addLink(LinkInterface* link) qWarning() << "Ran out of mavlink channels"; } - _links.append(link); + _sharedLinks.append(SharedLinkInterfacePointer(link)); emit newLink(link); } @@ -225,8 +212,8 @@ void LinkManager::_addLink(LinkInterface* link) void LinkManager::disconnectAll(void) { // Walk list in reverse order to preserve indices during delete - for (int i=_links.count()-1; i>=0; i--) { - disconnectLink(_links.value(i)); + for (int i=_sharedLinks.count()-1; i>=0; i--) { + disconnectLink(_sharedLinks[i].data()); } } @@ -243,23 +230,22 @@ bool LinkManager::connectLink(LinkInterface* link) void LinkManager::disconnectLink(LinkInterface* link) { - if (!link || !_links.contains(link)) { + if (!link || !containsLink(link)) { return; } link->_disconnect(); + LinkConfiguration* config = link->getLinkConfiguration(); - if (config) { - if (_autoconnectConfigurations.contains(config)) { - config->setLink(NULL); + for (int i=0; i<_sharedAutoconnectConfigurations.count(); i++) { + if (_sharedAutoconnectConfigurations[i].data() == config) { + qCDebug(LinkManagerLog) << "Removing disconnected autoconnect config" << config->name(); + _sharedAutoconnectConfigurations.removeAt(i); + break; } } + _deleteLink(link); - if (_autoconnectConfigurations.contains(config)) { - qCDebug(LinkManagerLog) << "Removing disconnected autoconnect config" << config->name(); - _autoconnectConfigurations.removeOne(config); - delete config; - } } void LinkManager::_deleteLink(LinkInterface* link) @@ -276,13 +262,29 @@ void LinkManager::_deleteLink(LinkInterface* link) // Free up the mavlink channel associated with this link _mavlinkChannelsUsedBitMask &= ~(1 << link->mavlinkChannel()); - _links.removeOne(link); - delete link; + for (int i=0; i<_sharedLinks.count(); i++) { + if (_sharedLinks[i].data() == link) { + _sharedLinks.removeAt(i); + break; + } + } // Emit removal of link emit linkDeleted(link); } +SharedLinkInterfacePointer LinkManager::sharedLinkInterfacePointerForLink(LinkInterface* link) +{ + for (int i=0; i<_sharedLinks.count(); i++) { + if (_sharedLinks[i].data() == link) { + return _sharedLinks[i]; + } + } + + qWarning() << "LinkManager::sharedLinkInterfaceForLink returning NULL"; + return SharedLinkInterfacePointer(NULL); +} + /// @brief If all new connections should be suspended a message is displayed to the user and true /// is returned; bool LinkManager::_connectionsSuspendedMsg(void) @@ -328,11 +330,10 @@ void LinkManager::saveLinkConfigurationList() QSettings settings; settings.remove(LinkConfiguration::settingsRoot()); int trueCount = 0; - for (int i = 0; i < _linkConfigurations.count(); i++) { - LinkConfiguration* linkConfig = _linkConfigurations.value(i); + for (int i = 0; i < _sharedConfigurations.count(); i++) { + SharedLinkConfigurationPointer linkConfig = _sharedConfigurations[i]; if (linkConfig) { - if(!linkConfig->isDynamic()) - { + if (!linkConfig->isDynamic()) { QString root = LinkConfiguration::settingsRoot(); root += QString("/Link%1").arg(trueCount++); settings.setValue(root + "/name", linkConfig->name()); @@ -353,9 +354,6 @@ void LinkManager::saveLinkConfigurationList() void LinkManager::loadLinkConfigurationList() { bool linksChanged = false; -#ifdef QT_DEBUG - bool mockPresent = false; -#endif QSettings settings; // Is the group even there? if(settings.contains(LinkConfiguration::settingsRoot() + "/count")) { @@ -373,7 +371,7 @@ void LinkManager::loadLinkConfigurationList() LinkConfiguration* pLink = NULL; bool autoConnect = settings.value(root + "/auto").toBool(); switch((LinkConfiguration::LinkType)type) { -#ifndef __ios__ +#ifndef NO_SERIAL_LINK case LinkConfiguration::TypeSerial: pLink = (LinkConfiguration*)new SerialConfiguration(name); break; @@ -397,7 +395,6 @@ void LinkManager::loadLinkConfigurationList() #ifdef QT_DEBUG case LinkConfiguration::TypeMock: pLink = (LinkConfiguration*)new MockConfiguration(name); - mockPresent = true; break; #endif default: @@ -408,7 +405,7 @@ void LinkManager::loadLinkConfigurationList() //-- Have the instance load its own values pLink->setAutoConnect(autoConnect); pLink->loadSettings(settings, root); - _linkConfigurations.append(pLink); + addConfiguration(pLink); linksChanged = true; } } else { @@ -425,16 +422,6 @@ void LinkManager::loadLinkConfigurationList() } } } - // Debug buids always add MockLink automatically (if one is not already there) -#ifdef QT_DEBUG - if(!mockPresent) - { - MockConfiguration* pMock = new MockConfiguration("Mock Link PX4"); - pMock->setDynamic(true); - _linkConfigurations.append(pMock); - linksChanged = true; - } -#endif if(linksChanged) { emit linkConfigurationsChanged(); @@ -443,17 +430,17 @@ void LinkManager::loadLinkConfigurationList() _configurationsLoaded = true; } -#ifndef __ios__ +#ifndef NO_SERIAL_LINK SerialConfiguration* LinkManager::_autoconnectConfigurationsContainsPort(const QString& portName) { QString searchPort = portName.trimmed(); - for (int i=0; i<_autoconnectConfigurations.count(); i++) { - SerialConfiguration* linkConfig = _autoconnectConfigurations.value(i); + for (int i=0; i<_sharedAutoconnectConfigurations.count(); i++) { + SerialConfiguration* serialConfig = qobject_cast(_sharedAutoconnectConfigurations[i].data()); - if (linkConfig) { - if (linkConfig->portName() == searchPort) { - return linkConfig; + if (serialConfig) { + if (serialConfig->portName() == searchPort) { + return serialConfig; } } else { qWarning() << "Internal error"; @@ -471,26 +458,37 @@ void LinkManager::_updateAutoConnectLinks(void) // Re-add UDP if we need to bool foundUDP = false; - for (int i=0; i<_links.count(); i++) { - LinkConfiguration* linkConfig = _links.value(i)->getLinkConfiguration(); + for (int i=0; i<_sharedLinks.count(); i++) { + LinkConfiguration* linkConfig = _sharedLinks[i]->getLinkConfiguration(); if (linkConfig->type() == LinkConfiguration::TypeUdp && linkConfig->name() == _defaultUPDLinkName) { foundUDP = true; break; } } - if (!foundUDP && _autoconnectUDP) { + if (!foundUDP && _autoConnectSettings->autoConnectUDP()->rawValue().toBool()) { qCDebug(LinkManagerLog) << "New auto-connect UDP port added"; UDPConfiguration* udpConfig = new UDPConfiguration(_defaultUPDLinkName); udpConfig->setLocalPort(QGC_UDP_LOCAL_PORT); - udpConfig->setDynamic(true); - _linkConfigurations.append(udpConfig); - createConnectedLink(udpConfig); + udpConfig->setDynamic(true); + SharedLinkConfigurationPointer config = addConfiguration(udpConfig); + createConnectedLink(config); emit linkConfigurationsChanged(); } -#ifndef __ios__ +#ifndef NO_SERIAL_LINK QStringList currentPorts; - QList portList = QGCSerialPortInfo::availablePorts(); + QList portList; + +#ifdef __android__ + // Android builds only support a single serial connection. Repeatedly calling availablePorts after that one serial + // port is connected leaks file handles due to a bug somewhere in android serial code. In order to work around that + // bug after we connect the first serial port we stop probing for additional ports. + if (!_sharedAutoconnectConfigurations.count()) { + portList = QGCSerialPortInfo::availablePorts(); + } +#else + portList = QGCSerialPortInfo::availablePorts(); +#endif // Iterate Comm Ports foreach (QGCSerialPortInfo portInfo, portList) { @@ -506,9 +504,10 @@ void LinkManager::_updateAutoConnectLinks(void) // Save port name currentPorts << portInfo.systemLocation(); - QGCSerialPortInfo::BoardType_t boardType = portInfo.boardType(); + QGCSerialPortInfo::BoardType_t boardType; + QString boardName; - if (boardType != QGCSerialPortInfo::BoardTypeUnknown) { + if (portInfo.getBoardInfo(boardType, boardName)) { if (portInfo.isBootloader()) { // Don't connect to bootloader qCDebug(LinkManagerLog) << "Waiting for bootloader to finish" << portInfo.systemLocation(); @@ -529,56 +528,30 @@ void LinkManager::_updateAutoConnectLinks(void) _autoconnectWaitList.remove(portInfo.systemLocation()); switch (boardType) { - case QGCSerialPortInfo::BoardTypePX4FMUV1: - case QGCSerialPortInfo::BoardTypePX4FMUV2: - case QGCSerialPortInfo::BoardTypePX4FMUV4: - if (_autoconnectPixhawk) { - pSerialConfig = new SerialConfiguration(QString("Pixhawk on %1").arg(portInfo.portName().trimmed())); - pSerialConfig->setUsbDirect(true); - } - break; - case QGCSerialPortInfo::BoardTypeAeroCore: - if (_autoconnectPixhawk) { - pSerialConfig = new SerialConfiguration(QString("AeroCore on %1").arg(portInfo.portName().trimmed())); - pSerialConfig->setUsbDirect(true); - } - break; - case QGCSerialPortInfo::BoardTypeMINDPXFMUV2: - if (_autoconnectPixhawk) { - pSerialConfig = new SerialConfiguration(QString("MindPX on %1").arg(portInfo.portName().trimmed())); - pSerialConfig->setUsbDirect(true); - } - break; - case QGCSerialPortInfo::BoardTypeTAPV1: - if (_autoconnectPixhawk) { - pSerialConfig = new SerialConfiguration(QString("TAP on %1").arg(portInfo.portName().trimmed())); - pSerialConfig->setUsbDirect(true); - } - break; - case QGCSerialPortInfo::BoardTypeASCV1: - if (_autoconnectPixhawk) { - pSerialConfig = new SerialConfiguration(QString("ASC on %1").arg(portInfo.portName().trimmed())); + case QGCSerialPortInfo::BoardTypePixhawk: + if (_autoConnectSettings->autoConnectPixhawk()->rawValue().toBool()) { + pSerialConfig = new SerialConfiguration(tr("%1 on %2 (AutoConnect)").arg(boardName).arg(portInfo.portName().trimmed())); pSerialConfig->setUsbDirect(true); } break; case QGCSerialPortInfo::BoardTypePX4Flow: - if (_autoconnectPX4Flow) { - pSerialConfig = new SerialConfiguration(QString("PX4Flow on %1").arg(portInfo.portName().trimmed())); + if (_autoConnectSettings->autoConnectPX4Flow()->rawValue().toBool()) { + pSerialConfig = new SerialConfiguration(tr("%1 on %2 (AutoConnect)").arg(boardName).arg(portInfo.portName().trimmed())); } break; - case QGCSerialPortInfo::BoardTypeSikRadio: - if (_autoconnect3DRRadio) { - pSerialConfig = new SerialConfiguration(QString("SiK Radio on %1").arg(portInfo.portName().trimmed())); + case QGCSerialPortInfo::BoardTypeSiKRadio: + if (_autoConnectSettings->autoConnectSiKRadio()->rawValue().toBool()) { + pSerialConfig = new SerialConfiguration(tr("%1 on %2 (AutoConnect)").arg(boardName).arg(portInfo.portName().trimmed())); } break; - case QGCSerialPortInfo::BoardTypeLibrePilot: - if (_autoconnectLibrePilot) { - pSerialConfig = new SerialConfiguration(QString("LibrePilot on %1").arg(portInfo.portName().trimmed())); + case QGCSerialPortInfo::BoardTypeOpenPilot: + if (_autoConnectSettings->autoConnectLibrePilot()->rawValue().toBool()) { + pSerialConfig = new SerialConfiguration(tr("%1 on %2 (AutoConnect)").arg(boardName).arg(portInfo.portName().trimmed())); } break; #ifndef __mobile__ case QGCSerialPortInfo::BoardTypeRTKGPS: - if (_autoconnectRTKGPS && !_toolbox->gpsManager()->connected()) { + if (_autoConnectSettings->autoConnectRTKGPS()->rawValue().toBool() && !_toolbox->gpsManager()->connected()) { qCDebug(LinkManagerLog) << "RTK GPS auto-connected"; _toolbox->gpsManager()->connectGPS(portInfo.systemLocation()); } @@ -591,25 +564,32 @@ void LinkManager::_updateAutoConnectLinks(void) if (pSerialConfig) { qCDebug(LinkManagerLog) << "New auto-connect port added: " << pSerialConfig->name() << portInfo.systemLocation(); - pSerialConfig->setBaud(boardType == QGCSerialPortInfo::BoardTypeSikRadio ? 57600 : 115200); + pSerialConfig->setBaud(boardType == QGCSerialPortInfo::BoardTypeSiKRadio ? 57600 : 115200); pSerialConfig->setDynamic(true); pSerialConfig->setPortName(portInfo.systemLocation()); - _autoconnectConfigurations.append(pSerialConfig); - createConnectedLink(pSerialConfig); + _sharedAutoconnectConfigurations.append(SharedLinkConfigurationPointer(pSerialConfig)); + createConnectedLink(_sharedAutoconnectConfigurations.last()); } } } } +#ifndef __android__ + // Android builds only support a single serial connection. Repeatedly calling availablePorts after that one serial + // port is connected leaks file handles due to a bug somewhere in android serial code. In order to work around that + // bug after we connect the first serial port we stop probing for additional ports. The means we must rely on + // the port disconnecting itself when the radio is pulled to signal communication list as opposed to automatically + // closing the Link. + // Now we go through the current configuration list and make sure any dynamic config has gone away QList _confToDelete; - for (int i=0; i<_autoconnectConfigurations.count(); i++) { - SerialConfiguration* linkConfig = _autoconnectConfigurations.value(i); - if (linkConfig) { - if (!currentPorts.contains(linkConfig->portName())) { - if (linkConfig->link()) { - if (linkConfig->link()->isConnected()) { - if (linkConfig->link()->active()) { + for (int i=0; i<_sharedAutoconnectConfigurations.count(); i++) { + SerialConfiguration* serialConfig = qobject_cast(_sharedAutoconnectConfigurations[i].data()); + if (serialConfig) { + if (!currentPorts.contains(serialConfig->portName())) { + if (serialConfig->link()) { + if (serialConfig->link()->isConnected()) { + if (serialConfig->link()->active()) { // We don't remove links which are still connected which have been active with a vehicle on them // even though at this point the cable may have been pulled. Instead we wait for the user to // Disconnect. Once the user disconnects, the link will be removed. @@ -617,7 +597,7 @@ void LinkManager::_updateAutoConnectLinks(void) } } } - _confToDelete.append(linkConfig); + _confToDelete.append(serialConfig); } } else { qWarning() << "Internal error"; @@ -627,13 +607,18 @@ void LinkManager::_updateAutoConnectLinks(void) // Now remove all configs that are gone foreach (LinkConfiguration* pDeleteConfig, _confToDelete) { qCDebug(LinkManagerLog) << "Removing unused autoconnect config" << pDeleteConfig->name(); - _autoconnectConfigurations.removeOne(pDeleteConfig); if (pDeleteConfig->link()) { disconnectLink(pDeleteConfig->link()); } - delete pDeleteConfig; + for (int i=0; i<_sharedAutoconnectConfigurations.count(); i++) { + if (_sharedAutoconnectConfigurations[i].data() == pDeleteConfig) { + _sharedAutoconnectConfigurations.removeAt(i); + break; + } + } } -#endif // __ios__ +#endif +#endif // NO_SERIAL_LINK } void LinkManager::shutdown(void) @@ -642,69 +627,13 @@ void LinkManager::shutdown(void) disconnectAll(); } -bool LinkManager::_setAutoconnectWorker(bool& currentAutoconnect, bool newAutoconnect, const char* autoconnectKey) -{ - if (currentAutoconnect != newAutoconnect) { - QSettings settings; - - settings.beginGroup(_settingsGroup); - settings.setValue(autoconnectKey, newAutoconnect); - currentAutoconnect = newAutoconnect; - return true; - } - - return false; -} - -void LinkManager::setAutoconnectUDP(bool autoconnect) -{ - if (_setAutoconnectWorker(_autoconnectUDP, autoconnect, _autoconnectUDPKey)) { - emit autoconnectUDPChanged(autoconnect); - } -} - -void LinkManager::setAutoconnectPixhawk(bool autoconnect) -{ - if (_setAutoconnectWorker(_autoconnectPixhawk, autoconnect, _autoconnectPixhawkKey)) { - emit autoconnectPixhawkChanged(autoconnect); - } -} - -void LinkManager::setAutoconnect3DRRadio(bool autoconnect) -{ - if (_setAutoconnectWorker(_autoconnect3DRRadio, autoconnect, _autoconnect3DRRadioKey)) { - emit autoconnect3DRRadioChanged(autoconnect); - } -} - -void LinkManager::setAutoconnectPX4Flow(bool autoconnect) -{ - if (_setAutoconnectWorker(_autoconnectPX4Flow, autoconnect, _autoconnectPX4FlowKey)) { - emit autoconnectPX4FlowChanged(autoconnect); - } -} - -void LinkManager::setAutoconnectRTKGPS(bool autoconnect) -{ - if (_setAutoconnectWorker(_autoconnectRTKGPS, autoconnect, _autoconnectRTKGPSKey)) { - emit autoconnectRTKGPSChanged(autoconnect); - } -} - -void LinkManager::setAutoconnectLibrePilot(bool autoconnect) -{ - if (_setAutoconnectWorker(_autoconnectLibrePilot, autoconnect, _autoconnectLibrePilotKey)) { - emit autoconnectLibrePilotChanged(autoconnect); - } -} - QStringList LinkManager::linkTypeStrings(void) const { //-- Must follow same order as enum LinkType in LinkConfiguration.h static QStringList list; if(!list.size()) { -#ifndef __ios__ +#ifndef NO_SERIAL_LINK list += "Serial"; #endif list += "UDP"; @@ -727,7 +656,7 @@ void LinkManager::_updateSerialPorts() { _commPortList.clear(); _commPortDisplayList.clear(); -#ifndef __ios__ +#ifndef NO_SERIAL_LINK QList portList = QSerialPortInfo::availablePorts(); foreach (const QSerialPortInfo &info, portList) { @@ -758,7 +687,7 @@ QStringList LinkManager::serialPorts(void) QStringList LinkManager::serialBaudRates(void) { -#ifdef __ios__ +#ifdef NO_SERIAL_LINK QStringList foo; return foo; #else @@ -784,14 +713,14 @@ bool LinkManager::endCreateConfiguration(LinkConfiguration* config) { Q_ASSERT(config != NULL); _fixUnnamed(config); - _linkConfigurations.append(config); + addConfiguration(config); saveLinkConfigurationList(); return true; } LinkConfiguration* LinkManager::createConfiguration(int type, const QString& name) { -#ifndef __ios__ +#ifndef NO_SERIAL_LINK if((LinkConfiguration::LinkType)type == LinkConfiguration::TypeSerial) _updateSerialPorts(); #endif @@ -801,7 +730,7 @@ LinkConfiguration* LinkManager::createConfiguration(int type, const QString& nam LinkConfiguration* LinkManager::startConfigurationEditing(LinkConfiguration* config) { Q_ASSERT(config != NULL); -#ifndef __ios__ +#ifndef NO_SERIAL_LINK if(config->type() == LinkConfiguration::TypeSerial) _updateSerialPorts(); #endif @@ -815,7 +744,7 @@ void LinkManager::_fixUnnamed(LinkConfiguration* config) //-- Check for "Unnamed" if (config->name() == "Unnamed") { switch(config->type()) { -#ifndef __ios__ +#ifndef NO_SERIAL_LINK case LinkConfiguration::TypeSerial: { QString tname = dynamic_cast(config)->portName(); #ifdef Q_OS_WIN @@ -878,16 +807,19 @@ void LinkManager::removeConfiguration(LinkConfiguration* config) if(iface) { disconnectLink(iface); } - // Remove configuration - _linkConfigurations.removeOne(config); - delete config; - // Save list + + _removeConfiguration(config); saveLinkConfigurationList(); } bool LinkManager::isAutoconnectLink(LinkInterface* link) { - return _autoconnectConfigurations.contains(link->getLinkConfiguration()); + for (int i=0; i<_sharedAutoconnectConfigurations.count(); i++) { + if (_sharedAutoconnectConfigurations[i].data() == link->getLinkConfiguration()) { + return true; + } + } + return false; } bool LinkManager::isBluetoothAvailable(void) @@ -895,7 +827,7 @@ bool LinkManager::isBluetoothAvailable(void) return qgcApp()->isBluetoothAvailable(); } -#ifndef __ios__ +#ifndef NO_SERIAL_LINK void LinkManager::_activeLinkCheck(void) { SerialLink* link = NULL; @@ -903,7 +835,7 @@ void LinkManager::_activeLinkCheck(void) if (_activeLinkCheckList.count() != 0) { link = _activeLinkCheckList.takeFirst(); - if (_links.contains(link) && link->isConnected()) { + if (containsLink(link) && link->isConnected()) { // Make sure there is a vehicle on the link QmlObjectListModel* vehicles = _toolbox->multiVehicleManager()->vehicles(); for (int i=0; icount(); i++) { @@ -940,3 +872,56 @@ void LinkManager::_activeLinkCheck(void) } } #endif + +bool LinkManager::containsLink(LinkInterface* link) +{ + for (int i=0; i<_sharedLinks.count(); i++) { + if (_sharedLinks[i].data() == link) { + return true; + } + } + return false; +} + +SharedLinkConfigurationPointer LinkManager::addConfiguration(LinkConfiguration* config) +{ + _qmlConfigurations.append(config); + _sharedConfigurations.append(SharedLinkConfigurationPointer(config)); + return _sharedConfigurations.last(); +} + +void LinkManager::_removeConfiguration(LinkConfiguration* config) +{ + _qmlConfigurations.removeOne(config); + + for (int i=0; i<_sharedConfigurations.count(); i++) { + if (_sharedConfigurations[i].data() == config) { + _sharedConfigurations.removeAt(i); + return; + } + } + + qWarning() << "LinkManager::_removeConfiguration called with unknown config"; +} + +QList LinkManager::links(void) +{ + QList rawLinks; + + for (int i=0; i<_sharedLinks.count(); i++) { + rawLinks.append(_sharedLinks[i].data()); + } + + return rawLinks; +} + +void LinkManager::startAutoConnectedLinks(void) +{ + SharedLinkConfigurationPointer conf; + + for(int i = 0; i < _sharedConfigurations.count(); i++) { + conf = _sharedConfigurations[i]; + if (conf->isAutoConnect()) + createConnectedLink(conf); + } +} diff --git a/src/comm/LinkManager.h b/src/comm/LinkManager.h index 330572033e848d670e3cb33a9abcdfc79c0a58eb..9341b5625a9a768b091533bde82e2279e17afda9 100644 --- a/src/comm/LinkManager.h +++ b/src/comm/LinkManager.h @@ -24,12 +24,12 @@ #include "QGCToolbox.h" #include "ProtocolInterface.h" #include "MAVLinkProtocol.h" -#ifndef __mobile__ +#if !defined(__mobile__) #include "LogReplayLink.h" #endif #include "QmlObjectListModel.h" -#ifndef __ios__ +#ifndef NO_SERIAL_LINK #include "SerialLink.h" #endif @@ -37,12 +37,12 @@ #include "MockLink.h" #endif -class UDPConfiguration; - Q_DECLARE_LOGGING_CATEGORY(LinkManagerLog) Q_DECLARE_LOGGING_CATEGORY(LinkManagerVerboseLog) class QGCApplication; +class UDPConfiguration; +class AutoConnectSettings; /// Manage communication links /// @@ -61,25 +61,11 @@ public: LinkManager(QGCApplication* app); ~LinkManager(); - Q_PROPERTY(bool autoconnectUDP READ autoconnectUDP WRITE setAutoconnectUDP NOTIFY autoconnectUDPChanged) - Q_PROPERTY(bool autoconnectPixhawk READ autoconnectPixhawk WRITE setAutoconnectPixhawk NOTIFY autoconnectPixhawkChanged) - Q_PROPERTY(bool autoconnect3DRRadio READ autoconnect3DRRadio WRITE setAutoconnect3DRRadio NOTIFY autoconnect3DRRadioChanged) - Q_PROPERTY(bool autoconnectPX4Flow READ autoconnectPX4Flow WRITE setAutoconnectPX4Flow NOTIFY autoconnectPX4FlowChanged) - Q_PROPERTY(bool autoconnectRTKGPS READ autoconnectRTKGPS WRITE setAutoconnectRTKGPS NOTIFY autoconnectRTKGPSChanged) - Q_PROPERTY(bool autoconnectLibrePilot READ autoconnectLibrePilot WRITE setAutoconnectLibrePilot NOTIFY autoconnectLibrePilotChanged) - Q_PROPERTY(bool isBluetoothAvailable READ isBluetoothAvailable CONSTANT) - - /// LinkInterface Accessor - Q_PROPERTY(QmlObjectListModel* links READ links CONSTANT) - /// LinkConfiguration Accessor - Q_PROPERTY(QmlObjectListModel* linkConfigurations READ linkConfigurations NOTIFY linkConfigurationsChanged) - /// List of comm type strings - Q_PROPERTY(QStringList linkTypeStrings READ linkTypeStrings CONSTANT) - /// List of supported baud rates for serial links - Q_PROPERTY(QStringList serialBaudRates READ serialBaudRates CONSTANT) - /// List of comm ports display names + Q_PROPERTY(bool isBluetoothAvailable READ isBluetoothAvailable CONSTANT) + Q_PROPERTY(QmlObjectListModel* linkConfigurations READ _qmlLinkConfigurations NOTIFY linkConfigurationsChanged) + Q_PROPERTY(QStringList linkTypeStrings READ linkTypeStrings CONSTANT) + Q_PROPERTY(QStringList serialBaudRates READ serialBaudRates CONSTANT) Q_PROPERTY(QStringList serialPortStrings READ serialPortStrings NOTIFY commPortStringsChanged) - /// List of comm ports Q_PROPERTY(QStringList serialPorts READ serialPorts NOTIFY commPortsChanged) // Create/Edit Link Configuration @@ -92,27 +78,13 @@ public: // Property accessors - bool autoconnectUDP (void) { return _autoconnectUDP; } - bool autoconnectPixhawk (void) { return _autoconnectPixhawk; } - bool autoconnect3DRRadio (void) { return _autoconnect3DRRadio; } - bool autoconnectPX4Flow (void) { return _autoconnectPX4Flow; } - bool autoconnectRTKGPS (void) { return _autoconnectRTKGPS; } - bool autoconnectLibrePilot (void) { return _autoconnectLibrePilot; } bool isBluetoothAvailable (void); - QmlObjectListModel* links (void) { return &_links; } - QmlObjectListModel* linkConfigurations (void) { return &_linkConfigurations; } - QStringList linkTypeStrings (void) const; - QStringList serialBaudRates (void); - QStringList serialPortStrings (void); - QStringList serialPorts (void); - - void setAutoconnectUDP (bool autoconnect); - void setAutoconnectPixhawk (bool autoconnect); - void setAutoconnect3DRRadio (bool autoconnect); - void setAutoconnectPX4Flow (bool autoconnect); - void setAutoconnectRTKGPS (bool autoconnect); - void setAutoconnectLibrePilot (bool autoconnect); + QList links (void); + QStringList linkTypeStrings (void) const; + QStringList serialBaudRates (void); + QStringList serialPortStrings (void); + QStringList serialPorts (void); /// Load list of link configurations from disk void loadLinkConfigurationList(); @@ -132,7 +104,10 @@ public: /// Creates, connects (and adds) a link based on the given configuration instance. /// Link takes ownership of config. - Q_INVOKABLE LinkInterface* createConnectedLink(LinkConfiguration* config); + LinkInterface* createConnectedLink(SharedLinkConfigurationPointer& config); + + // This should only be used by Qml code + Q_INVOKABLE void createConnectedLink(LinkConfiguration* config); /// Creates, connects (and adds) a link based on the given configuration name. LinkInterface* createConnectedLink(const QString& name); @@ -165,15 +140,22 @@ public: // Override from QGCTool virtual void setToolbox(QGCToolbox *toolbox); -signals: - void autoconnectUDPChanged (bool autoconnect); - void autoconnectPixhawkChanged (bool autoconnect); - void autoconnect3DRRadioChanged (bool autoconnect); - void autoconnectPX4FlowChanged (bool autoconnect); - void autoconnectRTKGPSChanged (bool autoconnect); - void autoconnectLibrePilotChanged (bool autoconnect); + /// @return This mavlink channel is never assigned to a vehicle. + uint8_t reservedMavlinkChannel(void) { return 0; } + /// If you are going to hold a reference to a LinkInterface* in your object you must reference count it + /// by using this method to get access to the shared pointer. + SharedLinkInterfacePointer sharedLinkInterfacePointerForLink(LinkInterface* link); + bool containsLink(LinkInterface* link); + + SharedLinkConfigurationPointer addConfiguration(LinkConfiguration* config); + + void startAutoConnectedLinks(void); + + static const char* settingsGroup; + +signals: void newLink(LinkInterface* link); // Link has been deleted. You may not necessarily get a linkInactive before the link is deleted. @@ -199,18 +181,19 @@ private slots: void _linkConnected(void); void _linkDisconnected(void); void _linkConnectionRemoved(LinkInterface* link); -#ifndef __ios__ +#ifndef NO_SERIAL_LINK void _activeLinkCheck(void); #endif private: + QmlObjectListModel* _qmlLinkConfigurations (void) { return &_qmlConfigurations; } bool _connectionsSuspendedMsg(void); void _updateAutoConnectLinks(void); void _updateSerialPorts(); void _fixUnnamed(LinkConfiguration* config); - bool _setAutoconnectWorker(bool& currentAutoconnect, bool newAutoconnect, const char* autoconnectKey); + void _removeConfiguration(LinkConfiguration* config); -#ifndef __ios__ +#ifndef NO_SERIAL_LINK SerialConfiguration* _autoconnectConfigurationsContainsPort(const QString& portName); #endif @@ -221,35 +204,24 @@ private: QTimer _portListTimer; uint32_t _mavlinkChannelsUsedBitMask; - MAVLinkProtocol* _mavlinkProtocol; + AutoConnectSettings* _autoConnectSettings; + MAVLinkProtocol* _mavlinkProtocol; - QmlObjectListModel _links; - QmlObjectListModel _linkConfigurations; - QmlObjectListModel _autoconnectConfigurations; + QList _sharedLinks; + QList _sharedConfigurations; + QList _sharedAutoconnectConfigurations; + QmlObjectListModel _qmlConfigurations; QMap _autoconnectWaitList; ///< key: QGCSerialPortInfo.systemLocation, value: wait count QStringList _commPortList; QStringList _commPortDisplayList; - bool _autoconnectUDP; - bool _autoconnectPixhawk; - bool _autoconnect3DRRadio; - bool _autoconnectPX4Flow; - bool _autoconnectRTKGPS; - bool _autoconnectLibrePilot; -#ifndef __ios__ +#ifndef NO_SERIAL_LINK QTimer _activeLinkCheckTimer; ///< Timer which checks for a vehicle showing up on a usb direct link QList _activeLinkCheckList; ///< List of links we are waiting for a vehicle to show up on static const int _activeLinkCheckTimeoutMSecs = 15000; ///< Amount of time to wait for a heatbeat. Keep in mind ArduPilot stack heartbeat is slow to come. #endif - static const char* _settingsGroup; - static const char* _autoconnectUDPKey; - static const char* _autoconnectPixhawkKey; - static const char* _autoconnect3DRRadioKey; - static const char* _autoconnectPX4FlowKey; - static const char* _autoconnectRTKGPSKey; - static const char* _autoconnectLibrePilotKey; static const char* _defaultUPDLinkName; static const int _autoconnectUpdateTimerMSecs; static const int _autoconnectConnectDelayMSecs; diff --git a/src/comm/LogReplayLink.cc b/src/comm/LogReplayLink.cc index 4a15dd8417a2038158390a5f108afe68f2c1f7e3..d6b818467c7fc1823d7fa9aa650260bc1dd42ffa 100644 --- a/src/comm/LogReplayLink.cc +++ b/src/comm/LogReplayLink.cc @@ -64,12 +64,13 @@ QString LogReplayLinkConfiguration::logFilenameShort(void) return fi.fileName(); } -LogReplayLink::LogReplayLink(LogReplayLinkConfiguration* config) : - _connected(false), - _replayAccelerationFactor(1.0f) +LogReplayLink::LogReplayLink(SharedLinkConfigurationPointer& config) + : LinkInterface(config) + , _logReplayConfig(qobject_cast(config.data())) + , _connected(false) + , _replayAccelerationFactor(1.0f) { - Q_ASSERT(config); - _config = config; + Q_ASSERT(_logReplayConfig); _readTickTimer.moveToThread(this); @@ -184,7 +185,7 @@ quint64 LogReplayLink::_seekToNextMavlinkMessage(mavlink_message_t* nextMsg) bool LogReplayLink::_loadLogFile(void) { QString errorMsg; - QString logFilename = _config->logFilename(); + QString logFilename = _logReplayConfig->logFilename(); QFileInfo logFileInfo; int logDurationSecondsTotal; diff --git a/src/comm/LogReplayLink.h b/src/comm/LogReplayLink.h index 923dfb6373cc6036645bd6f72048b7d162796ff0..10b55d8bdd4177f0b55b6ac202fa72a7a6a4fa95 100644 --- a/src/comm/LogReplayLink.h +++ b/src/comm/LogReplayLink.h @@ -40,7 +40,6 @@ public: void loadSettings (QSettings& settings, const QString& root); void saveSettings (QSettings& settings, const QString& root); void updateSettings (); - bool isAutoConnectAllowed () { return false; } QString settingsURL () { return "LogReplaySettings.qml"; } signals: void fileNameChanged(); @@ -57,8 +56,6 @@ class LogReplayLink : public LinkInterface friend class LinkManager; public: - virtual LinkConfiguration* getLinkConfiguration() { return _config; } - /// @return true: log is currently playing, false: log playback is paused bool isPlaying(void) { return _readTickTimer.isActive(); } @@ -111,7 +108,7 @@ private slots: private: // Links are only created/destroyed by LinkManager so constructor/destructor is not public - LogReplayLink(LogReplayLinkConfiguration* config); + LogReplayLink(SharedLinkConfigurationPointer& config); ~LogReplayLink(); void _replayError(const QString& errorMsg); @@ -129,7 +126,7 @@ private: // Virtuals from QThread virtual void run(void); - LogReplayLinkConfiguration* _config; + LogReplayLinkConfiguration* _logReplayConfig; bool _connected; QTimer _readTickTimer; ///< Timer which signals a read of next log record diff --git a/src/comm/MAVLinkProtocol.cc b/src/comm/MAVLinkProtocol.cc index 3e238138972e14698cb0270f8cd61c89c2fb8db3..0d031a4f88a72fd664325ff23fb27ad2b0e5d4a3 100644 --- a/src/comm/MAVLinkProtocol.cc +++ b/src/comm/MAVLinkProtocol.cc @@ -35,6 +35,7 @@ #include "QGCApplication.h" #include "QGCLoggingCategory.h" #include "MultiVehicleManager.h" +#include "SettingsManager.h" Q_DECLARE_METATYPE(mavlink_message_t) @@ -57,7 +58,7 @@ MAVLinkProtocol::MAVLinkProtocol(QGCApplication* app) #ifndef __mobile__ , _logSuspendError(false) , _logSuspendReplay(false) - , _logPromptForSave(false) + , _vehicleWasArmed(false) , _tempLogFile(QString("%2.%3").arg(_tempLogFileTemplate).arg(_logFileExtension)) #endif , _linkMgr(NULL) @@ -73,7 +74,7 @@ MAVLinkProtocol::MAVLinkProtocol(QGCApplication* app) MAVLinkProtocol::~MAVLinkProtocol() { storeSettings(); - + #ifndef __mobile__ _closeLogFile(); #endif @@ -159,39 +160,24 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) // Since receiveBytes signals cross threads we can end up with signals in the queue // that come through after the link is disconnected. For these we just drop the data // since the link is closed. - if (!_linkMgr->links()->contains(link)) { + if (!_linkMgr->containsLink(link)) { return; } - + // receiveMutex.lock(); mavlink_message_t message; mavlink_status_t status; int mavlinkChannel = link->mavlinkChannel(); - static int mavlink09Count = 0; static int nonmavlinkCount = 0; - static bool decodedFirstPacket = false; - static bool warnedUser = false; static bool checkedUserNonMavlink = false; static bool warnedUserNonMavlink = false; for (int position = 0; position < b.size(); position++) { unsigned int decodeState = mavlink_parse_char(mavlinkChannel, (uint8_t)(b[position]), &message, &status); - if ((uint8_t)b[position] == 0x55) mavlink09Count++; - if ((mavlink09Count > 100) && !decodedFirstPacket && !warnedUser) - { - warnedUser = true; - // Obviously the user tries to use a 0.9 autopilot - // with QGroundControl built for version 1.0 - emit protocolStatusMessage(tr("MAVLink Protocol"), tr("There is a MAVLink Version or Baud Rate Mismatch. " - "Your MAVLink device seems to use the deprecated version 0.9, while QGroundControl only supports version 1.0+. " - "Please upgrade the MAVLink version of your autopilot. " - "If your autopilot is using version 1.0, check if the baud rates of QGroundControl and your autopilot are the same.")); - } - - if (decodeState == 0 && !decodedFirstPacket) + if (decodeState == 0 && !link->decodedFirstMavlinkPacket()) { nonmavlinkCount++; if (nonmavlinkCount > 2000 && !warnedUserNonMavlink) @@ -212,15 +198,13 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) } if (decodeState == 1) { - decodedFirstPacket = true; - - mavlink_status_t* mavlinkStatus = mavlink_get_channel_status(mavlinkChannel); - if (!(mavlinkStatus->flags & MAVLINK_STATUS_FLAG_IN_MAVLINK1) && (mavlinkStatus->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1)) { - qDebug() << "switch to mavlink 2.0" << mavlinkStatus << mavlinkChannel << mavlinkStatus->flags; - mavlinkStatus->flags &= ~MAVLINK_STATUS_FLAG_OUT_MAVLINK1; - } else if ((mavlinkStatus->flags & MAVLINK_STATUS_FLAG_IN_MAVLINK1) && !(mavlinkStatus->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1)) { - qDebug() << "switch to mavlink 1.0" << mavlinkStatus << mavlinkChannel << mavlinkStatus->flags; - mavlinkStatus->flags |= MAVLINK_STATUS_FLAG_OUT_MAVLINK1; + if (!link->decodedFirstMavlinkPacket()) { + mavlink_status_t* mavlinkStatus = mavlink_get_channel_status(mavlinkChannel); + if (!(mavlinkStatus->flags & MAVLINK_STATUS_FLAG_IN_MAVLINK1) && (mavlinkStatus->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1)) { + qDebug() << "Switching outbound to mavlink 2.0 due to incoming mavlink 2.0 packet:" << mavlinkStatus << mavlinkChannel << mavlinkStatus->flags; + mavlinkStatus->flags &= ~MAVLINK_STATUS_FLAG_OUT_MAVLINK1; + } + link->setDecodedFirstMavlinkPacket(true); } if(message.msgid == MAVLINK_MSG_ID_RADIO_STATUS) @@ -255,7 +239,7 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) #ifndef __mobile__ // Log data - + if (!_logSuspendError && !_logSuspendReplay && _tempLogFile.isOpen()) { uint8_t buf[MAVLINK_MAX_PACKET_LEN+sizeof(quint64)]; @@ -280,13 +264,13 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) _stopLogging(); _logSuspendError = true; } - + // Check for the vehicle arming going by. This is used to trigger log save. - if (!_logPromptForSave && message.msgid == MAVLINK_MSG_ID_HEARTBEAT) { + if (!_vehicleWasArmed && message.msgid == MAVLINK_MSG_ID_HEARTBEAT) { mavlink_heartbeat_t state; mavlink_msg_heartbeat_decode(&message, &state); if (state.base_mode & MAV_MODE_FLAG_DECODE_POSITION_SAFETY) { - _logPromptForSave = true; + _vehicleWasArmed = true; } } } @@ -300,7 +284,7 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) mavlink_heartbeat_t heartbeat; mavlink_msg_heartbeat_decode(&message, &heartbeat); - emit vehicleHeartbeatInfo(link, message.sysid, heartbeat.mavlink_version, heartbeat.autopilot, heartbeat.type); + emit vehicleHeartbeatInfo(link, message.sysid, message.compid, heartbeat.mavlink_version, heartbeat.autopilot, heartbeat.type); } // Increase receive counter @@ -412,7 +396,7 @@ bool MAVLinkProtocol::_closeLogFile(void) return true; } } - + return false; } @@ -428,11 +412,7 @@ void MAVLinkProtocol::_startLogging(void) return; } - if (_app->promptFlightDataSaveNotArmed()) { - _logPromptForSave = true; - } - - qDebug() << "Temp log" << _tempLogFile.fileName() << _logPromptForSave; + qDebug() << "Temp log" << _tempLogFile.fileName(); _logSuspendError = false; } @@ -443,13 +423,14 @@ void MAVLinkProtocol::_stopLogging(void) { if (_closeLogFile()) { // If the signals are not connected it means we are running a unit test. In that case just delete log files - if (_logPromptForSave && _app->promptFlightDataSave()) { + SettingsManager* settingsManager = _app->toolbox()->settingsManager(); + if ((_vehicleWasArmed || settingsManager->appSettings()->promptFlightTelemetrySaveNotArmed()->rawValue().toBool()) && settingsManager->appSettings()->promptFlightTelemetrySave()->rawValue().toBool()) { emit saveTempFlightDataLog(_tempLogFile.fileName()); } else { QFile::remove(_tempLogFile.fileName()); } } - _logPromptForSave = false; + _vehicleWasArmed = false; } /// @brief Checks the temp directory for log files which may have been left there. @@ -458,11 +439,11 @@ void MAVLinkProtocol::_stopLogging(void) void MAVLinkProtocol::checkForLostLogFiles(void) { QDir tempDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); - + QString filter(QString("*.%1").arg(_logFileExtension)); QFileInfoList fileInfoList = tempDir.entryInfoList(QStringList(filter), QDir::Files); qDebug() << "Orphaned log file count" << fileInfoList.count(); - + foreach(const QFileInfo fileInfo, fileInfoList) { qDebug() << "Orphaned log file" << fileInfo.filePath(); if (fileInfo.size() == 0) { @@ -488,10 +469,10 @@ void MAVLinkProtocol::suspendLogForReplay(bool suspend) void MAVLinkProtocol::deleteTempLogFiles(void) { QDir tempDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); - + QString filter(QString("*.%1").arg(_logFileExtension)); QFileInfoList fileInfoList = tempDir.entryInfoList(QStringList(filter), QDir::Files); - + foreach(const QFileInfo fileInfo, fileInfoList) { QFile::remove(fileInfo.filePath()); } diff --git a/src/comm/MAVLinkProtocol.h b/src/comm/MAVLinkProtocol.h index 4a78d7f990d13eb119f014a7e134bdb052ea0ab4..3d1cd165799d4f0d7fe5f7465645d4a026669544 100644 --- a/src/comm/MAVLinkProtocol.h +++ b/src/comm/MAVLinkProtocol.h @@ -7,13 +7,6 @@ * ****************************************************************************/ - -/** - * @file - * @brief Definition of class MAVLinkProtocol - * @author Lorenz Meier - */ - #ifndef MAVLINKPROTOCOL_H_ #define MAVLINKPROTOCOL_H_ @@ -137,7 +130,7 @@ protected: signals: /// Heartbeat received on link - void vehicleHeartbeatInfo(LinkInterface* link, int vehicleId, int vehicleMavlinkVersion, int vehicleFirmwareType, int vehicleType); + void vehicleHeartbeatInfo(LinkInterface* link, int vehicleId, int componentId, int vehicleMavlinkVersion, int vehicleFirmwareType, int vehicleType); /** @brief Message received and directly copied via signal */ void messageReceived(LinkInterface* link, mavlink_message_t message); @@ -179,7 +172,7 @@ private: bool _logSuspendError; ///< true: Logging suspended due to error bool _logSuspendReplay; ///< true: Logging suspended due to replay - bool _logPromptForSave; ///< true: Prompt for log save when appropriate + bool _vehicleWasArmed; ///< true: Vehicle was armed during log sequence QGCTemporaryFile _tempLogFile; ///< File to log to static const char* _tempLogFileTemplate; ///< Template for temporary log file diff --git a/src/comm/MockLink.cc b/src/comm/MockLink.cc index 5dbec5851f95621e2abd90e469d264245e44b1b9..b3cd24ff6d4720a184c8f62e6d2ce1437d4c4898 100644 --- a/src/comm/MockLink.cc +++ b/src/comm/MockLink.cc @@ -11,8 +11,9 @@ #include "MockLink.h" #include "QGCLoggingCategory.h" #include "QGCApplication.h" -#ifndef __mobile__ -#include "UnitTest.h" + +#ifdef UNITTEST_BUILD + #include "UnitTest.h" #endif #include @@ -21,7 +22,8 @@ #include -#include "px4_custom_mode.h" +// FIXME: Hack to work around clean headers +#include "FirmwarePlugin/PX4/px4_custom_mode.h" QGC_LOGGING_CATEGORY(MockLinkLog, "MockLinkLog") QGC_LOGGING_CATEGORY(MockLinkVerboseLog, "MockLinkVerboseLog") @@ -42,8 +44,9 @@ const char* MockConfiguration::_vehicleTypeKey = "VehicleType"; const char* MockConfiguration::_sendStatusTextKey = "SendStatusText"; const char* MockConfiguration::_failureModeKey = "FailureMode"; -MockLink::MockLink(MockConfiguration* config) - : _missionItemHandler(this, qgcApp()->toolbox()->mavlinkProtocol()) +MockLink::MockLink(SharedLinkConfigurationPointer& config) + : LinkInterface(config) + , _missionItemHandler(this, qgcApp()->toolbox()->mavlinkProtocol()) , _name("MockLink") , _connected(false) , _vehicleSystemId(_nextVehicleSystemId++) @@ -65,14 +68,11 @@ MockLink::MockLink(MockConfiguration* config) , _logDownloadCurrentOffset(0) , _logDownloadBytesRemaining(0) { - _config = config; - if (_config) { - _firmwareType = config->firmwareType(); - _vehicleType = config->vehicleType(); - _sendStatusText = config->sendStatusText(); - _failureMode = config->failureMode(); - _config->setLink(this); - } + MockConfiguration* mockConfig = qobject_cast(_config.data()); + _firmwareType = mockConfig->firmwareType(); + _vehicleType = mockConfig->vehicleType(); + _sendStatusText = mockConfig->sendStatusText(); + _failureMode = mockConfig->failureMode(); union px4_custom_mode px4_cm; @@ -188,14 +188,14 @@ void MockLink::_loadParams(void) if (_firmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA) { if (_vehicleType == MAV_TYPE_FIXED_WING) { - paramFile.setFileName(":/unittest/APMArduPlaneMockLink.params"); + paramFile.setFileName(":/MockLink/APMArduPlaneMockLink.params"); } else if (_vehicleType == MAV_TYPE_SUBMARINE ) { - paramFile.setFileName(":/unittest/APMArduSubMockLink.params"); + paramFile.setFileName(":/MockLink/APMArduSubMockLink.params"); } else { - paramFile.setFileName(":/unittest/APMArduCopterMockLink.params"); + paramFile.setFileName(":/MockLink/APMArduCopterMockLink.params"); } } else { - paramFile.setFileName(":/unittest/PX4MockLink.params"); + paramFile.setFileName(":/MockLink/PX4MockLink.params"); } @@ -215,7 +215,6 @@ void MockLink::_loadParams(void) QStringList paramData = line.split("\t"); Q_ASSERT(paramData.count() == 5); - int componentId = paramData.at(1).toInt(); QString paramName = paramData.at(2); QString valStr = paramData.at(3); uint paramType = paramData.at(4).toUInt(); @@ -251,7 +250,7 @@ void MockLink::_loadParams(void) qCDebug(MockLinkVerboseLog) << "Loading param" << paramName << paramValue; - _mapParamName2Value[componentId][paramName] = paramValue; + _mapParamName2Value[_vehicleComponentId][paramName] = paramValue; _mapParamName2MavParamType[paramName] = static_cast(paramType); } } @@ -780,6 +779,9 @@ void MockLink::_handleFTP(const mavlink_message_t& msg) void MockLink::_handleCommandLong(const mavlink_message_t& msg) { + static bool firstCmdUser3 = true; + static bool firstCmdUser4 = true; + mavlink_command_long_t request; uint8_t commandResult = MAV_RESULT_UNSUPPORTED; @@ -805,6 +807,38 @@ void MockLink::_handleCommandLong(const mavlink_message_t& msg) commandResult = MAV_RESULT_ACCEPTED; _respondWithAutopilotVersion(); break; + case MAV_CMD_USER_1: + // Test command which always returns MAV_RESULT_ACCEPTED + commandResult = MAV_RESULT_ACCEPTED; + break; + case MAV_CMD_USER_2: + // Test command which always returns MAV_RESULT_FAILED + commandResult = MAV_RESULT_FAILED; + break; + case MAV_CMD_USER_3: + // Test command which returns MAV_RESULT_ACCEPTED on second attempt + if (firstCmdUser3) { + firstCmdUser3 = false; + return; + } else { + firstCmdUser3 = true; + commandResult = MAV_RESULT_ACCEPTED; + } + break; + case MAV_CMD_USER_4: + // Test command which returns MAV_RESULT_FAILED on second attempt + if (firstCmdUser4) { + firstCmdUser4 = false; + return; + } else { + firstCmdUser4 = true; + commandResult = MAV_RESULT_FAILED; + } + break; + case MAV_CMD_USER_5: + // No response + return; + break; } mavlink_message_t commandAck; @@ -1005,12 +1039,12 @@ void MockConfiguration::updateSettings() MockLink* MockLink::_startMockLink(MockConfiguration* mockConfig) { - LinkManager* linkManager = qgcApp()->toolbox()->linkManager(); + LinkManager* linkMgr = qgcApp()->toolbox()->linkManager(); mockConfig->setDynamic(true); - linkManager->linkConfigurations()->append(mockConfig); + SharedLinkConfigurationPointer config = linkMgr->addConfiguration(mockConfig); - return qobject_cast(linkManager->createConnectedLink(mockConfig)); + return qobject_cast(linkMgr->createConnectedLink(config)); } MockLink* MockLink::startPX4MockLink(bool sendStatusText, MockConfiguration::FailureMode_t failureMode) @@ -1159,7 +1193,7 @@ void MockLink::_handleLogRequestData(const mavlink_message_t& msg) mavlink_msg_log_request_data_decode(&msg, &request); if (_logDownloadFilename.isEmpty()) { - #ifndef __mobile__ + #ifdef UNITTEST_BUILD _logDownloadFilename = UnitTest::createRandomFile(_logDownloadFileSize); #endif } diff --git a/src/comm/MockLink.h b/src/comm/MockLink.h index cdb25373f8f98e3e4bf340f5437190701c9a4264..15e8a5eebdff9b9e37ced799ab0185bf93c24379 100644 --- a/src/comm/MockLink.h +++ b/src/comm/MockLink.h @@ -90,8 +90,7 @@ class MockLink : public LinkInterface Q_OBJECT public: - // LinkConfiguration is optional for MockLink - MockLink(MockConfiguration* config = NULL); + MockLink(SharedLinkConfigurationPointer& config); ~MockLink(void); // MockLink methods @@ -126,8 +125,6 @@ public: bool connect(void); bool disconnect(void); - LinkConfiguration* getLinkConfiguration() { return _config; } - /// Sets a failure mode for unit testing /// @param failureMode Type of failure to simulate void setMissionItemFailureMode(MockLinkMissionItemHandler::FailureMode_t failureMode); @@ -216,7 +213,6 @@ private: uint32_t _mavCustomMode; uint8_t _mavState; - MockConfiguration* _config; MAV_AUTOPILOT _firmwareType; MAV_TYPE _vehicleType; diff --git a/src/comm/MockLinkMissionItemHandler.cc b/src/comm/MockLinkMissionItemHandler.cc index 146e5d7f31bb321401f383498f3c1117ecb103e1..e9a0bff65f4aa15c7d8e11a9242d3d95711c756d 100644 --- a/src/comm/MockLinkMissionItemHandler.cc +++ b/src/comm/MockLinkMissionItemHandler.cc @@ -21,6 +21,9 @@ MockLinkMissionItemHandler::MockLinkMissionItemHandler(MockLink* mockLink, MAVLi , _failureMode(FailNone) , _sendHomePositionOnEmptyList(false) , _mavlinkProtocol(mavlinkProtocol) + , _failReadRequestListFirstResponse(true) + , _failReadRequest1FirstResponse(true) + , _failWriteMissionCountFirstResponse(true) { Q_ASSERT(mockLink); } @@ -82,9 +85,17 @@ void MockLinkMissionItemHandler::_handleMissionRequestList(const mavlink_message { qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequestList read sequence"; - if (_failureMode != FailReadRequestListNoResponse) { + _failReadRequest1FirstResponse = true; + + if (_failureMode == FailReadRequestListNoResponse) { + qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequestList not responding due to failure mode FailReadRequestListNoResponse"; + } else if (_failureMode == FailReadRequestListFirstResponse && _failReadRequestListFirstResponse) { + _failReadRequestListFirstResponse = false; + qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequestList not responding due to failure mode FailReadRequestListFirstResponse"; + } else { mavlink_mission_request_list_t request; + _failReadRequestListFirstResponse = true; mavlink_msg_mission_request_list_decode(&msg, &request); Q_ASSERT(request.target_system == _mockLink->vehicleId()); @@ -104,8 +115,6 @@ void MockLinkMissionItemHandler::_handleMissionRequestList(const mavlink_message msg.compid, // Target is original sender itemCount); // Number of mission items _mockLink->respondWithMavlinkMessage(responseMsg); - } else { - qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequestList not responding due to failure mode"; } } @@ -120,9 +129,13 @@ void MockLinkMissionItemHandler::_handleMissionRequest(const mavlink_message_t& Q_ASSERT(request.target_system == _mockLink->vehicleId()); Q_ASSERT(request.seq < _missionItems.count()); - if ((_failureMode == FailReadRequest0NoResponse && request.seq == 0) || - (_failureMode == FailReadRequest1NoResponse && request.seq == 1)) { - qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequest not responding due to failure mode"; + if (_failureMode == FailReadRequest0NoResponse && request.seq == 0) { + qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequest not responding due to failure mode FailReadRequest0NoResponse"; + } else if (_failureMode == FailReadRequest1NoResponse && request.seq == 1) { + qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequest not responding due to failure mode FailReadRequest1NoResponse"; + } else if (_failureMode == FailReadRequest1FirstResponse && request.seq == 1 && _failReadRequest1FirstResponse) { + _failReadRequest1FirstResponse = false; + qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequest not responding due to failure mode FailReadRequest1FirstResponse"; } else { // FIXME: Track whether all items are requested, or requested in sequence @@ -185,6 +198,16 @@ void MockLinkMissionItemHandler::_handleMissionCount(const mavlink_message_t& ms if (_writeSequenceCount == 0) { _sendAck(MAV_MISSION_ACCEPTED); } else { + if (_failureMode == FailWriteMissionCountNoResponse) { + qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionCount not responding due to failure mode FailWriteMissionCountNoResponse"; + return; + } + if (_failureMode == FailWriteMissionCountFirstResponse && _failWriteMissionCountFirstResponse) { + _failWriteMissionCountFirstResponse = false; + qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionCount not responding due to failure mode FailWriteMissionCountNoResponse"; + return; + } + _failWriteMissionCountFirstResponse = true; _writeSequenceIndex = 0; _requestNextMissionItem(_writeSequenceIndex); } @@ -194,9 +217,8 @@ void MockLinkMissionItemHandler::_requestNextMissionItem(int sequenceNumber) { qCDebug(MockLinkMissionItemHandlerLog) << "_requestNextMissionItem write sequence sequenceNumber:" << sequenceNumber << "_failureMode:" << _failureMode; - if ((_failureMode == FailWriteRequest0NoResponse && sequenceNumber == 0) || - (_failureMode == FailWriteRequest1NoResponse && sequenceNumber == 1)) { - qCDebug(MockLinkMissionItemHandlerLog) << "_requestNextMissionItem not responding due to failure mode"; + if (_failureMode == FailWriteRequest1NoResponse && sequenceNumber == 1) { + qCDebug(MockLinkMissionItemHandlerLog) << "_requestNextMissionItem not responding due to failure mode FailWriteRequest1NoResponse"; } else { if (sequenceNumber >= _writeSequenceCount) { qCWarning(MockLinkMissionItemHandlerLog) << "_requestNextMissionItem requested seqeuence number > write count sequenceNumber::_writeSequenceCount" << sequenceNumber << _writeSequenceCount; diff --git a/src/comm/MockLinkMissionItemHandler.h b/src/comm/MockLinkMissionItemHandler.h index 77c9ea238f63ac6bedf8c6eda674d5c586356cbe..765058fd62aa3fda8fedd38b06833af0ef5ac35d 100644 --- a/src/comm/MockLinkMissionItemHandler.h +++ b/src/comm/MockLinkMissionItemHandler.h @@ -42,18 +42,21 @@ public: typedef enum { FailNone, // No failures FailReadRequestListNoResponse, // Don't send MISSION_COUNT in response to MISSION_REQUEST_LIST + FailReadRequestListFirstResponse, // Don't send MISSION_COUNT in response to first MISSION_REQUEST_LIST, allow subsequent to go through FailReadRequest0NoResponse, // Don't send MISSION_ITEM in response to MISSION_REQUEST item 0 FailReadRequest1NoResponse, // Don't send MISSION_ITEM in response to MISSION_REQUEST item 1 + FailReadRequest1FirstResponse, // Don't send MISSION_ITEM in response to MISSION_REQUEST item 1 on first try, allow subsequent request to go through FailReadRequest0IncorrectSequence, // Respond to MISSION_REQUEST 0 with incorrect sequence number in MISSION_ITEM FailReadRequest1IncorrectSequence, // Respond to MISSION_REQUEST 1 with incorrect sequence number in MISSION_ITEM FailReadRequest0ErrorAck, // Respond to MISSION_REQUEST 0 with MISSION_ACK error FailReadRequest1ErrorAck, // Respond to MISSION_REQUEST 1 bogus MISSION_ACK error - FailWriteRequest0NoResponse, // Don't respond to MISSION_COUNT with MISSION_REQUEST 0 + FailWriteMissionCountNoResponse, // Don't respond to MISSION_COUNT with MISSION_REQUEST 0 + FailWriteMissionCountFirstResponse, // Don't respond to first MISSION_COUNT with MISSION_REQUEST 0, respond to subsequent MISSION_COUNT requests FailWriteRequest1NoResponse, // Don't respond to MISSION_ITEM 0 with MISSION_REQUEST 1 - FailWriteRequest0IncorrectSequence, // Respond to MISSION_COUNT 0 with MISSION_REQUEST with wrong sequence number - FailWriteRequest1IncorrectSequence, // Respond to MISSION_ITEM 0 with MISSION_REQUEST with wrong sequence number - FailWriteRequest0ErrorAck, // Respond to MISSION_COUNT 0 with MISSION_ACK error - FailWriteRequest1ErrorAck, // Respond to MISSION_ITEM 0 with MISSION_ACK error + FailWriteRequest0IncorrectSequence, // Item 0 MISSION_REQUEST sent has wrong sequence number + FailWriteRequest1IncorrectSequence, // Item 1 MISSION_REQUEST sent has wrong sequence number + FailWriteRequest0ErrorAck, // Instead of sending MISSION_REQUEST 0, send MISSION_ACK error + FailWriteRequest1ErrorAck, // Instead of sending MISSION_REQUEST 1, send MISSION_ACK error FailWriteFinalAckNoResponse, // Don't send the final MISSION_ACK FailWriteFinalAckErrorAck, // Send an error as the final MISSION_ACK FailWriteFinalAckMissingRequests, // Send the MISSION_ACK before all items have been requested @@ -102,6 +105,9 @@ private: FailureMode_t _failureMode; bool _sendHomePositionOnEmptyList; MAVLinkProtocol* _mavlinkProtocol; + bool _failReadRequestListFirstResponse; + bool _failReadRequest1FirstResponse; + bool _failWriteMissionCountFirstResponse; }; #endif diff --git a/src/comm/PX4MockLink.params b/src/comm/PX4MockLink.params index f975f257b6d1a6600a186cfdfbd236b10bc348fd..3ae08c462d27bac6f42ef3eea2d9ae85f1d51cad 100644 --- a/src/comm/PX4MockLink.params +++ b/src/comm/PX4MockLink.params @@ -1,556 +1,356 @@ -# Onboard parameters for system MAV 001 +# Onboard parameters for vehicle 1 # -# MAV ID COMPONENT ID PARAM NAME VALUE (FLOAT) -1 50 ATT_ACC_COMP 2 6 -1 50 ATT_J11 0.0018 9 -1 50 ATT_J22 0.0018 9 -1 50 ATT_J33 0.0037 9 -1 50 ATT_J_EN 0 6 -1 50 ATT_MAG_DECL 0 9 -1 50 BAT_CRIT_THR 0.05 9 -1 50 BAT_CAPACITY -1 9 -1 50 BAT_C_SCALING 0.0124 9 -1 50 BAT_LOW_THR 0.15 9 -1 50 BAT_N_CELLS 3 6 -1 50 BAT_V_CHARGED 4.2 9 -1 50 BAT_V_EMPTY 3.4 9 -1 50 BAT_V_LOAD_DROP 0.07 9 -1 50 BAT_V_SCALE_IO 10000 6 -1 50 BAT_V_SCALING 0.00989 9 -1 50 BD_GPROPERTIES 0.03 9 -1 50 BD_OBJ_CD 0.1 9 -1 50 BD_OBJ_MASS 0.6 9 -1 50 BD_OBJ_SURFACE 0.00311725 9 -1 50 BD_PRECISION 30 9 -1 50 BD_TURNRADIUS 120 9 -1 50 CAL_ACC0_ID 1246218 6 -1 50 CAL_ACC0_XOFF 0.0657825 9 -1 50 CAL_ACC0_XSCALE 0.99657 9 -1 50 CAL_ACC0_YOFF -0.0470138 9 -1 50 CAL_ACC0_YSCALE 1.00066 9 -1 50 CAL_ACC0_ZOFF 0.2244 9 -1 50 CAL_ACC0_ZSCALE 0.985475 9 -1 50 CAL_ACC1_ID 1114634 6 -1 50 CAL_ACC1_XOFF 0.976983 9 -1 50 CAL_ACC1_XSCALE 0.978487 9 -1 50 CAL_ACC1_YOFF 0.92215 9 -1 50 CAL_ACC1_YSCALE 1.01181 9 -1 50 CAL_ACC1_ZOFF 1.07291 9 -1 50 CAL_ACC1_ZSCALE 1.00673 9 -1 50 CAL_ACC2_ID 0 6 -1 50 CAL_ACC2_XOFF 0 9 -1 50 CAL_ACC2_XSCALE 1 9 -1 50 CAL_ACC2_YOFF 0 9 -1 50 CAL_ACC2_YSCALE 1 9 -1 50 CAL_ACC2_ZOFF 0 9 -1 50 CAL_ACC2_ZSCALE 1 9 -1 50 CAL_BOARD_ID 825374003 6 -1 50 CAL_GYRO0_ID 2163722 6 -1 50 CAL_GYRO0_XOFF 0.0102227 9 -1 50 CAL_GYRO0_XSCALE 1 9 -1 50 CAL_GYRO0_YOFF 0.0485427 9 -1 50 CAL_GYRO0_YSCALE 1 9 -1 50 CAL_GYRO0_ZOFF -0.00950837 9 -1 50 CAL_GYRO0_ZSCALE 1 9 -1 50 CAL_GYRO1_ID 2228490 6 -1 50 CAL_GYRO1_XOFF 0.012822 9 -1 50 CAL_GYRO1_XSCALE 1 9 -1 50 CAL_GYRO1_YOFF 0.00126972 9 -1 50 CAL_GYRO1_YSCALE 1 9 -1 50 CAL_GYRO1_ZOFF -0.0285923 9 -1 50 CAL_GYRO1_ZSCALE 1 9 -1 50 CAL_GYRO2_ID 0 6 -1 50 CAL_GYRO2_XOFF 0 9 -1 50 CAL_GYRO2_XSCALE 1 9 -1 50 CAL_GYRO2_YOFF 0 9 -1 50 CAL_GYRO2_YSCALE 1 9 -1 50 CAL_GYRO2_ZOFF 0 9 -1 50 CAL_GYRO2_ZSCALE 1 9 -1 50 CAL_MAG0_ID 73225 6 -1 50 CAL_MAG0_ROT 0 6 -1 50 CAL_MAG0_XOFF 0.0546612 9 -1 50 CAL_MAG0_XSCALE 1.03474 9 -1 50 CAL_MAG0_YOFF -0.0299049 9 -1 50 CAL_MAG0_YSCALE 0.934338 9 -1 50 CAL_MAG0_ZOFF -0.100793 9 -1 50 CAL_MAG0_ZSCALE 0.981021 9 -1 50 CAL_MAG1_ID 131594 6 -1 50 CAL_MAG1_ROT -1 6 -1 50 CAL_MAG1_XOFF -0.0239289 9 -1 50 CAL_MAG1_XSCALE 1 9 -1 50 CAL_MAG1_YOFF 0.0811809 9 -1 50 CAL_MAG1_YSCALE 1 9 -1 50 CAL_MAG1_ZOFF 0.0455695 9 -1 50 CAL_MAG1_ZSCALE 1 9 -1 50 CAL_MAG2_ID 0 6 -1 50 CAL_MAG2_ROT -1 6 -1 50 CAL_MAG2_XOFF 0 9 -1 50 CAL_MAG2_XSCALE 1 9 -1 50 CAL_MAG2_YOFF 0 9 -1 50 CAL_MAG2_YSCALE 1 9 -1 50 CAL_MAG2_ZOFF 0 9 -1 50 CAL_MAG2_ZSCALE 1 9 -1 50 CBRK_AIRSPD_CHK 0 6 -1 50 CBRK_ENGINEFAIL 284953 6 -1 50 CBRK_FLIGHTTERM 121212 6 -1 50 CBRK_IO_SAFETY 0 6 -1 50 CBRK_NO_VISION 0 6 -1 50 CBRK_RATE_CTRL 0 6 -1 50 CBRK_SUPPLY_CHK 0 6 -1 50 COM_DISARM_LAND 0 3 -1 50 COM_DL_LOSS_T 10 6 -1 50 COM_DL_REG_T 0 6 -1 50 COM_EF_C2T 5 9 -1 50 COM_EF_THROT 0.5 9 -1 50 COM_EF_TIME 10 9 -1 50 COM_FLTMODE1 -1 6 -1 50 COM_FLTMODE2 -1 6 -1 50 COM_FLTMODE3 -1 6 -1 50 COM_FLTMODE4 -1 6 -1 50 COM_FLTMODE5 -1 6 -1 50 COM_FLTMODE6 -1 6 -1 50 COM_LOW_BAT_ACT 0 5 -1 50 COM_RC_IN_MODE 0 6 -1 50 COM_RC_LOSS_T 0.5 9 -1 50 EKF_ATT_V3_Q0 0.0001 9 -1 50 EKF_ATT_V3_Q1 0.08 9 -1 50 EKF_ATT_V3_Q2 0.009 9 -1 50 EKF_ATT_V3_Q3 0.005 9 -1 50 EKF_ATT_V4_R0 0.0008 9 -1 50 EKF_ATT_V4_R1 10000 9 -1 50 EKF_ATT_V4_R2 100 9 -1 50 FPE_DEBUG 0 6 -1 50 FPE_LO_THRUST 0.4 9 -1 50 FPE_SONAR_LP_L 0.2 9 -1 50 FPE_SONAR_LP_U 0.5 9 -1 50 FW_AIRSPD_MAX 20 9 -1 50 FW_AIRSPD_MIN 10 9 -1 50 FW_AIRSPD_TRIM 15 9 -1 50 FW_ATT_TC 0.5 9 -1 50 FW_CLMBOUT_DIFF 25 9 -1 50 FW_FLARE_PMAX 15 9 -1 50 FW_FLARE_PMIN 2.5 9 -1 50 FW_L1_DAMPING 0.75 9 -1 50 FW_L1_PERIOD 25 9 -1 50 FW_LND_ANG 5 9 -1 50 FW_LND_FLALT 8 9 -1 50 FW_LND_HHDIST 15 9 -1 50 FW_LND_HVIRT 10 9 -1 50 FW_LND_TLALT -1 9 -1 50 FW_LND_USETER 0 6 -1 50 FW_MAN_P_MAX 45 9 -1 50 FW_MAN_R_MAX 45 9 -1 50 FW_PR_FF 0.4 9 -1 50 FW_PR_I 0 9 -1 50 FW_PR_IMAX 0.2 9 -1 50 FW_PR_P 0.05 9 -1 50 FW_PSP_OFF 0 9 -1 50 FW_P_LIM_MAX 45 9 -1 50 FW_P_LIM_MIN -45 9 -1 50 FW_P_RMAX_NEG 0 9 -1 50 FW_P_RMAX_POS 0 9 -1 50 FW_P_ROLLFF 0 9 -1 50 FW_RR_FF 0.3 9 -1 50 FW_RR_I 0 9 -1 50 FW_RR_IMAX 0.2 9 -1 50 FW_RR_P 0.05 9 -1 50 FW_RSP_OFF 0 9 -1 50 FW_R_LIM 45 9 -1 50 FW_R_RMAX 0 9 -1 50 FW_THR_CRUISE 0.7 9 -1 50 FW_THR_LND_MAX 1 9 -1 50 FW_THR_MAX 1 9 -1 50 FW_THR_MIN 0 9 -1 50 FW_THR_SLEW_MAX 0 9 -1 50 FW_T_CLMB_MAX 5 9 -1 50 FW_T_HGT_OMEGA 3 9 -1 50 FW_T_HRATE_FF 0 9 -1 50 FW_T_HRATE_P 0.05 9 -1 50 FW_T_INTEG_GAIN 0.1 9 -1 50 FW_T_PTCH_DAMP 0 9 -1 50 FW_T_RLL2THR 10 9 -1 50 FW_T_SINK_MAX 5 9 -1 50 FW_T_SINK_MIN 2 9 -1 50 FW_T_SPDWEIGHT 1 9 -1 50 FW_T_SPD_OMEGA 2 9 -1 50 FW_T_SRATE_P 0.05 9 -1 50 FW_T_THRO_CONST 8 9 -1 50 FW_T_THR_DAMP 0.5 9 -1 50 FW_T_TIME_CONST 5 9 -1 50 FW_T_VERT_ACC 7 9 -1 50 FW_YCO_METHOD 0 6 -1 50 FW_YCO_VMIN 1000 9 -1 50 FW_YR_FF 0.3 9 -1 50 FW_YR_I 0 9 -1 50 FW_YR_IMAX 0.2 9 -1 50 FW_YR_P 0.05 9 -1 50 FW_Y_RMAX 0 9 -1 50 GF_ACTION 1 6 -1 50 GF_ALTMODE 0 6 -1 50 GF_COUNT -1 6 -1 50 GF_MAX_HOR_DIST -1 6 -1 50 GF_MAX_VER_DIST -1 6 -1 50 GF_SOURCE 0 6 -1 50 INAV_DELAY_GPS 0.2 9 -1 50 INAV_ENABLED 0 6 -1 50 INAV_FLOW_K 0.15 9 -1 50 INAV_FLOW_Q_MIN 0.5 9 -1 50 INAV_LAND_DISP 0.7 9 -1 50 INAV_LAND_T 3 9 -1 50 INAV_LAND_THR 0.2 9 -1 50 INAV_SONAR_ERR 0.5 9 -1 50 INAV_SONAR_FILT 0.05 9 -1 50 INAV_W_ACC_BIAS 0.05 9 -1 50 INAV_W_GPS_FLOW 0.1 9 -1 50 INAV_W_XY_FLOW 5 9 -1 50 INAV_W_XY_GPS_P 1 9 -1 50 INAV_W_XY_GPS_V 2 9 -1 50 INAV_W_XY_RES_V 0.5 9 -1 50 INAV_W_XY_VIS_P 7 9 -1 50 INAV_W_XY_VIS_V 0 9 -1 50 INAV_W_Z_BARO 0.5 9 -1 50 INAV_W_Z_GPS_P 0.005 9 -1 50 INAV_W_Z_GPS_V 0 9 -1 50 INAV_W_Z_SONAR 3 9 -1 50 INAV_W_Z_VIS_P 0.5 9 -1 50 INAV_W_Z_VIS_V 0.5 9 -1 50 LPE_ENABLED 0 6 -1 50 LPE_INTEGRATE 1 6 -1 50 LPE_FLW_XY 0.015 9 -1 50 LPE_SNR_Z 0.2 9 -1 50 LPE_LDR_Z 0.1 9 -1 50 LPE_ACC_XY 1 9 -1 50 LPE_ACC_Z 0.10 9 -1 50 LPE_BAR_Z 3 9 -1 50 LPE_GPS_XY 2 9 -1 50 LPE_GPS_Z 3 9 -1 50 LPE_GPS_VXY 1 9 -1 50 LPE_GPS_VZ 1 9 -1 50 LPE_VIS_XY 0.5 9 -1 50 LPE_VIS_Z 0.5 9 -1 50 LPE_VIS_VXY 1 9 -1 50 LPE_VIS_VZ 1 9 -1 50 LPE_NO_VISION 0 6 -1 50 LPE_VIC_P 0.05 9 -1 50 LPE_PN_P 1 9 -1 50 LPE_PN_V 0.1 9 -1 50 LAUN_ALL_ON 0 6 -1 50 LAUN_CAT_A 30 9 -1 50 LAUN_CAT_MDEL 0 9 -1 50 LAUN_CAT_PMAX 30 9 -1 50 LAUN_CAT_T 0.05 9 -1 50 LAUN_THR_PRE 0 9 -1 50 LNDFW_AIRSPD_MAX 10 9 -1 50 LNDFW_VEL_XY_MAX 0.2 9 -1 50 LNDFW_VEL_Z_MAX 10 9 -1 50 LNDMC_ROT_MAX 20 9 -1 50 LNDMC_THR_MAX 0.2 9 -1 50 LNDMC_XY_VEL_MAX 1 9 -1 50 LNDMC_Z_VEL_MAX 0.3 9 -1 50 MAV_COMP_ID 50 6 -1 50 MAV_FWDEXTSP 1 6 -1 50 MAV_SYS_ID 76 6 -1 50 MAV_TYPE 2 6 -1 50 MAV_USEHILGPS 0 6 -1 50 MC_ACRO_P_MAX 90 9 -1 50 MC_ACRO_R_MAX 90 9 -1 50 MC_ACRO_Y_MAX 120 9 -1 50 MC_PITCHRATE_D 0.004 9 -1 50 MC_PITCHRATE_I 0 9 -1 50 MC_PITCHRATE_P 0.13 9 -1 50 MC_PITCH_P 7 9 -1 50 MC_PITCH_TC 0.200 9 -1 50 MC_ROLLRATE_D 0.004 9 -1 50 MC_ROLLRATE_I 0 9 -1 50 MC_ROLLRATE_P 0.13 9 -1 50 MC_ROLL_P 7 9 -1 50 MC_ROLL_TC 0.200 9 -1 50 MC_YAWRATE_D 0 9 -1 50 MC_YAWRATE_I 0.25 9 -1 50 MC_YAWRATE_MAX 120 9 -1 50 MC_YAWRATE_P 0.25 9 -1 50 MC_YAW_FF 0.5 9 -1 50 MC_YAW_P 2.5 9 -1 50 MIS_ALTMODE 0 6 -1 50 MIS_DIST_1WP 500 9 -1 50 MIS_ONBOARD_EN 1 6 -1 50 MIS_TAKEOFF_ALT 10 9 -1 50 MIS_YAWMODE 0 6 -1 50 MKBLCTRL_TEST 0 6 -1 50 MPC_LAND_SPEED 1 9 -1 50 MPC_MAN_P_MAX 35 9 -1 50 MPC_MAN_R_MAX 35 9 -1 50 MPC_MAN_Y_MAX 120 9 -1 50 MPC_MANTHR_MAX 0.900 9 -1 50 MPC_MANTHR_MIN 0.080 9 -1 50 MPC_THR_MAX 1 9 -1 50 MPC_THR_MIN 0.1 9 -1 50 MPC_THR_HOVER 0.5 9 -1 50 MPC_TILTMAX_AIR 45 9 -1 50 MPC_TILTMAX_LND 15 9 -1 50 MPC_XY_FF 0.5 9 -1 50 MPC_XY_P 1 9 -1 50 MPC_XY_VEL_D 0.01 9 -1 50 MPC_XY_VEL_I 0.02 9 -1 50 MPC_XY_VEL_MAX 5 9 -1 50 MPC_XY_VEL_P 0.1 9 -1 50 MPC_Z_FF 0.5 9 -1 50 MPC_Z_P 1 9 -1 50 MPC_Z_VEL_D 0 9 -1 50 MPC_Z_VEL_I 0.02 9 -1 50 MPC_Z_VEL_MAX 3 9 -1 50 MPC_Z_VEL_P 0.1 9 -1 50 MT_ACC_D 0 9 -1 50 MT_ACC_D_LP 0.5 9 -1 50 MT_ACC_MAX 40 9 -1 50 MT_ACC_MIN -40 9 -1 50 MT_ACC_P 0.3 9 -1 50 MT_AD_LP 0.5 9 -1 50 MT_ALT_LP 1 9 -1 50 MT_A_LP 0.5 9 -1 50 MT_ENABLED 0 6 -1 50 MT_FPA_D 0 9 -1 50 MT_FPA_D_LP 1 9 -1 50 MT_FPA_LP 1 9 -1 50 MT_FPA_MAX 30 9 -1 50 MT_FPA_MIN -20 9 -1 50 MT_FPA_P 0.3 9 -1 50 MT_LND_PIT_MAX 15 9 -1 50 MT_LND_PIT_MIN -5 9 -1 50 MT_LND_THR_MAX 0 9 -1 50 MT_LND_THR_MIN 0 9 -1 50 MT_PIT_FF 0.4 9 -1 50 MT_PIT_I 0.03 9 -1 50 MT_PIT_I_MAX 10 9 -1 50 MT_PIT_MAX 20 9 -1 50 MT_PIT_MIN -45 9 -1 50 MT_PIT_OFF 0 9 -1 50 MT_PIT_P 0.03 9 -1 50 MT_THR_FF 0.7 9 -1 50 MT_THR_I 0.25 9 -1 50 MT_THR_I_MAX 10 9 -1 50 MT_THR_MAX 1 9 -1 50 MT_THR_MIN 0 9 -1 50 MT_THR_OFF 0.7 9 -1 50 MT_THR_P 0.1 9 -1 50 MT_TKF_PIT_MAX 45 9 -1 50 MT_TKF_PIT_MIN 0 9 -1 50 MT_TKF_THR_MAX 1 9 -1 50 MT_TKF_THR_MIN 1 9 -1 50 MT_USP_PIT_MAX 0 9 -1 50 MT_USP_PIT_MIN -45 9 -1 50 MT_USP_THR_MAX 1 9 -1 50 MT_USP_THR_MIN 1 9 -1 50 NAV_ACC_RAD 2 9 -1 50 NAV_AH_ALT 600 9 -1 50 NAV_AH_LAT -265847810 6 -1 50 NAV_AH_LON 1518423250 6 -1 50 NAV_DLL_ACT 0 2 -1 50 NAV_DLL_AH_T 120 9 -1 50 NAV_DLL_CHSK 0 6 -1 50 NAV_DLL_CH_ALT 600 9 -1 50 NAV_DLL_CH_LAT -266072120 6 -1 50 NAV_DLL_CH_LON 1518453890 6 -1 50 NAV_DLL_CH_T 120 9 -1 50 NAV_DLL_N 2 6 -1 50 NAV_DLL_OBC 0 6 -1 50 NAV_GPSF_LT 30 9 -1 50 NAV_GPSF_P 0 9 -1 50 NAV_GPSF_R 15 9 -1 50 NAV_GPSF_TR 0.7 9 -1 50 NAV_LOITER_RAD 50 9 -1 50 NAV_RCL_ACT 0 2 -1 50 NAV_RCL_LT 120 9 -1 50 NAV_RCL_OBC 0 6 -1 50 PE_ABIAS_PNOISE 5e-05 9 -1 50 PE_ACC_PNOISE 0.25 9 -1 50 PE_EAS_NOISE 1.4 9 -1 50 PE_GBIAS_PNOISE 1e-07 9 -1 50 PE_GPS_ALT_WGT 0.9 9 -1 50 PE_GYRO_PNOISE 0.015 9 -1 50 PE_HGT_DELAY_MS 350 6 -1 50 PE_MAGB_PNOISE 0.0003 9 -1 50 PE_MAGE_PNOISE 0.0003 9 -1 50 PE_MAG_DELAY_MS 30 6 -1 50 PE_MAG_NOISE 0.05 9 -1 50 PE_POSDEV_INIT 5 9 -1 50 PE_POSD_NOISE 1 9 -1 50 PE_POSNE_NOISE 0.5 9 -1 50 PE_POS_DELAY_MS 210 6 -1 50 PE_TAS_DELAY_MS 210 6 -1 50 PE_VELD_NOISE 0.7 9 -1 50 PE_VELNE_NOISE 0.5 9 -1 50 PE_VEL_DELAY_MS 230 6 -1 50 RC10_DZ 0 9 -1 50 RC10_MAX 2000 9 -1 50 RC10_MIN 1000 9 -1 50 RC10_REV 1 9 -1 50 RC10_TRIM 1500 9 -1 50 RC11_DZ 0 9 -1 50 RC11_MAX 2000 9 -1 50 RC11_MIN 1000 9 -1 50 RC11_REV 1 9 -1 50 RC11_TRIM 1500 9 -1 50 RC12_DZ 0 9 -1 50 RC12_MAX 2000 9 -1 50 RC12_MIN 1000 9 -1 50 RC12_REV 1 9 -1 50 RC12_TRIM 1500 9 -1 50 RC13_DZ 0 9 -1 50 RC13_MAX 2000 9 -1 50 RC13_MIN 1000 9 -1 50 RC13_REV 1 9 -1 50 RC13_TRIM 1500 9 -1 50 RC14_DZ 0 9 -1 50 RC14_MAX 2000 9 -1 50 RC14_MIN 1000 9 -1 50 RC14_REV 1 9 -1 50 RC14_TRIM 1500 9 -1 50 RC15_DZ 0 9 -1 50 RC15_MAX 2000 9 -1 50 RC15_MIN 1000 9 -1 50 RC15_REV 1 9 -1 50 RC15_TRIM 1500 9 -1 50 RC16_DZ 0 9 -1 50 RC16_MAX 2000 9 -1 50 RC16_MIN 1000 9 -1 50 RC16_REV 1 9 -1 50 RC16_TRIM 1500 9 -1 50 RC17_DZ 0 9 -1 50 RC17_MAX 2000 9 -1 50 RC17_MIN 1000 9 -1 50 RC17_REV 1 9 -1 50 RC17_TRIM 1500 9 -1 50 RC18_DZ 0 9 -1 50 RC18_MAX 2000 9 -1 50 RC18_MIN 1000 9 -1 50 RC18_REV 1 9 -1 50 RC18_TRIM 1500 9 -1 50 RC1_DZ 10 9 -1 50 RC1_MAX 2000 9 -1 50 RC1_MIN 1000 9 -1 50 RC1_REV 1 9 -1 50 RC1_TRIM 1501 9 -1 50 RC2_DZ 10 9 -1 50 RC2_MAX 2000 9 -1 50 RC2_MIN 1000 9 -1 50 RC2_REV 1 9 -1 50 RC2_TRIM 1501 9 -1 50 RC3_DZ 10 9 -1 50 RC3_MAX 2000 9 -1 50 RC3_MIN 1000 9 -1 50 RC3_REV 1 9 -1 50 RC3_TRIM 1501 9 -1 50 RC4_DZ 10 9 -1 50 RC4_MAX 2000 9 -1 50 RC4_MIN 1000 9 -1 50 RC4_REV 1 9 -1 50 RC4_TRIM 1501 9 -1 50 RC5_DZ 10 9 -1 50 RC5_MAX 2000 9 -1 50 RC5_MIN 1000 9 -1 50 RC5_REV 1 9 -1 50 RC5_TRIM 1500 9 -1 50 RC6_DZ 10 9 -1 50 RC6_MAX 2000 9 -1 50 RC6_MIN 1000 9 -1 50 RC6_REV 1 9 -1 50 RC6_TRIM 1500 9 -1 50 RC7_DZ 10 9 -1 50 RC7_MAX 2000 9 -1 50 RC7_MIN 1000 9 -1 50 RC7_REV 1 9 -1 50 RC7_TRIM 1500 9 -1 50 RC8_DZ 10 9 -1 50 RC8_MAX 2000 9 -1 50 RC8_MIN 1000 9 -1 50 RC8_REV 1 9 -1 50 RC8_TRIM 1500 9 -1 50 RC9_DZ 0 9 -1 50 RC9_MAX 2000 9 -1 50 RC9_MIN 1000 9 -1 50 RC9_REV 1 9 -1 50 RC9_TRIM 1500 9 -1 50 RC_ACRO_TH 0.5 9 -1 50 RC_ASSIST_TH 0.25 9 -1 50 RC_AUTO_TH 0.75 9 -1 50 RC_CHAN_CNT 0 6 -1 50 RC_DSM_BIND -1 6 -1 50 RC_FAILS_THR 0 6 -1 50 RC_LOITER_TH 0.5 9 -1 50 RC_MAP_ACRO_SW 0 6 -1 50 RC_MAP_AUX1 11 6 -1 50 RC_MAP_AUX2 12 6 -1 50 RC_MAP_AUX3 0 6 -1 50 RC_MAP_FAILSAFE 0 6 -1 50 RC_MAP_FLAPS 10 6 -1 50 RC_MAP_FLTMODE 0 6 -1 50 RC_MAP_KILL_SW 0 6 -1 50 RC_MAP_LOITER_SW 9 6 -1 50 RC_MAP_MODE_SW 6 6 -1 50 RC_MAP_OFFB_SW 0 6 -1 50 RC_MAP_PARAM1 0 6 -1 50 RC_MAP_PARAM2 0 6 -1 50 RC_MAP_PARAM3 0 6 -1 50 RC_MAP_PITCH 2 6 -1 50 RC_MAP_POSCTL_SW 7 6 -1 50 RC_MAP_RETURN_SW 8 6 -1 50 RC_MAP_ROLL 1 6 -1 50 RC_MAP_THROTTLE 3 6 -1 50 RC_MAP_YAW 4 6 -1 50 RC_OFFB_TH 0.5 9 -1 50 RC_POSCTL_TH 0.5 9 -1 50 RC_RETURN_TH 0.5 9 -1 50 RC_TH_USER 1 6 -1 50 RTL_DESCEND_ALT 10 9 -1 50 RTL_LAND_DELAY -1 9 -1 50 RTL_LOITER_RAD 50 9 -1 50 RTL_RETURN_ALT 30 9 -1 50 RV_YAW_P 0.1 9 -1 50 SDLOG_EXT -1 6 -1 50 SDLOG_RATE -1 6 -1 50 SENS_BARO_QNH 1013.25 9 -1 50 SENS_BOARD_ROT 0 6 -1 50 SENS_BOARD_X_OFF 0 9 -1 50 SENS_BOARD_Y_OFF 0 9 -1 50 SENS_BOARD_Z_OFF 0 9 -1 50 SENS_DPRES_ANSC 0 9 -1 50 SENS_DPRES_OFF 0 9 -1 50 SENS_EXT_MAG 0 6 -1 50 SENS_EXT_MAG_ROT 0 6 -1 50 SENS_FLOW_ROT 0 6 -1 50 SYS_AUTOCONFIG 0 6 -1 50 SYS_AUTOSTART 10016 6 -1 50 SYS_COMPANION 157600 6 -1 50 SYS_PARAM_VER 1 6 -1 50 SYS_RESTART_TYPE 0 6 -1 50 SYS_USE_IO 1 6 -1 50 TEST_D 0.01 9 -1 50 TEST_DEV 2 9 -1 50 TEST_D_LP 10 9 -1 50 TEST_HP 10 9 -1 50 TEST_I 0.1 9 -1 50 TEST_I_MAX 1 9 -1 50 TEST_LP 10 9 -1 50 TEST_MAX 1 9 -1 50 TEST_MEAN 1 9 -1 50 TEST_MIN -1 9 -1 50 TEST_P 0.2 9 -1 50 TEST_TRIM 0.5 9 -1 50 TRIM_PITCH 0 9 -1 50 TRIM_ROLL 0 9 -1 50 TRIM_YAW 0 9 -1 50 UAVCAN_BITRATE 1000000 6 -1 50 UAVCAN_ENABLE 0 6 -1 50 UAVCAN_NODE_ID 1 6 -1 50 VT_ARSP_LP_GAIN 0.3 9 -1 50 VT_FW_PERM_STAB 0 6 -1 50 VT_FW_PITCH_TRIM 0 9 -1 50 VT_IDLE_PWM_MC 900 6 -1 50 VT_MC_ARSPD_MAX 30 9 -1 50 VT_MC_ARSPD_MIN 10 9 -1 50 VT_MC_ARSPD_TRIM 10 9 -1 50 VT_MOT_COUNT 0 6 -1 50 VT_POWER_MAX 120 9 -1 50 VT_PROP_EFF 0 9 -1 51 COMPONENT_51 51 6 +# MAV ID COMPONENT ID PARAM NAME VALUE (FLOAT) +1 1 BAT_A_PER_V 15.391030311584472656 9 +1 1 BAT_CAPACITY -1.000000000000000000 9 +1 1 BAT_CNT_V_CURR 0.000805664050858468 9 +1 1 BAT_CNT_V_VOLT 0.000805664050858468 9 +1 1 BAT_CRIT_THR 0.070000000298023224 9 +1 1 BAT_LOW_THR 0.150000005960464478 9 +1 1 BAT_N_CELLS 3 6 +1 1 BAT_R_INTERNAL -1.000000000000000000 9 +1 1 BAT_SOURCE 0 6 +1 1 BAT_V_CHARGED 4.050000190734863281 9 +1 1 BAT_V_DIV 10.177939414978027344 9 +1 1 BAT_V_EMPTY 3.400000095367431641 9 +1 1 BAT_V_LOAD_DROP 0.300000011920928955 9 +1 1 BAT_V_OFFS_CURR 0.000000000000000000 9 +1 1 BAT_V_SCALE_IO 10000 6 +1 1 CAL_ACC0_ID 1246218 6 +1 1 CAL_ACC1_ID 1114634 6 +1 1 CAL_ACC1_XOFF 0.982475280761718750 9 +1 1 CAL_ACC1_XSCALE 0.977573156356811523 9 +1 1 CAL_ACC1_YOFF 0.922321319580078125 9 +1 1 CAL_ACC1_YSCALE 1.008152961730957031 9 +1 1 CAL_ACC1_ZOFF 1.137038230895996094 9 +1 1 CAL_ACC1_ZSCALE 1.007824659347534180 9 +1 1 CAL_ACC2_ID 0 6 +1 1 CAL_ACC2_XOFF 0.000000000000000000 9 +1 1 CAL_ACC2_XSCALE 1.000000000000000000 9 +1 1 CAL_ACC2_YOFF 0.000000000000000000 9 +1 1 CAL_ACC2_YSCALE 1.000000000000000000 9 +1 1 CAL_ACC2_ZOFF 0.000000000000000000 9 +1 1 CAL_ACC2_ZSCALE 1.000000000000000000 9 +1 1 CAL_ACC_PRIME 1246218 6 +1 1 CAL_BARO_PRIME 0 6 +1 1 CAL_GYRO0_ID 2162688 6 +1 1 CAL_GYRO1_ID 2228490 6 +1 1 CAL_GYRO1_XOFF 0.015412596054375172 9 +1 1 CAL_GYRO1_XSCALE 1.000000000000000000 9 +1 1 CAL_GYRO1_YOFF 0.004993732087314129 9 +1 1 CAL_GYRO1_YSCALE 1.000000000000000000 9 +1 1 CAL_GYRO1_ZOFF -0.027027824893593788 9 +1 1 CAL_GYRO1_ZSCALE 1.000000000000000000 9 +1 1 CAL_GYRO2_ID 0 6 +1 1 CAL_GYRO2_XOFF 0.000000000000000000 9 +1 1 CAL_GYRO2_XSCALE 1.000000000000000000 9 +1 1 CAL_GYRO2_YOFF 0.000000000000000000 9 +1 1 CAL_GYRO2_YSCALE 1.000000000000000000 9 +1 1 CAL_GYRO2_ZOFF 0.000000000000000000 9 +1 1 CAL_GYRO2_ZSCALE 1.000000000000000000 9 +1 1 CAL_GYRO_PRIME 2162688 6 +1 1 CAL_MAG0_ID 73225 6 +1 1 CAL_MAG0_ROT 0 6 +1 1 CAL_MAG1_ID 131594 6 +1 1 CAL_MAG1_ROT -1 6 +1 1 CAL_MAG1_XOFF 0.010499725118279457 9 +1 1 CAL_MAG1_XSCALE 1.000000000000000000 9 +1 1 CAL_MAG1_YOFF 0.041090622544288635 9 +1 1 CAL_MAG1_YSCALE 1.000000000000000000 9 +1 1 CAL_MAG1_ZOFF 0.046924047172069550 9 +1 1 CAL_MAG1_ZSCALE 1.000000000000000000 9 +1 1 CAL_MAG2_ID 0 6 +1 1 CAL_MAG2_ROT -1 6 +1 1 CAL_MAG2_XOFF 0.000000000000000000 9 +1 1 CAL_MAG2_XSCALE 1.000000000000000000 9 +1 1 CAL_MAG2_YOFF 0.000000000000000000 9 +1 1 CAL_MAG2_YSCALE 1.000000000000000000 9 +1 1 CAL_MAG2_ZOFF 0.000000000000000000 9 +1 1 CAL_MAG2_ZSCALE 1.000000000000000000 9 +1 1 CAL_MAG_PRIME 73225 6 +1 1 CAL_MAG_SIDES 63 6 +1 1 CBRK_AIRSPD_CHK 0 6 +1 1 CBRK_BUZZER 0 6 +1 1 CBRK_ENGINEFAIL 284953 6 +1 1 CBRK_FLIGHTTERM 121212 6 +1 1 CBRK_GPSFAIL 0 6 +1 1 CBRK_IO_SAFETY 0 6 +1 1 CBRK_SUPPLY_CHK 0 6 +1 1 CBRK_USB_CHK 0 6 +1 1 COM_ARM_EKF_AB 0.004999999888241291 9 +1 1 COM_ARM_EKF_GB 0.000869999988935888 9 +1 1 COM_ARM_EKF_HGT 1.000000000000000000 9 +1 1 COM_ARM_EKF_POS 0.500000000000000000 9 +1 1 COM_ARM_EKF_VEL 0.500000000000000000 9 +1 1 COM_ARM_EKF_YAW 0.500000000000000000 9 +1 1 COM_ARM_IMU_ACC 0.699999988079071045 9 +1 1 COM_ARM_IMU_GYR 0.090000003576278687 9 +1 1 COM_ARM_WO_GPS 1 6 +1 1 COM_AUTOS_PAR 1 6 +1 1 COM_DISARM_LAND 0 6 +1 1 COM_DL_LOSS_T 10 6 +1 1 COM_DL_REG_T 0 6 +1 1 COM_EF_C2T 5.000000000000000000 9 +1 1 COM_EF_THROT 0.500000000000000000 9 +1 1 COM_EF_TIME 10.000000000000000000 9 +1 1 COM_FLTMODE1 -1 6 +1 1 COM_FLTMODE2 -1 6 +1 1 COM_FLTMODE3 -1 6 +1 1 COM_FLTMODE4 -1 6 +1 1 COM_FLTMODE5 -1 6 +1 1 COM_FLTMODE6 -1 6 +1 1 COM_HOME_H_T 5.000000000000000000 9 +1 1 COM_HOME_V_T 10.000000000000000000 9 +1 1 COM_LOW_BAT_ACT 0 6 +1 1 COM_OBL_ACT 0 6 +1 1 COM_OBL_RC_ACT 0 6 +1 1 COM_OF_LOSS_T 0.000000000000000000 9 +1 1 COM_RC_ARM_HYST 1000 6 +1 1 COM_RC_IN_MODE 0 6 +1 1 COM_RC_LOSS_T 0.500000000000000000 9 +1 1 EKF2_REC_RPL 0 6 +1 1 FW_AIRSPD_TRIM 15.000000000000000000 9 +1 1 FW_CLMBOUT_DIFF 10.000000000000000000 9 +1 1 FW_MAN_P_SC 1.000000000000000000 9 +1 1 FW_MAN_R_SC 1.000000000000000000 9 +1 1 FW_MAN_Y_SC 1.000000000000000000 9 +1 1 FW_THR_CRUISE 0.600000023841857910 9 +1 1 GF_ACTION 1 6 +1 1 GF_ALTMODE 0 6 +1 1 GF_COUNT -1 6 +1 1 GF_MAX_HOR_DIST 0.000000000000000000 9 +1 1 GF_MAX_VER_DIST 0.000000000000000000 9 +1 1 GF_SOURCE 0 6 +1 1 GPS_DUMP_COMM 0 6 +1 1 LED_RGB_MAXBRT 15 6 +1 1 MAV_BROADCAST 0 6 +1 1 MAV_COMP_ID 1 6 +1 1 MAV_FWDEXTSP 1 6 +1 1 MAV_PROTO_VER 0 6 +1 1 MAV_RADIO_ID 0 6 +1 1 MAV_SYS_ID 1 6 +1 1 MAV_TEST_PAR 1 6 +1 1 MAV_TYPE 2 6 +1 1 MAV_USEHILGPS 0 6 +1 1 MC_YAWRAUTO_MAX 45.000000000000000000 9 +1 1 MIS_ALTMODE 1 6 +1 1 MIS_DIST_1WP 900.000000000000000000 9 +1 1 MIS_LTRMIN_ALT 1.200000047683715820 9 +1 1 MIS_ONBOARD_EN 1 6 +1 1 MIS_TAKEOFF_ALT 2.500000000000000000 9 +1 1 MIS_YAWMODE 1 6 +1 1 MIS_YAW_ERR 12.000000000000000000 9 +1 1 MIS_YAW_TMT -1.000000000000000000 9 +1 1 MOT_SLEW_MAX 0.000000000000000000 9 +1 1 MPC_XY_CRUISE 5.000000000000000000 9 +1 1 NAV_ACC_RAD 10.000000000000000000 9 +1 1 NAV_AH_ALT 600.000000000000000000 9 +1 1 NAV_AH_LAT -265847810 6 +1 1 NAV_AH_LON 1518423250 6 +1 1 NAV_DLL_ACT 0 6 +1 1 NAV_DLL_AH_T 120.000000000000000000 9 +1 1 NAV_DLL_CHSK 0 6 +1 1 NAV_DLL_CH_ALT 600.000000000000000000 9 +1 1 NAV_DLL_CH_LAT -266072120 6 +1 1 NAV_DLL_CH_LON 1518453890 6 +1 1 NAV_DLL_CH_T 120.000000000000000000 9 +1 1 NAV_DLL_N 2 6 +1 1 NAV_FT_DST 8.000000000000000000 9 +1 1 NAV_FT_FS 1 6 +1 1 NAV_FT_RS 0.500000000000000000 9 +1 1 NAV_FW_ALT_RAD 10.000000000000000000 9 +1 1 NAV_GPSF_LT 30.000000000000000000 9 +1 1 NAV_GPSF_P 0.000000000000000000 9 +1 1 NAV_GPSF_R 15.000000000000000000 9 +1 1 NAV_GPSF_TR 0.699999988079071045 9 +1 1 NAV_LOITER_RAD 50.000000000000000000 9 +1 1 NAV_MC_ALT_RAD 3.000000000000000000 9 +1 1 NAV_MIN_FT_HT 8.000000000000000000 9 +1 1 NAV_RCL_ACT 2 6 +1 1 NAV_RCL_LT 120.000000000000000000 9 +1 1 PWM_AUX_DISARMED 1000 6 +1 1 PWM_AUX_MAX 2000 6 +1 1 PWM_AUX_MIN 1000 6 +1 1 PWM_DISARMED 0 6 +1 1 PWM_MAIN_REV1 0 6 +1 1 PWM_MAIN_REV2 0 6 +1 1 PWM_MAIN_REV3 0 6 +1 1 PWM_MAIN_REV4 0 6 +1 1 PWM_MAIN_REV5 0 6 +1 1 PWM_MAIN_REV6 0 6 +1 1 PWM_MAIN_REV7 0 6 +1 1 PWM_MAIN_REV8 0 6 +1 1 PWM_MAX 2000 6 +1 1 PWM_MIN 1000 6 +1 1 PWM_RATE 400 6 +1 1 PWM_SBUS_MODE 0 6 +1 1 RC10_DZ 0.000000000000000000 9 +1 1 RC10_MAX 2000.000000000000000000 9 +1 1 RC10_MIN 1000.000000000000000000 9 +1 1 RC10_REV 1.000000000000000000 9 +1 1 RC10_TRIM 1500.000000000000000000 9 +1 1 RC11_DZ 0.000000000000000000 9 +1 1 RC11_MAX 2000.000000000000000000 9 +1 1 RC11_MIN 1000.000000000000000000 9 +1 1 RC11_REV 1.000000000000000000 9 +1 1 RC11_TRIM 1500.000000000000000000 9 +1 1 RC12_DZ 0.000000000000000000 9 +1 1 RC12_MAX 2000.000000000000000000 9 +1 1 RC12_MIN 1000.000000000000000000 9 +1 1 RC12_REV 1.000000000000000000 9 +1 1 RC12_TRIM 1500.000000000000000000 9 +1 1 RC13_DZ 0.000000000000000000 9 +1 1 RC13_MAX 2000.000000000000000000 9 +1 1 RC13_MIN 1000.000000000000000000 9 +1 1 RC13_REV 1.000000000000000000 9 +1 1 RC13_TRIM 1500.000000000000000000 9 +1 1 RC14_DZ 0.000000000000000000 9 +1 1 RC14_MAX 2000.000000000000000000 9 +1 1 RC14_MIN 1000.000000000000000000 9 +1 1 RC14_REV 1.000000000000000000 9 +1 1 RC14_TRIM 1500.000000000000000000 9 +1 1 RC15_DZ 0.000000000000000000 9 +1 1 RC15_MAX 2000.000000000000000000 9 +1 1 RC15_MIN 1000.000000000000000000 9 +1 1 RC15_REV 1.000000000000000000 9 +1 1 RC15_TRIM 1500.000000000000000000 9 +1 1 RC16_DZ 0.000000000000000000 9 +1 1 RC16_MAX 2000.000000000000000000 9 +1 1 RC16_MIN 1000.000000000000000000 9 +1 1 RC16_REV 1.000000000000000000 9 +1 1 RC16_TRIM 1500.000000000000000000 9 +1 1 RC17_DZ 0.000000000000000000 9 +1 1 RC17_MAX 2000.000000000000000000 9 +1 1 RC17_MIN 1000.000000000000000000 9 +1 1 RC17_REV 1.000000000000000000 9 +1 1 RC17_TRIM 1500.000000000000000000 9 +1 1 RC18_DZ 0.000000000000000000 9 +1 1 RC18_MAX 2000.000000000000000000 9 +1 1 RC18_MIN 1000.000000000000000000 9 +1 1 RC18_REV 1.000000000000000000 9 +1 1 RC18_TRIM 1500.000000000000000000 9 +1 1 RC1_DZ 10.000000000000000000 9 +1 1 RC1_MAX 1900.000000000000000000 9 +1 1 RC1_MIN 1100.000000000000000000 9 +1 1 RC1_REV -1.000000000000000000 9 +1 1 RC1_TRIM 1492.000000000000000000 9 +1 1 RC2_DZ 10.000000000000000000 9 +1 1 RC2_MAX 1900.000000000000000000 9 +1 1 RC2_MIN 1100.000000000000000000 9 +1 1 RC2_REV 1.000000000000000000 9 +1 1 RC2_TRIM 1483.000000000000000000 9 +1 1 RC3_DZ 10.000000000000000000 9 +1 1 RC3_MAX 1901.000000000000000000 9 +1 1 RC3_MIN 1099.000000000000000000 9 +1 1 RC3_REV 1.000000000000000000 9 +1 1 RC3_TRIM 1099.000000000000000000 9 +1 1 RC4_DZ 10.000000000000000000 9 +1 1 RC4_MAX 1900.000000000000000000 9 +1 1 RC4_MIN 1100.000000000000000000 9 +1 1 RC4_REV -1.000000000000000000 9 +1 1 RC4_TRIM 1500.000000000000000000 9 +1 1 RC5_DZ 10.000000000000000000 9 +1 1 RC5_MAX 2000.000000000000000000 9 +1 1 RC5_MIN 1000.000000000000000000 9 +1 1 RC5_REV 1.000000000000000000 9 +1 1 RC5_TRIM 1500.000000000000000000 9 +1 1 RC6_DZ 10.000000000000000000 9 +1 1 RC6_MAX 1901.000000000000000000 9 +1 1 RC6_MIN 1099.000000000000000000 9 +1 1 RC6_REV 1.000000000000000000 9 +1 1 RC6_TRIM 1500.000000000000000000 9 +1 1 RC7_DZ 10.000000000000000000 9 +1 1 RC7_MAX 2000.000000000000000000 9 +1 1 RC7_MIN 1000.000000000000000000 9 +1 1 RC7_REV 1.000000000000000000 9 +1 1 RC7_TRIM 1500.000000000000000000 9 +1 1 RC8_DZ 10.000000000000000000 9 +1 1 RC8_MAX 2000.000000000000000000 9 +1 1 RC8_MIN 1000.000000000000000000 9 +1 1 RC8_REV 1.000000000000000000 9 +1 1 RC8_TRIM 1500.000000000000000000 9 +1 1 RC9_DZ 0.000000000000000000 9 +1 1 RC9_MAX 2000.000000000000000000 9 +1 1 RC9_MIN 1000.000000000000000000 9 +1 1 RC9_REV 1.000000000000000000 9 +1 1 RC9_TRIM 1500.000000000000000000 9 +1 1 RC_ACRO_TH 0.500000000000000000 9 +1 1 RC_ASSIST_TH 0.250000000000000000 9 +1 1 RC_AUTO_TH 0.750000000000000000 9 +1 1 RC_CHAN_CNT 8 6 +1 1 RC_DSM_BIND -1 6 +1 1 RC_FAILS_THR 0 6 +1 1 RC_GEAR_TH 0.250000000000000000 9 +1 1 RC_KILLSWITCH_TH 0.250000000000000000 9 +1 1 RC_LOITER_TH 0.500000000000000000 9 +1 1 RC_MAP_ACRO_SW 0 6 +1 1 RC_MAP_AUX1 0 6 +1 1 RC_MAP_AUX2 0 6 +1 1 RC_MAP_AUX3 0 6 +1 1 RC_MAP_AUX4 0 6 +1 1 RC_MAP_AUX5 0 6 +1 1 RC_MAP_FAILSAFE 0 6 +1 1 RC_MAP_FLAPS 0 6 +1 1 RC_MAP_FLTMODE 5 6 +1 1 RC_MAP_GEAR_SW 0 6 +1 1 RC_MAP_KILL_SW 0 6 +1 1 RC_MAP_LOITER_SW 0 6 +1 1 RC_MAP_MODE_SW 0 6 +1 1 RC_MAP_OFFB_SW 0 6 +1 1 RC_MAP_PARAM1 0 6 +1 1 RC_MAP_PARAM2 0 6 +1 1 RC_MAP_PARAM3 0 6 +1 1 RC_MAP_PITCH 2 6 +1 1 RC_MAP_POSCTL_SW 0 6 +1 1 RC_MAP_RATT_SW 0 6 +1 1 RC_MAP_RETURN_SW 0 6 +1 1 RC_MAP_ROLL 1 6 +1 1 RC_MAP_THROTTLE 3 6 +1 1 RC_MAP_TRANS_SW 0 6 +1 1 RC_MAP_YAW 4 6 +1 1 RC_OFFB_TH 0.500000000000000000 9 +1 1 RC_POSCTL_TH 0.500000000000000000 9 +1 1 RC_RATT_TH 0.500000000000000000 9 +1 1 RC_RETURN_TH 0.500000000000000000 9 +1 1 RC_RSSI_PWM_CHAN 0 6 +1 1 RC_RSSI_PWM_MAX 1000 6 +1 1 RC_RSSI_PWM_MIN 2000 6 +1 1 RC_TH_USER 1 6 +1 1 RC_TRANS_TH 0.250000000000000000 9 +1 1 RTL_DESCEND_ALT 30.000000000000000000 9 +1 1 RTL_LAND_DELAY -1.000000000000000000 9 +1 1 RTL_MIN_DIST 5.000000000000000000 9 +1 1 RTL_RETURN_ALT 60.000000000000000000 9 +1 1 SDLOG_EXT -1 6 +1 1 SDLOG_GPSTIME 1 6 +1 1 SDLOG_PRIO_BOOST 2 6 +1 1 SDLOG_RATE -1 6 +1 1 SENS_BARO_QNH 1013.250000000000000000 9 +1 1 SENS_BOARD_ROT 0 6 +1 1 SENS_BOARD_X_OFF 0.000000000000000000 9 +1 1 SENS_BOARD_Y_OFF 0.000000000000000000 9 +1 1 SENS_BOARD_Z_OFF 0.000000000000000000 9 +1 1 SENS_DPRES_ANSC 0.000000000000000000 9 +1 1 SENS_DPRES_OFF 0.000000000000000000 9 +1 1 SENS_EN_LL40LS 0 6 +1 1 SENS_EN_MB12XX 0 6 +1 1 SENS_EN_SF0X 0 6 +1 1 SENS_EN_SF1XX 0 6 +1 1 SENS_EN_THERMAL -1 6 +1 1 SENS_EN_TRONE 0 6 +1 1 SYS_AUTOCONFIG 1 6 +1 1 SYS_AUTOSTART 10018 6 +1 1 SYS_COMPANION 157600 6 +1 1 SYS_LOGGER 0 6 +1 1 SYS_MC_EST_GROUP 2 6 +1 1 SYS_PARAM_VER 1 6 +1 1 SYS_RESTART_TYPE 0 6 +1 1 SYS_USE_IO 1 6 +1 1 TRIG_MODE 0 6 +1 1 TRIM_PITCH 0.000000000000000000 9 +1 1 TRIM_ROLL 0.000000000000000000 9 +1 1 TRIM_YAW 0.000000000000000000 9 +1 1 UAVCAN_ENABLE 0 6 +1 1 VT_NAV_FORCE_VT 1 6 +1 1 VT_WV_LND_EN 0 6 +1 1 VT_WV_LTR_EN 0 6 diff --git a/src/comm/QGCFlightGearLink.cc b/src/comm/QGCFlightGearLink.cc index fcbb4029fb7c458908cea6d07b9545379c6eaa5c..ec5112e6f25d970336d75ed8a4342daf29abc653 100644 --- a/src/comm/QGCFlightGearLink.cc +++ b/src/comm/QGCFlightGearLink.cc @@ -32,7 +32,6 @@ #include "QGC.h" #include "QGCFileDialog.h" #include "QGCMessageBox.h" -#include "HomePositionManager.h" #include "QGCApplication.h" #include "Vehicle.h" #include "UAS.h" @@ -939,11 +938,12 @@ bool QGCFlightGearLink::connectSimulation() } // We start out at our home position - _fgArgList << QString("--lat=%1").arg(qgcApp()->toolbox()->homePositionManager()->getHomeLatitude()); - _fgArgList << QString("--lon=%1").arg(qgcApp()->toolbox()->homePositionManager()->getHomeLongitude()); + QGeoCoordinate homePosition = qgcApp()->lastKnownHomePosition(); + _fgArgList << QString("--lat=%1").arg(homePosition.latitude()); + _fgArgList << QString("--lon=%1").arg(homePosition.longitude()); // The altitude is not set because an altitude not equal to the ground altitude leads to a non-zero default throttle in flightgear // Without the altitude-setting the aircraft is positioned on the ground - //_fgArgList << QString("--altitude=%1").arg(qgcApp()->toolbox()->homePositionManager()->getHomeAltitude()); + //_fgArgList << QString("--altitude=%1").arg(homePosition.altitude()); #ifdef DEBUG_FLIGHTGEAR_CONNECT // This tell FlightGear to output highest debug level of log output. Handy for debuggin failures by looking at the FG diff --git a/src/comm/QGCSerialPortInfo.cc b/src/comm/QGCSerialPortInfo.cc index c8c0b79c50a0778e4421a36ddc1765409c87bdd5..5e50529b143297c1b99760f793020889fa23a238 100644 --- a/src/comm/QGCSerialPortInfo.cc +++ b/src/comm/QGCSerialPortInfo.cc @@ -9,33 +9,37 @@ #include "QGCSerialPortInfo.h" +#include "JsonHelper.h" + +#include +#include +#include +#include QGC_LOGGING_CATEGORY(QGCSerialPortInfoLog, "QGCSerialPortInfoLog") -static const struct VIDPIDMapInfo_s { - int vendorId; - int productId; - QGCSerialPortInfo::BoardType_t boardType; - const char * boardString; -} s_rgVIDPIDMappings[] = { - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::pixhawkFMUV4ProductId, QGCSerialPortInfo::BoardTypePX4FMUV4, "Found PX4 FMU V4" }, - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::pixhawkFMUV2ProductId, QGCSerialPortInfo::BoardTypePX4FMUV2, "Found PX4 FMU V2" }, - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::pixhawkFMUV2OldBootloaderProductId, QGCSerialPortInfo::BoardTypePX4FMUV2, "Found PX4 FMU V2"}, - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::pixhawkFMUV1ProductId, QGCSerialPortInfo::BoardTypePX4FMUV1, "Found PX4 FMU V1" }, - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::px4FlowProductId, QGCSerialPortInfo::BoardTypePX4Flow, "Found PX4 Flow" }, - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::AeroCoreProductId, QGCSerialPortInfo::BoardTypeAeroCore, "Found AeroCore" }, - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::MindPXFMUV2ProductId, QGCSerialPortInfo::BoardTypeMINDPXFMUV2,"Found MindPX FMU V2" }, - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::TAPV1ProductId, QGCSerialPortInfo::BoardTypeTAPV1, "Found TAP V1" }, - { QGCSerialPortInfo::px4VendorId, QGCSerialPortInfo::ASCV1ProductId, QGCSerialPortInfo::BoardTypeASCV1, "Found ASC V1" }, - { QGCSerialPortInfo::threeDRRadioVendorId, QGCSerialPortInfo::threeDRRadioProductId, QGCSerialPortInfo::BoardTypeSikRadio, "Found SiK Radio" }, - { QGCSerialPortInfo::siLabsRadioVendorId, QGCSerialPortInfo::siLabsRadioProductId, QGCSerialPortInfo::BoardTypeSikRadio, "Found SiK Radio" }, - { QGCSerialPortInfo::ubloxRTKVendorId, QGCSerialPortInfo::ubloxRTKProductId, QGCSerialPortInfo::BoardTypeRTKGPS, "Found RTK GPS" }, - { QGCSerialPortInfo::openpilotVendorId, QGCSerialPortInfo::revolutionProductId, QGCSerialPortInfo::BoardTypeLibrePilot, "Found OP Revolution" }, - { QGCSerialPortInfo::openpilotVendorId, QGCSerialPortInfo::oplinkProductId, QGCSerialPortInfo::BoardTypeLibrePilot, "Found OP OPLink" }, - { QGCSerialPortInfo::openpilotVendorId, QGCSerialPortInfo::sparky2ProductId, QGCSerialPortInfo::BoardTypeLibrePilot, "Found TL Sparky2" }, - { QGCSerialPortInfo::openpilotVendorId, QGCSerialPortInfo::CC3DProductId, QGCSerialPortInfo::BoardTypeLibrePilot, "Found OP CC3D" }, +bool QGCSerialPortInfo::_jsonLoaded = false; +const char* QGCSerialPortInfo::_jsonFileTypeValue = "USBBoardInfo"; +const char* QGCSerialPortInfo::_jsonBoardInfoKey = "boardInfo"; +const char* QGCSerialPortInfo::_jsonBoardFallbackKey = "boardFallback"; +const char* QGCSerialPortInfo::_jsonVendorIDKey = "vendorID"; +const char* QGCSerialPortInfo::_jsonProductIDKey = "productID"; +const char* QGCSerialPortInfo::_jsonBoardClassKey = "boardClass"; +const char* QGCSerialPortInfo::_jsonNameKey = "name"; +const char* QGCSerialPortInfo::_jsonRegExpKey = "regExp"; +const char* QGCSerialPortInfo::_jsonAndroidOnlyKey = "androidOnly"; + +const QGCSerialPortInfo::BoardClassString2BoardType_t QGCSerialPortInfo::_rgBoardClass2BoardType[] = { + { "Pixhawk", QGCSerialPortInfo::BoardTypePixhawk }, + { "PX4 Flow", QGCSerialPortInfo::BoardTypePX4Flow }, + { "RTK GPS", QGCSerialPortInfo::BoardTypeRTKGPS }, + { "SiK Radio", QGCSerialPortInfo::BoardTypeSiKRadio }, + { "OpenPilot", QGCSerialPortInfo::BoardTypeOpenPilot }, }; +QList QGCSerialPortInfo::_boardInfoList; +QList QGCSerialPortInfo::_boardFallbackList; + QGCSerialPortInfo::QGCSerialPortInfo(void) : QSerialPortInfo() { @@ -48,67 +52,202 @@ QGCSerialPortInfo::QGCSerialPortInfo(const QSerialPort & port) : } -QGCSerialPortInfo::BoardType_t QGCSerialPortInfo::boardType(void) const +void QGCSerialPortInfo::_loadJsonData(void) { - if (isNull()) { - return BoardTypeUnknown; + if (_jsonLoaded) { + return; + } + _jsonLoaded = true; + + QFile file(QStringLiteral(":/json/USBBoardInfo.json")); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning() << "Unable to open board info json:" << file.errorString(); + return; + } + + QByteArray bytes = file.readAll(); + + QJsonParseError jsonParseError; + QJsonDocument jsonDoc(QJsonDocument::fromJson(bytes, &jsonParseError)); + if (jsonParseError.error != QJsonParseError::NoError) { + qWarning() << "Unable to parse board info json:" << jsonParseError.errorString(); + return; + } + QJsonObject json = jsonDoc.object(); + + int fileVersion; + QString errorString; + if (!JsonHelper::validateQGCJsonFile(json, + _jsonFileTypeValue, // expected file type + 1, // minimum supported version + 1, // maximum supported version + fileVersion, + errorString)) { + qWarning() << errorString; + return; + } + + // Validate root object keys + QList rootKeyInfoList = { + { _jsonBoardInfoKey, QJsonValue::Array, true }, + { _jsonBoardFallbackKey, QJsonValue::Array, true }, + }; + if (!JsonHelper::validateKeys(json, rootKeyInfoList, errorString)) { + qWarning() << errorString; + return; } - BoardType_t boardType = BoardTypeUnknown; + // Load board info used to detect known board from vendor/product id - for (size_t i=0; i boardKeyInfoList = { + { _jsonVendorIDKey, QJsonValue::Double, true }, + { _jsonProductIDKey, QJsonValue::Double, true }, + { _jsonBoardClassKey, QJsonValue::String, true }, + { _jsonNameKey, QJsonValue::String, true }, + }; + + QJsonArray rgBoardInfo = json[_jsonBoardInfoKey].toArray(); + for (int i=0; i fallbackKeyInfoList = { + { _jsonRegExpKey, QJsonValue::String, true }, + { _jsonBoardClassKey, QJsonValue::String, true }, + { _jsonAndroidOnlyKey, QJsonValue::Bool, false }, + }; + + QJsonArray rgBoardFallback = json[_jsonBoardFallbackKey].toArray(); + for (int i=0; ivendorId && productIdentifier() == pIDMap->productId) { - boardType = pIDMap->boardType; - qCDebug(QGCSerialPortInfoLog) << pIDMap->boardString; +QGCSerialPortInfo::BoardType_t QGCSerialPortInfo::_boardClassStringToType(const QString& boardClass) +{ + for (size_t j=0; j QGCSerialPortInfo::availablePorts(void) { QList list; @@ -120,34 +259,34 @@ QList QGCSerialPortInfo::availablePorts(void) return list; } -bool QGCSerialPortInfo::boardTypePixhawk(void) const -{ - BoardType_t boardType = this->boardType(); - - return boardType == BoardTypePX4FMUV1 || boardType == BoardTypePX4FMUV2 - || boardType == BoardTypePX4FMUV4 || boardType == BoardTypeAeroCore - || boardType == BoardTypeMINDPXFMUV2 || boardType == BoardTypeTAPV1 - || boardType == BoardTypeASCV1; -} - bool QGCSerialPortInfo::isBootloader(void) const { - // FIXME: Check SerialLink bootloade detect code which is different - return boardTypePixhawk() && description().contains("BL"); + BoardType_t boardType; + QString name; + + if (getBoardInfo(boardType, name)) { + // FIXME: Check SerialLink bootloade detect code which is different + return boardType == BoardTypePixhawk && description().contains("BL"); + } else { + return false; + } } bool QGCSerialPortInfo::canFlash(void) { - BoardType_t boardType = this->boardType(); - switch(boardType){ - case QGCSerialPortInfo::BoardTypeUnknown: - case QGCSerialPortInfo::BoardTypeRTKGPS: - case QGCSerialPortInfo::BoardTypeLibrePilot: - return false; - default: - return true; + BoardType_t boardType; + QString name; + if (getBoardInfo(boardType, name)) { + switch(boardType){ + case QGCSerialPortInfo::BoardTypePixhawk: + case QGCSerialPortInfo::BoardTypePX4Flow: + case QGCSerialPortInfo::BoardTypeSiKRadio: + return true; + default: + return false; + } + } else { + return false; } - - } diff --git a/src/comm/QGCSerialPortInfo.h b/src/comm/QGCSerialPortInfo.h index 9609a4fa1496550663e69bdd4722eedd34b407cf..0148da2f0747de614859a00fe69f5c7f42a91085 100644 --- a/src/comm/QGCSerialPortInfo.h +++ b/src/comm/QGCSerialPortInfo.h @@ -27,70 +27,65 @@ class QGCSerialPortInfo : public QSerialPortInfo { public: typedef enum { - BoardTypePX4FMUV1, - BoardTypePX4FMUV2, - BoardTypePX4FMUV4, + BoardTypePixhawk, + BoardTypeSiKRadio, BoardTypePX4Flow, - BoardTypeSikRadio, - BoardTypeAeroCore, + BoardTypeOpenPilot, BoardTypeRTKGPS, - BoardTypeMINDPXFMUV2, - BoardTypeTAPV1, - BoardTypeASCV1, - BoardTypeLibrePilot, BoardTypeUnknown } BoardType_t; - // Vendor and products ids for the boards we care about - - static const int px4VendorId = 9900; ///< Vendor ID for Pixhawk board (V2 and V1) and PX4 Flow - - static const int pixhawkFMUV4ProductId = 18; ///< Product ID for Pixhawk V2 board - static const int pixhawkFMUV2ProductId = 17; ///< Product ID for Pixhawk V2 board - static const int pixhawkFMUV2OldBootloaderProductId = 22; ///< Product ID for Bootloader on older Pixhawk V2 boards - static const int pixhawkFMUV1ProductId = 16; ///< Product ID for PX4 FMU V1 board - - static const int AeroCoreProductId = 4097; ///< Product ID for the AeroCore board - - static const int px4FlowProductId = 21; ///< Product ID for PX4 Flow board - - static const int MindPXFMUV2ProductId = 48; ///< Product ID for the MindPX V2 board - static const int TAPV1ProductId = 64; ///< Product ID for the TAP V1 board - static const int ASCV1ProductId = 65; ///< Product ID for the ASC V1 board - - static const int threeDRRadioVendorId = 1027; ///< Vendor ID for 3DR Radio - static const int threeDRRadioProductId = 24597; ///< Product ID for 3DR Radio - - static const int siLabsRadioVendorId = 0x10c4; ///< Vendor ID for SILabs Radio - static const int siLabsRadioProductId = 0xea60; ///< Product ID for SILabs Radio - - static const int ubloxRTKVendorId = 5446; ///< Vendor ID for ublox RTK - static const int ubloxRTKProductId = 424; ///< Product ID for ublox RTK - - static const int openpilotVendorId = 0x20A0; ///< Vendor ID for OpenPilot - static const int revolutionProductId = 0x415E; ///< Product ID for OpenPilot Revolution - static const int oplinkProductId = 0x415C; ///< Product ID for OpenPilot OPLink - static const int sparky2ProductId = 0x41D0; ///< Product ID for Taulabs Sparky2 - static const int CC3DProductId = 0x415D; ///< Product ID for OpenPilot CC3D - QGCSerialPortInfo(void); QGCSerialPortInfo(const QSerialPort & port); /// Override of QSerialPortInfo::availablePorts static QList availablePorts(void); - BoardType_t boardType(void) const; + bool getBoardInfo(BoardType_t& boardType, QString& name) const; /// @return true: we can flash this board type bool canFlash(void); - /// @return true: board is a Pixhawk board - bool boardTypePixhawk(void) const; - /// @return true: Board is currently in bootloader bool isBootloader(void) const; private: + typedef struct { + const char* classString; + BoardType_t boardType; + } BoardClassString2BoardType_t; + + typedef struct { + int vendorId; + int productId; + BoardType_t boardType; + QString name; + } BoardInfo_t; + + typedef struct { + QString regExp; + BoardType_t boardType; + bool androidOnly; + } BoardFallback_t; + + static void _loadJsonData(void); + static BoardType_t _boardClassStringToType(const QString& boardClass); + static QString _boardTypeToString(BoardType_t boardType); + + static bool _jsonLoaded; + static const char* _jsonFileTypeValue; + static const char* _jsonBoardInfoKey; + static const char* _jsonBoardFallbackKey; + static const char* _jsonVendorIDKey; + static const char* _jsonProductIDKey; + static const char* _jsonBoardClassKey; + static const char* _jsonNameKey; + static const char* _jsonRegExpKey; + static const char* _jsonAndroidOnlyKey; + + static const BoardClassString2BoardType_t _rgBoardClass2BoardType[BoardTypeUnknown]; + static QList _boardInfoList; + static QList _boardFallbackList; }; #endif diff --git a/src/comm/QGCXPlaneLink.cc b/src/comm/QGCXPlaneLink.cc index a186a80118f6e25477be5b32228d0c8fe3bed0ff..87b4247eb64c5a29be08a73109dc4bb175cf6181 100644 --- a/src/comm/QGCXPlaneLink.cc +++ b/src/comm/QGCXPlaneLink.cc @@ -30,7 +30,6 @@ #include "UAS.h" #include "UASInterface.h" #include "QGCMessageBox.h" -#include "HomePositionManager.h" QGCXPlaneLink::QGCXPlaneLink(Vehicle* vehicle, QString remoteHost, QHostAddress localHost, quint16 localPort) : _vehicle(vehicle), diff --git a/src/comm/SerialLink.cc b/src/comm/SerialLink.cc index 3e345f682a23e24e83eedd5e42ef124f11221236..9e600db18d1256be835e7a0af4e8dba02d3b96f7 100644 --- a/src/comm/SerialLink.cc +++ b/src/comm/SerialLink.cc @@ -30,19 +30,19 @@ QGC_LOGGING_CATEGORY(SerialLinkLog, "SerialLinkLog") static QStringList kSupportedBaudRates; -SerialLink::SerialLink(SerialConfiguration* config) +SerialLink::SerialLink(SharedLinkConfigurationPointer& config) + : LinkInterface(config) + , _port(NULL) + , _bytesRead(0) + , _stopp(false) + , _reqReset(false) + , _serialConfig(qobject_cast(config.data())) { - _bytesRead = 0; - _port = Q_NULLPTR; - _stopp = false; - _reqReset = false; - Q_ASSERT(config != NULL); - _config = config; - _config->setLink(this); - - qCDebug(SerialLinkLog) << "Create SerialLink " << config->portName() << config->baud() << config->flowControl() - << config->parity() << config->dataBits() << config->stopBits(); - qCDebug(SerialLinkLog) << "portName: " << config->portName(); + Q_ASSERT(_serialConfig); + + qCDebug(SerialLinkLog) << "Create SerialLink " << _serialConfig->portName() << _serialConfig->baud() << _serialConfig->flowControl() + << _serialConfig->parity() << _serialConfig->dataBits() << _serialConfig->stopBits(); + qCDebug(SerialLinkLog) << "portName: " << _serialConfig->portName(); } void SerialLink::requestReset() @@ -53,10 +53,10 @@ void SerialLink::requestReset() SerialLink::~SerialLink() { - // Disconnect link from configuration - _config->setLink(NULL); _disconnect(); - if(_port) delete _port; + if (_port) { + delete _port; + } _port = NULL; } @@ -70,7 +70,7 @@ bool SerialLink::_isBootloader() { qCDebug(SerialLinkLog) << "PortName : " << info.portName() << "Description : " << info.description(); qCDebug(SerialLinkLog) << "Manufacturer: " << info.manufacturer(); - if (info.portName().trimmed() == _config->portName() && + if (info.portName().trimmed() == _serialConfig->portName() && (info.description().toLower().contains("bootloader") || info.description().toLower().contains("px4 bl") || info.description().toLower().contains("px4 fmu v1.6"))) { @@ -159,7 +159,7 @@ bool SerialLink::_hardwareConnect(QSerialPort::SerialPortError& error, QString& _port = NULL; } - qCDebug(SerialLinkLog) << "SerialLink: hardwareConnect to " << _config->portName(); + qCDebug(SerialLinkLog) << "SerialLink: hardwareConnect to " << _serialConfig->portName(); // If we are in the Pixhawk bootloader code wait for it to timeout if (_isBootloader()) { @@ -181,7 +181,7 @@ bool SerialLink::_hardwareConnect(QSerialPort::SerialPortError& error, QString& } } - _port = new QSerialPort(_config->portName()); + _port = new QSerialPort(_serialConfig->portName()); QObject::connect(_port, static_cast(&QSerialPort::error), this, &SerialLink::linkError); @@ -219,17 +219,17 @@ bool SerialLink::_hardwareConnect(QSerialPort::SerialPortError& error, QString& _port->setDataTerminalReady(true); qCDebug(SerialLinkLog) << "Configuring port"; - _port->setBaudRate (_config->baud()); - _port->setDataBits (static_cast (_config->dataBits())); - _port->setFlowControl (static_cast (_config->flowControl())); - _port->setStopBits (static_cast (_config->stopBits())); - _port->setParity (static_cast (_config->parity())); + _port->setBaudRate (_serialConfig->baud()); + _port->setDataBits (static_cast (_serialConfig->dataBits())); + _port->setFlowControl (static_cast (_serialConfig->flowControl())); + _port->setStopBits (static_cast (_serialConfig->stopBits())); + _port->setParity (static_cast (_serialConfig->parity())); emit communicationUpdate(getName(), "Opened port!"); emit connected(); - qCDebug(SerialLinkLog) << "Connection SeriaLink: " << "with settings" << _config->portName() - << _config->baud() << _config->dataBits() << _config->parity() << _config->stopBits(); + qCDebug(SerialLinkLog) << "Connection SeriaLink: " << "with settings" << _serialConfig->portName() + << _serialConfig->baud() << _serialConfig->dataBits() << _serialConfig->parity() << _serialConfig->stopBits(); return true; // successful connection } @@ -281,7 +281,7 @@ bool SerialLink::isConnected() const QString SerialLink::getName() const { - return _config->portName(); + return _serialConfig->portName(); } /** @@ -294,7 +294,7 @@ qint64 SerialLink::getConnectionSpeed() const if (_port) { baudRate = _port->baudRate(); } else { - baudRate = _config->baud(); + baudRate = _serialConfig->baud(); } qint64 dataRate; switch (baudRate) @@ -334,11 +334,11 @@ qint64 SerialLink::getConnectionSpeed() const void SerialLink::_resetConfiguration() { if (_port) { - _port->setBaudRate (_config->baud()); - _port->setDataBits (static_cast (_config->dataBits())); - _port->setFlowControl (static_cast (_config->flowControl())); - _port->setStopBits (static_cast (_config->stopBits())); - _port->setParity (static_cast (_config->parity())); + _port->setBaudRate (_serialConfig->baud()); + _port->setDataBits (static_cast (_serialConfig->dataBits())); + _port->setFlowControl (static_cast (_serialConfig->flowControl())); + _port->setStopBits (static_cast (_serialConfig->stopBits())); + _port->setParity (static_cast (_serialConfig->parity())); } } @@ -349,11 +349,6 @@ void SerialLink::_emitLinkError(const QString& errorMsg) emit communicationError(tr("Link Error"), msg.arg(getName()).arg(errorMsg)); } -LinkConfiguration* SerialLink::getLinkConfiguration() -{ - return _config; -} - //-------------------------------------------------------------------------- //-- SerialConfiguration diff --git a/src/comm/SerialLink.h b/src/comm/SerialLink.h index 82b0edee71352da494cf6881d9774fbb75e5e11d..be46a06e93661e5ef2e60f6fa84a045ab47dfac6 100644 --- a/src/comm/SerialLink.h +++ b/src/comm/SerialLink.h @@ -133,7 +133,6 @@ class SerialLink : public LinkInterface public: // LinkInterface - LinkConfiguration* getLinkConfiguration(); QString getName() const; void requestReset(); bool isConnected() const; @@ -168,7 +167,7 @@ private slots: private: // Links are only created/destroyed by LinkManager so constructor/destructor is not public - SerialLink(SerialConfiguration* config); + SerialLink(SharedLinkConfigurationPointer& config); ~SerialLink(); // From LinkInterface @@ -186,7 +185,7 @@ private: volatile bool _reqReset; QMutex _stoppMutex; // Mutex for accessing _stopp QByteArray _transmitBuffer; // An internal buffer for receiving data from member functions and actually transmitting them via the serial port. - SerialConfiguration* _config; + SerialConfiguration* _serialConfig; signals: void aboutToCloseFlag(); diff --git a/src/comm/TCPLink.cc b/src/comm/TCPLink.cc index a57cb61d87483aad406898c7d822383dbf407be1..d540f644496f86160585f1a941f531f695f8fa77 100644 --- a/src/comm/TCPLink.cc +++ b/src/comm/TCPLink.cc @@ -24,16 +24,14 @@ /// /// @author Don Gagne -TCPLink::TCPLink(TCPConfiguration *config) - : _config(config) +TCPLink::TCPLink(SharedLinkConfigurationPointer& config) + : LinkInterface(config) + , _tcpConfig(qobject_cast(config.data())) , _socket(NULL) , _socketIsConnected(false) { - Q_ASSERT(_config != NULL); - // We're doing it wrong - because the Qt folks got the API wrong: - // http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ + Q_ASSERT(_tcpConfig); moveToThread(this); - //qDebug() << "TCP Created " << _config->name(); } TCPLink::~TCPLink() @@ -69,7 +67,7 @@ void TCPLink::_writeDebugBytes(const QByteArray data) ascii.append(219); } } - qDebug() << "Sent" << size << "bytes to" << _config->address().toString() << ":" << _config->port() << "data:"; + qDebug() << "Sent" << size << "bytes to" << _tcpConfig->address().toString() << ":" << _tcpConfig->port() << "data:"; qDebug() << bytes; qDebug() << "ASCII:" << ascii; } @@ -148,7 +146,7 @@ bool TCPLink::_hardwareConnect() _socket = new QTcpSocket(); QSignalSpy errorSpy(_socket, static_cast(&QTcpSocket::error)); - _socket->connectToHost(_config->address(), _config->port()); + _socket->connectToHost(_tcpConfig->address(), _tcpConfig->port()); QObject::connect(_socket, &QTcpSocket::readyRead, this, &TCPLink::readBytes); QObject::connect(_socket,static_cast(&QTcpSocket::error), @@ -189,7 +187,7 @@ bool TCPLink::isConnected() const QString TCPLink::getName() const { - return _config->name(); + return _tcpConfig->name(); } qint64 TCPLink::getConnectionSpeed() const diff --git a/src/comm/TCPLink.h b/src/comm/TCPLink.h index c67606f583420054e0243bada84fdc52a6b21cb5..9eb2827feb43a947f8ccec9e975e9dff23017050 100644 --- a/src/comm/TCPLink.h +++ b/src/comm/TCPLink.h @@ -121,7 +121,6 @@ class TCPLink : public LinkInterface public: QTcpSocket* getSocket(void) { return _socket; } - virtual LinkConfiguration* getLinkConfiguration() { return _config; } void signalBytesWritten(void); @@ -160,7 +159,7 @@ protected: private: // Links are only created/destroyed by LinkManager so constructor/destructor is not public - TCPLink(TCPConfiguration* config); + TCPLink(SharedLinkConfigurationPointer& config); ~TCPLink(); // From LinkInterface @@ -174,7 +173,7 @@ private: void _writeDebugBytes(const QByteArray data); #endif - TCPConfiguration* _config; + TCPConfiguration* _tcpConfig; QTcpSocket* _socket; bool _socketIsConnected; diff --git a/src/comm/UDPLink.cc b/src/comm/UDPLink.cc index 627c6d282a8ba295c3a2fda584d57841339ae362..a286a078a05022a00af20213ff8df687cb0370f9 100644 --- a/src/comm/UDPLink.cc +++ b/src/comm/UDPLink.cc @@ -65,27 +65,22 @@ static QString get_ip_address(const QString& address) return QString(""); } -UDPLink::UDPLink(UDPConfiguration* config) - : _socket(NULL) - , _connectState(false) - #if defined(QGC_ZEROCONF_ENABLED) +UDPLink::UDPLink(SharedLinkConfigurationPointer& config) + : LinkInterface(config) +#if defined(QGC_ZEROCONF_ENABLED) , _dnssServiceRef(NULL) - #endif +#endif , _running(false) + , _socket(NULL) + , _udpConfig(qobject_cast(config.data())) + , _connectState(false) { - Q_ASSERT(config != NULL); - _config = config; - _config->setLink(this); - - // We're doing it wrong - because the Qt folks got the API wrong: - // http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ + Q_ASSERT(_udpConfig); moveToThread(this); } UDPLink::~UDPLink() { - // Disconnect link from configuration - _config->setLink(NULL); _disconnect(); // Tell the thread to exit _running = false; @@ -121,17 +116,17 @@ void UDPLink::_restartConnection() QString UDPLink::getName() const { - return _config->name(); + return _udpConfig->name(); } void UDPLink::addHost(const QString& host) { - _config->addHost(host); + _udpConfig->addHost(host); } void UDPLink::removeHost(const QString& host) { - _config->removeHost(host); + _udpConfig->removeHost(host); } void UDPLink::_writeBytes(const QByteArray data) @@ -143,7 +138,7 @@ void UDPLink::_writeBytes(const QByteArray data) // Send to all connected systems QString host; int port; - if(_config->firstHost(host, port)) { + if(_udpConfig->firstHost(host, port)) { do { QHostAddress currentHost(host); if(_socket->writeDatagram(data, currentHost, (quint16)port) < 0) { @@ -162,10 +157,10 @@ void UDPLink::_writeBytes(const QByteArray data) // unit sent by UDP. _logOutputDataRate(data.size(), QDateTime::currentMSecsSinceEpoch()); } - } while (_config->nextHost(host, port)); + } while (_udpConfig->nextHost(host, port)); //-- Remove hosts that are no longer there foreach (const QString& ghost, goneHosts) { - _config->removeHost(ghost); + _udpConfig->removeHost(ghost); } } } @@ -194,7 +189,7 @@ void UDPLink::readBytes() // added to the list and will start receiving datagrams from here. Even a port scanner // would trigger this. // Add host to broadcast list if not yet present, or update its port - _config->addHost(sender.toString(), (int)senderPort); + _udpConfig->addHost(sender.toString(), (int)senderPort); } //-- Send whatever is left if(databuffer.size()) { @@ -248,8 +243,9 @@ bool UDPLink::_hardwareConnect() QHostAddress host = QHostAddress::AnyIPv4; _socket = new QUdpSocket(); _socket->setProxy(QNetworkProxy::NoProxy); - _connectState = _socket->bind(host, _config->localPort(), QAbstractSocket::ReuseAddressHint | QUdpSocket::ShareAddress); + _connectState = _socket->bind(host, _udpConfig->localPort(), QAbstractSocket::ReuseAddressHint | QUdpSocket::ShareAddress); if (_connectState) { + _socket->joinMulticastGroup(QHostAddress("224.0.0.1")); //-- Make sure we have a large enough IO buffers #ifdef __mobile__ _socket->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, 64 * 1024); @@ -258,11 +254,11 @@ bool UDPLink::_hardwareConnect() _socket->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, 256 * 1024); _socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 512 * 1024); #endif - _registerZeroconf(_config->localPort(), kZeroconfRegistration); + _registerZeroconf(_udpConfig->localPort(), kZeroconfRegistration); QObject::connect(_socket, &QUdpSocket::readyRead, this, &UDPLink::readBytes); emit connected(); } else { - emit communicationError("UDP Link Error", "Error binding UDP port"); + emit communicationError(tr("UDP Link Error"), tr("Error binding UDP port: %1").arg(_socket->errorString())); } return _connectState; } diff --git a/src/comm/UDPLink.h b/src/comm/UDPLink.h index 1c1c977a9080f3e8a269d8e8b0f38cfbdef8ca8e..a20efa26e47c1436d055e23096de416e8db7db68 100644 --- a/src/comm/UDPLink.h +++ b/src/comm/UDPLink.h @@ -131,12 +131,13 @@ public: QStringList hostList () { return _hostList; } /// From LinkConfiguration - LinkType type () { return LinkConfiguration::TypeUdp; } - void copyFrom (LinkConfiguration* source); - void loadSettings (QSettings& settings, const QString& root); - void saveSettings (QSettings& settings, const QString& root); - void updateSettings (); - QString settingsURL () { return "UdpSettings.qml"; } + LinkType type () { return LinkConfiguration::TypeUdp; } + void copyFrom (LinkConfiguration* source); + void loadSettings (QSettings& settings, const QString& root); + void saveSettings (QSettings& settings, const QString& root); + void updateSettings (); + bool isAutoConnectAllowed () { return true; } + QString settingsURL () { return "UdpSettings.qml"; } signals: void localPortChanged (); @@ -177,10 +178,7 @@ public: bool connect(void); bool disconnect(void); - LinkConfiguration* getLinkConfiguration() { return _config; } - public slots: - /*! @brief Add a new host to broadcast messages to */ void addHost (const QString& host); /*! @brief Remove a host from broadcasting messages to */ @@ -189,23 +187,11 @@ public slots: void readBytes(); private slots: - /*! - * @brief Write a number of bytes to the interface. - * - * @param data Pointer to the data byte array - * @param size The size of the bytes array - **/ void _writeBytes(const QByteArray data); -protected: - - QUdpSocket* _socket; - UDPConfiguration* _config; - bool _connectState; - private: // Links are only created/destroyed by LinkManager so constructor/destructor is not public - UDPLink(UDPConfiguration* config); + UDPLink(SharedLinkConfigurationPointer& config); ~UDPLink(); // From LinkInterface @@ -223,6 +209,9 @@ private: #endif bool _running; + QUdpSocket* _socket; + UDPConfiguration* _udpConfig; + bool _connectState; }; #endif // UDPLINK_H diff --git a/src/comm/USBBoardInfo.json b/src/comm/USBBoardInfo.json new file mode 100644 index 0000000000000000000000000000000000000000..424fb6e019d9eb4babee2a5d58d5c8a107be79da --- /dev/null +++ b/src/comm/USBBoardInfo.json @@ -0,0 +1,50 @@ +{ + "comment": "AutoConnect usb board info", + + "version": 1, + "fileType": "USBBoardInfo", + "groundStation": "QGroundControl", + + "boardInfo": [ + { "vendorID": 9900, "productID": 16, "boardClass": "Pixhawk", "name": "PX4 FMU V1" }, + { "vendorID": 9900, "productID": 17, "boardClass": "Pixhawk", "name": "PX4 FMU V2" }, + { "vendorID": 9900, "productID": 18, "boardClass": "Pixhawk", "name": "PX4 FMU V4" }, + { "vendorID": 9900, "productID": 22, "boardClass": "Pixhawk", "name": "PX4 FMU V2", "comment": "Bootloader on older Pixhawk V2 boards" }, + { "vendorID": 9900, "productID": 4097, "boardClass": "Pixhawk", "name": "AeroCore" }, + { "vendorID": 9900, "productID": 33, "boardClass": "Pixhawk", "name": "AUAV X2.1 FMU V2" }, + { "vendorID": 9900, "productID": 48, "boardClass": "Pixhawk", "name": "MindPX FMU V2" }, + { "vendorID": 9900, "productID": 64, "boardClass": "Pixhawk", "name": "TAP V1" }, + { "vendorID": 9900, "productID": 65, "boardClass": "Pixhawk", "name": "ASC V1" }, + + { "vendorID": 9900, "productID": 21, "boardClass": "PX4 Flow", "name": "PX4 Flow" }, + + { "vendorID": 1027, "productID": 24597, "boardClass": "SiK Radio", "name": "SiK Radio", "comment": "3DR Radio" }, + { "vendorID": 4292, "productID": 600000, "boardClass": "SiK Radio", "name": "SiK Radio", "comment": "SILabs Radio" }, + + { "vendorID": 546, "productID": 424, "boardClass": "RTK GPS", "name": "RTK GPS", "comment": "Ublox RTK GPS" }, + + { "vendorID": 8352, "productID": 16732, "boardClass": "OpenPilot", "name": "OpenPilot OPLink" }, + { "vendorID": 8352, "productID": 16733, "boardClass": "OpenPilot", "name": "OpenPilot CC3D" }, + { "vendorID": 8352, "productID": 16734, "boardClass": "OpenPilot", "name": "OpenPilot Revolution" }, + { "vendorID": 8352, "productID": 16848, "boardClass": "OpenPilot", "name": "Taulabs Sparky2" } + ], + + "boardFallback": [ + { "regExp": "^PX4 FMU v4.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 BL FMU v4.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 FMU v2.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 BL FMU v2.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 FMU v1.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 BL FMU v1.x$", "boardClass": "Pixhawk" }, + { "regExp": "^MindPX FMU v2.x$", "boardClass": "Pixhawk" }, + { "regExp": "^MindPX BL FMU v2.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 TAP v1.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 BL TAP v1.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 ASC v1.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 BL ASC v1.x$", "boardClass": "Pixhawk" }, + { "regExp": "^PX4 FMU", "boardClass": "Pixhawk" }, + { "regExp": "PX4.*Flow", "boardClass": "PX4 Flow" }, + { "regExp": "^FT231X USB UART$", "boardClass": "SiK Radio" }, + { "regExp": "USB UART$", "boardClass": "SiK Radio", "androidOnly": true, "comment": "Very broad fallback, too dangerous for non-android" } + ] +} diff --git a/src/comm/XbeeLink.cpp b/src/comm/XbeeLink.cpp deleted file mode 100644 index c3a7b153790bfbc4da8e5453868b385e70f6df95..0000000000000000000000000000000000000000 --- a/src/comm/XbeeLink.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include -#include -#include -#include -#include -#include "XbeeLink.h" - -XbeeLink::XbeeLink(QString portName, int baudRate) : - m_xbeeCon(NULL), - m_portName(NULL), - m_portNameLength(0), - m_baudRate(baudRate), - m_connected(false), - m_addrHigh(0), - m_addrLow(0) -{ - - /* setup the xbee */ - this->setPortName(portName); -} - -XbeeLink::~XbeeLink() -{ - if(m_portName) - { - delete m_portName; - m_portName = NULL; - } - _disconnect(); -} - -QString XbeeLink::getPortName() const -{ - QString portName; - for(unsigned int i = 0;im_portNameLength;i++) - { - portName.append(this->m_portName[i]); - } - return portName; -} - -int XbeeLink::getBaudRate() const -{ - return this->m_baudRate; -} - -bool XbeeLink::setPortName(QString portName) -{ - bool reconnect(false); - if(this->m_connected) - { - _disconnect(); - reconnect = true; - } - if(m_portName) - { - delete m_portName; - m_portName = NULL; - } - QStringList list = portName.split(QRegExp("\\s+"),QString::SkipEmptyParts); - if(list.size()>0) - { - this->m_portNameLength = list[0].size()+1; - m_portName = new char[this->m_portNameLength]; - for(int i=0;im_portName[i]=list[0][i].toLatin1(); - } - this->m_portName[list[0].size()] = '\0'; - } - else - { - this->m_portNameLength = 1; - m_portName = new char[this->m_portNameLength]; - this->m_portName[0] = '\0'; - } - - bool retVal(true); - if(reconnect) - { - retVal = _connect(); - } - - return retVal; -} - -bool XbeeLink::setBaudRate(int rate) -{ - bool reconnect(false); - if(this->m_connected) - { - _disconnect(); - reconnect = true; - } - bool retVal(true); - this->m_baudRate = rate; - if(reconnect) - { - retVal = _connect(); - } - return retVal; -} - -QString XbeeLink::getName() const -{ - return this->m_name; -} - -bool XbeeLink::isConnected() const -{ - return this->m_connected; -} - -qint64 XbeeLink::getConnectionSpeed() const -{ - return this->m_baudRate; -} - -qint64 XbeeLink::getCurrentInDataRate() const -{ - return 0; -} - -qint64 XbeeLink::getCurrentOutDataRate() const -{ - return 0; -} - -bool XbeeLink::hardwareConnect() -{ - emit tryConnectBegin(true); - if(this->isConnected()) - { - _disconnect(); - } - if (*this->m_portName == '\0') - { - return false; - } - if (xbee_setupAPI(this->m_portName,this->m_baudRate,0x2B,0x3E8) == -1) - { - /* oh no... it failed */ - qDebug() <<"xbee_setup() failed...\n"; - emit tryConnectEnd(true); - return false; - } - this->m_xbeeCon = xbee_newcon('A',xbee2_data,0x13A200,0x403D0935); - emit tryConnectEnd(true); - this->m_connected = true; - emit connected(); - return true; -} - -bool XbeeLink::_connect(void) -{ - if (this->isRunning()) _disconnect(); - this->start(LowPriority); - return true; -} - -void XbeeLink::_disconnect(void) -{ - if(this->isRunning()) this->terminate(); //stop running the thread, restart it upon connect - - if(this->m_xbeeCon) - { - xbee_end(); - this->m_xbeeCon = NULL; - } - this->m_connected = false; - - emit disconnected(); -} - -void XbeeLink::_writeBytes(const QByteArray bytes) -{ - if(!xbee_nsenddata(this->m_xbeeCon,const_cast(bytes.data()),bytes.size())) // return value of 0 is successful written - { - _logOutputDataRate(bytes.size(), QDateTime::currentMSecsSinceEpoch()); - } - else - { - _disconnect(); - emit communicationError(tr("Link Error"), QString("Error on link: %1. Could not send data - link is disconnected!").arg(getName())); - } -} - -void XbeeLink::readBytes() -{ - xbee_pkt *xbeePkt; - xbeePkt = xbee_getpacketwait(this->m_xbeeCon); - if(!(NULL==xbeePkt)) - { - QByteArray data; - for(unsigned int i=0;i<=xbeePkt->datalen;i++) - { - data.push_back(xbeePkt->data[i]); - } - - _logInputDataRate(data.length(), QDateTime::currentMSecsSinceEpoch()); - emit bytesReceived(this, data); - } -} - -void XbeeLink::run() -{ - // Initialize the connection - if(this->hardwareConnect()) - { - // Qt way to make clear what a while(1) loop does - forever - { - this->readBytes(); - } - } -} - -bool XbeeLink::setRemoteAddressHigh(quint32 high) -{ - this->m_addrHigh = high; - return true; -} - -bool XbeeLink::setRemoteAddressLow(quint32 low) -{ - this->m_addrLow = low; - return true; -} - -/* -void CALLTYPE XbeeLink::portCallback(xbee_con *xbeeCon, xbee_pkt *XbeePkt) -{ - QByteArray buf; - for(quint8 i=0;idatalen;i++) - { - buf.push_back(XbeePkt->data[i]); - } - emit bytesReceived(this, buf); -}*/ diff --git a/src/comm/XbeeLink.h b/src/comm/XbeeLink.h deleted file mode 100644 index 02180dd254415dfa0043dbbba2e774c6afe7cdc2..0000000000000000000000000000000000000000 --- a/src/comm/XbeeLink.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _XBEELINK_H_ -#define _XBEELINK_H_ - -#include -#include -#include -#include -#include -#include -#include "XbeeLinkInterface.h" -#include -#include "CallConv.h" - -class XbeeLink : public XbeeLinkInterface -{ - Q_OBJECT - -public: - XbeeLink(QString portName = "", int baudRate=57600); - ~XbeeLink(); - -public: // virtual functions from XbeeLinkInterface - QString getPortName() const; - void requestReset() { } - int getBaudRate() const; - - // These are left unimplemented in order to cause linker errors which indicate incorrect usage of - // connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager. - bool connect(void); - bool disconnect(void); - -public slots: // virtual functions from XbeeLinkInterface - bool setPortName(QString portName); - bool setBaudRate(int rate); - bool setRemoteAddressHigh(quint32 high); - bool setRemoteAddressLow(quint32 low); - -public: - // virtual functions from LinkInterface - QString getName() const; - bool isConnected() const; - - // Extensive statistics for scientific purposes - qint64 getConnectionSpeed() const; - qint64 getCurrentOutDataRate() const; - qint64 getCurrentInDataRate() const; - -private slots: // virtual functions from LinkInterface - void _writeBytes(const QByteArray bytes); - -protected slots: // virtual functions from LinkInterface - void readBytes(); - -public: - void run(); // initiating the thread - -protected: - xbee_con *m_xbeeCon; - char *m_portName; - unsigned int m_portNameLength; - int m_baudRate; - bool m_connected; - QString m_name; - quint32 m_addrHigh; - quint32 m_addrLow; - -private: - // From LinkInterface - virtual bool _connect(void); - virtual void _disconnect(void); - - bool hardwareConnect(); - //void CALLTYPE portCallback(xbee_con *XbeeCon, xbee_pkt *XbeePkt); -}; - - -#endif // _XBEELINK_H_ diff --git a/src/comm/XbeeLinkInterface.h b/src/comm/XbeeLinkInterface.h deleted file mode 100644 index d359f579d7a5ab64b58de534f8fd991eb031b448..0000000000000000000000000000000000000000 --- a/src/comm/XbeeLinkInterface.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef XBEELINKINTERFACE_H_ -#define XBEELINKINTERFACE_H_ - -#include -#include -#include - -class XbeeLinkInterface : public LinkInterface -{ - Q_OBJECT - -public: - virtual QString getPortName() const = 0; - virtual int getBaudRate() const = 0; - -public slots: - virtual bool setPortName(QString portName) = 0; - virtual bool setBaudRate(int rate) = 0; - virtual bool setRemoteAddressHigh(quint32 high) = 0; - virtual bool setRemoteAddressLow(quint32 low) = 0; - -signals: - void tryConnectBegin(bool toTrue); - void tryConnectEnd(bool toTrue); -}; - -#endif // XBEELINKINTERFACE_H_ diff --git a/src/main.cc b/src/main.cc index 5a582ce66fa0c19946e9fe9e11c06af681c2cbf7..8c2ff2ddc39e6e92d4ab06a6bdae70a87096af9d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -27,16 +27,16 @@ #include "QGCApplication.h" #include "AppMessages.h" -#define SINGLE_INSTANCE_PORT 14499 - #ifndef __mobile__ #include "QGCSerialPortInfo.h" + #include "RunGuard.h" +#endif + +#ifdef UNITTEST_BUILD + #include "UnitTest.h" #endif #ifdef QT_DEBUG - #ifndef __mobile__ - #include "UnitTest.h" - #endif #include "CmdLineOptParser.h" #ifdef Q_OS_WIN #include @@ -73,7 +73,7 @@ int WindowsCrtReportHook(int reportType, char* message, int* returnValue) #endif -#ifdef __android__ +#if defined(__android__) && !defined(NO_SERIAL_LINK) #include #include "qserialport.h" @@ -102,6 +102,13 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) int main(int argc, char *argv[]) { +#ifndef __mobile__ + RunGuard guard("QGroundControlRunGuardKey"); + if (!guard.tryToRun()) { + return 0; + } +#endif + #ifdef Q_OS_UNIX //Force writing to the console on UNIX/BSD devices if (!qEnvironmentVariableIsSet("QT_LOGGING_TO_CONSOLE")) @@ -111,16 +118,6 @@ int main(int argc, char *argv[]) // install the message handler AppMessages::installHandler(); -#ifndef __mobile__ - //-- Test for another instance already running. If that's the case, we simply exit. - QHostAddress host("127.0.0.1"); - QUdpSocket socket; - if(!socket.bind(host, SINGLE_INSTANCE_PORT, QAbstractSocket::DontShareAddress)) { - qWarning() << "Another instance already running. Exiting."; - exit(-1); - } -#endif - #ifdef Q_OS_MAC #ifndef __ios__ // Prevent Apple's app nap from screwing us over @@ -150,7 +147,7 @@ int main(int argc, char *argv[]) // that we use these types in signals, and without calling qRegisterMetaType we can't queue // these signals. In general we don't queue these signals, but we do what the warning says // anyway to silence the debug output. -#ifndef __ios__ +#ifndef NO_SERIAL_LINK qRegisterMetaType(); #endif #ifdef QGC_ENABLE_BLUETOOTH @@ -229,8 +226,7 @@ int main(int argc, char *argv[]) int exitCode = 0; -#ifndef __mobile__ -#ifdef QT_DEBUG +#ifdef UNITTEST_BUILD if (runUnitTests) { for (int i=0; i < (stressUnitTests ? 20 : 1); i++) { if (!app->_initForUnitTests()) { @@ -249,7 +245,6 @@ int main(int argc, char *argv[]) } } } else -#endif #endif { if (!app->_initForNormalAppBoot()) { @@ -258,6 +253,7 @@ int main(int argc, char *argv[]) exitCode = app->exec(); } + app->_shutdown(); delete app; //-- Shutdown Cache System destroyMapEngine(); diff --git a/src/qgcunittest/LinkManagerTest.cc b/src/qgcunittest/LinkManagerTest.cc index bc5af5bb3a30eacdb83c1a03275c09760805e4cc..77f4e8b3c5da883e6dca21698ab9da41994ea04b 100644 --- a/src/qgcunittest/LinkManagerTest.cc +++ b/src/qgcunittest/LinkManagerTest.cc @@ -57,29 +57,29 @@ void LinkManagerTest::cleanup(void) void LinkManagerTest::_add_test(void) { Q_ASSERT(_linkMgr); - Q_ASSERT(_linkMgr->links()->count() == 0); + Q_ASSERT(_linkMgr->links().count() == 0); _connectMockLink(); - QCOMPARE(_linkMgr->links()->count(), 1); - QCOMPARE(_linkMgr->links()->value(0), _mockLink); + QCOMPARE(_linkMgr->links().count(), 1); + QCOMPARE(_linkMgr->links().at(0), _mockLink); } void LinkManagerTest::_delete_test(void) { Q_ASSERT(_linkMgr); - Q_ASSERT(_linkMgr->links()->count() == 0); + Q_ASSERT(_linkMgr->links().count() == 0); _connectMockLink(); _disconnectMockLink(); - QCOMPARE(_linkMgr->links()->count(), 0); + QCOMPARE(_linkMgr->links().count(), 0); } void LinkManagerTest::_addSignals_test(void) { Q_ASSERT(_linkMgr); - Q_ASSERT(_linkMgr->links()->count() == 0); + Q_ASSERT(_linkMgr->links().count() == 0); Q_ASSERT(_multiSpy->checkNoSignals() == true); _connectMockLink(); @@ -99,7 +99,7 @@ void LinkManagerTest::_addSignals_test(void) void LinkManagerTest::_deleteSignals_test(void) { Q_ASSERT(_linkMgr); - Q_ASSERT(_linkMgr->links()->count() == 0); + Q_ASSERT(_linkMgr->links().count() == 0); Q_ASSERT(_multiSpy->checkNoSignals() == true); _connectMockLink(); diff --git a/src/qgcunittest/RadioConfigTest.cc b/src/qgcunittest/RadioConfigTest.cc index 0d8f21c6747ddc802f09e516431ccfcf0f7f2ed7..63c8ba31c95d5a76b279200b57ad2d3d869a4e85 100644 --- a/src/qgcunittest/RadioConfigTest.cc +++ b/src/qgcunittest/RadioConfigTest.cc @@ -332,28 +332,6 @@ void RadioConfigTest::_switchMinMaxStep(void) QCOMPARE(_controller->_currentStep, saveStep + 1); } -void RadioConfigTest::_switchSelectAutoStep(const char* functionStr, RadioComponentController::rcCalFunctions function) -{ - Q_UNUSED(functionStr); - ////qCDebug(RadioConfigTestLog)() << "_switchSelectAutoStep" << functionStr << "function:" << function; - - int buttonMask = cancelButtonMask; - if (function != RadioComponentController::rcCalFunctionModeSwitch) { - buttonMask |= skipButtonMask; - } - - CHK_BUTTONS(buttonMask); - - int saveStep = _controller->_currentStep; - - // Wiggle stick for channel - int channel = _rgFunctionChannelMap[function]; - _mockLink->emitRemoteControlChannelRawChanged(channel, _testMinValue); - _mockLink->emitRemoteControlChannelRawChanged(channel, _testMaxValue); - - QCOMPARE(_controller->_currentStep, saveStep + 1); -} - void RadioConfigTest::_fullCalibrationWorker(MAV_AUTOPILOT firmwareType) { _init(firmwareType); @@ -409,15 +387,15 @@ void RadioConfigTest::_fullCalibrationWorker(MAV_AUTOPILOT firmwareType) _channelHomePosition(); _controller->nextButtonClicked(); _beginCalibration(); - _stickMoveAutoStep("Throttle", RadioComponentController::rcCalFunctionThrottle, moveToMax, true /* identify step */); - _stickMoveAutoStep("Throttle", RadioComponentController::rcCalFunctionThrottle, moveToMin, false /* not identify step */); - _stickMoveAutoStep("Yaw", RadioComponentController::rcCalFunctionYaw, moveToMax, true /* identify step */); - _stickMoveAutoStep("Yaw", RadioComponentController::rcCalFunctionYaw, moveToMin, false /* not identify step */); - _stickMoveAutoStep("Roll", RadioComponentController::rcCalFunctionRoll, moveToMax, true /* identify step */); - _stickMoveAutoStep("Roll", RadioComponentController::rcCalFunctionRoll, moveToMin, false /* not identify step */); - _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToMax, true /* identify step */); - _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToMin, false /* not identify step */); - _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToCenter, false /* not identify step */); + _stickMoveAutoStep("Throttle", RadioComponentController::rcCalFunctionThrottle, moveToMax, true /* identify step */); + _stickMoveAutoStep("Throttle", RadioComponentController::rcCalFunctionThrottle, moveToMin, false /* not identify step */); + _stickMoveAutoStep("Yaw", RadioComponentController::rcCalFunctionYaw, moveToMax, true /* identify step */); + _stickMoveAutoStep("Yaw", RadioComponentController::rcCalFunctionYaw, moveToMin, false /* not identify step */); + _stickMoveAutoStep("Roll", RadioComponentController::rcCalFunctionRoll, moveToMax, true /* identify step */); + _stickMoveAutoStep("Roll", RadioComponentController::rcCalFunctionRoll, moveToMin, false /* not identify step */); + _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToMax, true /* identify step */); + _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToMin, false /* not identify step */); + _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToCenter, false /* not identify step */); _switchMinMaxStep(); // One more click and the parameters should get saved diff --git a/src/qgcunittest/RadioConfigTest.h b/src/qgcunittest/RadioConfigTest.h index d66031e58261ae4df7c72538482a014cfa9293d5..7791d097cfaf864a518a94101a9698e9efb97b69 100644 --- a/src/qgcunittest/RadioConfigTest.h +++ b/src/qgcunittest/RadioConfigTest.h @@ -76,7 +76,6 @@ private: void _stickMoveWaitForSettle(int channel, int value); void _stickMoveAutoStep(const char* functionStr, enum RadioComponentController::rcCalFunctions function, enum MoveToDirection direction, bool identifyStep); void _switchMinMaxStep(void); - void _switchSelectAutoStep(const char* functionStr, RadioComponentController::rcCalFunctions function); bool _px4Vehicle(void) const; const struct RadioComponentController::FunctionInfo* _functionInfo(void) const; const struct ChannelSettings* _channelSettings(void) const; diff --git a/src/qgcunittest/TCPLinkTest.cc b/src/qgcunittest/TCPLinkTest.cc index f1a1835ceffbf63833f1aae05ec7e0224f44a9fc..996951eaf4896760f0839d562227c6e3ecaf7c19 100644 --- a/src/qgcunittest/TCPLinkTest.cc +++ b/src/qgcunittest/TCPLinkTest.cc @@ -17,8 +17,7 @@ #include "TCPLoopBackServer.h" TCPLinkTest::TCPLinkTest(void) - : _config(NULL) - , _link(NULL) + : _link(NULL) , _multiSpy(NULL) { @@ -31,13 +30,12 @@ void TCPLinkTest::init(void) Q_ASSERT(_link == nullptr); Q_ASSERT(_multiSpy == nullptr); - Q_ASSERT(_config == nullptr); - _config = new TCPConfiguration("MockTCP"); - _config->setAddress(QHostAddress::LocalHost); - _config->setPort(5760); - _link = new TCPLink(_config); - Q_ASSERT(_link != NULL); + TCPConfiguration* tcpConfig = new TCPConfiguration("MockTCP"); + tcpConfig->setAddress(QHostAddress::LocalHost); + tcpConfig->setPort(5760); + _sharedConfig = SharedLinkConfigurationPointer(tcpConfig); + _link = new TCPLink(_sharedConfig); _rgSignals[bytesReceivedSignalIndex] = SIGNAL(bytesReceived(LinkInterface*, QByteArray)); _rgSignals[connectedSignalIndex] = SIGNAL(connected(void)); @@ -55,7 +53,6 @@ void TCPLinkTest::cleanup(void) { Q_ASSERT(_multiSpy); Q_ASSERT(_link); - Q_ASSERT(_config); delete _multiSpy; _multiSpy = nullptr; @@ -63,15 +60,13 @@ void TCPLinkTest::cleanup(void) delete _link; _link = nullptr; - delete _config; - _config = nullptr; + _sharedConfig.clear(); UnitTest::cleanup(); } void TCPLinkTest::_connectFail_test(void) { - Q_ASSERT(_config); Q_ASSERT(_link); Q_ASSERT(_multiSpy); Q_ASSERT(_multiSpy->checkNoSignals() == true); @@ -110,7 +105,8 @@ void TCPLinkTest::_connectSucceed_test(void) Q_ASSERT(_multiSpy->checkNoSignals() == true); // Start the server side - TCPLoopBackServer* server = new TCPLoopBackServer(_config->address(), _config->port()); + TCPConfiguration* tcpConfig = qobject_cast(_sharedConfig.data()); + TCPLoopBackServer* server = new TCPLoopBackServer(tcpConfig->address(), tcpConfig->port()); Q_CHECK_PTR(server); // Connect to the server diff --git a/src/qgcunittest/TCPLinkTest.h b/src/qgcunittest/TCPLinkTest.h index 196da6ef02839d9f35630ee500281ab3125c94d3..e34d993da7fe78ff4de0b361eeb02233d4938e8d 100644 --- a/src/qgcunittest/TCPLinkTest.h +++ b/src/qgcunittest/TCPLinkTest.h @@ -60,11 +60,11 @@ private: //deleteLinkSignalMask = 1 << deleteLinkSignalIndex, }; - TCPConfiguration* _config; - TCPLink* _link; - MultiSignalSpy* _multiSpy; - static const size_t _cSignals = maxSignalIndex; - const char* _rgSignals[_cSignals]; + SharedLinkConfigurationPointer _sharedConfig; + TCPLink* _link; + MultiSignalSpy* _multiSpy; + static const size_t _cSignals = maxSignalIndex; + const char* _rgSignals[_cSignals]; }; #endif diff --git a/src/qgcunittest/UnitTestList.cc b/src/qgcunittest/UnitTestList.cc index d0c70f8a760ae704cd015dca89260991197a6799..924ae4024ce5a75232227e5241efcd9e7134b493 100644 --- a/src/qgcunittest/UnitTestList.cc +++ b/src/qgcunittest/UnitTestList.cc @@ -31,6 +31,7 @@ #include "ParameterManagerTest.h" #include "MissionCommandTreeTest.h" #include "LogDownloadTest.h" +#include "SendMavCommandTest.h" UT_REGISTER_TEST(FactSystemTestGeneric) UT_REGISTER_TEST(FactSystemTestPX4) @@ -50,6 +51,7 @@ UT_REGISTER_TEST(TCPLinkTest) UT_REGISTER_TEST(ParameterManagerTest) UT_REGISTER_TEST(MissionCommandTreeTest) UT_REGISTER_TEST(LogDownloadTest) +UT_REGISTER_TEST(SendMavCommandTest) // List of unit test which are currently disabled. // If disabling a new test, include reason in comment. diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index 840bf7c3aa6f1fe1c1cfa84ce1e5049b0292760f..eb23c566a0560a63c31742954f6b819423c00e9c 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -7,14 +7,7 @@ * ****************************************************************************/ - -/** - * @file - * @brief Represents one unmanned aerial vehicle - * - * @author Lorenz Meier - * - */ +// THIS CLASS IS DEPRECATED. ALL NEW FUNCTIONALITY SHOULD GO INTO Vehicle class #include #include @@ -30,13 +23,12 @@ #include "UAS.h" #include "LinkInterface.h" -#include "HomePositionManager.h" #include "QGC.h" #include "GAudioOutput.h" #include "MAVLinkProtocol.h" #include "QGCMAVLink.h" #include "LinkManager.h" -#ifndef __ios__ +#ifndef NO_SERIAL_LINK #include "SerialLink.h" #endif #include "FirmwarePluginManager.h" @@ -47,13 +39,7 @@ QGC_LOGGING_CATEGORY(UASLog, "UASLog") -/** -* Gets the settings from the previous UAS (name, airframe, autopilot, battery specs) -* by calling readSettings. This means the new UAS will have the same settings -* as the previous one created unless one calls deleteSettings in the code after -* creating the UAS. -*/ - +// THIS CLASS IS DEPRECATED. ALL NEW FUNCTIONALITY SHOULD GO INTO Vehicle class UAS::UAS(MAVLinkProtocol* protocol, Vehicle* vehicle, FirmwarePluginManager * firmwarePluginManager) : UASInterface(), lipoFull(4.2f), lipoEmpty(3.5f), @@ -77,30 +63,6 @@ UAS::UAS(MAVLinkProtocol* protocol, Vehicle* vehicle, FirmwarePluginManager * fi manualYawAngle(0), manualThrust(0), - isGlobalPositionKnown(false), - - latitude(0.0), - longitude(0.0), - altitudeAMSL(0.0), - altitudeAMSLFT(0.0), - altitudeRelative(0.0), - - satRawHDOP(1e10f), - satRawVDOP(1e10f), - satRawCOG(0.0), - - globalEstimatorActive(false), - - latitude_gps(0.0), - longitude_gps(0.0), - altitude_gps(0.0), - - speedX(0.0), - speedY(0.0), - speedZ(0.0), - - airSpeed(std::numeric_limits::quiet_NaN()), - groundSpeed(std::numeric_limits::quiet_NaN()), #ifndef __mobile__ fileManager(this, vehicle), #endif @@ -283,14 +245,6 @@ void UAS::receiveMessage(mavlink_message_t message) emit valueChanged(uasId, name.arg("custom_mode"), "bits", state.custom_mode, time); emit valueChanged(uasId, name.arg("system_status"), "-", state.system_status, time); - if ((state.system_status != this->status) && state.system_status != MAV_STATE_UNINIT) - { - this->status = state.system_status; - getStatusForCode((int)state.system_status, uasState, stateDescription); - emit statusChanged(this, uasState, stateDescription); - emit statusChanged(this->status); - } - // We got the mode receivedMode = true; } @@ -318,25 +272,7 @@ void UAS::receiveMessage(mavlink_message_t message) emit valueChanged(uasId, name.arg("errors_count4"), "-", state.errors_count4, time); // Process CPU load. - emit loadChanged(this,state.load/10.0f); emit valueChanged(uasId, name.arg("load"), "%", state.load/10.0f, time); - - // control_sensors_enabled: - // relevant bits: 11: attitude stabilization, 12: yaw position, 13: z/altitude control, 14: x/y position control - emit attitudeControlEnabled(state.onboard_control_sensors_enabled & (1 << 11)); - emit positionYawControlEnabled(state.onboard_control_sensors_enabled & (1 << 12)); - emit positionZControlEnabled(state.onboard_control_sensors_enabled & (1 << 13)); - emit positionXYControlEnabled(state.onboard_control_sensors_enabled & (1 << 14)); - - // Trigger drop rate updates as needed. Here we convert the incoming - // drop_rate_comm value from 1/100 of a percent in a uint16 to a true - // percentage as a float. We also cap the incoming value at 100% as defined - // by the MAVLink specifications. - if (state.drop_rate_comm > 10000) - { - state.drop_rate_comm = 10000; - } - emit dropRateChanged(this->getUASID(), state.drop_rate_comm/100.0f); emit valueChanged(uasId, name.arg("drop_rate_comm"), "%", state.drop_rate_comm/100.0f, time); } break; @@ -357,7 +293,6 @@ void UAS::receiveMessage(mavlink_message_t message) attitudeKnown = true; emit attitudeChanged(this, getRoll(), getPitch(), getYaw(), time); - emit attitudeRotationRatesChanged(uasId, attitude.rollspeed, attitude.pitchspeed, attitude.yawspeed, time); } } break; @@ -418,7 +353,6 @@ void UAS::receiveMessage(mavlink_message_t message) attitudeKnown = true; emit attitudeChanged(this, getRoll(), getPitch(), getYaw(), time); - emit attitudeRotationRatesChanged(uasId, attitude.rollspeed, attitude.pitchspeed, attitude.yawspeed, time); } } break; @@ -434,41 +368,12 @@ void UAS::receiveMessage(mavlink_message_t message) mavlink_vfr_hud_t hud; mavlink_msg_vfr_hud_decode(&message, &hud); quint64 time = getUnixTime(); - // Display updated values - emit thrustChanged(this, hud.throttle/100.0); if (!attitudeKnown) { setYaw(QGC::limitAngleToPMPId((((double)hud.heading)/180.0)*M_PI)); emit attitudeChanged(this, getRoll(), getPitch(), getYaw(), time); } - - setAltitudeAMSL(hud.alt); - setGroundSpeed(hud.groundspeed); - if (!qIsNaN(hud.airspeed)) - setAirSpeed(hud.airspeed); - speedZ = -hud.climb; - emit altitudeChanged(this, altitudeAMSL, altitudeRelative, -speedZ, time); - emit speedChanged(this, groundSpeed, airSpeed, time); - } - break; - case MAVLINK_MSG_ID_LOCAL_POSITION_NED: - //std::cerr << std::endl; - //std::cerr << "Decoded attitude message:" << " roll: " << std::dec << mavlink_msg_attitude_get_roll(message.payload) << " pitch: " << mavlink_msg_attitude_get_pitch(message.payload) << " yaw: " << mavlink_msg_attitude_get_yaw(message.payload) << std::endl; - { - mavlink_local_position_ned_t pos; - mavlink_msg_local_position_ned_decode(&message, &pos); - quint64 time = getUnixTime(pos.time_boot_ms); - - if (!wrongComponent) - { - speedX = pos.vx; - speedY = pos.vy; - speedZ = pos.vz; - - // Emit - emit velocityChanged_NED(this, speedX, speedY, speedZ, time); - } } break; case MAVLINK_MSG_ID_GLOBAL_VISION_POSITION_ESTIMATE: @@ -479,114 +384,6 @@ void UAS::receiveMessage(mavlink_message_t message) emit attitudeChanged(this, message.compid, pos.roll, pos.pitch, pos.yaw, time); } break; - case MAVLINK_MSG_ID_GLOBAL_POSITION_INT: - //std::cerr << std::endl; - //std::cerr << "Decoded attitude message:" << " roll: " << std::dec << mavlink_msg_attitude_get_roll(message.payload) << " pitch: " << mavlink_msg_attitude_get_pitch(message.payload) << " yaw: " << mavlink_msg_attitude_get_yaw(message.payload) << std::endl; - { - mavlink_global_position_int_t pos; - mavlink_msg_global_position_int_decode(&message, &pos); - - quint64 time = getUnixTime(); - - setLatitude(pos.lat/(double)1E7); - setLongitude(pos.lon/(double)1E7); - setAltitudeRelative(pos.relative_alt/1000.0); - - globalEstimatorActive = true; - - speedX = pos.vx/100.0; - speedY = pos.vy/100.0; - speedZ = pos.vz/100.0; - - emit globalPositionChanged(this, getLatitude(), getLongitude(), getAltitudeAMSL(), time); - emit altitudeChanged(this, altitudeAMSL, altitudeRelative, -speedZ, time); - // We had some frame mess here, global and local axes were mixed. - emit velocityChanged_NED(this, speedX, speedY, speedZ, time); - - setGroundSpeed(qSqrt(speedX*speedX+speedY*speedY)); - emit speedChanged(this, groundSpeed, airSpeed, time); - - isGlobalPositionKnown = true; - } - break; - case MAVLINK_MSG_ID_GPS_RAW_INT: - { - mavlink_gps_raw_int_t pos; - mavlink_msg_gps_raw_int_decode(&message, &pos); - - quint64 time = getUnixTime(pos.time_usec); - - // TODO: track localization state not only for gps but also for other loc. sources - int loc_type = pos.fix_type; - if (loc_type == 1) - { - loc_type = 0; - } - setSatelliteCount(pos.satellites_visible); - - if (pos.fix_type > 2) - { - isGlobalPositionKnown = true; - - latitude_gps = pos.lat/(double)1E7; - longitude_gps = pos.lon/(double)1E7; - altitude_gps = pos.alt/1000.0; - - // If no GLOBAL_POSITION_INT messages ever received, use these raw GPS values instead. - if (!globalEstimatorActive) { - setLatitude(latitude_gps); - setLongitude(longitude_gps); - emit globalPositionChanged(this, getLatitude(), getLongitude(), getAltitudeAMSL(), time); - emit altitudeChanged(this, altitudeAMSL, altitudeRelative, -speedZ, time); - - float vel = pos.vel/100.0f; - // Smaller than threshold and not NaN - if ((vel < 1000000) && !qIsNaN(vel) && !qIsInf(vel)) { - setGroundSpeed(vel); - emit speedChanged(this, groundSpeed, airSpeed, time); - } else { - emit textMessageReceived(uasId, message.compid, MAV_SEVERITY_NOTICE, QString("GCS ERROR: RECEIVED INVALID SPEED OF %1 m/s").arg(vel)); - } - } - } - - double dtmp; - //-- Raw GPS data - dtmp = pos.eph == 0xFFFF ? 1e10f : pos.eph / 100.0; - if(dtmp != satRawHDOP) - { - satRawHDOP = dtmp; - emit satRawHDOPChanged(satRawHDOP); - } - dtmp = pos.epv == 0xFFFF ? 1e10f : pos.epv / 100.0; - if(dtmp != satRawVDOP) - { - satRawVDOP = dtmp; - emit satRawVDOPChanged(satRawVDOP); - } - dtmp = pos.cog == 0xFFFF ? 0.0 : pos.cog / 100.0; - if(dtmp != satRawCOG) - { - satRawCOG = dtmp; - emit satRawCOGChanged(satRawCOG); - } - - // Emit this signal after the above signals. This way a trigger on gps lock signal which then asks for vehicle position - // gets a good position. - emit localizationChanged(this, loc_type); - } - break; - case MAVLINK_MSG_ID_GPS_STATUS: - { - mavlink_gps_status_t pos; - mavlink_msg_gps_status_decode(&message, &pos); - for(int i = 0; i < (int)pos.satellites_visible; i++) - { - emit gpsSatelliteStatusChanged(uasId, (unsigned char)pos.satellite_prn[i], (unsigned char)pos.satellite_elevation[i], (unsigned char)pos.satellite_azimuth[i], (unsigned char)pos.satellite_snr[i], static_cast(pos.satellite_used[i])); - } - setSatelliteCount(pos.satellites_visible); - } - break; case MAVLINK_MSG_ID_PARAM_VALUE: { @@ -610,7 +407,6 @@ void UAS::receiveMessage(mavlink_message_t message) float roll, pitch, yaw; mavlink_quaternion_to_euler(out.q, &roll, &pitch, &yaw); quint64 time = getUnixTimeFromMs(out.time_boot_ms); - emit attitudeThrustSetPointChanged(this, roll, pitch, yaw, out.thrust, time); // For plotting emit roll sp, pitch sp and yaw sp values emit valueChanged(uasId, "roll sp", "rad", roll, time); @@ -619,25 +415,6 @@ void UAS::receiveMessage(mavlink_message_t message) } break; - case MAVLINK_MSG_ID_POSITION_TARGET_LOCAL_NED: - { - if (multiComponentSourceDetected && wrongComponent) - { - break; - } - mavlink_position_target_local_ned_t p; - mavlink_msg_position_target_local_ned_decode(&message, &p); - quint64 time = getUnixTimeFromMs(p.time_boot_ms); - emit positionSetPointsChanged(uasId, p.x, p.y, p.z, 0/* XXX remove yaw and move it to attitude */, time); - } - break; - case MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED: - { - mavlink_set_position_target_local_ned_t p; - mavlink_msg_set_position_target_local_ned_decode(&message, &p); - emit userPositionSetPointsChanged(uasId, p.x, p.y, p.z, 0/* XXX remove yaw and move it to attitude */); - } - break; case MAVLINK_MSG_ID_STATUSTEXT: { QByteArray b; @@ -718,17 +495,6 @@ void UAS::receiveMessage(mavlink_message_t message) } break; - case MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT: - { - mavlink_nav_controller_output_t p; - mavlink_msg_nav_controller_output_decode(&message,&p); - setDistToWaypoint(p.wp_dist); - setBearingToWaypoint(p.nav_bearing); - emit navigationControllerErrorsChanged(this, p.alt_error, p.aspd_error, p.xtrack_error); - emit NavigationControllerDataChanged(this, p.nav_roll, p.nav_pitch, p.nav_bearing, p.target_bearing, p.wp_dist); - } - break; - case MAVLINK_MSG_ID_LOG_ENTRY: { mavlink_log_entry_t log; @@ -762,6 +528,7 @@ void UAS::startCalibration(UASInterface::StartCalibrationType calType) int airspeedCal = 0; int radioCal = 0; int accelCal = 0; + int pressureCal = 0; int escCal = 0; switch (calType) { @@ -786,6 +553,9 @@ void UAS::startCalibration(UASInterface::StartCalibrationType calType) case StartCalibrationLevel: accelCal = 2; break; + case StartCalibrationPressure: + pressureCal = 1; + break; case StartCalibrationEsc: escCal = 1; break; @@ -797,6 +567,8 @@ void UAS::startCalibration(UASInterface::StartCalibrationType calType) break; } + // We can't use sendMavCommand here since we have no idea how long it will be before the command returns a result. This in turn + // causes the retry logic to break down. mavlink_message_t msg; mavlink_msg_command_long_pack_chan(mavlink->getSystemId(), mavlink->getComponentId(), @@ -808,7 +580,7 @@ void UAS::startCalibration(UASInterface::StartCalibrationType calType) 0, // 0=first transmission of command gyroCal, // gyro cal magCal, // mag cal - 0, // ground pressure + pressureCal, // ground pressure radioCal, // radio cal accelCal, // accel cal airspeedCal, // PX4: airspeed cal, ArduPilot: compass mot @@ -822,23 +594,16 @@ void UAS::stopCalibration(void) return; } - mavlink_message_t msg; - mavlink_msg_command_long_pack_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - uasId, - _vehicle->defaultComponentId(), // target component - MAV_CMD_PREFLIGHT_CALIBRATION, // command id - 0, // 0=first transmission of command - 0, // gyro cal - 0, // mag cal - 0, // ground pressure - 0, // radio cal - 0, // accel cal - 0, // airspeed cal - 0); // unused - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), // target component + MAV_CMD_PREFLIGHT_CALIBRATION, // command id + true, // showError + 0, // gyro cal + 0, // mag cal + 0, // ground pressure + 0, // radio cal + 0, // accel cal + 0, // airspeed cal + 0); // unused } void UAS::startBusConfig(UASInterface::StartBusConfigType calType) @@ -858,23 +623,10 @@ void UAS::startBusConfig(UASInterface::StartBusConfigType calType) break; } - mavlink_message_t msg; - mavlink_msg_command_long_pack_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - uasId, - _vehicle->defaultComponentId(), // target component - MAV_CMD_PREFLIGHT_UAVCAN, // command id - 0, // 0=first transmission of command - actuatorCal, // actuators - 0, - 0, - 0, - 0, - 0, - 0); - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), // target component + MAV_CMD_PREFLIGHT_UAVCAN, // command id + true, // showError + actuatorCal); // actuators } void UAS::stopBusConfig(void) @@ -883,23 +635,10 @@ void UAS::stopBusConfig(void) return; } - mavlink_message_t msg; - mavlink_msg_command_long_pack_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - uasId, - _vehicle->defaultComponentId(), // target component - MAV_CMD_PREFLIGHT_UAVCAN, // command id - 0, // 0=first transmission of command - 0, - 0, - 0, - 0, - 0, - 0, - 0); - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), // target component + MAV_CMD_PREFLIGHT_UAVCAN, // command id + true, // showError + 0); // cancel } /** @@ -1233,33 +972,6 @@ void UAS::processParamValueMsg(mavlink_message_t& msg, const QString& paramName, emit parameterUpdate(uasId, compId, paramName, rawValue.param_count, rawValue.param_index, rawValue.param_type, paramValue); } -void UAS::executeCommand(MAV_CMD command, int confirmation, float param1, float param2, float param3, float param4, float param5, float param6, float param7, int component) -{ - if (!_vehicle) { - return; - } - - mavlink_message_t msg; - mavlink_command_long_t cmd; - cmd.command = (uint16_t)command; - cmd.confirmation = confirmation; - cmd.param1 = param1; - cmd.param2 = param2; - cmd.param3 = param3; - cmd.param4 = param4; - cmd.param5 = param5; - cmd.param6 = param6; - cmd.param7 = param7; - cmd.target_system = uasId; - cmd.target_component = component; - mavlink_msg_command_long_encode_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - &cmd); - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); -} - /** * Set the manual control commands. * This can only be done if the system has manual inputs enabled and is armed. @@ -1270,6 +982,10 @@ void UAS::setExternalControlSetpoint(float roll, float pitch, float yaw, float t return; } + if (!_vehicle->priorityLink()) { + return; + } + // Store the previous manual commands static float manualRollAngle = 0.0; static float manualPitchAngle = 0.0; @@ -1446,8 +1162,6 @@ void UAS::setExternalControlSetpoint(float roll, float pitch, float yaw, float t } _vehicle->sendMessageOnLink(_vehicle->priorityLink(), message); - // Emit an update in control values to other UI elements, like the HSI display - emit attitudeThrustSetPointChanged(this, roll, pitch, yaw, thrust, QGC::groundTimeMilliseconds()); } } @@ -1486,8 +1200,6 @@ void UAS::setManual6DOFControlCommands(double x, double y, double z, double roll MAV_FRAME_LOCAL_NED, position_mask, x, y, z, 0, 0, 0, 0, 0, 0, yaw, yawrate); _vehicle->sendMessageOnLink(_vehicle->priorityLink(), message); qDebug() << __FILE__ << __LINE__ << ": SENT 6DOF CONTROL MESSAGES: x" << x << " y: " << y << " z: " << z << " roll: " << roll << " pitch: " << pitch << " yaw: " << yaw; - - //emit attitudeThrustSetPointChanged(this, roll, pitch, yaw, thrust, QGC::groundTimeMilliseconds()); } else { @@ -1501,20 +1213,47 @@ void UAS::setManual6DOFControlCommands(double x, double y, double z, double roll */ void UAS::pairRX(int rxType, int rxSubType) { - if (!_vehicle) { - return; + if (_vehicle) { + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), // target component + MAV_CMD_START_RX_PAIR, // command id + true, // showError + rxType, + rxSubType); } +} - mavlink_message_t msg; +/** +* Order the robot to take a picture (Testing -- Incomplete API) +*/ +void UAS::takePhoto() +{ + if (_vehicle) { + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), // target component + MAV_CMD_IMAGE_START_CAPTURE, // command id + true, // showError + 0, // Duration between two consecutive pictures (in seconds) + 1, // Number of images to capture total - 0 for unlimited capture + 0, // Resolution in megapixels (0.3 for 640x480, 1.3 for 1280x720, etc), set to 0 if param 4/5 are used + 1920, // Resolution horizontal in pixels + 1080); // Resolution horizontal in pixels + } +} - mavlink_msg_command_long_pack_chan(mavlink->getSystemId(), - mavlink->getComponentId(), - _vehicle->priorityLink()->mavlinkChannel(), - &msg, - uasId, - _vehicle->defaultComponentId(), - MAV_CMD_START_RX_PAIR, 0, rxType, rxSubType, 0, 0, 0, 0, 0); - _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); +/** +* Order the robot to toggle video recording (Testing -- Incomplete API) +*/ +void UAS::toggleVideo() +{ + if (_vehicle) { + _vehicle->sendMavCommand(_vehicle->defaultComponentId(), // target component + MAV_CMD_VIDEO_START_CAPTURE, // command id + true, // showError + 0, // Camera ID (0 for all cameras), 1 for first, 2 for second, etc. + 60, // Frames per second + 0, // Resolution in megapixels (0.3 for 640x480, 1.3 for 1280x720, etc), set to 0 if param 4/5 are used + 1920, // Resolution horizontal in pixels + 1080); // Resolution horizontal in pixels + } } /** diff --git a/src/uas/UAS.h b/src/uas/UAS.h index 1e93a06702404203b6b6e57469d983edf5c0dcf6..4820fb41adc4a7c1f1f4c173d1bc93073fab61cb 100644 --- a/src/uas/UAS.h +++ b/src/uas/UAS.h @@ -65,197 +65,13 @@ public: /** @brief The time interval the robot is switched on */ quint64 getUptime() const; - Q_PROPERTY(double latitude READ getLatitude WRITE setLatitude NOTIFY latitudeChanged) - Q_PROPERTY(double longitude READ getLongitude WRITE setLongitude NOTIFY longitudeChanged) - Q_PROPERTY(double satelliteCount READ getSatelliteCount WRITE setSatelliteCount NOTIFY satelliteCountChanged) - Q_PROPERTY(bool isGlobalPositionKnown READ globalPositionKnown) Q_PROPERTY(double roll READ getRoll WRITE setRoll NOTIFY rollChanged) Q_PROPERTY(double pitch READ getPitch WRITE setPitch NOTIFY pitchChanged) Q_PROPERTY(double yaw READ getYaw WRITE setYaw NOTIFY yawChanged) - Q_PROPERTY(double distToWaypoint READ getDistToWaypoint WRITE setDistToWaypoint NOTIFY distToWaypointChanged) - Q_PROPERTY(double airSpeed READ getGroundSpeed WRITE setGroundSpeed NOTIFY airSpeedChanged) - Q_PROPERTY(double groundSpeed READ getGroundSpeed WRITE setGroundSpeed NOTIFY groundSpeedChanged) - Q_PROPERTY(double bearingToWaypoint READ getBearingToWaypoint WRITE setBearingToWaypoint NOTIFY bearingToWaypointChanged) - Q_PROPERTY(double altitudeAMSL READ getAltitudeAMSL WRITE setAltitudeAMSL NOTIFY altitudeAMSLChanged) - Q_PROPERTY(double altitudeAMSLFT READ getAltitudeAMSLFT NOTIFY altitudeAMSLFTChanged) - Q_PROPERTY(double altitudeRelative READ getAltitudeRelative WRITE setAltitudeRelative NOTIFY altitudeRelativeChanged) - Q_PROPERTY(double satRawHDOP READ getSatRawHDOP NOTIFY satRawHDOPChanged) - Q_PROPERTY(double satRawVDOP READ getSatRawVDOP NOTIFY satRawVDOPChanged) - Q_PROPERTY(double satRawCOG READ getSatRawCOG NOTIFY satRawCOGChanged) /// Vehicle is about to go away void shutdownVehicle(void); - void setGroundSpeed(double val) - { - groundSpeed = val; - emit groundSpeedChanged(val,"groundSpeed"); - emit valueChanged(this->uasId,"groundSpeed","m/s",QVariant(val),getUnixTime()); - } - double getGroundSpeed() const - { - return groundSpeed; - } - - void setAirSpeed(double val) - { - airSpeed = val; - emit airSpeedChanged(val,"airSpeed"); - emit valueChanged(this->uasId,"airSpeed","m/s",QVariant(val),getUnixTime()); - } - - double getAirSpeed() const - { - return airSpeed; - } - - void setLocalX(double val) - { - localX = val; - emit localXChanged(val,"localX"); - emit valueChanged(this->uasId,"localX","m",QVariant(val),getUnixTime()); - } - - double getLocalX() const - { - return localX; - } - - void setLocalY(double val) - { - localY = val; - emit localYChanged(val,"localY"); - emit valueChanged(this->uasId,"localY","m",QVariant(val),getUnixTime()); - } - double getLocalY() const - { - return localY; - } - - void setLocalZ(double val) - { - localZ = val; - emit localZChanged(val,"localZ"); - emit valueChanged(this->uasId,"localZ","m",QVariant(val),getUnixTime()); - } - double getLocalZ() const - { - return localZ; - } - - void setLatitude(double val) - { - latitude = val; - emit latitudeChanged(val,"latitude"); - emit valueChanged(this->uasId,"latitude","deg",QVariant(val),getUnixTime()); - } - - double getLatitude() const - { - return latitude; - } - - void setLongitude(double val) - { - longitude = val; - emit longitudeChanged(val,"longitude"); - emit valueChanged(this->uasId,"longitude","deg",QVariant(val),getUnixTime()); - } - - double getLongitude() const - { - return longitude; - } - - void setAltitudeAMSL(double val) - { - altitudeAMSL = val; - emit altitudeAMSLChanged(val, "altitudeAMSL"); - emit valueChanged(this->uasId,"altitudeAMSL","m",QVariant(altitudeAMSL),getUnixTime()); - altitudeAMSLFT = 3.28084 * altitudeAMSL; - emit altitudeAMSLFTChanged(val, "altitudeAMSLFT"); - emit valueChanged(this->uasId,"altitudeAMSLFT","m",QVariant(altitudeAMSLFT),getUnixTime()); - } - - double getAltitudeAMSL() const - { - return altitudeAMSL; - } - - double getAltitudeAMSLFT() const - { - return altitudeAMSLFT; - } - - void setAltitudeRelative(double val) - { - altitudeRelative = val; - emit altitudeRelativeChanged(val, "altitudeRelative"); - emit valueChanged(this->uasId,"altitudeRelative","m",QVariant(val),getUnixTime()); - } - - double getAltitudeRelative() const - { - return altitudeRelative; - } - - double getSatRawHDOP() const - { - return satRawHDOP; - } - - double getSatRawVDOP() const - { - return satRawVDOP; - } - - double getSatRawCOG() const - { - return satRawCOG; - } - - void setSatelliteCount(double val) - { - satelliteCount = val; - emit satelliteCountChanged(val,"satelliteCount"); - emit valueChanged(this->uasId,"satelliteCount","",QVariant(val),getUnixTime()); - } - - double getSatelliteCount() const - { - return satelliteCount; - } - - virtual bool globalPositionKnown() const - { - return isGlobalPositionKnown; - } - - void setDistToWaypoint(double val) - { - distToWaypoint = val; - emit distToWaypointChanged(val,"distToWaypoint"); - emit valueChanged(this->uasId,"distToWaypoint","m",QVariant(val),getUnixTime()); - } - - double getDistToWaypoint() const - { - return distToWaypoint; - } - - void setBearingToWaypoint(double val) - { - bearingToWaypoint = val; - emit bearingToWaypointChanged(val,"bearingToWaypoint"); - emit valueChanged(this->uasId,"bearingToWaypoint","deg",QVariant(val),getUnixTime()); - } - - double getBearingToWaypoint() const - { - return bearingToWaypoint; - } - - void setRoll(double val) { roll = val; @@ -377,34 +193,6 @@ protected: //COMMENTS FOR TEST UNIT /// POSITION bool isGlobalPositionKnown; ///< If the global position has been received for this MAV - double localX; - double localY; - double localZ; - - double latitude; ///< Global latitude as estimated by position estimator - double longitude; ///< Global longitude as estimated by position estimator - double altitudeAMSL; ///< Global altitude as estimated by position estimator, AMSL - double altitudeAMSLFT; ///< Global altitude as estimated by position estimator, AMSL - double altitudeRelative; ///< Altitude above home as estimated by position estimator - - double satRawHDOP; - double satRawVDOP; - double satRawCOG; - - double satelliteCount; ///< Number of satellites visible to raw GPS - bool globalEstimatorActive; ///< Global position estimator present, do not fall back to GPS raw for position - double latitude_gps; ///< Global latitude as estimated by raw GPS - double longitude_gps; ///< Global longitude as estimated by raw GPS - double altitude_gps; ///< Global altitude as estimated by raw GPS - double speedX; ///< True speed in X axis - double speedY; ///< True speed in Y axis - double speedZ; ///< True speed in Z axis - - /// WAYPOINT NAVIGATION - double distToWaypoint; ///< Distance to next waypoint - double airSpeed; ///< Airspeed - double groundSpeed; ///< Groundspeed - double bearingToWaypoint; ///< Bearing to next waypoint #ifndef __mobile__ FileManager fileManager; #endif @@ -472,11 +260,12 @@ public: void requestImage(); public slots: - /** @brief Executes a command with 7 params */ - void executeCommand(MAV_CMD command, int confirmation, float param1, float param2, float param3, float param4, float param5, float param6, float param7, int component); - /** @brief Order the robot to pair its receiver **/ void pairRX(int rxType, int rxSubType); + /** @brief Order the robot to take a picture **/ + void takePhoto(); + /** @brief Order the robot to toggle video recording **/ + void toggleVideo(); /** @brief Enable / disable HIL */ #ifndef __mobile__ @@ -548,34 +337,16 @@ public slots: /** @brief Send command to disable all bindings/maps between RC and parameters */ void unsetRCToParameterMap(); signals: - void loadChanged(UASInterface* uas, double load); void imageStarted(quint64 timestamp); /** @brief A new camera image has arrived */ void imageReady(UASInterface* uas); /** @brief HIL controls have changed */ void hilControlsChanged(quint64 time, float rollAilerons, float pitchElevator, float yawRudder, float throttle, quint8 systemMode, quint8 navMode); - void localXChanged(double val,QString name); - void localYChanged(double val,QString name); - void localZChanged(double val,QString name); - void longitudeChanged(double val,QString name); - void latitudeChanged(double val,QString name); - void altitudeAMSLChanged(double val,QString name); - void altitudeAMSLFTChanged(double val,QString name); - void altitudeRelativeChanged(double val,QString name); - - void satRawHDOPChanged (double value); - void satRawVDOPChanged (double value); - void satRawCOGChanged (double value); - void rollChanged(double val,QString name); void pitchChanged(double val,QString name); void yawChanged(double val,QString name); - void satelliteCountChanged(double val,QString name); - void distToWaypointChanged(double val,QString name); - void groundSpeedChanged(double val, QString name); - void airSpeedChanged(double val, QString name); - void bearingToWaypointChanged(double val,QString name); + protected: /** @brief Get the UNIX timestamp in milliseconds, enter microseconds */ quint64 getUnixTime(quint64 time=0); diff --git a/src/uas/UASInterface.h b/src/uas/UASInterface.h index cf022f5932c4c6955baf1b47d30bf84130678a2b..5f35f1408a7ebb2bfc73f69361edb4206a73ebea 100644 --- a/src/uas/UASInterface.h +++ b/src/uas/UASInterface.h @@ -50,12 +50,6 @@ public: /** @brief The time interval the robot is switched on **/ virtual quint64 getUptime() const = 0; - virtual double getLatitude() const = 0; - virtual double getLongitude() const = 0; - virtual double getAltitudeAMSL() const = 0; - virtual double getAltitudeRelative() const = 0; - virtual bool globalPositionKnown() const = 0; - virtual double getRoll() const = 0; virtual double getPitch() const = 0; virtual double getYaw() const = 0; @@ -117,6 +111,7 @@ public: StartCalibrationAirspeed, StartCalibrationAccel, StartCalibrationLevel, + StartCalibrationPressure, StartCalibrationEsc, StartCalibrationCopyTrims, StartCalibrationUavcanEsc, @@ -141,12 +136,12 @@ public: virtual void stopBusConfig(void) = 0; public slots: - - /** @brief Executes a command **/ - virtual void executeCommand(MAV_CMD command, int confirmation, float param1, float param2, float param3, float param4, float param5, float param6, float param7, int component) = 0; - /** @brief Order the robot to pair its receiver **/ virtual void pairRX(int rxType, int rxSubType) = 0; + /** @brief Order the robot to take a picture **/ + virtual void takePhoto() {} + /** @brief Order the robot to toggle video recording **/ + virtual void toggleVideo() {} /** @brief Send the full HIL state to the MAV */ #ifndef __mobile__ @@ -176,16 +171,6 @@ protected: QColor color; signals: - /** @brief The robot state has changed */ - void statusChanged(int stateFlag); - /** @brief The robot state has changed - * - * @param uas this robot - * @param status short description of status, e.g. "connected" - * @param description longer textual description. Should be however limited to a short text, e.g. 200 chars. - */ - void statusChanged(UASInterface* uas, QString status, QString description); - /** @brief A text message from the system has been received */ void textMessageReceived(int uasid, int componentid, int severity, QString text); @@ -204,13 +189,6 @@ signals: */ void errCountChanged(int uasid, QString component, QString device, int count); - /** - * @brief Drop rate of communication link updated - * - * @param systemId id of the air system - * @param receiveDrop drop rate of packets this MAV receives (sent from GCS or other MAVs) - */ - void dropRateChanged(int systemId, float receiveDrop); /** @brief The robot is connected **/ void connected(); /** @brief The robot is disconnected **/ @@ -242,39 +220,12 @@ signals: */ void batteryChanged(UASInterface* uas, double voltage, double current, double percent, int seconds); void statusChanged(UASInterface* uas, QString status); - void thrustChanged(UASInterface*, double thrust); void attitudeChanged(UASInterface*, double roll, double pitch, double yaw, quint64 usec); void attitudeChanged(UASInterface*, int component, double roll, double pitch, double yaw, quint64 usec); - void attitudeRotationRatesChanged(int uas, double rollrate, double pitchrate, double yawrate, quint64 usec); - void attitudeThrustSetPointChanged(UASInterface*, float rollDesired, float pitchDesired, float yawDesired, float thrustDesired, quint64 usec); - /** @brief The MAV set a new setpoint in the local (not body) NED X, Y, Z frame */ - void positionSetPointsChanged(int uasid, float xDesired, float yDesired, float zDesired, float yawDesired, quint64 usec); - /** @brief A user (or an autonomous mission or obstacle avoidance planner) requested to set a new setpoint */ - void userPositionSetPointsChanged(int uasid, float xDesired, float yDesired, float zDesired, float yawDesired); - void globalPositionChanged(UASInterface*, double lat, double lon, double altAMSL, quint64 usec); - void altitudeChanged(UASInterface*, double altitudeAMSL, double altitudeRelative, double climbRate, quint64 usec); - /** @brief Update the status of one satellite used for localization */ - void gpsSatelliteStatusChanged(int uasid, int satid, float azimuth, float direction, float snr, bool used); - - // The horizontal speed (a scalar) - void speedChanged(UASInterface* uas, double groundSpeed, double airSpeed, quint64 usec); - // Consider adding a MAV_FRAME parameter to this; could help specifying what the 3 scalars are. - void velocityChanged_NED(UASInterface*, double vx, double vy, double vz, quint64 usec); - - void navigationControllerErrorsChanged(UASInterface*, double altitudeError, double speedError, double xtrackError); - void NavigationControllerDataChanged(UASInterface *uas, float navRoll, float navPitch, float navBearing, float targetBearing, float targetDist); void imageStarted(int imgid, int width, int height, int depth, int channels); void imageDataReceived(int imgid, const unsigned char* imageData, int length, int startIndex); - /** @brief Attitude control enabled/disabled */ - void attitudeControlEnabled(bool enabled); - /** @brief Position 2D control enabled/disabled */ - void positionXYControlEnabled(bool enabled); - /** @brief Altitude control enabled/disabled */ - void positionZControlEnabled(bool enabled); - /** @brief Heading control enabled/disabled */ - void positionYawControlEnabled(bool enabled); /** @brief Optical flow status changed */ void opticalFlowStatusChanged(bool supported, bool enabled, bool ok); /** @brief Vision based localization status changed */ @@ -292,12 +243,6 @@ signals: /** @brief Differential pressure / airspeed status changed */ void airspeedStatusChanged(bool supported, bool enabled, bool ok); - /** - * @brief Localization quality changed - * @param fix 0: lost, 1: 2D local position hold, 2: 2D localization, 3: 3D localization - */ - void localizationChanged(UASInterface* uas, int fix); - // ERROR AND STATUS SIGNALS /** @brief Name of system changed */ void nameChanged(QString newName); @@ -307,6 +252,7 @@ signals: // Log Download Signals void logEntry (UASInterface* uas, uint32_t time_utc, uint32_t size, uint16_t id, uint16_t num_logs, uint16_t last_log_num); void logData (UASInterface* uas, uint32_t ofs, uint16_t id, uint8_t count, const uint8_t* data); + }; Q_DECLARE_INTERFACE(UASInterface, "org.qgroundcontrol/1.0") diff --git a/src/uas/UASMessageHandler.cc b/src/uas/UASMessageHandler.cc index db0c98db9587adc4b1d4ff43803d0d48bd537ad9..51941c9a65ad77d077a3811e0d58a9abc54546de 100644 --- a/src/uas/UASMessageHandler.cc +++ b/src/uas/UASMessageHandler.cc @@ -41,7 +41,7 @@ bool UASMessage::severityIsError() UASMessageHandler::UASMessageHandler(QGCApplication* app) : QGCTool(app) - , _activeUAS(NULL) + , _activeVehicle(NULL) , _activeComponent(-1) , _multiComp(false) , _errorCount(0) @@ -87,27 +87,28 @@ void UASMessageHandler::clearMessages() void UASMessageHandler::_activeVehicleChanged(Vehicle* vehicle) { // If we were already attached to an autopilot, disconnect it. - if (_activeUAS) - { - disconnect(_activeUAS, &UASInterface::textMessageReceived, this, &UASMessageHandler::handleTextMessage); - _activeUAS = NULL; + if (_activeVehicle) { + disconnect(_activeVehicle->uas(), &UASInterface::textMessageReceived, this, &UASMessageHandler::handleTextMessage); + _activeVehicle = NULL; clearMessages(); emit textMessageReceived(NULL); } - // And now if there's an autopilot to follow, set up the UI. - if (vehicle) - { - UAS* uas = vehicle->uas(); + // And now if there's an autopilot to follow, set up the UI. + if (vehicle) { // Connect to the new UAS. clearMessages(); - _activeUAS = uas; - connect(uas, &UASInterface::textMessageReceived, this, &UASMessageHandler::handleTextMessage); + _activeVehicle = vehicle; + connect(_activeVehicle->uas(), &UASInterface::textMessageReceived, this, &UASMessageHandler::handleTextMessage); } } void UASMessageHandler::handleTextMessage(int, int compId, int severity, QString text) { + // Hack to prevent calibration messages from cluttering things up + if (_activeVehicle->px4Firmware() && text.startsWith(QStringLiteral("[cal] "))) { + return; + } // Color the output depending on the message severity. We have 3 distinct cases: // 1: If we have an ERROR or worse, make it bigger, bolder, and highlight it red. diff --git a/src/uas/UASMessageHandler.h b/src/uas/UASMessageHandler.h index ed8cefe4bb00dceeec09df7fe9fc6de1f623f962..3b039e22e30730c2cac042e28cc62f136ee29eb7 100644 --- a/src/uas/UASMessageHandler.h +++ b/src/uas/UASMessageHandler.h @@ -144,7 +144,7 @@ private slots: void _activeVehicleChanged(Vehicle* vehicle); private: - UASInterface* _activeUAS; + Vehicle* _activeVehicle; int _activeComponent; bool _multiComp; QVector _messages; diff --git a/src/ui/AppSettings.qml b/src/ui/AppSettings.qml index f6ce5a4505b8e35043d283c567acccf06f92e456..4b161474d03682ed13867078311e623f3d946b32 100644 --- a/src/ui/AppSettings.qml +++ b/src/ui/AppSettings.qml @@ -30,13 +30,13 @@ Rectangle { readonly property real _buttonHeight: ScreenTools.isTinyScreen ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight * 2 readonly property real _buttonWidth: ScreenTools.defaultFontPixelWidth * 10 + property bool _first: true + QGCPalette { id: qgcPal } Component.onCompleted: { - //-- Default to General Settings - __rightPanel.source = "GeneralSettings.qml" - _generalButton.checked = true - panelActionGroup.current = _generalButton + //-- Default Settings + __rightPanel.source = QGroundControl.corePlugin.settings[QGroundControl.corePlugin.defaultSettings].url } QGCFlickable { @@ -81,90 +81,24 @@ Rectangle { visible: !ScreenTools.isShortScreen } - QGCButton { - id: _generalButton - height: _buttonHeight - text: qsTr("General") - exclusiveGroup: panelActionGroup - onClicked: { - if(__rightPanel.source != "GeneralSettings.qml") { - __rightPanel.source = "GeneralSettings.qml" - } - checked = true - } - } - - QGCButton { - height: _buttonHeight - text: qsTr("Comm Links") - exclusiveGroup: panelActionGroup - onClicked: { - if(__rightPanel.source != "LinkSettings.qml") { - __rightPanel.source = "LinkSettings.qml" - } - checked = true - } - } - - QGCButton { - height: _buttonHeight - text: qsTr("Offline Maps") - exclusiveGroup: panelActionGroup - onClicked: { - if(__rightPanel.source != "OfflineMap.qml") { - __rightPanel.source = "OfflineMap.qml" - } - checked = true - } - } - - QGCButton { - height: _buttonHeight - text: qsTr("MavLink") - exclusiveGroup: panelActionGroup - onClicked: { - if(__rightPanel.source != "MavlinkSettings.qml") { - __rightPanel.source = "MavlinkSettings.qml" - } - checked = true - } - } - - QGCButton { - height: _buttonHeight - text: qsTr("Console") - exclusiveGroup: panelActionGroup - onClicked: { - if(__rightPanel.source != "QGroundControl/Controls/AppMessages.qml") { - __rightPanel.source = "QGroundControl/Controls/AppMessages.qml" - } - checked = true - } - } - - QGCButton { - height: _buttonHeight - text: qsTr("Mock Link") - visible: ScreenTools.isDebug - exclusiveGroup: panelActionGroup - onClicked: { - if(__rightPanel.source != "MockLink.qml") { - __rightPanel.source = "MockLink.qml" + Repeater { + model: QGroundControl.corePlugin.settings + QGCButton { + height: _buttonHeight + text: modelData.title + exclusiveGroup: panelActionGroup + onClicked: { + if(__rightPanel.source !== modelData.url) { + __rightPanel.source = modelData.url + } + checked = true } - checked = true - } - } - - QGCButton { - height: _buttonHeight - text: qsTr("Debug") - visible: ScreenTools.isDebug - exclusiveGroup: panelActionGroup - onClicked: { - if(__rightPanel.source != "DebugWindow.qml") { - __rightPanel.source = "DebugWindow.qml" + Component.onCompleted: { + if(_first) { + _first = false + checked = true + } } - checked = true } } } diff --git a/src/ui/Linechart.ui b/src/ui/Linechart.ui index a46a5069117d415631d0e562afbe0a9999bc2e36..d56d7c2cfe5721c409cf0afc27372737f3528215 100644 --- a/src/ui/Linechart.ui +++ b/src/ui/Linechart.ui @@ -29,7 +29,16 @@ - + + 6 + + + 6 + + + 6 + + 6 @@ -103,8 +112,8 @@ 0 0 - 884 - 491 + 879 + 462 @@ -113,7 +122,7 @@ - 2 + 4 @@ -139,7 +148,7 @@ - 0 + 6 @@ -172,7 +181,7 @@ - 0 + 6 QLayout::SetMinimumSize diff --git a/src/ui/MAVLinkDecoder.cc b/src/ui/MAVLinkDecoder.cc index 5b02b32b33b319e6347a33c0411ec611684c1b44..e7c814e59bd057b8bac19cbf9838b47176b9d360 100644 --- a/src/ui/MAVLinkDecoder.cc +++ b/src/ui/MAVLinkDecoder.cc @@ -3,24 +3,13 @@ #include -MAVLinkDecoder::MAVLinkDecoder(MAVLinkProtocol* protocol, QObject *parent) : - QThread() +MAVLinkDecoder::MAVLinkDecoder(MAVLinkProtocol* protocol) : + QThread(), creationThread(QThread::currentThread()) { - Q_UNUSED(parent); // We're doing it wrong - because the Qt folks got the API wrong: // http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ moveToThread(this); - memset(receivedMessages, 0, sizeof(mavlink_message_t)*256); - for (unsigned int i = 0; i<255;++i) - { - componentID[i] = -1; - componentMulti[i] = false; - onboardTimeOffset[i] = 0; - onboardToGCSUnixTimeOffsetAndDelay[i] = 0; - firstOnboardTime[i] = 0; - } - // Fill filter // Allow system status // messageFilter.insert(MAVLINK_MSG_ID_HEARTBEAT, false); @@ -52,6 +41,7 @@ MAVLinkDecoder::MAVLinkDecoder(MAVLinkProtocol* protocol, QObject *parent) : // textMessageFilter.insert(MAVLINK_MSG_ID_HIGHRES_IMU, false); connect(protocol, &MAVLinkProtocol::messageReceived, this, &MAVLinkDecoder::receiveMessage); + connect(this, &MAVLinkDecoder::finish, this, &QThread::quit); start(LowPriority); } @@ -63,38 +53,39 @@ MAVLinkDecoder::MAVLinkDecoder(MAVLinkProtocol* protocol, QObject *parent) : void MAVLinkDecoder::run() { exec(); + moveToThread(creationThread); } void MAVLinkDecoder::receiveMessage(LinkInterface* link,mavlink_message_t message) { - if (message.msgid >= cMessageIds) { - // No support for messag ids above 255 - return; - } - Q_UNUSED(link); - memcpy(receivedMessages+message.msgid, &message, sizeof(mavlink_message_t)); - uint8_t msgid = message.msgid; + uint32_t msgid = message.msgid; const mavlink_message_info_t* msgInfo = mavlink_get_message_info(&message); + if(!msgInfo) { + qWarning() << "Invalid MAVLink message received. ID:" << msgid; + return; + } + + msgDict[message.msgid] = message; // Store an arrival time for this message. This value ends up being calculated later. quint64 time = 0; - + // The SYSTEM_TIME message is special, in that it's handled here for synchronizing the QGC time with the remote time. if (message.msgid == MAVLINK_MSG_ID_SYSTEM_TIME) { mavlink_system_time_t timebase; mavlink_msg_system_time_decode(&message, &timebase); - onboardTimeOffset[message.sysid] = (timebase.time_unix_usec+500)/1000 - timebase.time_boot_ms; - onboardToGCSUnixTimeOffsetAndDelay[message.sysid] = static_cast(QGC::groundTimeMilliseconds() - (timebase.time_unix_usec+500)/1000); + sysDict[msgid].onboardTimeOffset = (timebase.time_unix_usec+500)/1000 - timebase.time_boot_ms; + sysDict[msgid].onboardToGCSUnixTimeOffsetAndDelay = static_cast(QGC::groundTimeMilliseconds() - (timebase.time_unix_usec+500)/1000); } else { // See if first value is a time value and if it is, use that as the arrival time for this data. uint8_t fieldid = 0; - uint8_t* m = (uint8_t*)&((mavlink_message_t*)(receivedMessages+msgid))->payload64[0]; + uint8_t* m = (uint8_t*)(msgDict[msgid].payload64); if (QString(msgInfo->fields[fieldid].name) == QString("time_boot_ms") && msgInfo->fields[fieldid].type == MAVLINK_TYPE_UINT32_T) { @@ -125,7 +116,7 @@ quint64 MAVLinkDecoder::getUnixTimeFromMs(int systemID, quint64 time) quint64 ret = 0; if (time == 0) { - ret = QGC::groundTimeMilliseconds() - onboardToGCSUnixTimeOffsetAndDelay[systemID]; + ret = QGC::groundTimeMilliseconds() - sysDict[systemID].onboardToGCSUnixTimeOffsetAndDelay; } // Check if time is smaller than 40 years, // assuming no system without Unix timestamp @@ -149,15 +140,15 @@ quint64 MAVLinkDecoder::getUnixTimeFromMs(int systemID, quint64 time) else if (time < 1261440000000) #endif { - if (onboardTimeOffset[systemID] == 0 || time < (firstOnboardTime[systemID]-100)) + if (sysDict[systemID].onboardTimeOffset == 0 || time < (sysDict[systemID].firstOnboardTime -100)) { - firstOnboardTime[systemID] = time; - onboardTimeOffset[systemID] = QGC::groundTimeMilliseconds() - time; + sysDict[systemID].firstOnboardTime = time; + sysDict[systemID].onboardTimeOffset = QGC::groundTimeMilliseconds() - time; } - if (time > firstOnboardTime[systemID]) firstOnboardTime[systemID] = time; + if (time > sysDict[systemID].firstOnboardTime ) sysDict[systemID].firstOnboardTime = time; - ret = time + onboardTimeOffset[systemID]; + ret = time + sysDict[systemID].onboardTimeOffset; } else { @@ -203,28 +194,36 @@ void MAVLinkDecoder::emitFieldValue(mavlink_message_t* msg, int fieldid, quint64 bool multiComponentSourceDetected = false; const mavlink_message_info_t* msgInfo = mavlink_get_message_info(msg); + uint32_t msgid = msg->msgid; + + // create new system data if it wasn't dectected yet + if (!(sysDict.keys().contains(msgid))) { + sysDict[msgid] = SystemData(); + } + // Store component ID - if (componentID[msg->msgid] == -1) + if (sysDict[msgid].componentID == -1) { - componentID[msg->msgid] = msg->compid; + sysDict[msgid].componentID = msg->compid; } else { // Got this message already - if (componentID[msg->msgid] != msg->compid) + if (sysDict[msgid].componentID != msg->compid) { - componentMulti[msg->msgid] = true; + sysDict[msgid].componentMulti = true; } } - if (componentMulti[msg->msgid] == true) multiComponentSourceDetected = true; + if (sysDict[msgid].componentMulti == true) { + multiComponentSourceDetected = true; + } // Add field tree widget item - uint8_t msgid = msg->msgid; if (messageFilter.contains(msgid)) return; QString fieldName(msgInfo->fields[fieldid].name); QString fieldType; - uint8_t* m = (uint8_t*)&((mavlink_message_t*)(receivedMessages+msgid))->payload64[0]; + uint8_t* m = (uint8_t*)(msgDict[msgid].payload64); QString name("%1.%2"); QString unit(""); diff --git a/src/ui/MAVLinkDecoder.h b/src/ui/MAVLinkDecoder.h index eaa1909061e87b7fe57482b2ff22000c9ba4031a..9f715bace9ef7fe24d30f2aa4f6eb56b1358bb3c 100644 --- a/src/ui/MAVLinkDecoder.h +++ b/src/ui/MAVLinkDecoder.h @@ -2,19 +2,40 @@ #define MAVLINKDECODER_H #include +#include + #include "MAVLinkProtocol.h" +struct SystemData { + /** + * @brief Holds mavlink system data + */ + SystemData() : + componentID(-1), + componentMulti(false), + onboardTimeOffset(0), + onboardToGCSUnixTimeOffsetAndDelay(0), + firstOnboardTime(0) { + } + int componentID; ///< Multi component detection + bool componentMulti; ///< Multi components detected + quint64 onboardTimeOffset; ///< Offset of onboard time from Unix epoch (of the receiving GCS) + qint64 onboardToGCSUnixTimeOffsetAndDelay; ///< Offset of onboard time and GCS Unix time + quint64 firstOnboardTime; ///< First seen onboard time +}; + class MAVLinkDecoder : public QThread { Q_OBJECT public: - MAVLinkDecoder(MAVLinkProtocol* protocol, QObject *parent = 0); + MAVLinkDecoder(MAVLinkProtocol* protocol); void run(); signals: void textMessageReceived(int uasid, int componentid, int severity, const QString& text); void valueChanged(const int uasId, const QString& name, const QString& unit, const QVariant& value, const quint64 msec); + void finish(); ///< Trigger a thread safe shutdown public slots: /** @brief Receive one message from the protocol and decode it */ @@ -25,16 +46,11 @@ protected: /** @brief Shift a timestamp in Unix time if necessary */ quint64 getUnixTimeFromMs(int systemID, quint64 time); - static const size_t cMessageIds = 256; - - mavlink_message_t receivedMessages[cMessageIds]; ///< Available / known messages QMap messageFilter; ///< Message/field names not to emit QMap textMessageFilter; ///< Message/field names not to emit in text mode - int componentID[cMessageIds]; ///< Multi component detection - bool componentMulti[cMessageIds]; ///< Multi components detected - quint64 onboardTimeOffset[cMessageIds]; ///< Offset of onboard time from Unix epoch (of the receiving GCS) - qint64 onboardToGCSUnixTimeOffsetAndDelay[cMessageIds]; ///< Offset of onboard time and GCS Unix time - quint64 firstOnboardTime[cMessageIds]; ///< First seen onboard time + QHash msgDict; ///< dictionary of all mavlink messages + QHash sysDict; ///< dictionary of all systmes + QThread* creationThread; ///< QThread on which the object is created }; #endif // MAVLINKDECODER_H diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 4435feddbe9ed20dd7f5ada60604920ec3f532e7..c24a052ed161cc60c630b25aab275b8b34e980e0 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -37,13 +37,11 @@ #include "MAVLinkDecoder.h" #include "QGCApplication.h" #include "MultiVehicleManager.h" -#include "HomePositionManager.h" #include "LogCompressor.h" #include "UAS.h" #include "QGCImageProvider.h" #ifndef __mobile__ -#include "QGCDataPlot2D.h" #include "Linecharts.h" #include "QGCUASFileViewMulti.h" #include "UASQuickView.h" @@ -54,7 +52,7 @@ #include "AppMessages.h" #endif -#ifndef __ios__ +#ifndef NO_SERIAL_LINK #include "SerialLink.h" #endif @@ -276,6 +274,11 @@ MainWindow::MainWindow() MainWindow::~MainWindow() { + // Enforce thread-safe shutdown of the mavlink decoder + mavlinkDecoder->finish(); + mavlinkDecoder->wait(1000); + mavlinkDecoder->deleteLater(); + // This needs to happen before we get into the QWidget dtor // otherwise the QML engine reads freed data and tries to // destroy MainWindow a second time. @@ -292,8 +295,7 @@ QString MainWindow::_getWindowGeometryKey() void MainWindow::_buildCommonWidgets(void) { // Add generic MAVLink decoder - // TODO: This is never deleted - mavlinkDecoder = new MAVLinkDecoder(qgcApp()->toolbox()->mavlinkProtocol(), this); + mavlinkDecoder = new MAVLinkDecoder(qgcApp()->toolbox()->mavlinkProtocol()); connect(mavlinkDecoder.data(), &MAVLinkDecoder::valueChanged, this, &MainWindow::valueChanged); // Log player @@ -452,28 +454,7 @@ void MainWindow::storeSettings() void MainWindow::configureWindowName() { - QList hostAddresses = QNetworkInterface::allAddresses(); - QString windowname = qApp->applicationName() + " " + qApp->applicationVersion(); - - // XXX we do have UDP MAVLink heartbeat broadcast now in SITL and will have it on the - // WIFI radio, so people should not be in need any more of knowing their IP. - // this can go once we are certain its not needed any more. - #if 0 - bool prevAddr = false; - windowname.append(" (" + QHostInfo::localHostName() + ": "); - for (int i = 0; i < hostAddresses.size(); i++) - { - // Exclude loopback IPv4 and all IPv6 addresses - if (hostAddresses.at(i) != QHostAddress("127.0.0.1") && !hostAddresses.at(i).toString().contains(":")) - { - if(prevAddr) windowname.append("/"); - windowname.append(hostAddresses.at(i).toString()); - prevAddr = true; - } - } - windowname.append(")"); - #endif - setWindowTitle(windowname); + setWindowTitle(qApp->applicationName() + " " + qApp->applicationVersion()); } /** @@ -482,11 +463,6 @@ void MainWindow::configureWindowName() **/ void MainWindow::connectCommonActions() { - // Audio output - _ui.actionMuteAudioOutput->setChecked(qgcApp()->toolbox()->audioOutput()->isMuted()); - connect(qgcApp()->toolbox()->audioOutput(), &GAudioOutput::mutedChanged, _ui.actionMuteAudioOutput, &QAction::setChecked); - connect(_ui.actionMuteAudioOutput, &QAction::triggered, qgcApp()->toolbox()->audioOutput(), &GAudioOutput::mute); - // Connect internal actions connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::vehicleAdded, this, &MainWindow::_vehicleAdded); } diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index 3f7c31d381b0d9c1b7335b7973a74977d794811f..dc1706a42273d710b52f23b8e649a7efa0aec71a 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -33,9 +33,7 @@ #include "UASInterface.h" #include "LogCompressor.h" #include "QGCMAVLinkInspector.h" -#ifndef __mobile__ #include "QGCMAVLinkLogPlayer.h" -#endif #include "MAVLinkDecoder.h" #include "Vehicle.h" #include "QGCDockWidget.h" @@ -49,7 +47,6 @@ class QGCStatusBar; class Linecharts; -class QGCDataPlot2D; /** * @brief Main Application Window @@ -117,12 +114,10 @@ signals: #endif //QGC_MOUSE_ENABLED_LINUX public: -#ifndef __mobile__ QGCMAVLinkLogPlayer* getLogPlayer() { return logPlayer; } -#endif protected: void connectCommonActions(); @@ -133,9 +128,7 @@ protected: QSettings settings; QPointer mavlinkDecoder; -#ifndef __mobile__ QGCMAVLinkLogPlayer* logPlayer; -#endif #ifdef QGC_MOUSE_ENABLED_WIN /** @brief 3d Mouse support (WIN only) */ Mouse3DInput* mouseInput; ///< 3dConnexion 3dMouse SDK @@ -164,10 +157,7 @@ protected: private slots: void _closeWindow(void) { close(); } void _vehicleAdded(Vehicle* vehicle); - -#ifndef __mobile__ void _showDockWidgetAction(bool show); -#endif #ifdef UNITTEST_BUILD void _showQmlTestWidget(void); @@ -179,22 +169,17 @@ private: void _openUrl(const QString& url, const QString& errorMessage); -#ifndef __mobile__ QMap _mapName2DockWidget; QMap _mapName2Action; -#endif void _storeCurrentViewState(void); void _loadCurrentViewState(void); - -#ifndef __mobile__ bool _createInnerDockWidget(const QString& widgetName); void _buildCommonWidgets(void); void _hideAllDockWidgets(void); void _showDockWidget(const QString &name, bool show); void _loadVisibleWidgetsSettings(void); void _storeVisibleWidgetsSettings(void); -#endif bool _lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets bool _showStatusBar; diff --git a/src/ui/MainWindow.ui b/src/ui/MainWindow.ui index 4d6bb7f5312c5e027194cbe5fa17d7ee54d15101..1e2fcd86fe9c28db09748ca350a6be3c54f32b9c 100644 --- a/src/ui/MainWindow.ui +++ b/src/ui/MainWindow.ui @@ -59,7 +59,6 @@ File - @@ -86,14 +85,6 @@ Manage Communication Links - - - true - - - Mute Audio Output - - true diff --git a/src/ui/MainWindowInner.qml b/src/ui/MainWindowInner.qml index 1943f30e9952833388dc407a7d47efb076e11c35..0276d40550a9d298d10ba4d7c1de14d20cbb6bb0 100644 --- a/src/ui/MainWindowInner.qml +++ b/src/ui/MainWindowInner.qml @@ -29,11 +29,6 @@ Item { QGCPalette { id: qgcPal; colorGroupEnabled: true } - property real tbHeight: ScreenTools.isMobile ? (ScreenTools.isTinyScreen ? (mainWindow.width * 0.0666) : (mainWindow.width * 0.05)) : ScreenTools.defaultFontPixelHeight * 3 - property int tbCellHeight: tbHeight * 0.75 - property real tbSpacing: ScreenTools.isMobile ? width * 0.00824 : 9.54 - property real tbButtonWidth: tbCellHeight * 1.35 - property real menuButtonWidth: (tbButtonWidth * 2) + (tbSpacing * 4) + 1 property var gcsPosition: QtPositioning.coordinate() // Starts as invalid coordinate property var currentPopUp: null property real currentCenterX: 0 @@ -66,10 +61,10 @@ Item { } //-- In settings view, the full height is available. Set to 0 so it is ignored. ScreenTools.availableHeight = 0 + hideAllViews() if (settingsViewLoader.source != _settingsViewSource) { settingsViewLoader.source = _settingsViewSource } - hideAllViews() settingsViewLoader.visible = true toolBar.checkSettingsButton() } @@ -80,10 +75,10 @@ Item { } //-- In setup view, the full height is available. Set to 0 so it is ignored. ScreenTools.availableHeight = 0 + hideAllViews() if (setupViewLoader.source != _setupViewSource) { setupViewLoader.source = _setupViewSource } - hideAllViews() setupViewLoader.visible = true toolBar.checkSetupButton() } @@ -260,21 +255,19 @@ Item { MainToolBar { id: toolBar - height: tbHeight + height: ScreenTools.toolbarHeight anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - mainWindow: mainWindow isBackgroundDark: flightView.isBackgroundDark z: QGroundControl.zOrderTopMost - onShowSettingsView: mainWindow.showSettingsView() - onShowSetupView: mainWindow.showSetupView() - onShowPlanView: mainWindow.showPlanView() - onShowFlyView: mainWindow.showFlyView() - onShowAnalyzeView: mainWindow.showAnalyzeView() - Component.onCompleted: { - ScreenTools.availableHeight = parent.height - toolBar.height - } + + Component.onCompleted: ScreenTools.availableHeight = parent.height - toolBar.height + onShowSettingsView: mainWindow.showSettingsView() + onShowSetupView: mainWindow.showSetupView() + onShowPlanView: mainWindow.showPlanView() + onShowFlyView: mainWindow.showFlyView() + onShowAnalyzeView: mainWindow.showAnalyzeView() } Loader { @@ -284,13 +277,13 @@ Item { anchors.top: toolBar.bottom anchors.bottom: parent.bottom visible: false - +/* onVisibleChanged: { if (!visible) { // Free up the memory for this when not shown. No need to persist. source = "" } - } + }*/ } Loader { @@ -364,7 +357,7 @@ Item { border.width: 2 anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top - anchors.topMargin: tbHeight + ScreenTools.defaultFontPixelHeight + anchors.topMargin: toolBar.height + ScreenTools.defaultFontPixelHeight MouseArea { // This MouseArea prevents the Map below it from getting Mouse events. Without this // things like mousewheel will scroll the Flickable and then scroll the map as well. @@ -442,7 +435,7 @@ Item { radius: ScreenTools.defaultFontPixelHeight * 0.5 anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top - anchors.topMargin: tbHeight + ScreenTools.defaultFontPixelHeight / 2 + anchors.topMargin: toolBar.height + ScreenTools.defaultFontPixelHeight / 2 border.color: "#808080" border.width: 2 @@ -537,5 +530,14 @@ Item { } } } + + //------------------------------------------------------------------------- + //-- Loader helper for any child, no matter how deep can display an element + // in the middle of the main window. + Loader { + id: rootLoader + anchors.centerIn: parent + } + } diff --git a/src/ui/QGCDataPlot2D.cc b/src/ui/QGCDataPlot2D.cc deleted file mode 100644 index 472b91e1f4ffc03d86a9b1c8780dd3bfb46d0332..0000000000000000000000000000000000000000 --- a/src/ui/QGCDataPlot2D.cc +++ /dev/null @@ -1,734 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/** - * @file - * @brief Implementation of QGCDataPlot2D - * @author Lorenz Meier - * - */ - -#include -#ifndef __mobile__ -#include -#include -#endif -#include -#include -#include -#include -#include - -#include - -#include "QGCDataPlot2D.h" -#include "ui_QGCDataPlot2D.h" -#include "MG.h" -#include "QGCFileDialog.h" -#include "QGCMessageBox.h" - -QGCDataPlot2D::QGCDataPlot2D(QWidget *parent) : - QWidget(parent), - plot(new IncrementalPlot(parent)), - logFile(NULL), - ui(new Ui::QGCDataPlot2D) -{ - ui->setupUi(this); - - // Add plot to ui - QHBoxLayout* layout = new QHBoxLayout(ui->plotFrame); - layout->addWidget(plot); - ui->plotFrame->setLayout(layout); - ui->gridCheckBox->setChecked(plot->gridEnabled()); - - // Connect user actions - connect(ui->selectFileButton, &QPushButton::clicked, this, &QGCDataPlot2D::selectFile); - connect(ui->saveCsvButton, &QPushButton::clicked, this, &QGCDataPlot2D::saveCsvLog); - connect(ui->reloadButton, &QPushButton::clicked, this, &QGCDataPlot2D::reloadFile); - connect(ui->savePlotButton, &QPushButton::clicked, this, &QGCDataPlot2D::savePlot); - connect(ui->printButton, &QPushButton::clicked, this, &QGCDataPlot2D::print); - connect(ui->legendCheckBox, &QCheckBox::clicked, plot, &IncrementalPlot::showLegend); - connect(ui->symmetricCheckBox,&QCheckBox::clicked, plot, &IncrementalPlot::setSymmetric); - connect(ui->gridCheckBox, &QCheckBox::clicked, plot, &IncrementalPlot::showGrid); - - connect(ui->style, static_cast(&QComboBox::currentIndexChanged), - plot, &IncrementalPlot::setStyleText); - - //TODO: calculateRegression returns bool, slots are expected to return void, this makes - // converting to new style way too hard. - connect(ui->regressionButton, SIGNAL(clicked()), this, SLOT(calculateRegression())); - - // Allow style changes to propagate through this widget - connect(qgcApp(), &QGCApplication::styleChanged, plot, &IncrementalPlot::styleChanged); -} - -void QGCDataPlot2D::reloadFile() -{ - if (QFileInfo(fileName).isReadable()) { - if (ui->inputFileType->currentText().contains("pxIMU") || ui->inputFileType->currentText().contains("RAW")) { - loadRawLog(fileName, ui->xAxis->currentText(), ui->yAxis->text()); - } else if (ui->inputFileType->currentText().contains("CSV")) { - loadCsvLog(fileName, ui->xAxis->currentText(), ui->yAxis->text()); - } - } -} - -void QGCDataPlot2D::loadFile() -{ - qDebug() << "DATA PLOT: Loading file:" << fileName; - if (QFileInfo(fileName).isReadable()) { - if (ui->inputFileType->currentText().contains("pxIMU") || ui->inputFileType->currentText().contains("RAW")) { - loadRawLog(fileName); - } else if (ui->inputFileType->currentText().contains("CSV")) { - loadCsvLog(fileName); - } - } -} - -void QGCDataPlot2D::loadFile(QString file) -{ - // TODO This "filename" is a private/protected member variable. It should be named in such way - // it indicates so. This same name is used in several places within this file in local scopes. - fileName = file; - QFileInfo fi(fileName); - if (fi.isReadable()) { - if (fi.suffix() == QString("raw") || fi.suffix() == QString("imu")) { - loadRawLog(fileName); - } else if (fi.suffix() == QString("txt") || fi.suffix() == QString("csv")) { - loadCsvLog(fileName); - } - // TODO Else, tell the user it doesn't know what to do with the file... - } -} - -/** - * This function brings up a file name dialog and asks the user to enter a file to save to - */ -QString QGCDataPlot2D::getSavePlotFilename() -{ - QString fileName = QGCFileDialog::getSaveFileName( - this, "Save Plot File", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), - "PDF Documents (*.pdf);;SVG Images (*.svg)", - "pdf"); - return fileName; -} - -/** - * This function aks the user for a filename and exports to either PDF or SVG, depending on the filename - */ -void QGCDataPlot2D::savePlot() -{ - QString fileName = getSavePlotFilename(); - if (fileName.isEmpty()) - return; - - while(!(fileName.endsWith(".svg") || fileName.endsWith(".pdf"))) { - QMessageBox::StandardButton button = QGCMessageBox::warning( - tr("Unsuitable file extension for Plot document type."), - tr("Please choose .pdf or .svg as file extension. Click OK to change the file extension, cancel to not save the file."), - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Ok); - // Abort if cancelled - if (button == QMessageBox::Cancel) { - return; - } - - fileName = getSavePlotFilename(); - if (fileName.isEmpty()) - return; //Abort if cancelled - } - - if (fileName.endsWith(".pdf")) { - exportPDF(fileName); - } else if (fileName.endsWith(".svg")) { - exportSVG(fileName); - } -} - - -void QGCDataPlot2D::print() -{ -#ifndef __mobile__ - QPrinter printer(QPrinter::HighResolution); - // printer.setOutputFormat(QPrinter::PdfFormat); - // //QPrinter printer(QPrinter::HighResolution); - // printer.setOutputFileName(fileName); - - QString docName = plot->title().text(); - if ( !docName.isEmpty() ) { - docName.replace (QRegExp (QString::fromLatin1 ("\n")), tr (" -- ")); - printer.setDocName (docName); - } - - printer.setCreator("QGroundControl"); - printer.setOrientation(QPrinter::Landscape); - - QPrintDialog dialog(&printer); - if ( dialog.exec() ) { - plot->setStyleSheet("QWidget { background-color: #FFFFFF; color: #000000; background-clip: border; font-size: 10pt;}"); - plot->setCanvasBackground(Qt::white); - // FIXME: QwtPlotPrintFilter no longer exists in Qwt 6.1 - //QwtPlotPrintFilter filter; - //filter.color(Qt::white, QwtPlotPrintFilter::CanvasBackground); - //filter.color(Qt::black, QwtPlotPrintFilter::AxisScale); - //filter.color(Qt::black, QwtPlotPrintFilter::AxisTitle); - //filter.color(Qt::black, QwtPlotPrintFilter::MajorGrid); - //filter.color(Qt::black, QwtPlotPrintFilter::MinorGrid); - //if ( printer.colorMode() == QPrinter::GrayScale ) { - // int options = QwtPlotPrintFilter::PrintAll; - // options &= ~QwtPlotPrintFilter::PrintBackground; - // options |= QwtPlotPrintFilter::PrintFrameWithScales; - // filter.setOptions(options); - //} - //plot->print(printer); - plot->setStyleSheet("QWidget { background-color: #050508; color: #DDDDDF; background-clip: border; font-size: 11pt;}"); - //plot->setCanvasBackground(QColor(5, 5, 8)); - } -#endif -} - -void QGCDataPlot2D::exportPDF(QString fileName) -{ -#ifdef __mobile__ - Q_UNUSED(fileName) -#else - QPrinter printer; - printer.setOutputFormat(QPrinter::PdfFormat); - printer.setOutputFileName(fileName); - //printer.setFullPage(true); - printer.setPageMargins(10.0, 10.0, 10.0, 10.0, QPrinter::Millimeter); - printer.setPageSize(QPrinter::A4); - - QString docName = plot->title().text(); - if ( !docName.isEmpty() ) { - docName.replace (QRegExp (QString::fromLatin1 ("\n")), tr (" -- ")); - printer.setDocName (docName); - } - - printer.setCreator("QGroundControl"); - printer.setOrientation(QPrinter::Landscape); - - plot->setStyleSheet("QWidget { background-color: #FFFFFF; color: #000000; background-clip: border; font-size: 10pt;}"); - // plot->setCanvasBackground(Qt::white); - // FIXME: QwtPlotPrintFilter no longer exists in Qwt 6.1 - // QwtPlotPrintFilter filter; - // filter.color(Qt::white, QwtPlotPrintFilter::CanvasBackground); - // filter.color(Qt::black, QwtPlotPrintFilter::AxisScale); - // filter.color(Qt::black, QwtPlotPrintFilter::AxisTitle); - // filter.color(Qt::black, QwtPlotPrintFilter::MajorGrid); - // filter.color(Qt::black, QwtPlotPrintFilter::MinorGrid); - // if ( printer.colorMode() == QPrinter::GrayScale ) - // { - // int options = QwtPlotPrintFilter::PrintAll; - // options &= ~QwtPlotPrintFilter::PrintBackground; - // options |= QwtPlotPrintFilter::PrintFrameWithScales; - // filter.setOptions(options); - // } - //plot->print(printer); - plot->setStyleSheet("QWidget { background-color: #050508; color: #DDDDDF; background-clip: border; font-size: 11pt;}"); - //plot->setCanvasBackground(QColor(5, 5, 8)); -#endif -} - -void QGCDataPlot2D::exportSVG(QString fileName) -{ -#ifdef __mobile__ - Q_UNUSED(fileName) -#else - if ( !fileName.isEmpty() ) { - plot->setStyleSheet("QWidget { background-color: #FFFFFF; color: #000000; background-clip: border; font-size: 10pt;}"); - //plot->setCanvasBackground(Qt::white); - QSvgGenerator generator; - generator.setFileName(fileName); - generator.setSize(QSize(800, 600)); - - // FIXME: QwtPlotPrintFilter no longer exists in Qwt 6.1 - //QwtPlotPrintFilter filter; - //filter.color(Qt::white, QwtPlotPrintFilter::CanvasBackground); - //filter.color(Qt::black, QwtPlotPrintFilter::AxisScale); - //filter.color(Qt::black, QwtPlotPrintFilter::AxisTitle); - //filter.color(Qt::black, QwtPlotPrintFilter::MajorGrid); - //filter.color(Qt::black, QwtPlotPrintFilter::MinorGrid); - - //plot->print(generator); - plot->setStyleSheet("QWidget { background-color: #050508; color: #DDDDDF; background-clip: border; font-size: 11pt;}"); - } -#endif -} - -/** - * Selects a filename and attempts immediately to load it. - */ -void QGCDataPlot2D::selectFile() -{ - // Open a file dialog prompting the user for the file to load. - // Note the special case for the Pixhawk. - if (ui->inputFileType->currentText().contains("pxIMU") || ui->inputFileType->currentText().contains("RAW")) { - fileName = QGCFileDialog::getOpenFileName(this, tr("Load Log File"), QString(), "Log Files (*.imu *.raw)"); - } - else - { - fileName = QGCFileDialog::getOpenFileName(this, tr("Load Log File"), QString(), "Log Files (*.csv);;All Files (*)"); - } - - // Check if the user hit cancel, which results in an empty string. - // If this is the case, we just stop. - if (fileName.isEmpty()) - { - return; - } - - // Now attempt to open the file - QFileInfo fileInfo(fileName); - if (!fileInfo.isReadable()) - { - // TODO This needs some TLC. File used by another program sounds like a Windows only issue. - QGCMessageBox::critical( - tr("Could not open file"), - tr("The file is owned by user %1. Is the file currently used by another program?").arg(fileInfo.owner())); - ui->filenameLabel->setText(tr("Could not open %1").arg(fileInfo.fileName())); - } - else - { - ui->filenameLabel->setText(tr("Opened %1").arg(fileInfo.completeBaseName()+"."+fileInfo.completeSuffix())); - // Open and import the file - loadFile(); - } - -} - -void QGCDataPlot2D::loadRawLog(QString file, QString xAxisName, QString yAxisFilter) -{ - Q_UNUSED(xAxisName); - Q_UNUSED(yAxisFilter); - - if (logFile != NULL) { - logFile->close(); - delete logFile; - } - // Postprocess log file - logFile = new QTemporaryFile("qt_qgc_temp_log.XXXXXX.csv"); - compressor = new LogCompressor(file, logFile->fileName()); - connect(compressor, &LogCompressor::finishedFile, this, static_cast(&QGCDataPlot2D::loadFile)); - compressor->startCompression(); -} - -/** - * This function loads a CSV file into the plot. It tries to assign the dimension names - * based on the first data row and tries to guess the separator char. - * - * @param file Name of the file to open - * @param xAxisName Optional paramater. If given, the x axis dimension will be selected to match this string - * @param yAxisFilter Optional parameter. If given, only data dimension names present in the filter string will be - * plotted - * - * @code - * - * QString file = "/home/user/datalog.txt"; // With header: xyz - * QString xAxis = "x"; - * QString yAxis = "z"; - * - * // Plotted result will be x vs z with y ignored. - * @endcode - */ -void QGCDataPlot2D::loadCsvLog(QString file, QString xAxisName, QString yAxisFilter) -{ - if (logFile != NULL) { - logFile->close(); - delete logFile; - curveNames.clear(); - } - logFile = new QFile(file); - - // Load CSV data - if (!logFile->open(QIODevice::ReadOnly | QIODevice::Text)) - return; - - // Set plot title - if (ui->plotTitle->text() != "") plot->setTitle(ui->plotTitle->text()); - if (ui->plotXAxisLabel->text() != "") plot->setAxisTitle(QwtPlot::xBottom, ui->plotXAxisLabel->text()); - if (ui->plotYAxisLabel->text() != "") plot->setAxisTitle(QwtPlot::yLeft, ui->plotYAxisLabel->text()); - - // Extract header - - // Read in values - // Find all keys - QTextStream in(logFile); - - // First line is header - QString header = in.readLine(); - - bool charRead = false; - QString separator = ""; - QList sepCandidates; - sepCandidates << '\t'; - sepCandidates << ','; - sepCandidates << ';'; - sepCandidates << ' '; - sepCandidates << '~'; - sepCandidates << '|'; - - // Iterate until separator is found - // or full header is parsed - for (int i = 0; i < header.length(); i++) { - if (sepCandidates.contains(header.at(i))) { - // Separator found - if (charRead) { - separator += header[i]; - } - } else { - // Char found - charRead = true; - // If the separator is not empty, this char - // has been read after a separator, so detection - // is now complete - if (separator != "") break; - } - } - - QString out = separator; - out.replace("\t", ""); - ui->filenameLabel->setText(file.split("/").last().split("\\").last()+" Separator: \""+out+"\""); - //qDebug() << "READING CSV:" << header; - - // Clear plot - plot->removeData(); - - QMap* > xValues; - QMap* > yValues; - - curveNames.append(header.split(separator, QString::SkipEmptyParts)); - - // Eliminate any non-string curve names - for (int i = 0; i < curveNames.count(); ++i) - { - if (curveNames.at(i).length() == 0 || - curveNames.at(i) == " " || - curveNames.at(i) == "\n" || - curveNames.at(i) == "\t" || - curveNames.at(i) == "\r") - { - // Remove bogus curve name - curveNames.removeAt(i); - } - } - - QString curveName; - - // Clear UI elements - ui->xAxis->clear(); - ui->yAxis->clear(); - ui->xRegressionComboBox->clear(); - ui->yRegressionComboBox->clear(); - ui->regressionOutput->clear(); - - int curveNameIndex = 0; - - QString xAxisFilter; - if (xAxisName == "") { - xAxisFilter = curveNames.first(); - } else { - xAxisFilter = xAxisName; - } - - // Fill y-axis renaming lookup table - // Allow the user to rename data dimensions in the plot - QMap renaming; - - QStringList yCurves = yAxisFilter.split("|", QString::SkipEmptyParts); - - // Figure out the correct renaming - for (int i = 0; i < yCurves.count(); ++i) - { - if (yCurves.at(i).contains(":")) - { - QStringList parts = yCurves.at(i).split(":", QString::SkipEmptyParts); - if (parts.count() > 1) - { - // Insert renaming map - renaming.insert(parts.first(), parts.last()); - // Replace curve value with first part only - yCurves.replace(i, parts.first()); - } - } -// else -// { -// // Insert same value, not renaming anything -// renaming.insert(yCurves.at(i), yCurves.at(i)); -// } - } - - - foreach(curveName, curveNames) { - // Add to plot x axis selection - ui->xAxis->addItem(curveName); - // Add to regression selection - ui->xRegressionComboBox->addItem(curveName); - ui->yRegressionComboBox->addItem(curveName); - if (curveName != xAxisFilter) { - if ((yAxisFilter == "") || yCurves.contains(curveName)) { - yValues.insert(curveName, new QVector()); - xValues.insert(curveName, new QVector()); - // Add separator starting with second item - if (curveNameIndex > 0 && curveNameIndex < curveNames.count()) { - ui->yAxis->setText(ui->yAxis->text()+"|"); - } - // If this curve was renamed, re-add the renaming to the text field - QString renamingText = ""; - if (renaming.contains(curveName)) renamingText = QString(":%1").arg(renaming.value(curveName)); - ui->yAxis->setText(ui->yAxis->text()+curveName+renamingText); - // Insert same value, not renaming anything - if (!renaming.contains(curveName)) renaming.insert(curveName, curveName); - curveNameIndex++; - } - } - } - - // Select current axis in UI - ui->xAxis->setCurrentIndex(curveNames.indexOf(xAxisFilter)); - - // Read data - - double x = 0; - double y = 0; - - while (!in.atEnd()) - { - QString line = in.readLine(); - - // Keep empty parts here - we still have to act on them - QStringList values = line.split(separator, QString::KeepEmptyParts); - - bool headerfound = false; - - // First get header - ORDER MATTERS HERE! - foreach(curveName, curveNames) - { - if (curveName == xAxisFilter) - { - // X AXIS HANDLING - - // Take this value as x if it is selected - QString text = values.at(curveNames.indexOf(curveName)); - text = text.trimmed(); - if (text.length() > 0 && text != " " && text != "\n" && text != "\r" && text != "\t") - { - bool okx = true; - x = text.toDouble(&okx); - if (okx && !qIsNaN(x) && !qIsInf(x)) - { - headerfound = true; - } - } - } - } - - if (headerfound) - { - // Search again from start for values - ORDER MATTERS HERE! - foreach(curveName, curveNames) - { - // Y AXIS HANDLING - // Only plot non-x curver and those selected in the yAxisFilter (or all if the filter is not set) - if(curveName != xAxisFilter && (yAxisFilter == "" || yCurves.contains(curveName))) - { - bool oky; - int curveNameIndex = curveNames.indexOf(curveName); - if (values.count() > curveNameIndex) - { - QString text(values.at(curveNameIndex)); - text = text.trimmed(); - y = text.toDouble(&oky); - // Only INF is really an issue for the plot - // NaN is fine - if (oky && !qIsNaN(y) && !qIsInf(y) && text.length() > 0 && text != " " && text != "\n" && text != "\r" && text != "\t") - { - // Only append definitely valid values - xValues.value(curveName)->append(x); - yValues.value(curveName)->append(y); - } - } - } - } - } - } - - // Add data array of each curve to the plot at once (fast) - // Iterates through all x-y curve combinations - for (int i = 0; i < yValues.count(); i++) { - if (renaming.contains(yValues.keys().at(i))) - { - plot->appendData(renaming.value(yValues.keys().at(i)), xValues.values().at(i)->data(), yValues.values().at(i)->data(), xValues.values().at(i)->count()); - } - else - { - plot->appendData(yValues.keys().at(i), xValues.values().at(i)->data(), yValues.values().at(i)->data(), xValues.values().at(i)->count()); - } - } - plot->updateScale(); - plot->setStyleText(ui->style->currentText()); -} - -bool QGCDataPlot2D::calculateRegression() -{ - // TODO: Add support for quadratic / cubic curve fitting - return calculateRegression(ui->xRegressionComboBox->currentText(), ui->yRegressionComboBox->currentText(), "linear"); -} - -/** - * @param xName Name of the x dimension - * @param yName Name of the y dimension - * @param method Regression method, either "linear", "quadratic" or "cubic". Only linear is supported at this point - */ -bool QGCDataPlot2D::calculateRegression(QString xName, QString yName, QString method) -{ - bool result = false; - QString function; - if (xName != yName) { - if (QFileInfo(fileName).isReadable()) { - loadCsvLog(fileName, xName, yName); - ui->xRegressionComboBox->setCurrentIndex(curveNames.indexOf(xName)); - ui->yRegressionComboBox->setCurrentIndex(curveNames.indexOf(yName)); - } - - // Create a couple of arrays for us to use to temporarily store some of the data from the plot. - // These arrays are allocated on the heap as they are far too big to go in the stack and will - // cause an overflow. - // TODO: Look into if this would be better done by having a getter return const double pointers instead - // of using memcpy(). - const int size = 100000; - double *x = new double[size]; - double *y = new double[size]; - int copied = plot->data(yName, x, y, size); - - if (method == "linear") { - double a; // Y-axis crossing - double b; // Slope - double r; // Regression coefficient - if (linearRegression(x, y, copied, &a, &b, &r)) { - function = tr("%1 = %2 * %3 + %4 | R-coefficient: %5").arg(yName, QString::number(b), xName, QString::number(a), QString::number(r)); - - // Plot curve - // y-axis crossing (x = 0) - // Set plotting to lines only - plot->appendData(tr("regression %1-%2").arg(xName, yName), 0.0, a); - plot->setStyleText("lines"); - // x-value of the current rightmost x position in the plot - plot->appendData(tr("regression %1-%2").arg(xName, yName), plot->invTransform(QwtPlot::xBottom, plot->width() - plot->width()*0.08f), (a + b*plot->invTransform(QwtPlot::xBottom, plot->width() - plot->width() * 0.08f))); - - result = true; - } else { - function = tr("Linear regression failed. (Limit: %1 data points. Try with less)").arg(size); - } - } else { - function = tr("Regression method %1 not found").arg(method); - } - - delete[] x; - delete[] y; - } else { - // xName == yName - function = tr("Please select different X and Y dimensions, not %1 = %2").arg(xName, yName); - } - ui->regressionOutput->setText(function); - return result; -} - -/** - * Linear regression (least squares) for n data points. - * Computes: - * - * y = a * x + b - * - * @param x values on x axis - * @param y corresponding values on y axis - * @param n Number of values - * @param a returned slope of line - * @param b y-axis intersection - * @param r regression coefficient. The larger the coefficient is, the better is - * the match of the regression. - * @return 1 on success, 0 on failure (e.g. because of infinite slope) - */ -bool QGCDataPlot2D::linearRegression(double *x, double *y, int n, double *a, double *b, double *r) -{ - int i; - double sumx=0,sumy=0,sumx2=0,sumy2=0,sumxy=0; - double sxx,syy,sxy; - - *a = 0; - *b = 0; - *r = 0; - if (n < 2) - return true; - - /* Conpute some things we need */ - for (i=0; icopy(fileName); - - qDebug() << "Saved CSV log (" << fileName << "). Success: " << success; - - //qDebug() << "READE TO SAVE CSV LOG TO " << fileName; -} - -QGCDataPlot2D::~QGCDataPlot2D() -{ - delete ui; -} - -void QGCDataPlot2D::changeEvent(QEvent *e) -{ - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } -} diff --git a/src/ui/QGCDataPlot2D.h b/src/ui/QGCDataPlot2D.h deleted file mode 100644 index 2ff6cacab03072209f2478ec60fe5f9b247d4d6a..0000000000000000000000000000000000000000 --- a/src/ui/QGCDataPlot2D.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef QGCDATAPLOT2D_H -#define QGCDATAPLOT2D_H - -#include -#include -#include "IncrementalPlot.h" -#include "LogCompressor.h" - -namespace Ui -{ -class QGCDataPlot2D; -} - -class QGCDataPlot2D : public QWidget -{ - Q_OBJECT -public: - QGCDataPlot2D(QWidget *parent = 0); - ~QGCDataPlot2D(); - - /** @brief Calculate and display regression function*/ - bool calculateRegression(QString xName, QString yName, QString method="linear"); - - /** @brief Linear regression over data points */ - bool linearRegression(double *x, double *y, int n, double *a, double *b, double *r); - -public slots: - /** @brief Load previously selected file */ - void loadFile(); - /** @brief Load file with this name */ - void loadFile(QString file); - /** @brief Reload a file, with filtering enabled */ - void reloadFile(); - void selectFile(); - void loadCsvLog(QString file, QString xAxisName="", QString yAxisFilter=""); - void loadRawLog(QString file, QString xAxisName="", QString yAxisFilter=""); - void saveCsvLog(); - /** @brief Save plot to PDF or SVG */ - void savePlot(); - /** @brief Export PDF file */ - void exportPDF(QString fileName); - /** @brief Export SVG file */ - void exportSVG(QString file); - /** @brief Print or save PDF file (MacOS/Linux) */ - void print(); - /** @brief Calculate and display regression function*/ - bool calculateRegression(); - -signals: - void visibilityChanged(bool visible); - -protected: - void showEvent(QShowEvent* event) - { - QWidget::showEvent(event); - emit visibilityChanged(true); - } - - void hideEvent(QHideEvent* event) - { - QWidget::hideEvent(event); - emit visibilityChanged(false); - } - - void changeEvent(QEvent *e); - QString getSavePlotFilename(); - IncrementalPlot* plot; - LogCompressor* compressor; - QFile* logFile; - QString fileName; - QStringList curveNames; - -private: - Ui::QGCDataPlot2D *ui; -}; - -#endif // QGCDATAPLOT2D_H diff --git a/src/ui/QGCDataPlot2D.ui b/src/ui/QGCDataPlot2D.ui deleted file mode 100644 index dba180727019ccfa8c490b4e524f156f1e9573b2..0000000000000000000000000000000000000000 --- a/src/ui/QGCDataPlot2D.ui +++ /dev/null @@ -1,309 +0,0 @@ - - - QGCDataPlot2D - - - - 0 - 0 - 1463 - 311 - - - - Form - - - - - - X - - - - - - - - - - Y - - - - - - - - - - Set line style - - - - Only lines - - - - - Only crosses - - - - - Only circles - - - - - Only rectangles - - - - - Lines and crosses - - - - - Lines and circles - - - - - Lines and rects - - - - - Dotted lines and crosses - - - - - Dotted lines and circles - - - - - Dotted lines and rects - - - - - Dashed lines and crosses - - - - - Dashed lines and circles - - - - - Dashed lines and rects - - - - - - - - Replot - - - - - - - Qt::Vertical - - - - - - - Save Image - - - - - - - Print - - - - - - - Title - - - - - - - - - - X label - - - - - - - - - - Y label - - - - - - - - - - Symmetric - - - - - - - Legend - - - - - - - Grid - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - File - - - - - - - - CSV - - - - - pxIMU - - - - - RAW - - - - - - - - Please select input file.. - - - - - - - Select file - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - - - - Regression - - - - - - - - - - - - - Calculate - - - - - - - true - - - - - - - Save Data - - - - - - - Qt::Horizontal - - - - 5 - 20 - - - - - - - - - diff --git a/src/ui/QGCMAVLinkLogPlayer.cc b/src/ui/QGCMAVLinkLogPlayer.cc index e3242e1c3f560dc1809cba023be78027f8106fca..55f26ec585b6f1823b3af25fdc28fffb94071c9a 100644 --- a/src/ui/QGCMAVLinkLogPlayer.cc +++ b/src/ui/QGCMAVLinkLogPlayer.cc @@ -2,7 +2,7 @@ #include #include "MainWindow.h" -#ifndef __ios__ +#ifndef NO_SERIAL_LINK #include "SerialLink.h" #endif #include "QGCMAVLinkLogPlayer.h" @@ -17,7 +17,7 @@ QGCMAVLinkLogPlayer::QGCMAVLinkLogPlayer(QWidget *parent) : QWidget(parent), _replayLink(NULL), _ui(new Ui::QGCMAVLinkLogPlayer) -{ +{ _ui->setupUi(this); _ui->horizontalLayout->setAlignment(Qt::AlignTop); @@ -26,7 +26,7 @@ QGCMAVLinkLogPlayer::QGCMAVLinkLogPlayer(QWidget *parent) : connect(_ui->playButton, &QPushButton::clicked, this, &QGCMAVLinkLogPlayer::_playPauseToggle); connect(_ui->positionSlider, &QSlider::valueChanged, this, &QGCMAVLinkLogPlayer::_setPlayheadFromSlider); connect(_ui->positionSlider, &QSlider::sliderPressed, this, &QGCMAVLinkLogPlayer::_pause); - + #if 0 // Speed slider is removed from 3.0 release. Too broken to fix. connect(_ui->speedSlider, &QSlider::valueChanged, this, &QGCMAVLinkLogPlayer::_setAccelerationFromSlider); @@ -36,10 +36,10 @@ QGCMAVLinkLogPlayer::QGCMAVLinkLogPlayer(QWidget *parent) : #endif _enablePlaybackControls(false); - + _ui->positionSlider->setMinimum(0); _ui->positionSlider->setMaximum(100); - + } QGCMAVLinkLogPlayer::~QGCMAVLinkLogPlayer() @@ -68,7 +68,7 @@ void QGCMAVLinkLogPlayer::_selectLogFileForPlayback(void) QGCMessageBox::information(tr("Log Replay"), tr("You must close all connections prior to replaying a log.")); return; } - + QString logFilename = QGCFileDialog::getOpenFileName( this, tr("Load MAVLink Log File"), @@ -78,21 +78,24 @@ void QGCMAVLinkLogPlayer::_selectLogFileForPlayback(void) if (logFilename.isEmpty()) { return; } - + LinkInterface* createConnectedLink(LinkConfiguration* config); - + LogReplayLinkConfiguration* linkConfig = new LogReplayLinkConfiguration(QString("Log Replay")); linkConfig->setLogFilename(logFilename); linkConfig->setName(linkConfig->logFilenameShort()); _ui->logFileNameLabel->setText(linkConfig->logFilenameShort()); - _replayLink = (LogReplayLink*)qgcApp()->toolbox()->linkManager()->createConnectedLink(linkConfig); - + + LinkManager* linkMgr = qgcApp()->toolbox()->linkManager(); + SharedLinkConfigurationPointer sharedConfig = linkMgr->addConfiguration(linkConfig); + _replayLink = (LogReplayLink*)qgcApp()->toolbox()->linkManager()->createConnectedLink(sharedConfig); + connect(_replayLink, &LogReplayLink::logFileStats, this, &QGCMAVLinkLogPlayer::_logFileStats); connect(_replayLink, &LogReplayLink::playbackStarted, this, &QGCMAVLinkLogPlayer::_playbackStarted); connect(_replayLink, &LogReplayLink::playbackPaused, this, &QGCMAVLinkLogPlayer::_playbackPaused); connect(_replayLink, &LogReplayLink::playbackPercentCompleteChanged, this, &QGCMAVLinkLogPlayer::_playbackPercentCompleteChanged); connect(_replayLink, &LogReplayLink::disconnected, this, &QGCMAVLinkLogPlayer::_replayLinkDisconnected); - + _ui->positionSlider->setValue(0); #if 0 _ui->speedSlider->setValue(0); @@ -123,9 +126,9 @@ void QGCMAVLinkLogPlayer::_logFileStats(bool logTimestamped, ///< tru { Q_UNUSED(logTimestamped); Q_UNUSED(binaryBaudRate); - + _logDurationSeconds = logDurationSeconds; - + _ui->logStatsLabel->setText(_secondsToHMS(logDurationSeconds)); } @@ -174,9 +177,9 @@ void QGCMAVLinkLogPlayer::_setAccelerationFromSlider(int value) if (_replayLink) { _replayLink->setAccelerationFactor(value); } - + // Factor: -100: 0.01x, 0: 1.0x, 100: 100x - + float accelerationFactor; if (value < 0) { accelerationFactor = 0.01f; @@ -189,7 +192,7 @@ void QGCMAVLinkLogPlayer::_setAccelerationFromSlider(int value) } else { accelerationFactor = 1.0f; } - + _ui->speedLabel->setText(QString("Speed: %1X").arg(accelerationFactor, 5, 'f', 2, '0')); } #endif diff --git a/src/ui/XbeeConfigurationWindow.cpp b/src/ui/XbeeConfigurationWindow.cpp deleted file mode 100644 index 847ab8e93dd22c73cfcd2962f7f775015b022e5a..0000000000000000000000000000000000000000 --- a/src/ui/XbeeConfigurationWindow.cpp +++ /dev/null @@ -1,444 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -//#include -#include -#endif - -#if defined (__APPLE__) && defined (__MACH__) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __MWERKS__ -#define __CF_USE_FRAMEWORK_INCLUDES__ -#endif - - -#include - -#include -#include -#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3) -#include -#endif -#include - -// Apple internal modems default to local echo being on. If your modem has local echo disabled, -// undefine the following macro. -#define LOCAL_ECHO - -#define kATCommandString "AT\r" - -#ifdef LOCAL_ECHO -#define kOKResponseString "AT\r\r\nOK\r\n" -#else -#define kOKResponseString "\r\nOK\r\n" -#endif -#endif - - -// Some helper functions for serial port enumeration -#if defined (__APPLE__) && defined (__MACH__) - -enum { - kNumRetries = 3 -}; - -// Function prototypes -static kern_return_t FindModems(io_iterator_t *matchingServices); -static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize); - -// Returns an iterator across all known modems. Caller is responsible for -// releasing the iterator when iteration is complete. -static kern_return_t FindModems(io_iterator_t *matchingServices) -{ - kern_return_t kernResult; - CFMutableDictionaryRef classesToMatch; - - /*! @function IOServiceMatching - @abstract Create a matching dictionary that specifies an IOService class match. - @discussion A very common matching criteria for IOService is based on its class. IOServiceMatching will create a matching dictionary that specifies any IOService of a class, or its subclasses. The class is specified by C-string name. - @param name The class name, as a const C-string. Class matching is successful on IOService's of this class or any subclass. - @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */ - - // Serial devices are instances of class IOSerialBSDClient - classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); - if (classesToMatch == NULL) { - printf("IOServiceMatching returned a NULL dictionary.\n"); - } else { - /*! - @function CFDictionarySetValue - Sets the value of the key in the dictionary. - @param theDict The dictionary to which the value is to be set. If this - parameter is not a valid mutable CFDictionary, the behavior is - undefined. If the dictionary is a fixed-capacity dictionary and - it is full before this operation, and the key does not exist in - the dictionary, the behavior is undefined. - @param key The key of the value to set into the dictionary. If a key - which matches this key is already present in the dictionary, only - the value is changed ("add if absent, replace if present"). If - no key matches the given key, the key-value pair is added to the - dictionary. If added, the key is retained by the dictionary, - using the retain callback provided - when the dictionary was created. If the key is not of the sort - expected by the key retain callback, the behavior is undefined. - @param value The value to add to or replace into the dictionary. The value - is retained by the dictionary using the retain callback provided - when the dictionary was created, and the previous value if any is - released. If the value is not of the sort expected by the - retain or release callbacks, the behavior is undefined. - */ - CFDictionarySetValue(classesToMatch, - CFSTR(kIOSerialBSDTypeKey), - CFSTR(kIOSerialBSDModemType)); - - // Each serial device object has a property with key - // kIOSerialBSDTypeKey and a value that is one of kIOSerialBSDAllTypes, - // kIOSerialBSDModemType, or kIOSerialBSDRS232Type. You can experiment with the - // matching by changing the last parameter in the above call to CFDictionarySetValue. - - // As shipped, this sample is only interested in modems, - // so add this property to the CFDictionary we're matching on. - // This will find devices that advertise themselves as modems, - // such as built-in and USB modems. However, this match won't find serial modems. - } - - /*! @function IOServiceGetMatchingServices - @abstract Look up registered IOService objects that match a matching dictionary. - @discussion This is the preferred method of finding IOService objects currently registered by IOKit. IOServiceAddNotification can also supply this information and install a notification of new IOServices. The matching information used in the matching dictionary may vary depending on the class of service being looked up. - @param masterPort The master port obtained from IOMasterPort(). - @param matching A CF dictionary containing matching information, of which one reference is consumed by this function. IOKitLib can contruct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOOpenFirmwarePathMatching. - @param existing An iterator handle is returned on success, and should be released by the caller when the iteration is finished. - @result A kern_return_t error code. */ - - kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices); - if (KERN_SUCCESS != kernResult) { - printf("IOServiceGetMatchingServices returned %d\n", kernResult); - goto exit; - } - -exit: - return kernResult; -} - -/** Given an iterator across a set of modems, return the BSD path to the first one. - * If no modems are found the path name is set to an empty string. - */ -static kern_return_t GetModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize) -{ - io_object_t modemService; - kern_return_t kernResult = KERN_FAILURE; - Boolean modemFound = false; - - // Initialize the returned path - *bsdPath = '\0'; - - // Iterate across all modems found. In this example, we bail after finding the first modem. - - while ((modemService = IOIteratorNext(serialPortIterator)) && !modemFound) { - CFTypeRef bsdPathAsCFString; - - // Get the callout device's path (/dev/cu.xxxxx). The callout device should almost always be - // used: the dialin device (/dev/tty.xxxxx) would be used when monitoring a serial port for - // incoming calls, e.g. a fax listener. - - bsdPathAsCFString = IORegistryEntryCreateCFProperty(modemService, - CFSTR(kIOCalloutDeviceKey), - kCFAllocatorDefault, - 0); - if (bsdPathAsCFString) { - Boolean result; - - // Convert the path from a CFString to a C (NUL-terminated) string for use - // with the POSIX open() call. - - result = CFStringGetCString((CFStringRef)bsdPathAsCFString, - bsdPath, - maxPathSize, - kCFStringEncodingUTF8); - CFRelease(bsdPathAsCFString); - - if (result) { - //printf("Modem found with BSD path: %s", bsdPath); - modemFound = true; - kernResult = KERN_SUCCESS; - } - } - - printf("\n"); - - // Release the io_service_t now that we are done with it. - - (void) IOObjectRelease(modemService); - } - - return kernResult; -} -#endif - -XbeeConfigurationWindow::XbeeConfigurationWindow(LinkInterface* link, QWidget *parent, Qt::WindowFlags flags): QWidget(parent, flags), - userConfigured(false) -{ - XbeeLinkInterface *xbeeLink = dynamic_cast(link); - - if(xbeeLink != 0) - { - this->link = xbeeLink; - - baudLabel = new QLabel; - baudLabel->setText(tr("Baut Rate")); - baudBox = new QComboBox; - baudLabel->setBuddy(baudBox); - portLabel = new QLabel; - portLabel->setText(tr("SerialPort")); - portBox = new QComboBox; - portBox->setEditable(true); - portLabel->setBuddy(portBox); - highAddrLabel = new QLabel; - highAddrLabel->setText(tr("Remote hex Address &High")); - highAddr = new HexSpinBox(this); - highAddrLabel->setBuddy(highAddr); - lowAddrLabel = new QLabel; - lowAddrLabel->setText(tr("Remote hex Address &Low")); - lowAddr = new HexSpinBox(this); - lowAddrLabel->setBuddy(lowAddr); - actionLayout = new QGridLayout; - actionLayout->addWidget(baudLabel,1,1); - actionLayout->addWidget(baudBox,1,2); - actionLayout->addWidget(portLabel,2,1); - actionLayout->addWidget(portBox,2,2); - actionLayout->addWidget(highAddrLabel,3,1); - actionLayout->addWidget(highAddr,3,2); - actionLayout->addWidget(lowAddrLabel,4,1); - actionLayout->addWidget(lowAddr,4,2); - tmpLayout = new QVBoxLayout; - tmpLayout->addStretch(); - tmpLayout->addLayout(actionLayout); - xbeeLayout = new QHBoxLayout; - xbeeLayout->addStretch(); - xbeeLayout->addLayout(tmpLayout); - this->setLayout(xbeeLayout); - - //connect(portBox,SIGNAL(activated(QString)),this,SLOT(setPortName(QString))); - //connect(baudBox,SIGNAL(activated(QString)),this,SLOT(setBaudRateString(QString))); - connect(portBox,SIGNAL(currentIndexChanged(QString)),this,SLOT(setPortName(QString))); - connect(portBox,SIGNAL(editTextChanged(QString)),this,SLOT(setPortName(QString))); - connect(baudBox,SIGNAL(currentIndexChanged(QString)),this,SLOT(setBaudRateString(QString))); - connect(highAddr,SIGNAL(valueChanged(int)),this,SLOT(addrChangedHigh(int))); - connect(lowAddr,SIGNAL(valueChanged(int)),this,SLOT(addrChangedLow(int))); - connect(this,SIGNAL(addrHighChanged(quint32)),xbeeLink,SLOT(setRemoteAddressHigh(quint32))); - connect(this,SIGNAL(addrLowChanged(quint32)),xbeeLink,SLOT(setRemoteAddressLow(quint32))); - - baudBox->addItem("1200",1200); - baudBox->addItem("2400",2400); - baudBox->addItem("4800",4800); - baudBox->addItem("9600",9600); - baudBox->addItem("19200",19200); - baudBox->addItem("38400",38400); - baudBox->addItem("57600",57600); - baudBox->setCurrentIndex(6); - - // try to open xbeeConf file for last remote address - QFile in("Xbeeconf.txt"); - if(in.open(QIODevice::ReadOnly)) - { - QDataStream inStr(&in); - int tmpaddrHigh; - int tmpaddrLow; - inStr >> tmpaddrHigh; - inStr >> tmpaddrLow; - highAddr->setValue(tmpaddrHigh); - lowAddr->setValue(tmpaddrLow); - } - else - { - highAddr->setValue(0x13A200); - lowAddr->setValue(0x40DDDDDD); - } - - - - this->setupPortList(); - - portCheckTimer = new QTimer(this); - portCheckTimer->setInterval(1000); - connect(portCheckTimer, SIGNAL(timeout()), this, SLOT(setupPortList())); - - // Display the widget - this->window()->setWindowTitle(tr("Xbee Communication Settings")); - } - else - { - qDebug() << "This is not a Xbee Link"; - } -} - -XbeeConfigurationWindow::~XbeeConfigurationWindow() -{ - -} - -void XbeeConfigurationWindow::setupPortList() -{ - #ifdef __linux - - // TODO Linux has no standard way of enumerating serial ports - // However the device files are only present when the physical - // device is connected, therefore listing the files should be - // sufficient. - - QString devdir = "/dev"; - QDir dir(devdir); - dir.setFilter(QDir::System); - - QFileInfoList list = dir.entryInfoList(); - for (int i = 0; i < list.size(); ++i) { - QFileInfo fileInfo = list.at(i); - if (fileInfo.fileName().contains(QString("ttyUSB")) || fileInfo.fileName().contains(QString("ttyS"))) { - if (portBox->findText(fileInfo.canonicalFilePath()) == -1) { - portBox->addItem(fileInfo.canonicalFilePath()); - if (!userConfigured) portBox->setEditText(fileInfo.canonicalFilePath()); - } - } - } -#endif - -#if defined (__APPLE__) && defined (__MACH__) - - // Enumerate serial ports - //int fileDescriptor; - kern_return_t kernResult; // on PowerPC this is an int (4 bytes) - - io_iterator_t serialPortIterator; - char bsdPath[MAXPATHLEN]; - - kernResult = FindModems(&serialPortIterator); - - kernResult = GetModemPath(serialPortIterator, bsdPath, sizeof(bsdPath)); - - IOObjectRelease(serialPortIterator); // Release the iterator. - - // Add found modems - if (bsdPath[0]) { - if (portBox->findText(QString(bsdPath)) == -1) { - portBox->addItem(QString(bsdPath)); - if (!userConfigured) portBox->setEditText(QString(bsdPath)); - } - } - - // Add USB serial port adapters - // TODO Strangely usb serial port adapters are not enumerated, even when connected - QString devdir = "/dev"; - QDir dir(devdir); - dir.setFilter(QDir::System); - - QFileInfoList list = dir.entryInfoList(); - for (int i = list.size() - 1; i >= 0; i--) { - QFileInfo fileInfo = list.at(i); - if (fileInfo.fileName().contains(QString("ttyUSB")) || fileInfo.fileName().contains(QString("ttyS")) || fileInfo.fileName().contains(QString("tty.usbserial"))) { - if (portBox->findText(fileInfo.canonicalFilePath()) == -1) { - portBox->addItem(fileInfo.canonicalFilePath()); - if (!userConfigured) portBox->setEditText(fileInfo.canonicalFilePath()); - } - } - } - - -#endif - -#ifdef _WIN32 - // Get the ports available on this system - QList ports = QSerialPortInfo::availablePorts(); - //QList ports = QextSerialEnumerator::getPorts(); - - // Add the ports in reverse order, because we prepend them to the list - for (int i = ports.size() - 1; i >= 0; i--) { - QString portString = QString(ports.at(i).portName().toLocal8Bit().constData()); - // Prepend newly found port to the list - if (portBox->findText(portString) == -1) { - portBox->insertItem(0, portString); - if (!userConfigured) portBox->setEditText(portString); - } - } - - //printf("port name: %s\n", ports.at(i).portName.toLocal8Bit().constData()); - //printf("friendly name: %s\n", ports.at(i).friendName.toLocal8Bit().constData()); - //printf("physical name: %s\n", ports.at(i).physName.toLocal8Bit().constData()); - //printf("enumerator name: %s\n", ports.at(i).enumName.toLocal8Bit().constData()); - //printf("===================================\n\n"); -#endif -} - -void XbeeConfigurationWindow::showEvent(QShowEvent* event) -{ - Q_UNUSED(event); - portCheckTimer->start(); -} - -void XbeeConfigurationWindow::hideEvent(QHideEvent* event) -{ - Q_UNUSED(event); - portCheckTimer->stop(); -} - -void XbeeConfigurationWindow::configureCommunication() -{ - this->setupPortList(); - this->show(); -} - -void XbeeConfigurationWindow::setPortName(QString port) -{ - link->setPortName(port); -} - -void XbeeConfigurationWindow::setBaudRateString(QString baud) -{ - int rate = baud.toInt(); - this->link->setBaudRate(rate); -} - -void XbeeConfigurationWindow::addrChangedHigh(int addr) -{ - quint32 uaddr = static_cast(addr); - QFile out("Xbeeconf.txt"); - if(out.open(QIODevice::WriteOnly)) - { - QDataStream outStr(&out); - outStr << this->highAddr->value(); - outStr << this->lowAddr->value(); - } - emit addrHighChanged(uaddr); -} - -void XbeeConfigurationWindow::addrChangedLow(int addr) -{ - quint32 uaddr = static_cast(addr); - QFile out("Xbeeconf.txt"); - if(out.open(QIODevice::WriteOnly)) - { - QDataStream outStr(&out); - outStr << this->highAddr->value(); - outStr << this->lowAddr->value(); - } - emit addrLowChanged(uaddr); -} diff --git a/src/ui/XbeeConfigurationWindow.h b/src/ui/XbeeConfigurationWindow.h deleted file mode 100644 index 1a6f233fd03c3fd292590f0cb413360e672a15d8..0000000000000000000000000000000000000000 --- a/src/ui/XbeeConfigurationWindow.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _XBEECONFIGURATIONWINDOW_H_ -#define _XBEECONFIGURATIONWINDOW_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include"XbeeLinkInterface.h" -#include "HexSpinBox.h" - - -class XbeeConfigurationWindow : public QWidget -{ - Q_OBJECT - -public: - XbeeConfigurationWindow(LinkInterface* link, QWidget *parent = 0, Qt::WindowFlags flags = Qt::Sheet); - ~XbeeConfigurationWindow(); - -public slots: - void configureCommunication(); - void setPortName(QString port); - void setBaudRateString(QString baud); - void setupPortList(); - -private slots: - void addrChangedHigh(int addr); - void addrChangedLow(int addr); - -protected: - void showEvent(QShowEvent* event); - void hideEvent(QHideEvent* event); - bool userConfigured; ///< Switch to detect if current values are user-selected and shouldn't be overriden - -private: - QLabel *portLabel; - QLabel *baudLabel; - QComboBox *portBox; - QComboBox *baudBox; - QGridLayout *actionLayout; - QHBoxLayout *xbeeLayout; - QVBoxLayout *tmpLayout; - XbeeLinkInterface* link; - QTimer* portCheckTimer; - HexSpinBox* highAddr; - HexSpinBox* lowAddr; - QLabel* highAddrLabel; - QLabel* lowAddrLabel; - -signals: - void addrHighChanged(quint32 addrHigh); - void addrLowChanged(quint32 addrLow); -}; - - -#endif //_XBEECONFIGURATIONWINDOW_H_ diff --git a/src/ui/linechart/ChartPlot.cc b/src/ui/linechart/ChartPlot.cc index 61f1de095beca1fd9520887d04c37d9e2ee32520..574be4c639dd9e0376e1e506d746e4df358dd457 100644 --- a/src/ui/linechart/ChartPlot.cc +++ b/src/ui/linechart/ChartPlot.cc @@ -1,81 +1,74 @@ #include "ChartPlot.h" #include "QGCApplication.h" +#include "SettingsManager.h" const QColor ChartPlot::baseColors[numColors] = { - QColor(242,255,128), - QColor(70,80,242), - QColor(232,33,47), - QColor(116,251,110), - QColor(81,183,244), - QColor(234,38,107), - QColor(92,247,217), - QColor(151,59,239), - QColor(231,72,28), - QColor(236,48,221), - QColor(75,133,243), - QColor(203,254,121), - QColor(104,64,240), - QColor(200,54,238), - QColor(104,250,138), - QColor(235,43,165), - QColor(98,248,176), - QColor(161,252,116), - QColor(87,231,246), - QColor(230,126,23) + QColor(242, 255, 128), + QColor(70, 80, 242), + QColor(232, 33, 47), + QColor(116, 251, 110), + QColor(81, 183, 244), + QColor(234, 38, 107), + QColor(92, 247, 217), + QColor(151, 59, 239), + QColor(231, 72, 28), + QColor(236, 48, 221), + QColor(75, 133, 243), + QColor(203, 254, 121), + QColor(104, 64, 240), + QColor(200, 54, 238), + QColor(104, 250, 138), + QColor(235, 43, 165), + QColor(98, 248, 176), + QColor(161, 252, 116), + QColor(87, 231, 246), + QColor(230, 126, 23) }; -ChartPlot::ChartPlot(QWidget *parent): +ChartPlot::ChartPlot(QWidget* parent): QwtPlot(parent), - nextColorIndex(0), - symbolWidth(2.0f), - curveWidth(2.0f), - gridWidth(0.8f) + _nextColorIndex(0), + _symbolWidth(2.0f), + _curveWidth(2.0f), + _gridWidth(0.8f) { // Initialize the list of curves. - curves = QMap(); - + _curves = QMap(); // Set the grid. The colorscheme was already set in generateColorScheme(). - grid = new QwtPlotGrid; - grid->enableXMin(true); - grid->attach(this); - - colors = QList(); - + _grid = new QwtPlotGrid; + _grid->enableXMin(true); + _grid->attach(this); + _colors = QList(); ///> Color map for plots, includes 20 colors ///> Map will start from beginning when the first 20 colors are exceeded - for (int i = 0; i < numColors; ++i) - { - colors.append(baseColors[i]); + for(int i = 0; i < numColors; ++i) { + _colors.append(baseColors[i]); } - // Now that all objects have been initialized, color everything. - styleChanged(qgcApp()->styleIsDark()); + styleChanged(qgcApp()->toolbox()->settingsManager()->appSettings()->indoorPalette()->rawValue().toBool()); } ChartPlot::~ChartPlot() { - } QColor ChartPlot::getNextColor() { - if(nextColorIndex >= colors.count()) - { - nextColorIndex = 0; + if(_nextColorIndex >= _colors.count()) { + _nextColorIndex = 0; } - return colors[nextColorIndex++]; + return _colors[_nextColorIndex++]; } -QColor ChartPlot::getColorForCurve(const QString &id) +QColor ChartPlot::getColorForCurve(const QString& id) { - return curves.value(id)->pen().color(); + return _curves.value(id)->pen().color(); } void ChartPlot::shuffleColors() { - foreach (QwtPlotCurve* curve, curves) - { - if (curve->isVisible()) { + foreach(QwtPlotCurve* curve, _curves) { + if(curve->isVisible()) { QPen pen(curve->pen()); pen.setColor(getNextColor()); curve->setPen(pen); @@ -86,32 +79,24 @@ void ChartPlot::shuffleColors() void ChartPlot::styleChanged(bool styleIsDark) { // Generate a new color list for curves and recolor them. - for (int i = 0; i < numColors; ++i) - { - colors[i] = styleIsDark ? baseColors[i].lighter(150) : baseColors[i].darker(150); + for(int i = 0; i < numColors; ++i) { + _colors[i] = styleIsDark ? baseColors[i].lighter(150) : baseColors[i].darker(150); } shuffleColors(); - // Configure the rest of the UI colors based on the current theme. - if (styleIsDark) - { + if(styleIsDark) { // Set canvas background setCanvasBackground(QColor(0, 0, 0)); - // Configure the plot grid. - grid->setMinorPen(QPen(QColor(0xAA, 0xAA, 0xAA), gridWidth, Qt::DotLine)); - grid->setMajorPen(QPen(QColor(0xDD, 0xDD, 0xDD), gridWidth, Qt::DotLine)); - } - else - { + _grid->setMinorPen(QPen(QColor(64, 64, 64), _gridWidth, Qt::SolidLine)); + _grid->setMajorPen(QPen(QColor(96, 96, 96), _gridWidth, Qt::SolidLine)); + } else { // Set canvas background setCanvasBackground(QColor(0xFF, 0xFF, 0xFF)); - // Configure the plot grid. - grid->setMinorPen(QPen(QColor(0x55, 0x55, 0x55), gridWidth, Qt::DotLine)); - grid->setMajorPen(QPen(QColor(0x22, 0x22, 0x22), gridWidth, Qt::DotLine)); + _grid->setMinorPen(QPen(QColor(192, 192, 192), _gridWidth, Qt::SolidLine)); + _grid->setMajorPen(QPen(QColor(128, 128, 128), _gridWidth, Qt::SolidLine)); } - // And finally refresh the widget to make sure all color changes are redrawn. replot(); } diff --git a/src/ui/linechart/ChartPlot.h b/src/ui/linechart/ChartPlot.h index acbb85a46b9199513a309fe59226231b33ec6302..1a6a5b52a3ee90a515995bf91e96e51c6903391a 100644 --- a/src/ui/linechart/ChartPlot.h +++ b/src/ui/linechart/ChartPlot.h @@ -31,14 +31,15 @@ public slots: protected: const static int numColors = 20; const static QColor baseColors[numColors]; - QList colors; ///< Colormap for curves - int nextColorIndex; ///< Next index in color map - QMap curves; ///< Plot curves - QwtPlotGrid* grid; ///< Plot grid - - float symbolWidth; ///< Width of curve symbols in pixels - float curveWidth; ///< Width of curve lines in pixels - float gridWidth; ///< Width of gridlines in pixels + + QList _colors; ///< Colormap for curves + int _nextColorIndex; ///< Next index in color map + QMap _curves; ///< Plot curves + QwtPlotGrid* _grid; ///< Plot grid + + float _symbolWidth; ///< Width of curve symbols in pixels + float _curveWidth; ///< Width of curve lines in pixels + float _gridWidth; ///< Width of gridlines in pixels }; #endif // CHARTPLOT_H diff --git a/src/ui/linechart/IncrementalPlot.cc b/src/ui/linechart/IncrementalPlot.cc index ff594e27cd688f64b783a2c1e2a1c92d9d232b53..11f336e6a1a8336a6a966867f5248dabd503e77c 100644 --- a/src/ui/linechart/IncrementalPlot.cc +++ b/src/ui/linechart/IncrementalPlot.cc @@ -143,7 +143,7 @@ void IncrementalPlot::showLegend(bool show) void IncrementalPlot::setStyleText(const QString &style) { styleText = style.toLower(); - foreach (QwtPlotCurve* curve, curves) { + foreach (QwtPlotCurve* curve, _curves) { updateStyle(curve); } replot(); @@ -161,24 +161,24 @@ void IncrementalPlot::updateStyle(QwtPlotCurve *curve) // Update the symbol style QwtSymbol *newSymbol = NULL; if (styleText.contains("circles")) { - newSymbol = new QwtSymbol(QwtSymbol::Ellipse, Qt::NoBrush, QPen(oldColor, symbolWidth), QSize(6, 6)); + newSymbol = new QwtSymbol(QwtSymbol::Ellipse, Qt::NoBrush, QPen(oldColor, _symbolWidth), QSize(6, 6)); } else if (styleText.contains("crosses")) { - newSymbol = new QwtSymbol(QwtSymbol::XCross, Qt::NoBrush, QPen(oldColor, symbolWidth), QSize(5, 5)); + newSymbol = new QwtSymbol(QwtSymbol::XCross, Qt::NoBrush, QPen(oldColor, _symbolWidth), QSize(5, 5)); } else if (styleText.contains("rect")) { - newSymbol = new QwtSymbol(QwtSymbol::Rect, Qt::NoBrush, QPen(oldColor, symbolWidth), QSize(6, 6)); + newSymbol = new QwtSymbol(QwtSymbol::Rect, Qt::NoBrush, QPen(oldColor, _symbolWidth), QSize(6, 6)); } // Else-case already handled by NULL value, which indicates no symbol curve->setSymbol(newSymbol); // Update the line style if (styleText.contains("dotted")) { - curve->setPen(QPen(oldColor, curveWidth, Qt::DotLine)); + curve->setPen(QPen(oldColor, _curveWidth, Qt::DotLine)); } else if (styleText.contains("dashed")) { - curve->setPen(QPen(oldColor, curveWidth, Qt::DashLine)); + curve->setPen(QPen(oldColor, _curveWidth, Qt::DashLine)); } else if (styleText.contains("line") || styleText.contains("solid")) { - curve->setPen(QPen(oldColor, curveWidth, Qt::SolidLine)); + curve->setPen(QPen(oldColor, _curveWidth, Qt::SolidLine)); } else { - curve->setPen(QPen(oldColor, curveWidth, Qt::NoPen)); + curve->setPen(QPen(oldColor, _curveWidth, Qt::NoPen)); } curve->setStyle(QwtPlotCurve::Lines); } @@ -260,22 +260,22 @@ void IncrementalPlot::appendData(const QString &key, double *x, double *y, int s } // If this is a new curve, create it. - if (!curves.contains(key)) { + if (!_curves.contains(key)) { curve = new QwtPlotCurve(key); - curves.insert(key, curve); + _curves.insert(key, curve); curve->setStyle(QwtPlotCurve::NoCurve); curve->setPaintAttribute(QwtPlotCurve::FilterPoints); // Set the color. Only the pen needs to be set const QColor &c = getNextColor(); - curve->setPen(c, symbolWidth); + curve->setPen(c, _symbolWidth); qDebug() << "Creating curve" << key << "with color" << c; updateStyle(curve); curve->attach(this); } else { - curve = curves.value(key); + curve = _curves.value(key); } data->append(x, y, size); @@ -359,21 +359,21 @@ int IncrementalPlot::data(const QString &key, double* r_x, double* r_y, int maxS */ void IncrementalPlot::showGrid(bool show) { - grid->setVisible(show); + _grid->setVisible(show); replot(); } bool IncrementalPlot::gridEnabled() const { - return grid->isVisible(); + return _grid->isVisible(); } void IncrementalPlot::removeData() { - foreach (QwtPlotCurve* curve, curves) { + foreach (QwtPlotCurve* curve, _curves) { delete curve; } - curves.clear(); + _curves.clear(); foreach (CurveData* data, d_data) { delete data; diff --git a/src/ui/linechart/LinechartPlot.cc b/src/ui/linechart/LinechartPlot.cc index dc6b84f96f0c5b4beb883f2a62c833e60d81d9de..61d14b870fa9f3ecf36607efe7b3621430b81040 100644 --- a/src/ui/linechart/LinechartPlot.cc +++ b/src/ui/linechart/LinechartPlot.cc @@ -190,7 +190,7 @@ void LinechartPlot::removeTimedOutCurves() { // Remove this curve // Delete curves - QwtPlotCurve* curve = curves.take(key); + QwtPlotCurve* curve = _curves.take(key); // Delete the object delete curve; // Set the pointer null @@ -276,7 +276,7 @@ void LinechartPlot::appendData(QString dataname, quint64 ms, double value) valueInterval = maxValue - minValue; // Assign dataset to curve - QwtPlotCurve* curve = curves.value(dataname); + QwtPlotCurve* curve = _curves.value(dataname); curve->setRawSamples(dataset->getPlotX(), dataset->getPlotY(), dataset->getPlotCount()); // qDebug() << "mintime" << minTime << "maxtime" << maxTime << "last max time" << "window position" << getWindowPosition(); @@ -321,7 +321,7 @@ void LinechartPlot::addCurve(QString id) // Create new curve and set style QwtPlotCurve* curve = new QwtPlotCurve(id); // Add curve to list - curves.insert(id, curve); + _curves.insert(id, curve); curve->setStyle(QwtPlotCurve::Lines); curve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); @@ -414,15 +414,15 @@ void LinechartPlot::setScaling(int scaling) **/ void LinechartPlot::setVisibleById(QString id, bool visible) { - if(curves.contains(id)) { - curves.value(id)->setVisible(visible); + if(_curves.contains(id)) { + _curves.value(id)->setVisible(visible); if(visible) { - curves.value(id)->attach(this); + _curves.value(id)->attach(this); } else { - curves.value(id)->detach(); + _curves.value(id)->detach(); } } } @@ -467,9 +467,9 @@ void LinechartPlot::showCurve(QString id) **/ void LinechartPlot::setCurveColor(QString id, QColor color) { - QwtPlotCurve* curve = curves.value(id); + QwtPlotCurve* curve = _curves.value(id); // Change the color of the curve. - curve->setPen(QPen(QBrush(color), curveWidth)); + curve->setPen(QPen(QBrush(color), _curveWidth)); //qDebug() << "Setting curve" << id << "to" << color; @@ -477,7 +477,7 @@ void LinechartPlot::setCurveColor(QString id, QColor color) const QwtSymbol *oldSymbol = curve->symbol(); QwtSymbol *newSymbol = NULL; if (oldSymbol) { - newSymbol = new QwtSymbol(oldSymbol->style(), QBrush(color), QPen(color, symbolWidth), QSize(symbolWidth, symbolWidth)); + newSymbol = new QwtSymbol(oldSymbol->style(), QBrush(color), QPen(color, _symbolWidth), QSize(_symbolWidth, _symbolWidth)); } curve->setSymbol(newSymbol); } @@ -490,7 +490,7 @@ void LinechartPlot::setCurveColor(QString id, QColor color) **/ bool LinechartPlot::isVisible(QString id) { - return curves.value(id)->isVisible(); + return _curves.value(id)->isVisible(); } /** @@ -499,9 +499,9 @@ bool LinechartPlot::isVisible(QString id) bool LinechartPlot::anyCurveVisible() { bool visible = false; - foreach (const QString &key, curves.keys()) + foreach (const QString &key, _curves.keys()) { - if (curves.value(key)->isVisible()) + if (_curves.value(key)->isVisible()) { visible = true; } @@ -530,7 +530,7 @@ void LinechartPlot::setAutoScroll(bool active) **/ QList LinechartPlot::getCurves() { - return curves.values(); + return _curves.values(); } /** @@ -702,10 +702,10 @@ void LinechartPlot::removeAllData() datalock.lock(); // Delete curves QMap::iterator i; - for(i = curves.begin(); i != curves.end(); ++i) + for(i = _curves.begin(); i != _curves.end(); ++i) { // Remove from curve list - QwtPlotCurve* curve = curves.take(i.key()); + QwtPlotCurve* curve = _curves.take(i.key()); // Delete the object delete curve; // Set the pointer null diff --git a/src/ui/linechart/LinechartWidget.cc b/src/ui/linechart/LinechartWidget.cc index ba6ca0414cc0136a241b15d52e9193cc6d650082..f0d1a3a3b7e4721653f72b9ce810d5817da4f149 100644 --- a/src/ui/linechart/LinechartWidget.cc +++ b/src/ui/linechart/LinechartWidget.cc @@ -40,6 +40,7 @@ #include "QGCFileDialog.h" #include "QGCMessageBox.h" #include "QGCApplication.h" +#include "SettingsManager.h" LinechartWidget::LinechartWidget(int systemid, QWidget *parent) : QWidget(parent), sysid(systemid), @@ -52,7 +53,6 @@ LinechartWidget::LinechartWidget(int systemid, QWidget *parent) : QWidget(parent curveMeans(new QMap()), curveMedians(new QMap()), curveVariances(new QMap()), - curveMenu(new QMenu(this)), logFile(new QFile()), logindex(1), logging(false), @@ -63,34 +63,28 @@ LinechartWidget::LinechartWidget(int systemid, QWidget *parent) : QWidget(parent { // Add elements defined in Qt Designer ui.setupUi(this); - this->setMinimumSize(200, 150); + this->setMinimumSize(600, 400); // Add and customize curve list elements (left side) curvesWidget = new QWidget(ui.curveListWidget); ui.curveListWidget->setWidget(curvesWidget); curvesWidgetLayout = new QGridLayout(curvesWidget); - curvesWidgetLayout->setMargin(2); - curvesWidgetLayout->setSpacing(4); - //curvesWidgetLayout->setSizeConstraint(QSizePolicy::Expanding); + curvesWidgetLayout->setMargin(6); + curvesWidgetLayout->setSpacing(6); curvesWidgetLayout->setAlignment(Qt::AlignTop); + curvesWidgetLayout->setColumnMinimumWidth(0, 10); curvesWidgetLayout->setColumnStretch(0, 0); - curvesWidgetLayout->setColumnStretch(1, 0); + curvesWidgetLayout->setColumnStretch(1, 10); curvesWidgetLayout->setColumnStretch(2, 80); curvesWidgetLayout->setColumnStretch(3, 50); curvesWidgetLayout->setColumnStretch(4, 50); curvesWidgetLayout->setColumnStretch(5, 50); -// horizontalLayout->setColumnStretch(median, 50); curvesWidgetLayout->setColumnStretch(6, 50); curvesWidget->setLayout(curvesWidgetLayout); // Create curve list headings - QLabel* label; - QLabel* value; - QLabel* mean; - QLabel* variance; - connect(ui.recolorButton, &QPushButton::clicked, this, &LinechartWidget::recolor); connect(ui.shortNameCheckBox, &QCheckBox::clicked, this, &LinechartWidget::setShortNames); connect(ui.plotFilterLineEdit, &QLineEdit::textChanged, this, &LinechartWidget::filterCurves); @@ -100,43 +94,38 @@ LinechartWidget::LinechartWidget(int systemid, QWidget *parent) : QWidget(parent int labelRow = curvesWidgetLayout->rowCount(); - selectAllCheckBox = new QCheckBox("", this); + selectAllCheckBox = new QCheckBox(this); connect(selectAllCheckBox, &QCheckBox::clicked, this, &LinechartWidget::selectAllCurves); - curvesWidgetLayout->addWidget(selectAllCheckBox, labelRow, 0, 1, 2); + curvesWidgetLayout->addWidget(selectAllCheckBox, labelRow, 0); - label = new QLabel(this); - label->setText("Name"); - curvesWidgetLayout->addWidget(label, labelRow, 2); + QWidget* colorIcon = new QWidget(this); + colorIcon->setMinimumSize(QSize(5, 14)); + colorIcon->setMaximumSize(QSize(5, 14)); + curvesWidgetLayout->addWidget(colorIcon, labelRow, 1); - // Value - value = new QLabel(this); - value->setText("Val"); - curvesWidgetLayout->addWidget(value, labelRow, 3); + curvesWidgetLayout->addWidget(new QLabel(tr("Name")), labelRow, 2); + curvesWidgetLayout->addWidget(new QLabel(tr("Val")), labelRow, 3, Qt::AlignRight); - // Unit - //curvesWidgetLayout->addWidget(new QLabel(tr("Unit")), labelRow, 4); + QLabel* pUnit = new QLabel(tr("Unit")); + curvesWidgetLayout->addWidget(pUnit, labelRow, 4); - // Mean - mean = new QLabel(this); - mean->setText("Mean"); - curvesWidgetLayout->addWidget(mean, labelRow, 5); + curvesWidgetLayout->addWidget(new QLabel(tr("Mean")), labelRow, 5, Qt::AlignRight); + curvesWidgetLayout->addWidget(new QLabel(tr("Variance")), labelRow, 6, Qt::AlignRight); - // Variance - variance = new QLabel(this); - variance->setText("Variance"); - curvesWidgetLayout->addWidget(variance, labelRow, 6); // Create the layout createLayout(); // And make sure we're listening for future style changes - connect(qgcApp(), &QGCApplication::styleChanged, this, &LinechartWidget::recolor); + connect(qgcApp()->toolbox()->settingsManager()->appSettings()->indoorPalette(), &Fact::rawValueChanged, this, &LinechartWidget::recolor); updateTimer->setInterval(updateInterval); connect(updateTimer, &QTimer::timeout, this, &LinechartWidget::refresh); - connect(ui.uasSelectionBox, static_cast(&QComboBox::currentIndexChanged), - this, &LinechartWidget::selectActiveSystem); + connect(ui.uasSelectionBox, static_cast(&QComboBox::currentIndexChanged), this, &LinechartWidget::selectActiveSystem); + readSettings(); + pUnit->setVisible(ui.showUnitsCheckBox->isChecked()); + connect(ui.showUnitsCheckBox, &QCheckBox::clicked, pUnit, &QLabel::setVisible); } LinechartWidget::~LinechartWidget() @@ -320,24 +309,25 @@ void LinechartWidget::appendData(int uasId, const QString& curve, const QString& if(!ok || type == QMetaType::QByteArray || type == QMetaType::QString) return; bool isDouble = type == QMetaType::Float || type == QMetaType::Double; + QString curveID = curve + unit; if ((selectedMAV == -1 && isVisible()) || (selectedMAV == uasId && isVisible())) { // Order matters here, first append to plot, then update curve list - activePlot->appendData(curve+unit, usec, value); + activePlot->appendData(curveID, usec, value); // Store data - QLabel* label = curveLabels->value(curve+unit, NULL); + QLabel* label = curveLabels->value(curveID, NULL); // Make sure the curve will be created if it does not yet exist if(!label) { if(!isDouble) - intData.insert(curve+unit, 0); + intData.insert(curveID, 0); addCurve(curve, unit); } // Add int data if(!isDouble) - intData.insert(curve+unit, variant.toInt()); + intData.insert(curveID, variant.toInt()); } if (lastTimestamp == 0 && usec != 0) @@ -360,7 +350,7 @@ void LinechartWidget::appendData(int uasId, const QString& curve, const QString& // Log data if (logging) { - if (activePlot->isVisible(curve+unit)) + if (activePlot->isVisible(curveID)) { if (usec == 0) usec = QGC::groundTimeMilliseconds(); if (logStartTime == 0) logStartTime = usec; @@ -514,67 +504,59 @@ void LinechartWidget::createActions() void LinechartWidget::addCurve(const QString& curve, const QString& unit) { LinechartPlot* plot = activePlot; -// QHBoxLayout *horizontalLayout; - QCheckBox *checkBox; - QLabel* label; - QLabel* value; - QLabel* unitLabel; - QLabel* mean; - QLabel* variance; - - curveNames.insert(curve+unit, curve); - + QString curveID = curve + unit; + curveNames.insert(curveID, curve); int labelRow = curvesWidgetLayout->rowCount(); // Checkbox - checkBox = new QCheckBox(this); + QCheckBox* checkBox = new QCheckBox(this); checkBox->setCheckable(true); - checkBox->setObjectName(curve+unit); + checkBox->setObjectName(curveID); checkBox->setToolTip(tr("Enable the curve in the graph window")); checkBox->setWhatsThis(tr("Enable the curve in the graph window")); - checkBoxes.insert(curve+unit, checkBox); + checkBoxes.insert(curveID, checkBox); curvesWidgetLayout->addWidget(checkBox, labelRow, 0); // Icon QWidget* colorIcon = new QWidget(this); - colorIcons.insert(curve+unit, colorIcon); + colorIcons.insert(curveID, colorIcon); colorIcon->setMinimumSize(QSize(5, 14)); - colorIcon->setMaximumSize(4, 14); + colorIcon->setMaximumSize(QSize(5, 14)); curvesWidgetLayout->addWidget(colorIcon, labelRow, 1); // Label - label = new QLabel(this); - label->setText(getCurveName(curve+unit, ui.shortNameCheckBox->isChecked())); - curveNameLabels.insert(curve+unit, label); + QLabel* label = new QLabel(this); + label->setText(getCurveName(curveID, ui.shortNameCheckBox->isChecked())); + curveNameLabels.insert(curveID, label); curvesWidgetLayout->addWidget(label, labelRow, 2); // Value - value = new QLabel(this); + QLabel* value = new QLabel(this); value->setNum(0.00); value->setStyleSheet(QString("QLabel {font-family:\"Courier\"; font-weight: bold;}")); value->setToolTip(tr("Current value of %1 in %2 units").arg(curve, unit)); value->setWhatsThis(tr("Current value of %1 in %2 units").arg(curve, unit)); - curveLabels->insert(curve+unit, value); - curvesWidgetLayout->addWidget(value, labelRow, 3); + curveLabels->insert(curveID, value); + curvesWidgetLayout->addWidget(value, labelRow, 3, Qt::AlignRight); // Unit - unitLabel = new QLabel(this); + QLabel* unitLabel = new QLabel(this); unitLabel->setText(unit); unitLabel->setToolTip(tr("Unit of ") + curve); unitLabel->setWhatsThis(tr("Unit of ") + curve); - curveUnits.insert(curve+unit, unitLabel); + curveUnits.insert(curveID, unitLabel); curvesWidgetLayout->addWidget(unitLabel, labelRow, 4); unitLabel->setVisible(ui.showUnitsCheckBox->isChecked()); connect(ui.showUnitsCheckBox, &QCheckBox::clicked, unitLabel, &QLabel::setVisible); // Mean - mean = new QLabel(this); + QLabel* mean = new QLabel(this); mean->setNum(0.00); mean->setStyleSheet(QString("QLabel {font-family:\"Courier\"; font-weight: bold;}")); mean->setToolTip(tr("Arithmetic mean of %1 in %2 units").arg(curve, unit)); mean->setWhatsThis(tr("Arithmetic mean of %1 in %2 units").arg(curve, unit)); - curveMeans->insert(curve+unit, mean); - curvesWidgetLayout->addWidget(mean, labelRow, 5); + curveMeans->insert(curveID, mean); + curvesWidgetLayout->addWidget(mean, labelRow, 5, Qt::AlignRight); // // Median // median = new QLabel(form); @@ -583,13 +565,13 @@ void LinechartWidget::addCurve(const QString& curve, const QString& unit) // horizontalLayout->addWidget(median); // Variance - variance = new QLabel(this); + QLabel* variance = new QLabel(this); variance->setNum(0.00); variance->setStyleSheet(QString("QLabel {font-family:\"Courier\"; font-weight: bold;}")); variance->setToolTip(tr("Variance of %1 in (%2)^2 units").arg(curve, unit)); variance->setWhatsThis(tr("Variance of %1 in (%2)^2 units").arg(curve, unit)); - curveVariances->insert(curve+unit, variance); - curvesWidgetLayout->addWidget(variance, labelRow, 6); + curveVariances->insert(curveID, variance); + curvesWidgetLayout->addWidget(variance, labelRow, 6, Qt::AlignRight); /* Color picker QColor color = QColorDialog::getColor(Qt::green, this); @@ -612,7 +594,7 @@ void LinechartWidget::addCurve(const QString& curve, const QString& unit) // Set UI components to initial state checkBox->setChecked(false); - plot->setVisibleById(curve+unit, false); + plot->setVisibleById(curveID, false); } /** @@ -656,7 +638,7 @@ void LinechartWidget::removeCurve(QString curve) void LinechartWidget::recolor() { - activePlot->styleChanged(qgcApp()->styleIsDark()); + activePlot->styleChanged(qgcApp()->toolbox()->settingsManager()->appSettings()->indoorPalette()->rawValue().toBool()); foreach (const QString &key, colorIcons.keys()) { QWidget* colorIcon = colorIcons.value(key, 0); @@ -684,7 +666,7 @@ void LinechartWidget::filterCurve(const QString &key, bool match) (*curveLabels)[key]->setVisible(match); (*curveMeans)[key]->setVisible(match); (*curveVariances)[key]->setVisible(match); - curveUnits[key]->setVisible(match); + curveUnits[key]->setVisible(match && ui.showUnitsCheckBox->isChecked()); checkBoxes[key]->setVisible(match); } } diff --git a/src/ui/linechart/LinechartWidget.h b/src/ui/linechart/LinechartWidget.h index cac806a1492c9d4e788bb6fd8fd7ca2c47d95419..372acfa43690cc27d1016b88d2c8381b0888c9ae 100644 --- a/src/ui/linechart/LinechartWidget.h +++ b/src/ui/linechart/LinechartWidget.h @@ -138,7 +138,6 @@ protected: QAction* addNewCurve; ///< Add curve candidate to the active curves - QMenu* curveMenu; QComboBox *timeScaleCmb; QToolButton* scalingLogButton; diff --git a/src/ui/preferences/GeneralSettings.qml b/src/ui/preferences/GeneralSettings.qml index d3d85307e725597da9f0cfecb88c8ca80b22610e..4506b9174cbbbb677b6defdebe9f48430d380c6e 100644 --- a/src/ui/preferences/GeneralSettings.qml +++ b/src/ui/preferences/GeneralSettings.qml @@ -13,6 +13,7 @@ import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2 import QtQuick.Dialogs 1.1 import QtMultimedia 5.5 +import QtQuick.Layouts 1.2 import QGroundControl 1.0 import QGroundControl.FactSystem 1.0 @@ -22,6 +23,7 @@ import QGroundControl.ScreenTools 1.0 import QGroundControl.MultiVehicleManager 1.0 import QGroundControl.Palette 1.0 import QGroundControl.Controllers 1.0 +import QGroundControl.SettingsManager 1.0 QGCView { id: qgcView @@ -30,10 +32,14 @@ QGCView { anchors.fill: parent anchors.margins: ScreenTools.defaultFontPixelWidth - property Fact _percentRemainingAnnounce: QGroundControl.batteryPercentRemainingAnnounce + property Fact _percentRemainingAnnounce: QGroundControl.settingsManager.appSettings.batteryPercentRemainingAnnounce + property Fact _autoLoadDir: QGroundControl.settingsManager.appSettings.missionAutoLoadDir + property Fact _appFontPointSize: QGroundControl.settingsManager.appSettings.appFontPointSize property real _labelWidth: ScreenTools.defaultFontPixelWidth * 15 property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30 + readonly property string _requiresRestart: qsTr("(Requires Restart)") + QGCPalette { id: qgcPal } QGCViewPanel { @@ -49,13 +55,15 @@ QGCView { width: qgcView.width spacing: ScreenTools.defaultFontPixelHeight * 0.5 anchors.margins: ScreenTools.defaultFontPixelWidth + //----------------------------------------------------------------- //-- Units Item { - width: qgcView.width * 0.8 - height: unitLabel.height - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + width: qgcView.width * 0.8 + height: unitLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.unitsSettings.visible QGCLabel { id: unitLabel text: qsTr("Units (Requires Restart)") @@ -63,162 +71,64 @@ QGCView { } } Rectangle { - height: unitsCol.height + (ScreenTools.defaultFontPixelHeight * 2) - width: qgcView.width * 0.8 - color: qgcPal.windowShade - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + height: unitsCol.height + (ScreenTools.defaultFontPixelHeight * 2) + width: qgcView.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.unitsSettings.visible Column { id: unitsCol spacing: ScreenTools.defaultFontPixelWidth anchors.centerIn: parent - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCLabel { - width: _labelWidth - anchors.baseline: distanceUnitsCombo.baseline - text: qsTr("Distance:") - } - FactComboBox { - id: distanceUnitsCombo - width: _editFieldWidth - fact: QGroundControl.distanceUnits - indexModel: false - } - } - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCLabel { - width: _labelWidth - anchors.baseline: areaUnitsCombo.baseline - text: qsTr("Area:") - } - FactComboBox { - id: areaUnitsCombo - width: _editFieldWidth - fact: QGroundControl.areaUnits - indexModel: false - } - } - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCLabel { - width: _labelWidth - anchors.baseline: speedUnitsCombo.baseline - text: qsTr("Speed:") - } - FactComboBox { - id: speedUnitsCombo - width: _editFieldWidth - fact: QGroundControl.speedUnits - indexModel: false - } - } - } - } - //----------------------------------------------------------------- - //-- Offline mission editing - Item { - width: qgcView.width * 0.8 - height: offlineLabel.height - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter - QGCLabel { - id: offlineLabel - text: qsTr("Offline Mission Editing (Requires Restart)") - font.family: ScreenTools.demiboldFontFamily - } - } - Rectangle { - height: offlineCol.height + (ScreenTools.defaultFontPixelHeight * 2) - width: qgcView.width * 0.8 - color: qgcPal.windowShade - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter - Column { - id: offlineCol - spacing: ScreenTools.defaultFontPixelWidth - anchors.centerIn: parent - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCLabel { - text: qsTr("Firmware:") - width: _labelWidth - anchors.baseline: offlineTypeCombo.baseline - } - FactComboBox { - id: offlineTypeCombo - width: _editFieldWidth - fact: QGroundControl.offlineEditingFirmwareType - indexModel: false - } - } - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCLabel { - text: qsTr("Vehicle:") - width: _labelWidth - anchors.baseline: offlineVehicleCombo.baseline - } - FactComboBox { - id: offlineVehicleCombo - width: _editFieldWidth - fact: QGroundControl.offlineEditingVehicleType - indexModel: false - } - } - Row { - spacing: ScreenTools.defaultFontPixelWidth - visible: offlineVehicleCombo.currentText != "Multicopter" - QGCLabel { - text: qsTr("Cruise speed:") - width: _labelWidth - anchors.baseline: cruiseSpeedField.baseline - } - FactTextField { - id: cruiseSpeedField - width: _editFieldWidth - fact: QGroundControl.offlineEditingCruiseSpeed - enabled: true - } - } - Row { - spacing: ScreenTools.defaultFontPixelWidth - visible: offlineVehicleCombo.currentText != "Fixedwing" - QGCLabel { - id: hoverSpeedLabel - text: qsTr("Hover speed:") - width: _labelWidth - anchors.baseline: hoverSpeedField.baseline - } - FactTextField { - id: hoverSpeedField - width: _editFieldWidth - fact: QGroundControl.offlineEditingHoverSpeed - enabled: true + + Repeater { + id: unitsRepeater + model: [ QGroundControl.settingsManager.unitsSettings.distanceUnits, QGroundControl.settingsManager.unitsSettings.areaUnits, QGroundControl.settingsManager.unitsSettings.speedUnits ] + + property var names: [ qsTr("Distance:"), qsTr("Area:"), qsTr("Speed:") ] + + Row { + spacing: ScreenTools.defaultFontPixelWidth + visible: modelData.visible + + QGCLabel { + width: _labelWidth + anchors.baseline: factCombo.baseline + text: unitsRepeater.names[index] + } + FactComboBox { + id: factCombo + width: _editFieldWidth + fact: modelData + indexModel: false + } } } } } + //----------------------------------------------------------------- - //-- Miscelanous + //-- Miscellanous Item { - width: qgcView.width * 0.8 - height: miscLabel.height - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + width: qgcView.width * 0.8 + height: miscLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.appSettings.visible QGCLabel { id: miscLabel - text: qsTr("Miscelaneous") + text: qsTr("Miscellaneous") font.family: ScreenTools.demiboldFontFamily } } Rectangle { - height: miscCol.height + (ScreenTools.defaultFontPixelHeight * 2) - width: qgcView.width * 0.8 - color: qgcPal.windowShade - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + height: miscCol.height + (ScreenTools.defaultFontPixelHeight * 2) + width: qgcView.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.appSettings.visible Column { id: miscCol spacing: ScreenTools.defaultFontPixelWidth @@ -226,10 +136,11 @@ QGCView { //----------------------------------------------------------------- //-- Base UI Font Point Size Row { + visible: _appFontPointSize.visible spacing: ScreenTools.defaultFontPixelWidth QGCLabel { id: baseFontLabel - text: qsTr("Base UI font size:") + text: qsTr("Font size:") anchors.verticalCenter: parent.verticalCenter } Row { @@ -242,71 +153,77 @@ QGCView { height: baseFontEdit.height text: "-" onClicked: { - if(ScreenTools.defaultFontPointSize > 6) { - QGroundControl.baseFontPointSize = QGroundControl.baseFontPointSize - 1 + if (_appFontPointSize.value > _appFontPointSize.min) { + _appFontPointSize.value = _appFontPointSize.value - 1 } } } - QGCTextField { - id: baseFontEdit - width: _editFieldWidth - (decrementButton.width * 2) - (baseFontRow.spacing * 2) - text: QGroundControl.baseFontPointSize - showUnits: true - unitsLabel: "pt" - maximumLength: 6 - validator: DoubleValidator {bottom: 6.0; top: 48.0; decimals: 2;} - onEditingFinished: { - var point = parseFloat(text) - if(point >= 6.0 && point <= 48.0) - QGroundControl.baseFontPointSize = point; - } + FactTextField { + id: baseFontEdit + width: _editFieldWidth - (decrementButton.width * 2) - (baseFontRow.spacing * 2) + fact: QGroundControl.settingsManager.appSettings.appFontPointSize } QGCButton { width: height height: baseFontEdit.height text: "+" onClicked: { - if(ScreenTools.defaultFontPointSize < 49) { - QGroundControl.baseFontPointSize = QGroundControl.baseFontPointSize + 1 + if (_appFontPointSize.value < _appFontPointSize.max) { + _appFontPointSize.value = _appFontPointSize.value + 1 } } } } QGCLabel { anchors.verticalCenter: parent.verticalCenter - text: qsTr("(Requires Restart)") + text: _requiresRestart + } + } + //----------------------------------------------------------------- + //-- Palette Styles + Row { + spacing: ScreenTools.defaultFontPixelWidth + visible: QGroundControl.settingsManager.appSettings.indoorPalette.visible + QGCLabel { + anchors.baseline: paletteCombo.baseline + text: qsTr("Color scheme:") + width: _labelWidth + } + FactComboBox { + id: paletteCombo + width: _editFieldWidth + fact: QGroundControl.settingsManager.appSettings.indoorPalette + indexModel: false } } //----------------------------------------------------------------- //-- Audio preferences - QGCCheckBox { + FactCheckBox { text: qsTr("Mute all audio output") - checked: QGroundControl.isAudioMuted - onClicked: { - QGroundControl.isAudioMuted = checked - } + fact: _audioMuted + visible: _audioMuted.visible + + property Fact _audioMuted: QGroundControl.settingsManager.appSettings.audioMuted } //----------------------------------------------------------------- //-- Prompt Save Log - QGCCheckBox { + FactCheckBox { id: promptSaveLog text: qsTr("Prompt to save Flight Data Log after each flight") - checked: QGroundControl.isSaveLogPrompt - visible: !ScreenTools.isMobile - onClicked: { - QGroundControl.isSaveLogPrompt = checked - } + fact: _promptFlightTelemetrySave + visible: !ScreenTools.isMobile && _promptFlightTelemetrySave.visible + + property Fact _promptFlightTelemetrySave: QGroundControl.settingsManager.appSettings.promptFlightTelemetrySave } //----------------------------------------------------------------- //-- Prompt Save even if not armed - QGCCheckBox { + FactCheckBox { text: qsTr("Prompt to save Flight Data Log even if vehicle was not armed") - checked: QGroundControl.isSaveLogPromptNotArmed - visible: !ScreenTools.isMobile + fact: _promptFlightTelemetrySaveNotArmed + visible: !ScreenTools.isMobile && _promptFlightTelemetrySaveNotArmed.visible enabled: promptSaveLog.checked - onClicked: { - QGroundControl.isSaveLogPromptNotArmed = checked - } + + property Fact _promptFlightTelemetrySaveNotArmed: QGroundControl.settingsManager.appSettings.promptFlightTelemetrySaveNotArmed } //----------------------------------------------------------------- //-- Clear settings @@ -360,10 +277,63 @@ QGCView { } //----------------------------------------------------------------- //-- Virtual joystick settings - QGCCheckBox { + FactCheckBox { text: qsTr("Virtual Joystick") - checked: QGroundControl.virtualTabletJoystick - onClicked: QGroundControl.virtualTabletJoystick = checked + visible: _virtualJoystick.visible + fact: _virtualJoystick + + property Fact _virtualJoystick: QGroundControl.settingsManager.appSettings.virtualJoystick + } + //----------------------------------------------------------------- + //-- Default mission item altitude + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + anchors.baseline: defaultItemAltitudeField.baseline + text: qsTr("Default mission item altitude:") + } + FactTextField { + id: defaultItemAltitudeField + fact: QGroundControl.settingsManager.appSettings.defaultMissionItemAltitude + } + } + //----------------------------------------------------------------- + //-- Mission AutoLoad + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCCheckBox { + id: autoLoadCheckbox + anchors.verticalCenter: parent.verticalCenter + text: qsTr("AutoLoad mission directory:") + checked: _autoLoadDir.valueString + + onClicked: { + if (checked) { + _autoLoadDir.rawValue = QGroundControl.urlToLocalFile(autoloadDirPicker.shortcuts.home) + } else { + _autoLoadDir.rawValue = "" + } + } + } + FactTextField { + id: autoLoadDirField + width: _editFieldWidth + enabled: autoLoadCheckbox.checked + anchors.verticalCenter: parent.verticalCenter + fact: _autoLoadDir + } + QGCButton { + text: qsTr("Browse") + onClicked: autoloadDirPicker.visible = true + + FileDialog { + id: autoloadDirPicker + title: qsTr("Choose the location of mission file.") + folder: shortcuts.home + selectFolder: true + onAccepted: _autoLoadDir.rawValue = QGroundControl.urlToLocalFile(autoloadDirPicker.fileUrl) + } + } } //----------------------------------------------------------------- //-- Map Providers @@ -402,100 +372,69 @@ QGCView { } } } - //----------------------------------------------------------------- - //-- Palette Styles - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCLabel { - anchors.baseline: paletteCombo.baseline - text: qsTr("UI Style:") - width: _labelWidth - } - QGCComboBox { - id: paletteCombo - width: _editFieldWidth - model: [ qsTr("Indoor"), qsTr("Outdoor") ] - currentIndex: QGroundControl.isDarkStyle ? 0 : 1 - onActivated: { - if (index != -1) { - currentIndex = index - QGroundControl.isDarkStyle = index === 0 ? true : false - } - } - } - } } } + //----------------------------------------------------------------- //-- Autoconnect settings Item { - width: qgcView.width * 0.8 - height: autoConnectLabel.height - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + width: qgcView.width * 0.8 + height: autoConnectLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.autoConnectSettings.visible QGCLabel { id: autoConnectLabel - text: qsTr("Autoconnect to the following devices:") + text: qsTr("AutoConnect to the following devices:") font.family: ScreenTools.demiboldFontFamily } } Rectangle { - height: autoConnectCol.height + (ScreenTools.defaultFontPixelHeight * 2) - width: qgcView.width * 0.8 - color: qgcPal.windowShade - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + height: autoConnectCol.height + (ScreenTools.defaultFontPixelHeight * 2) + width: qgcView.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.autoConnectSettings.visible + Column { id: autoConnectCol spacing: ScreenTools.defaultFontPixelWidth anchors.centerIn: parent - //----------------------------------------------------------------- - //-- Autoconnect settings + Row { spacing: ScreenTools.defaultFontPixelWidth * 2 - QGCCheckBox { - text: qsTr("Pixhawk") - visible: !ScreenTools.isiOS - checked: QGroundControl.linkManager.autoconnectPixhawk - onClicked: QGroundControl.linkManager.autoconnectPixhawk = checked - } - QGCCheckBox { - text: qsTr("SiK Radio") - visible: !ScreenTools.isiOS - checked: QGroundControl.linkManager.autoconnect3DRRadio - onClicked: QGroundControl.linkManager.autoconnect3DRRadio = checked - } - QGCCheckBox { - text: qsTr("PX4 Flow") - visible: !ScreenTools.isiOS - checked: QGroundControl.linkManager.autoconnectPX4Flow - onClicked: QGroundControl.linkManager.autoconnectPX4Flow = checked - } - QGCCheckBox { - text: qsTr("LibrePilot") - checked: QGroundControl.linkManager.autoconnectLibrePilot - onClicked: QGroundControl.linkManager.autoconnectLibrePilot = checked - } - QGCCheckBox { - text: qsTr("UDP") - checked: QGroundControl.linkManager.autoconnectUDP - onClicked: QGroundControl.linkManager.autoconnectUDP = checked - } - QGCCheckBox { - text: qsTr("RTK GPS") - checked: QGroundControl.linkManager.autoconnectRTKGPS - onClicked: QGroundControl.linkManager.autoconnectRTKGPS = checked + + Repeater { + id: autoConnectRepeater + model: [ QGroundControl.settingsManager.autoConnectSettings.autoConnectPixhawk, + QGroundControl.settingsManager.autoConnectSettings.autoConnectSiKRadio, + QGroundControl.settingsManager.autoConnectSettings.autoConnectPX4Flow, + QGroundControl.settingsManager.autoConnectSettings.autoConnectLibrePilot, + QGroundControl.settingsManager.autoConnectSettings.autoConnectUDP, + QGroundControl.settingsManager.autoConnectSettings.autoConnectRTKGPS + ] + + property var names: [ qsTr("Pixhawk"), qsTr("SiK Radio"), qsTr("PX4 Flow"), qsTr("LibrePilot"), qsTr("UDP"), qsTr("RTK GPS") ] + + FactCheckBox { + text: autoConnectRepeater.names[index] + fact: modelData + visible: !ScreenTools.isiOS && modelData.visible + } } } } } + //----------------------------------------------------------------- //-- Video Source Item { - width: qgcView.width * 0.8 - height: videoLabel.height - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + width: qgcView.width * 0.8 + height: videoLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.videoSettings.visible QGCLabel { id: videoLabel text: qsTr("Video (Requires Restart)") @@ -503,77 +442,122 @@ QGCView { } } Rectangle { - height: videoCol.height + (ScreenTools.defaultFontPixelHeight * 2) - width: qgcView.width * 0.8 - color: qgcPal.windowShade - anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + height: videoCol.height + (ScreenTools.defaultFontPixelHeight * 2) + width: qgcView.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.videoSettings.visible + Column { id: videoCol spacing: ScreenTools.defaultFontPixelWidth anchors.centerIn: parent + + Row { spacing: ScreenTools.defaultFontPixelWidth + visible: QGroundControl.settingsManager.videoSettings.videoSource.visible QGCLabel { anchors.baseline: videoSource.baseline text: qsTr("Video Source:") width: _labelWidth } - QGCComboBox { - id: videoSource - width: _editFieldWidth - model: QGroundControl.videoManager.videoSourceList - Component.onCompleted: { - var index = videoSource.find(QGroundControl.videoManager.videoSource) - if (index >= 0) { - videoSource.currentIndex = index - } - } - onActivated: { - if (index != -1) { - currentIndex = index - QGroundControl.videoManager.videoSource = model[index] - } - } + FactComboBox { + id: videoSource + width: _editFieldWidth + indexModel: false + fact: QGroundControl.settingsManager.videoSettings.videoSource } } Row { spacing: ScreenTools.defaultFontPixelWidth - visible: QGroundControl.videoManager.isGStreamer && videoSource.currentIndex === 0 + visible: QGroundControl.settingsManager.videoSettings.udpPort.visible && QGroundControl.videoManager.isGStreamer && videoSource.currentIndex === 0 QGCLabel { anchors.baseline: udpField.baseline text: qsTr("UDP Port:") width: _labelWidth } - QGCTextField { + FactTextField { id: udpField width: _editFieldWidth - text: QGroundControl.videoManager.udpPort - validator: IntValidator {bottom: 1024; top: 65535;} - inputMethodHints: Qt.ImhDigitsOnly - onEditingFinished: { - QGroundControl.videoManager.udpPort = parseInt(text) - } + fact: QGroundControl.settingsManager.videoSettings.udpPort } } Row { spacing: ScreenTools.defaultFontPixelWidth - visible: QGroundControl.videoManager.isGStreamer && videoSource.currentIndex === 1 + visible: QGroundControl.settingsManager.videoSettings.rtspUrl.visible && QGroundControl.videoManager.isGStreamer && videoSource.currentIndex === 1 QGCLabel { anchors.baseline: rtspField.baseline text: qsTr("RTSP URL:") width: _labelWidth } - QGCTextField { + FactTextField { id: rtspField width: _editFieldWidth - text: QGroundControl.videoManager.rtspURL - onEditingFinished: { - QGroundControl.videoManager.rtspURL = text + fact: QGroundControl.settingsManager.videoSettings.rtspUrl + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + visible: QGroundControl.videoManager.isGStreamer && videoSource.currentIndex < 2 && QGroundControl.settingsManager.videoSettings.aspectRatio.visible + QGCLabel { + anchors.baseline: aspectField.baseline + text: qsTr("Aspect Ratio:") + width: _labelWidth + } + FactTextField { + id: aspectField + width: _editFieldWidth + fact: QGroundControl.settingsManager.videoSettings.aspectRatio + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + visible: QGroundControl.videoManager.isGStreamer && videoSource.currentIndex < 2 && QGroundControl.settingsManager.videoSettings.gridLines.visible + QGCLabel { + anchors.baseline: gridField.baseline + text: qsTr("Grid Lines:") + width: _labelWidth + } + FactComboBox { + id: gridField + width: _editFieldWidth + fact: QGroundControl.settingsManager.videoSettings.gridLines + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + visible: QGroundControl.settingsManager.videoSettings.videoSavePath.visible && QGroundControl.videoManager.isGStreamer && QGroundControl.videoManager.recordingEnabled + QGCLabel { + anchors.baseline: pathField.baseline + text: qsTr("Save Path:") + width: _labelWidth + } + FactTextField { + id: pathField + width: _editFieldWidth + fact: QGroundControl.settingsManager.videoSettings.videoSavePath + } + QGCButton { + text: "Browse" + onClicked: videoLocationFileDialog.visible = true + + FileDialog { + id: videoLocationFileDialog + title: "Choose a location to save video files." + folder: shortcuts.home + selectFolder: true + onAccepted: QGroundControl.settingsManager.videoSettings.videoSavePath.value = QGroundControl.urlToLocalFile(videoLocationFileDialog.fileUrl) } } } } + } // Video Source - Rectangle + + QGCLabel { + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("QGroundControl Version: " + QGroundControl.qgcVersion) } } // settingsColumn } // QGCFlickable diff --git a/src/ui/preferences/LinkSettings.qml b/src/ui/preferences/LinkSettings.qml index 202d5edcd7802d027fc95aaf264c9ee13b9b23bf..cd4d75be08845dd8082c9def1135b00c59704e92 100644 --- a/src/ui/preferences/LinkSettings.qml +++ b/src/ui/preferences/LinkSettings.qml @@ -61,12 +61,13 @@ Rectangle { spacing: ScreenTools.defaultFontPixelHeight / 2 Repeater { model: QGroundControl.linkManager.linkConfigurations - delegate: - QGCButton { - text: object.name - width: _linkRoot.width * 0.5 - exclusiveGroup: linkGroup - anchors.horizontalCenter: settingsColumn.horizontalCenter + delegate: QGCButton { + anchors.horizontalCenter: settingsColumn.horizontalCenter + width: _linkRoot.width * 0.5 + text: object.name + exclusiveGroup: linkGroup + visible: !object.dynamic + onClicked: { checked = true _currentSelection = object @@ -270,12 +271,11 @@ Rectangle { height: ScreenTools.defaultFontPixelHeight * 0.5 width: parent.width } - /* - //-- Auto Connect + //-- Auto Connect on Start QGCCheckBox { text: "Automatically Connect on Start" checked: false - enabled: editConfig ? editConfig.autoConnectAllowed : false + visible: editConfig ? editConfig.autoConnectAllowed : false onCheckedChanged: { if(editConfig) { editConfig.autoConnect = checked @@ -286,7 +286,6 @@ Rectangle { checked = editConfig.autoConnect } } - */ Item { height: ScreenTools.defaultFontPixelHeight width: parent.width diff --git a/src/ui/preferences/MavlinkSettings.qml b/src/ui/preferences/MavlinkSettings.qml index 37ac33284738907b82949d711ebc5f5686f32259..83ac9ac8c2e3edc35e53342dbb05a8586a3dbb26 100644 --- a/src/ui/preferences/MavlinkSettings.qml +++ b/src/ui/preferences/MavlinkSettings.qml @@ -25,56 +25,588 @@ Rectangle { color: qgcPal.window anchors.fill: parent + property real _labelWidth: ScreenTools.defaultFontPixelWidth * 28 + property real _valueWidth: ScreenTools.defaultFontPixelWidth * 24 + property int _selectedCount: 0 + property real _columnSpacing: ScreenTools.defaultFontPixelHeight * 0.25 + property bool _uploadedSelected: false + QGCPalette { id: qgcPal } + Connections { + target: QGroundControl.mavlinkLogManager + onSelectedCountChanged: { + _uploadedSelected = false + var selected = 0 + for(var i = 0; i < QGroundControl.mavlinkLogManager.logFiles.count; i++) { + var logFile = QGroundControl.mavlinkLogManager.logFiles.get(i) + if(logFile.selected) { + selected++ + //-- If an uploaded file is selected, disable "Upload" button + if(logFile.uploaded) { + _uploadedSelected = true + } + } + } + _selectedCount = selected + } + } + + function saveItems() + { + QGroundControl.mavlinkSystemID = parseInt(sysidField.text) + QGroundControl.mavlinkLogManager.videoURL = videoUrlField.text + QGroundControl.mavlinkLogManager.feedback = feedbackTextArea.text + QGroundControl.mavlinkLogManager.emailAddress = emailField.text + QGroundControl.mavlinkLogManager.description = descField.text + QGroundControl.mavlinkLogManager.uploadURL = urlField.text + QGroundControl.mavlinkLogManager.emailAddress = emailField.text + if(autoUploadCheck.checked && QGroundControl.mavlinkLogManager.emailAddress === "") { + autoUploadCheck.checked = false + } else { + QGroundControl.mavlinkLogManager.enableAutoUpload = autoUploadCheck.checked + } + } + + MessageDialog { + id: emptyEmailDialog + visible: false + icon: StandardIcon.Warning + standardButtons: StandardButton.Close + title: qsTr("MAVLink Logging") + text: qsTr("Please enter an email address before uploading MAVLink log files.") + } + QGCFlickable { clip: true anchors.fill: parent anchors.margins: ScreenTools.defaultFontPixelWidth contentHeight: settingsColumn.height contentWidth: settingsColumn.width + flickableDirection: Flickable.VerticalFlick Column { id: settingsColumn - spacing: ScreenTools.defaultFontPixelHeight + width: __mavlinkRoot.width + spacing: ScreenTools.defaultFontPixelHeight * 0.5 anchors.margins: ScreenTools.defaultFontPixelWidth - anchors.left: parent.left - anchors.top: parent.top //----------------------------------------------------------------- - //-- System ID - Row { - spacing: ScreenTools.defaultFontPixelWidth + //-- Ground Station + Item { + width: __mavlinkRoot.width * 0.8 + height: gcsLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter QGCLabel { - text: qsTr("Ground Station MavLink System ID:") - anchors.verticalCenter: parent.verticalCenter + id: gcsLabel + text: qsTr("Ground Station") + font.family: ScreenTools.demiboldFontFamily } - QGCTextField { - id: sysidField - text: QGroundControl.mavlinkSystemID.toString() - width: ScreenTools.defaultFontPixelWidth * 6 - inputMethodHints: Qt.ImhFormattedNumbersOnly - anchors.verticalCenter: parent.verticalCenter - onEditingFinished: { - QGroundControl.mavlinkSystemID = parseInt(sysidField.text) + } + Rectangle { + height: gcsColumn.height + (ScreenTools.defaultFontPixelHeight * 2) + width: __mavlinkRoot.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + Column { + id: gcsColumn + spacing: _columnSpacing + anchors.centerIn: parent + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + width: _labelWidth + anchors.baseline: sysidField.baseline + text: qsTr("MAVLink System ID:") + } + QGCTextField { + id: sysidField + text: QGroundControl.mavlinkSystemID.toString() + width: _valueWidth + inputMethodHints: Qt.ImhFormattedNumbersOnly + anchors.verticalCenter: parent.verticalCenter + onEditingFinished: { + saveItems(); + } + } + } + //----------------------------------------------------------------- + //-- Mavlink Heartbeats + QGCCheckBox { + text: qsTr("Emit heartbeat") + checked: QGroundControl.multiVehicleManager.gcsHeartBeatEnabled + onClicked: { + QGroundControl.multiVehicleManager.gcsHeartBeatEnabled = checked + } + } + //----------------------------------------------------------------- + //-- Mavlink Version Check + QGCCheckBox { + text: qsTr("Only accept MAVs with same protocol version") + checked: QGroundControl.isVersionCheckEnabled + onClicked: { + QGroundControl.isVersionCheckEnabled = checked + } } } } //----------------------------------------------------------------- - //-- Mavlink Heartbeats - QGCCheckBox { - text: qsTr("Emit heartbeat") - checked: QGroundControl.multiVehicleManager.gcsHeartBeatEnabled - onClicked: { - QGroundControl.multiVehicleManager.gcsHeartBeatEnabled = checked + //-- Mavlink Logging + Item { + width: __mavlinkRoot.width * 0.8 + height: mavlogLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + id: mavlogLabel + text: qsTr("MAVLink 2.0 Logging (PX4 Firmware Only)") + font.family: ScreenTools.demiboldFontFamily + } + } + Rectangle { + height: mavlogColumn.height + (ScreenTools.defaultFontPixelHeight * 2) + width: __mavlinkRoot.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + Column { + id: mavlogColumn + width: gcsColumn.width + spacing: _columnSpacing + anchors.centerIn: parent + //----------------------------------------------------------------- + //-- Manual Start/Stop + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + width: _labelWidth + text: qsTr("Manual Start/Stop:") + anchors.verticalCenter: parent.verticalCenter + } + QGCButton { + text: qsTr("Start Logging") + width: (_valueWidth * 0.5) - (ScreenTools.defaultFontPixelWidth * 0.5) + enabled: !QGroundControl.mavlinkLogManager.logRunning && QGroundControl.mavlinkLogManager.canStartLog + onClicked: QGroundControl.mavlinkLogManager.startLogging() + anchors.verticalCenter: parent.verticalCenter + } + QGCButton { + text: qsTr("Stop Logging") + width: (_valueWidth * 0.5) - (ScreenTools.defaultFontPixelWidth * 0.5) + enabled: QGroundControl.mavlinkLogManager.logRunning + onClicked: QGroundControl.mavlinkLogManager.stopLogging() + anchors.verticalCenter: parent.verticalCenter + } + } + //----------------------------------------------------------------- + //-- Enable auto log on arming + QGCCheckBox { + text: qsTr("Enable automatic logging") + checked: QGroundControl.mavlinkLogManager.enableAutoStart + onClicked: { + QGroundControl.mavlinkLogManager.enableAutoStart = checked + } + } } } //----------------------------------------------------------------- - //-- Mavlink Version Check - QGCCheckBox { - text: qsTr("Only accept MAVs with same protocol version") - checked: QGroundControl.isVersionCheckEnabled - onClicked: { - QGroundControl.isVersionCheckEnabled = checked + //-- Mavlink Logging + Item { + width: __mavlinkRoot.width * 0.8 + height: logLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + id: logLabel + text: qsTr("MAVLink 2.0 Log Uploads (PX4 Firmware Only)") + font.family: ScreenTools.demiboldFontFamily + } + } + Rectangle { + height: logColumn.height + (ScreenTools.defaultFontPixelHeight * 2) + width: __mavlinkRoot.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + Column { + id: logColumn + spacing: _columnSpacing + anchors.centerIn: parent + //----------------------------------------------------------------- + //-- Email address Field + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + width: _labelWidth + anchors.baseline: emailField.baseline + text: qsTr("Email address for Log Upload:") + } + QGCTextField { + id: emailField + text: QGroundControl.mavlinkLogManager.emailAddress + width: _valueWidth + inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhEmailCharactersOnly + anchors.verticalCenter: parent.verticalCenter + onEditingFinished: { + saveItems(); + } + } + } + //----------------------------------------------------------------- + //-- Description Field + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + width: _labelWidth + anchors.baseline: descField.baseline + text: qsTr("Default Description:") + } + QGCTextField { + id: descField + text: QGroundControl.mavlinkLogManager.description + width: _valueWidth + anchors.verticalCenter: parent.verticalCenter + onEditingFinished: { + saveItems(); + } + } + } + //----------------------------------------------------------------- + //-- Upload URL + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + width: _labelWidth + anchors.baseline: urlField.baseline + text: qsTr("Default Upload URL") + } + QGCTextField { + id: urlField + text: QGroundControl.mavlinkLogManager.uploadURL + width: _valueWidth + inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhUrlCharactersOnly + anchors.verticalCenter: parent.verticalCenter + onEditingFinished: { + saveItems(); + } + } + } + //----------------------------------------------------------------- + //-- Video URL + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + width: _labelWidth + anchors.baseline: videoUrlField.baseline + text: qsTr("Video URL:") + } + QGCTextField { + id: videoUrlField + text: QGroundControl.mavlinkLogManager.videoURL + width: _valueWidth + inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhUrlCharactersOnly + anchors.verticalCenter: parent.verticalCenter + } + } + //----------------------------------------------------------------- + //-- Wind Speed + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + width: _labelWidth + anchors.baseline: windCombo.baseline + text: qsTr("Wind Speed:") + } + QGCComboBox { + id: windCombo + width: _valueWidth + model: ListModel { + id: windItems + ListElement { text: "Please Select"; value: -1 } + ListElement { text: "Calm"; value: 0 } + ListElement { text: "Breeze"; value: 5 } + ListElement { text: "Gale"; value: 8 } + ListElement { text: "Storm"; value: 10 } + } + onActivated: { + saveItems(); + QGroundControl.mavlinkLogManager.windSpeed = windItems.get(index).value + console.log('Set Wind: ' + windItems.get(index).value) + } + Component.onCompleted: { + for(var i = 0; i < windItems.count; i++) { + if(windItems.get(i).value === QGroundControl.mavlinkLogManager.windSpeed) { + windCombo.currentIndex = i; + console.log('Wind: ' + windItems.get(i).value) + break; + } + } + } + } + } + //----------------------------------------------------------------- + //-- Flight Rating + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + width: _labelWidth + anchors.baseline: ratingCombo.baseline + text: qsTr("Flight Rating:") + } + QGCComboBox { + id: ratingCombo + width: _valueWidth + model: ListModel { + id: ratingItems + ListElement { text: "Please Select"; value: "notset"} + ListElement { text: "Crashed (Pilot Error)"; value: "crash_pilot" } + ListElement { text: "Crashed (Software or Hardware issue)"; value: "crash_sw_hw" } + ListElement { text: "Unsatisfactory"; value: "unsatisfactory" } + ListElement { text: "Good"; value: "good" } + ListElement { text: "Great"; value: "great" } + } + onActivated: { + saveItems(); + QGroundControl.mavlinkLogManager.rating = ratingItems.get(index).value + console.log('Set Rating: ' + ratingItems.get(index).value) + } + Component.onCompleted: { + for(var i = 0; i < ratingItems.count; i++) { + if(ratingItems.get(i).value === QGroundControl.mavlinkLogManager.rating) { + ratingCombo.currentIndex = i; + console.log('Rating: ' + ratingItems.get(i).value) + break; + } + } + } + } + } + //----------------------------------------------------------------- + //-- Feedback + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + width: _labelWidth + text: qsTr("Additional Feedback:") + } + TextArea { + id: feedbackTextArea + width: _valueWidth + height: ScreenTools.defaultFontPixelHeight * 4 + frameVisible: false + font.pointSize: ScreenTools.defaultFontPointSize + text: QGroundControl.mavlinkLogManager.feedback + style: TextAreaStyle { + textColor: qgcPal.windowShade + backgroundColor: qgcPal.text + } + } + } + //----------------------------------------------------------------- + //-- Public Log + QGCCheckBox { + text: qsTr("Make this log publicly available") + checked: QGroundControl.mavlinkLogManager.publicLog + onClicked: { + QGroundControl.mavlinkLogManager.publicLog = checked + } + } + //----------------------------------------------------------------- + //-- Automatic Upload + QGCCheckBox { + id: autoUploadCheck + text: qsTr("Enable automatic log uploads") + checked: QGroundControl.mavlinkLogManager.enableAutoUpload + onClicked: { + saveItems(); + if(checked && QGroundControl.mavlinkLogManager.emailAddress === "") + emptyEmailDialog.open() + } + } + //----------------------------------------------------------------- + //-- Delete log after upload + QGCCheckBox { + text: qsTr("Delete log file after uploading") + checked: QGroundControl.mavlinkLogManager.deleteAfterUpload + enabled: autoUploadCheck.checked + onClicked: { + QGroundControl.mavlinkLogManager.deleteAfterUpload = checked + } + } + } + } + //----------------------------------------------------------------- + //-- Log Files + Item { + width: __mavlinkRoot.width * 0.8 + height: logFilesLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + id: logFilesLabel + text: qsTr("Saved Log Files") + font.family: ScreenTools.demiboldFontFamily + } + } + Rectangle { + height: logFilesColumn.height + (ScreenTools.defaultFontPixelHeight * 2) + width: __mavlinkRoot.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + Column { + id: logFilesColumn + spacing: _columnSpacing * 4 + anchors.centerIn: parent + width: ScreenTools.defaultFontPixelWidth * 68 + Rectangle { + width: ScreenTools.defaultFontPixelWidth * 64 + height: ScreenTools.defaultFontPixelHeight * 14 + anchors.horizontalCenter: parent.horizontalCenter + color: qgcPal.window + border.color: qgcPal.text + border.width: 0.5 + QGCListView { + width: ScreenTools.defaultFontPixelWidth * 56 + height: ScreenTools.defaultFontPixelHeight * 12 + anchors.centerIn: parent + orientation: ListView.Vertical + model: QGroundControl.mavlinkLogManager.logFiles + clip: true + delegate: Rectangle { + width: ScreenTools.defaultFontPixelWidth * 52 + height: selectCheck.height + color: qgcPal.window + Row { + width: ScreenTools.defaultFontPixelWidth * 50 + anchors.centerIn: parent + spacing: ScreenTools.defaultFontPixelWidth + QGCCheckBox { + id: selectCheck + width: ScreenTools.defaultFontPixelWidth * 4 + checked: object.selected + enabled: !object.writing && !object.uploading + anchors.verticalCenter: parent.verticalCenter + onClicked: { + object.selected = checked + } + } + QGCLabel { + text: object.name + width: ScreenTools.defaultFontPixelWidth * 28 + color: object.writing ? qgcPal.warningText : qgcPal.text + anchors.verticalCenter: parent.verticalCenter + } + QGCLabel { + text: Number(object.size).toLocaleString(Qt.locale(), 'f', 0) + visible: !object.uploading && !object.uploaded + width: ScreenTools.defaultFontPixelWidth * 20; + color: object.writing ? qgcPal.warningText : qgcPal.text + horizontalAlignment: Text.AlignRight + anchors.verticalCenter: parent.verticalCenter + } + QGCLabel { + text: qsTr("Uploaded") + visible: object.uploaded + width: ScreenTools.defaultFontPixelWidth * 20; + horizontalAlignment: Text.AlignRight + anchors.verticalCenter: parent.verticalCenter + } + ProgressBar { + visible: object.uploading && !object.uploaded + width: ScreenTools.defaultFontPixelWidth * 20; + height: ScreenTools.defaultFontPixelHeight + anchors.verticalCenter: parent.verticalCenter + minimumValue: 0 + maximumValue: 100 + value: object.progress * 100.0 + } + } + } + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCButton { + text: qsTr("Check All") + enabled: !QGroundControl.mavlinkLogManager.uploading && !QGroundControl.mavlinkLogManager.logRunning + onClicked: { + for(var i = 0; i < QGroundControl.mavlinkLogManager.logFiles.count; i++) { + var logFile = QGroundControl.mavlinkLogManager.logFiles.get(i) + logFile.selected = true + } + } + } + QGCButton { + text: qsTr("Check None") + enabled: !QGroundControl.mavlinkLogManager.uploading && !QGroundControl.mavlinkLogManager.logRunning + onClicked: { + for(var i = 0; i < QGroundControl.mavlinkLogManager.logFiles.count; i++) { + var logFile = QGroundControl.mavlinkLogManager.logFiles.get(i) + logFile.selected = false + } + } + } + QGCButton { + text: qsTr("Delete Selected") + enabled: _selectedCount > 0 && !QGroundControl.mavlinkLogManager.uploading && !QGroundControl.mavlinkLogManager.logRunning + onClicked: deleteDialog.open() + MessageDialog { + id: deleteDialog + visible: false + icon: StandardIcon.Warning + standardButtons: StandardButton.Yes | StandardButton.No + title: qsTr("Delete Selected Log Files") + text: qsTr("Confirm deleting selected log files?") + onYes: { + QGroundControl.mavlinkLogManager.deleteLog() + } + } + } + QGCButton { + text: qsTr("Upload Selected") + enabled: _selectedCount > 0 && !QGroundControl.mavlinkLogManager.uploading && !QGroundControl.mavlinkLogManager.logRunning && !_uploadedSelected + visible: !QGroundControl.mavlinkLogManager.uploading + onClicked: { + saveItems(); + if(QGroundControl.mavlinkLogManager.emailAddress === "") + emptyEmailDialog.open() + else + uploadDialog.open() + } + MessageDialog { + id: uploadDialog + visible: false + icon: StandardIcon.Question + standardButtons: StandardButton.Yes | StandardButton.No + title: qsTr("Upload Selected Log Files") + text: qsTr("Confirm uploading selected log files?") + onYes: { + QGroundControl.mavlinkLogManager.uploadLog() + } + } + } + QGCButton { + text: qsTr("Cancel") + enabled: QGroundControl.mavlinkLogManager.uploading && !QGroundControl.mavlinkLogManager.logRunning + visible: QGroundControl.mavlinkLogManager.uploading + onClicked: cancelDialog.open() + MessageDialog { + id: cancelDialog + visible: false + icon: StandardIcon.Warning + standardButtons: StandardButton.Yes | StandardButton.No + title: qsTr("Cancel Upload") + text: qsTr("Confirm canceling the upload process?") + onYes: { + QGroundControl.mavlinkLogManager.cancelUpload() + } + } + } + } } } } diff --git a/src/ui/toolbar/BatteryIndicator.qml b/src/ui/toolbar/BatteryIndicator.qml new file mode 100644 index 0000000000000000000000000000000000000000..344c7714a0559fd888c5df48bbf1db8cbfc43354 --- /dev/null +++ b/src/ui/toolbar/BatteryIndicator.qml @@ -0,0 +1,129 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.MultiVehicleManager 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +//------------------------------------------------------------------------- +//-- Battery Indicator +Item { + anchors.top: parent.top + anchors.bottom: parent.bottom + width: batteryIndicatorRow.width + + function getBatteryColor() { + if(activeVehicle) { + if(activeVehicle.battery.percentRemaining.value > 75) { + return qgcPal.text + } + if(activeVehicle.battery.percentRemaining.value > 50) { + return colorOrange + } + if(activeVehicle.battery.percentRemaining.value > 0.1) { + return colorRed + } + } + return colorGrey + } + + function getBatteryPercentageText() { + if(activeVehicle) { + if(activeVehicle.battery.percentRemaining.value > 98.9) { + return "100%" + } + if(activeVehicle.battery.percentRemaining.value > 0.1) { + return activeVehicle.battery.percentRemaining.valueString + activeVehicle.battery.percentRemaining.units + } + if(activeVehicle.battery.voltage.value >= 0) { + return activeVehicle.battery.voltage.valueString + activeVehicle.battery.voltage.units + } + } + return "N/A" + } + + Component { + id: batteryInfo + + Rectangle { + width: battCol.width + ScreenTools.defaultFontPixelWidth * 3 + height: battCol.height + ScreenTools.defaultFontPixelHeight * 2 + radius: ScreenTools.defaultFontPixelHeight * 0.5 + color: qgcPal.window + border.color: qgcPal.text + + Column { + id: battCol + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + width: Math.max(battGrid.width, battLabel.width) + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.centerIn: parent + + QGCLabel { + id: battLabel + text: qsTr("Battery Status") + font.family: ScreenTools.demiboldFontFamily + anchors.horizontalCenter: parent.horizontalCenter + } + + GridLayout { + id: battGrid + anchors.margins: ScreenTools.defaultFontPixelHeight + columnSpacing: ScreenTools.defaultFontPixelWidth + columns: 2 + anchors.horizontalCenter: parent.horizontalCenter + + QGCLabel { text: qsTr("Voltage:") } + QGCLabel { text: (activeVehicle && activeVehicle.battery.voltage.value != -1) ? (activeVehicle.battery.voltage.valueString + " " + activeVehicle.battery.voltage.units) : "N/A" } + QGCLabel { text: qsTr("Accumulated Consumption:") } + QGCLabel { text: (activeVehicle && activeVehicle.battery.mahConsumed.value != -1) ? (activeVehicle.battery.mahConsumed.valueString + " " + activeVehicle.battery.mahConsumed.units) : "N/A" } + } + } + + Component.onCompleted: { + var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) + x = pos.x + y = pos.y + ScreenTools.defaultFontPixelHeight + } + } + } + + Row { + id: batteryIndicatorRow + anchors.top: parent.top + anchors.bottom: parent.bottom + opacity: (activeVehicle && activeVehicle.battery.voltage.value >= 0) ? 1 : 0.5 + QGCColoredImage { + anchors.top: parent.top + anchors.bottom: parent.bottom + width: height + sourceSize.width: width + source: "/qmlimages/Battery.svg" + fillMode: Image.PreserveAspectFit + color: qgcPal.text + } + QGCLabel { + text: getBatteryPercentageText() + font.pointSize: ScreenTools.mediumFontPointSize + color: getBatteryColor() + anchors.verticalCenter: parent.verticalCenter + } + } + MouseArea { + anchors.fill: parent + onClicked: mainWindow.showPopUp(batteryInfo, mapToItem(toolBar, x, y).x + (width / 2)) + } +} diff --git a/src/ui/toolbar/GPS.qml b/src/ui/toolbar/GPS.qml deleted file mode 100644 index af0001d8476e6b11bc3cf2b6f3247249bad01319..0000000000000000000000000000000000000000 --- a/src/ui/toolbar/GPS.qml +++ /dev/null @@ -1,34 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/** - * @file - * @brief QGC Main Tool GPS - * @author Gus Grubba - */ - -import QtQuick 2.4 -import QGroundControl.Controls 1.0 - -Item { - id: gpsRoot - property real size: 50 - property real percent: 0 - width: size - height: size - Image { - source: "/qmlimages/Gps.svg" - fillMode: Image.PreserveAspectFit - mipmap: true - smooth: true - anchors.fill: parent - opacity: (percent + 25) * 0.8 - } -} diff --git a/src/ui/toolbar/GPSIndicator.qml b/src/ui/toolbar/GPSIndicator.qml new file mode 100644 index 0000000000000000000000000000000000000000..d73479069f19b09b5d551d35cea5b56e3e06f9e2 --- /dev/null +++ b/src/ui/toolbar/GPSIndicator.qml @@ -0,0 +1,122 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.MultiVehicleManager 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +//------------------------------------------------------------------------- +//-- GPS Indicator +Item { + id: satelitte + width: (gpsValuesColumn.x + gpsValuesColumn.width) * 1.1 + anchors.top: parent.top + anchors.bottom: parent.bottom + + Component { + id: gpsInfo + + Rectangle { + width: gpsCol.width + ScreenTools.defaultFontPixelWidth * 3 + height: gpsCol.height + ScreenTools.defaultFontPixelHeight * 2 + radius: ScreenTools.defaultFontPixelHeight * 0.5 + color: qgcPal.window + border.color: qgcPal.text + + Column { + id: gpsCol + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + width: Math.max(gpsGrid.width, gpsLabel.width) + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.centerIn: parent + + QGCLabel { + id: gpsLabel + text: (activeVehicle && activeVehicle.gps.count.value >= 0) ? qsTr("GPS Status") : qsTr("GPS Data Unavailable") + font.family: ScreenTools.demiboldFontFamily + anchors.horizontalCenter: parent.horizontalCenter + } + + GridLayout { + id: gpsGrid + visible: (activeVehicle && activeVehicle.gps.count.value >= 0) + anchors.margins: ScreenTools.defaultFontPixelHeight + columnSpacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + columns: 2 + + QGCLabel { text: qsTr("GPS Count:") } + QGCLabel { text: activeVehicle ? activeVehicle.gps.count.valueString : qsTr("N/A", "No data to display") } + QGCLabel { text: qsTr("GPS Lock:") } + QGCLabel { text: activeVehicle ? activeVehicle.gps.lock.enumStringValue : qsTr("N/A", "No data to display") } + QGCLabel { text: qsTr("HDOP:") } + QGCLabel { text: activeVehicle ? activeVehicle.gps.hdop.valueString : qsTr("--.--", "No data to display") } + QGCLabel { text: qsTr("VDOP:") } + QGCLabel { text: activeVehicle ? activeVehicle.gps.vdop.valueString : qsTr("--.--", "No data to display") } + QGCLabel { text: qsTr("Course Over Ground:") } + QGCLabel { text: activeVehicle ? activeVehicle.gps.courseOverGround.valueString : qsTr("--.--", "No data to display") } + } + } + + Component.onCompleted: { + var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) + x = pos.x + y = pos.y + ScreenTools.defaultFontPixelHeight + } + } + } + + QGCColoredImage { + id: gpsIcon + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom + source: "/qmlimages/Gps.svg" + fillMode: Image.PreserveAspectFit + sourceSize.height: height + opacity: (activeVehicle && activeVehicle.gps.count.value >= 0) ? 1 : 0.5 + color: qgcPal.buttonText + } + + Column { + id: gpsValuesColumn + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2 + anchors.left: gpsIcon.right + + QGCLabel { + anchors.horizontalCenter: hdopValue.horizontalCenter + visible: activeVehicle && !isNaN(activeVehicle.gps.hdop.value) + color: qgcPal.buttonText + text: activeVehicle ? activeVehicle.gps.count.valueString : "" + } + + QGCLabel { + id: hdopValue + visible: activeVehicle && !isNaN(activeVehicle.gps.hdop.value) + color: qgcPal.buttonText + text: activeVehicle ? activeVehicle.gps.hdop.value.toFixed(1) : "" + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + var centerX = mapToItem(toolBar, x, y).x + (width / 2) + mainWindow.showPopUp(gpsInfo, centerX) + } + } +} diff --git a/src/ui/toolbar/Images/Analyze.svg b/src/ui/toolbar/Images/Analyze.svg index 3088987155fecef96a76c4be0d2a2c79ca32600d..d96303a5ef22f9600ddd83b0bd3d7496c58dfed2 100644 --- a/src/ui/toolbar/Images/Analyze.svg +++ b/src/ui/toolbar/Images/Analyze.svg @@ -1,34 +1,17 @@ - - - - - - - - - - + + + + + + + diff --git a/src/ui/toolbar/Images/CameraIcon.svg b/src/ui/toolbar/Images/CameraIcon.svg new file mode 100644 index 0000000000000000000000000000000000000000..1509445bd9c554f6976a46465cdc97aa6fd6faf0 --- /dev/null +++ b/src/ui/toolbar/Images/CameraIcon.svg @@ -0,0 +1,44 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/ui/toolbar/MainToolBar.qml b/src/ui/toolbar/MainToolBar.qml index c8603706776a9ab9382487015d5a2c4fd92ce8a0..8f656ceea56589625bc4ba1fd051f29f7db2a10d 100644 --- a/src/ui/toolbar/MainToolBar.qml +++ b/src/ui/toolbar/MainToolBar.qml @@ -7,17 +7,9 @@ * ****************************************************************************/ - -/** - * @file - * @brief QGC Main Tool Bar - * @author Gus Grubba - */ - -import QtQuick 2.5 -import QtQuick.Layouts 1.2 -import QtQuick.Controls 1.2 -import QtQuick.Controls.Styles 1.2 +import QtQuick 2.5 +import QtQuick.Layouts 1.2 +import QtQuick.Controls 1.2 import QGroundControl 1.0 import QGroundControl.Controls 1.0 @@ -32,18 +24,17 @@ Rectangle { QGCPalette { id: qgcPal; colorGroupEnabled: true } - property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle - property var mainWindow: null - property bool isMessageImportant: activeVehicle ? !activeVehicle.messageTypeNormal && !activeVehicle.messageTypeNone : false + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property bool isMessageImportant: _activeVehicle ? !_activeVehicle.messageTypeNormal && !_activeVehicle.messageTypeNone : false property bool isBackgroundDark: true property bool opaqueBackground: false - readonly property var colorGreen: "#05f068" - readonly property var colorOrange: "#f0ab06" - readonly property var colorRed: "#fc4638" - readonly property var colorGrey: "#7f7f7f" - readonly property var colorBlue: "#636efe" - readonly property var colorWhite: "#ffffff" + readonly property color colorGreen: "#05f068" + readonly property color colorOrange: "#f0ab06" + readonly property color colorRed: "#fc4638" + readonly property color colorGrey: "#7f7f7f" + readonly property color colorBlue: "#636efe" + readonly property color colorWhite: "#ffffff" signal showSettingsView signal showSetupView @@ -51,8 +42,6 @@ Rectangle { signal showFlyView signal showAnalyzeView - MainToolBarController { id: _controller } - function checkSettingsButton() { settingsButton.checked = true } @@ -73,365 +62,164 @@ Rectangle { analyzeButton.checked = true } - function getBatteryColor() { - if(activeVehicle) { - if(activeVehicle.battery.percentRemaining.value > 75) { - return qgcPal.text - } - if(activeVehicle.battery.percentRemaining.value > 50) { - return colorOrange - } - if(activeVehicle.battery.percentRemaining.value > 0.1) { - return colorRed - } - } - return colorGrey - } - - function getRSSIColor(value) { - if(value >= 0) - return colorGrey; - if(value > -60) - return colorGreen; - if(value > -90) - return colorOrange; - return colorRed; - } - Component.onCompleted: { //-- TODO: Get this from the actual state flyButton.checked = true } - //--------------------------------------------- - // GPS Info - Component { - id: gpsInfo - - Rectangle { - width: gpsCol.width + ScreenTools.defaultFontPixelWidth * 3 - height: gpsCol.height + ScreenTools.defaultFontPixelHeight * 2 - radius: ScreenTools.defaultFontPixelHeight * 0.5 - color: qgcPal.window - - Column { - id: gpsCol - spacing: ScreenTools.defaultFontPixelHeight * 0.5 - width: Math.max(gpsGrid.width, gpsLabel.width) - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.centerIn: parent - - QGCLabel { - id: gpsLabel - text: (activeVehicle && activeVehicle.gps.count.value >= 0) ? qsTr("GPS Status") : qsTr("GPS Data Unavailable") - font.family: ScreenTools.demiboldFontFamily - anchors.horizontalCenter: parent.horizontalCenter - } + /// Bottom single pixel divider + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + height: 1 + color: "black" + visible: qgcPal.globalTheme == QGCPalette.Light + } - GridLayout { - id: gpsGrid - visible: (activeVehicle && activeVehicle.gps.count.value >= 0) - anchors.margins: ScreenTools.defaultFontPixelHeight - columnSpacing: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter - columns: 2 - - QGCLabel { text: qsTr("GPS Count:") } - QGCLabel { text: activeVehicle ? activeVehicle.gps.count.valueString : qsTr("N/A", "No data to display") } - QGCLabel { text: qsTr("GPS Lock:") } - QGCLabel { text: activeVehicle ? activeVehicle.gps.lock.enumStringValue : qsTr("N/A", "No data to display") } - QGCLabel { text: qsTr("HDOP:") } - QGCLabel { text: activeVehicle ? activeVehicle.gps.hdop.valueString : qsTr("--.--", "No data to display") } - QGCLabel { text: qsTr("VDOP:") } - QGCLabel { text: activeVehicle ? activeVehicle.gps.vdop.valueString : qsTr("--.--", "No data to display") } - QGCLabel { text: qsTr("Course Over Ground:") } - QGCLabel { text: activeVehicle ? activeVehicle.gps.courseOverGround.valueString : qsTr("--.--", "No data to display") } - } + RowLayout { + anchors.bottomMargin: 1 + anchors.rightMargin: ScreenTools.defaultFontPixelWidth / 2 + anchors.fill: parent + spacing: ScreenTools.defaultFontPixelWidth * 2 + + //--------------------------------------------- + // Toolbar Row + Row { + id: viewRow + anchors.top: parent.top + anchors.bottom: parent.bottom + spacing: ScreenTools.defaultFontPixelWidth / 2 + + ExclusiveGroup { id: mainActionGroup } + + QGCToolBarButton { + id: settingsButton + anchors.top: parent.top + anchors.bottom: parent.bottom + exclusiveGroup: mainActionGroup + source: "/res/QGCLogoWhite" + logo: true + onClicked: toolBar.showSettingsView() + visible: !QGroundControl.corePlugin.options.combineSettingsAndSetup } - Component.onCompleted: { - var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) - x = pos.x - y = pos.y + ScreenTools.defaultFontPixelHeight + QGCToolBarButton { + id: setupButton + anchors.top: parent.top + anchors.bottom: parent.bottom + exclusiveGroup: mainActionGroup + source: "/qmlimages/Gears.svg" + onClicked: toolBar.showSetupView() } - } - } - - //--------------------------------------------- - // Battery Info - Component { - id: batteryInfo - - Rectangle { - width: battCol.width + ScreenTools.defaultFontPixelWidth * 3 - height: battCol.height + ScreenTools.defaultFontPixelHeight * 2 - radius: ScreenTools.defaultFontPixelHeight * 0.5 - color: qgcPal.window - - Column { - id: battCol - spacing: ScreenTools.defaultFontPixelHeight * 0.5 - width: Math.max(battGrid.width, battLabel.width) - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.centerIn: parent - - QGCLabel { - id: battLabel - text: qsTr("Battery Status") - font.family: ScreenTools.demiboldFontFamily - anchors.horizontalCenter: parent.horizontalCenter - } - GridLayout { - id: battGrid - anchors.margins: ScreenTools.defaultFontPixelHeight - columnSpacing: ScreenTools.defaultFontPixelWidth - columns: 2 - anchors.horizontalCenter: parent.horizontalCenter - - QGCLabel { text: qsTr("Voltage:") } - QGCLabel { text: (activeVehicle && activeVehicle.battery.voltage.value != -1) ? (activeVehicle.battery.voltage.valueString + " " + activeVehicle.battery.voltage.units) : "N/A" } - QGCLabel { text: qsTr("Accumulated Consumption:") } - QGCLabel { text: (activeVehicle && activeVehicle.battery.mahConsumed.value != -1) ? (activeVehicle.battery.mahConsumed.valueString + " " + activeVehicle.battery.mahConsumed.units) : "N/A" } - } + QGCToolBarButton { + id: planButton + anchors.top: parent.top + anchors.bottom: parent.bottom + exclusiveGroup: mainActionGroup + source: "/qmlimages/Plan.svg" + onClicked: toolBar.showPlanView() } - Component.onCompleted: { - var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) - x = pos.x - y = pos.y + ScreenTools.defaultFontPixelHeight + QGCToolBarButton { + id: flyButton + anchors.top: parent.top + anchors.bottom: parent.bottom + exclusiveGroup: mainActionGroup + source: "/qmlimages/PaperPlane.svg" + onClicked: toolBar.showFlyView() } - } - } - - //--------------------------------------------- - // RC RSSI Info - Component { - id: rcRSSIInfo - - Rectangle { - width: rcrssiCol.width + ScreenTools.defaultFontPixelWidth * 3 - height: rcrssiCol.height + ScreenTools.defaultFontPixelHeight * 2 - radius: ScreenTools.defaultFontPixelHeight * 0.5 - color: qgcPal.window - - Column { - id: rcrssiCol - spacing: ScreenTools.defaultFontPixelHeight * 0.5 - width: Math.max(rcrssiGrid.width, rssiLabel.width) - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.centerIn: parent - - QGCLabel { - id: rssiLabel - text: activeVehicle ? (activeVehicle.rcRSSI != 255 ? qsTr("RC RSSI Status") : qsTr("RC RSSI Data Unavailable")) : qsTr("N/A", "No data available") - font.family: ScreenTools.demiboldFontFamily - anchors.horizontalCenter: parent.horizontalCenter - } - GridLayout { - id: rcrssiGrid - visible: activeVehicle && activeVehicle.rcRSSI != 255 - anchors.margins: ScreenTools.defaultFontPixelHeight - columnSpacing: ScreenTools.defaultFontPixelWidth - columns: 2 - anchors.horizontalCenter: parent.horizontalCenter - - QGCLabel { text: qsTr("RSSI:") } - QGCLabel { text: activeVehicle ? (activeVehicle.rcRSSI + "%") : 0 } - } + QGCToolBarButton { + id: analyzeButton + anchors.top: parent.top + anchors.bottom: parent.bottom + exclusiveGroup: mainActionGroup + source: "/qmlimages/Analyze.svg" + visible: !ScreenTools.isMobile + onClicked: toolBar.showAnalyzeView() } - Component.onCompleted: { - var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) - x = pos.x - y = pos.y + ScreenTools.defaultFontPixelHeight + Rectangle { + anchors.margins: ScreenTools.defaultFontPixelHeight / 2 + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 1 + color: qgcPal.text + visible: _activeVehicle } } - } - //--------------------------------------------- - // Telemetry RSSI Info - Component { - id: telemRSSIInfo - - Rectangle { - width: telemCol.width + ScreenTools.defaultFontPixelWidth * 3 - height: telemCol.height + ScreenTools.defaultFontPixelHeight * 2 - radius: ScreenTools.defaultFontPixelHeight * 0.5 - color: qgcPal.window - - Column { - id: telemCol - spacing: ScreenTools.defaultFontPixelHeight * 0.5 - width: Math.max(telemGrid.width, telemLabel.width) - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.centerIn: parent - - QGCLabel { - id: telemLabel - text: qsTr("Telemetry RSSI Status") - font.family: ScreenTools.demiboldFontFamily - anchors.horizontalCenter: parent.horizontalCenter - } + //------------------------------------------------------------------------- + //-- Vehicle Selector + QGCButton { + id: vehicleSelectorButton + width: ScreenTools.defaultFontPixelHeight * 8 + text: "Vehicle " + (_activeVehicle ? _activeVehicle.id : "None") + visible: QGroundControl.multiVehicleManager.vehicles.count > 1 + anchors.verticalCenter: parent.verticalCenter - GridLayout { - id: telemGrid - anchors.margins: ScreenTools.defaultFontPixelHeight - columnSpacing: ScreenTools.defaultFontPixelWidth - columns: 2 - anchors.horizontalCenter: parent.horizontalCenter - - QGCLabel { text: qsTr("Local RSSI:") } - QGCLabel { text: _controller.telemetryLRSSI + " dBm" } - QGCLabel { text: qsTr("Remote RSSI:") } - QGCLabel { text: _controller.telemetryRRSSI + " dBm" } - QGCLabel { text: qsTr("RX Errors:") } - QGCLabel { text: _controller.telemetryRXErrors } - QGCLabel { text: qsTr("Errors Fixed:") } - QGCLabel { text: _controller.telemetryFixed } - QGCLabel { text: qsTr("TX Buffer:") } - QGCLabel { text: _controller.telemetryTXBuffer } - QGCLabel { text: qsTr("Local Noise:") } - QGCLabel { text: _controller.telemetryLNoise } - QGCLabel { text: qsTr("Remote Noise:") } - QGCLabel { text: _controller.telemetryRNoise } - } - } + menu: vehicleMenu - Component.onCompleted: { - var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) - x = pos.x - y = pos.y + ScreenTools.defaultFontPixelHeight + Menu { + id: vehicleMenu } - } - } - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - height: 1 - color: "black" - visible: qgcPal.globalTheme == QGCPalette.Light - } + Component { + id: vehicleMenuItemComponent - //--------------------------------------------- - // Toolbar Row - Row { - id: viewRow - height: mainWindow.tbCellHeight - spacing: mainWindow.tbSpacing - anchors.left: parent.left - anchors.bottomMargin: 1 - anchors.top: parent.top - anchors.bottom: parent.bottom + MenuItem { + onTriggered: QGroundControl.multiVehicleManager.activeVehicle = vehicle - ExclusiveGroup { id: mainActionGroup } + property int vehicleId: Number(text.split(" ")[1]) + property var vehicle: QGroundControl.multiVehicleManager.getVehicleById(vehicleId) + } + } - QGCToolBarButton { - id: settingsButton - width: mainWindow.tbButtonWidth - anchors.top: parent.top - anchors.bottom: parent.bottom - exclusiveGroup: mainActionGroup - source: "/res/QGCLogoWhite" - logo: true - onClicked: toolBar.showSettingsView() - } + property var vehicleMenuItems: [] - QGCToolBarButton { - id: setupButton - width: mainWindow.tbButtonWidth - anchors.top: parent.top - anchors.bottom: parent.bottom - exclusiveGroup: mainActionGroup - source: "/qmlimages/Gears.svg" - onClicked: toolBar.showSetupView() - } + function updateVehicleMenu() { + // Remove old menu items + for (var i = 0; i < vehicleMenuItems.length; i++) { + vehicleMenu.removeItem(vehicleMenuItems[i]) + } + vehicleMenuItems.length = 0 + + // Add new items + for (var i=0; i indicatorLoader.x + indicatorLoader.width && !disconnectButton.visible && source != "" - fillMode: Image.PreserveAspectFit - source: activeVehicle ? activeVehicle.brandImage : "" - } - } // Progress bar @@ -439,7 +227,7 @@ Rectangle { id: progressBar anchors.bottom: parent.bottom height: toolBar.height * 0.05 - width: parent.width * _controller.progressBarValue + width: _activeVehicle ? _activeVehicle.parameterManager.loadProgress * parent.width : 0 color: colorGreen } diff --git a/src/ui/toolbar/MainToolBarController.cc b/src/ui/toolbar/MainToolBarController.cc deleted file mode 100644 index 50a6d298ce606b970350da1a1d266d5b5845290c..0000000000000000000000000000000000000000 --- a/src/ui/toolbar/MainToolBarController.cc +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/** - * @file - * @brief QGC Main Tool Bar - * @author Gus Grubba - */ - -#include -#include - -#include "MainToolBarController.h" -#include "ScreenToolsController.h" -#include "UASMessageView.h" -#include "UASMessageHandler.h" -#include "QGCApplication.h" -#include "MultiVehicleManager.h" -#include "UAS.h" -#include "ParameterManager.h" - -MainToolBarController::MainToolBarController(QObject* parent) - : QObject(parent) - , _vehicle(NULL) - , _mav(NULL) - , _progressBarValue(0.0f) - , _telemetryRRSSI(0) - , _telemetryLRSSI(0) -{ - _activeVehicleChanged(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()); - connect(qgcApp()->toolbox()->mavlinkProtocol(), &MAVLinkProtocol::radioStatusChanged, this, &MainToolBarController::_telemetryChanged); - connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::activeVehicleChanged, this, &MainToolBarController::_activeVehicleChanged); -} - -MainToolBarController::~MainToolBarController() -{ - -} - -void MainToolBarController::_activeVehicleChanged(Vehicle* vehicle) -{ - // Disconnect the previous one (if any) - if (_vehicle) { - disconnect(_vehicle->parameterManager(), &ParameterManager::parameterListProgress, this, &MainToolBarController::_setProgressBarValue); - _mav = NULL; - _vehicle = NULL; - } - - // Connect new system - if (vehicle) - { - _vehicle = vehicle; - _mav = vehicle->uas(); - connect(_vehicle->parameterManager(), &ParameterManager::parameterListProgress, this, &MainToolBarController::_setProgressBarValue); - } -} - -void MainToolBarController::_telemetryChanged(LinkInterface*, unsigned rxerrors, unsigned fixed, int rssi, int remrssi, unsigned txbuf, unsigned noise, unsigned remnoise) -{ - if(_telemetryLRSSI != rssi) { - _telemetryLRSSI = rssi; - emit telemetryLRSSIChanged(_telemetryLRSSI); - } - if(_telemetryRRSSI != remrssi) { - _telemetryRRSSI = remrssi; - emit telemetryRRSSIChanged(_telemetryRRSSI); - } - if(_telemetryRXErrors != rxerrors) { - _telemetryRXErrors = rxerrors; - emit telemetryRXErrorsChanged(_telemetryRXErrors); - } - if(_telemetryFixed != fixed) { - _telemetryFixed = fixed; - emit telemetryFixedChanged(_telemetryFixed); - } - if(_telemetryTXBuffer != txbuf) { - _telemetryTXBuffer = txbuf; - emit telemetryTXBufferChanged(_telemetryTXBuffer); - } - if(_telemetryLNoise != noise) { - _telemetryLNoise = noise; - emit telemetryLNoiseChanged(_telemetryLNoise); - } - if(_telemetryRNoise != remnoise) { - _telemetryRNoise = remnoise; - emit telemetryRNoiseChanged(_telemetryRNoise); - } -} - -void MainToolBarController::_setProgressBarValue(float value) -{ - _progressBarValue = value; - emit progressBarValueChanged(value); -} diff --git a/src/ui/toolbar/MainToolBarController.h b/src/ui/toolbar/MainToolBarController.h deleted file mode 100644 index 99b8f232f667ba75f87f63a3aad526ba4950ac87..0000000000000000000000000000000000000000 --- a/src/ui/toolbar/MainToolBarController.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** - * - * (c) 2009-2016 QGROUNDCONTROL PROJECT - * - * QGroundControl is licensed according to the terms in the file - * COPYING.md in the root of the source code directory. - * - ****************************************************************************/ - - -/** - * @file - * @brief QGC Main Tool Bar - * @author Gus Grubba - */ - -#ifndef MainToolBarController_H -#define MainToolBarController_H - -#include - -#include "Vehicle.h" -#include "UASMessageView.h" - -#define TOOL_BAR_SETTINGS_GROUP "TOOLBAR_SETTINGS_GROUP" -#define TOOL_BAR_SHOW_BATTERY "ShowBattery" -#define TOOL_BAR_SHOW_GPS "ShowGPS" -#define TOOL_BAR_SHOW_MAV "ShowMav" -#define TOOL_BAR_SHOW_MESSAGES "ShowMessages" -#define TOOL_BAR_SHOW_RSSI "ShowRSSI" - -class MainToolBarController : public QObject -{ - Q_OBJECT - -public: - MainToolBarController(QObject* parent = NULL); - ~MainToolBarController(); - - Q_PROPERTY(double height MEMBER _toolbarHeight NOTIFY heightChanged) - Q_PROPERTY(float progressBarValue MEMBER _progressBarValue NOTIFY progressBarValueChanged) - Q_PROPERTY(int telemetryRRSSI READ telemetryRRSSI NOTIFY telemetryRRSSIChanged) - Q_PROPERTY(int telemetryLRSSI READ telemetryLRSSI NOTIFY telemetryLRSSIChanged) - Q_PROPERTY(unsigned int telemetryRXErrors READ telemetryRXErrors NOTIFY telemetryRXErrorsChanged) - Q_PROPERTY(unsigned int telemetryFixed READ telemetryFixed NOTIFY telemetryFixedChanged) - Q_PROPERTY(unsigned int telemetryTXBuffer READ telemetryTXBuffer NOTIFY telemetryTXBufferChanged) - Q_PROPERTY(unsigned int telemetryLNoise READ telemetryLNoise NOTIFY telemetryLNoiseChanged) - Q_PROPERTY(unsigned int telemetryRNoise READ telemetryRNoise NOTIFY telemetryRNoiseChanged) - - void viewStateChanged (const QString& key, bool value); - - int telemetryRRSSI () { return _telemetryRRSSI; } - int telemetryLRSSI () { return _telemetryLRSSI; } - unsigned int telemetryRXErrors () { return _telemetryRXErrors; } - unsigned int telemetryFixed () { return _telemetryFixed; } - unsigned int telemetryTXBuffer () { return _telemetryTXBuffer; } - unsigned int telemetryLNoise () { return _telemetryLNoise; } - unsigned int telemetryRNoise () { return _telemetryRNoise; } - -signals: - void progressBarValueChanged (float value); - void telemetryRRSSIChanged (int value); - void telemetryLRSSIChanged (int value); - void heightChanged (double height); - void telemetryRXErrorsChanged (unsigned int value); - void telemetryFixedChanged (unsigned int value); - void telemetryTXBufferChanged (unsigned int value); - void telemetryLNoiseChanged (unsigned int value); - void telemetryRNoiseChanged (unsigned int value); - -private slots: - void _activeVehicleChanged (Vehicle* vehicle); - void _setProgressBarValue (float value); - void _telemetryChanged (LinkInterface* link, unsigned rxerrors, unsigned fixed, int rssi, int remrssi, unsigned txbuf, unsigned noise, unsigned remnoise); - -private: - Vehicle* _vehicle; - UASInterface* _mav; - float _progressBarValue; - double _remoteRSSIstore; - int _telemetryRRSSI; - int _telemetryLRSSI; - uint32_t _telemetryRXErrors; - uint32_t _telemetryFixed; - uint32_t _telemetryTXBuffer; - uint32_t _telemetryLNoise; - uint32_t _telemetryRNoise; - - double _toolbarHeight; - - QStringList _toolbarMessageQueue; - QMutex _toolbarMessageQueueMutex; -}; - -#endif // MainToolBarController_H diff --git a/src/ui/toolbar/MainToolBarIndicators.qml b/src/ui/toolbar/MainToolBarIndicators.qml index bf2f0143b980b452f3cfdac4dc8c33fe7708cc85..16caea17a6076389c8bb0545ee92a245a8e8df01 100644 --- a/src/ui/toolbar/MainToolBarIndicators.qml +++ b/src/ui/toolbar/MainToolBarIndicators.qml @@ -8,385 +8,68 @@ ****************************************************************************/ -import QtQuick 2.5 -import QtQuick.Controls 1.2 -import QtGraphicalEffects 1.0 -import QtQuick.Controls.Styles 1.2 -import QtQuick.Dialogs 1.1 +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.2 -import QGroundControl 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.ScreenTools 1.0 -import QGroundControl.Palette 1.0 +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.MultiVehicleManager 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 -Row { - spacing: tbSpacing * 2 +Item { + property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property bool communicationLost: activeVehicle ? activeVehicle.connectionLost : false QGCPalette { id: qgcPal } - //------------------------------------------------------------------------- - function getMessageColor() { - if (activeVehicle) { - if (activeVehicle.messageTypeNone) - return colorGrey - if (activeVehicle.messageTypeNormal) - return colorBlue; - if (activeVehicle.messageTypeWarning) - return colorOrange; - if (activeVehicle.messageTypeError) - return colorRed; - // Cannot be so make make it obnoxious to show error - console.log("Invalid vehicle message type") - return "purple"; - } - //-- It can only get here when closing (vehicle gone while window active) - return "white"; - } - - //------------------------------------------------------------------------- - function getBatteryVoltageText() { - if (activeVehicle.battery.voltage.value >= 0) { - return activeVehicle.battery.voltage.valueString + activeVehicle.battery.voltage.units - } - return 'N/A'; - } - - //------------------------------------------------------------------------- - function getBatteryPercentageText() { - if(activeVehicle) { - if(activeVehicle.battery.percentRemaining.value > 98.9) { - return "100%" - } - if(activeVehicle.battery.percentRemaining.value > 0.1) { - return activeVehicle.battery.percentRemaining.valueString + activeVehicle.battery.percentRemaining.units - } - if(activeVehicle.battery.voltage.value >= 0) { - return activeVehicle.battery.voltage.valueString + activeVehicle.battery.voltage.units + Row { + id: indicatorRow + anchors.top: parent.top + anchors.bottom: parent.bottom + spacing: ScreenTools.defaultFontPixelWidth * 1.5 + visible: !communicationLost + Repeater { + model: QGroundControl.corePlugin.toolBarIndicators + Loader { + anchors.top: parent.top + anchors.bottom: parent.bottom + source: modelData; } } - return "N/A" } - //------------------------------------------------------------------------- - //-- Message Indicator - Item { - id: messages - width: mainWindow.tbCellHeight - height: mainWindow.tbCellHeight - visible: activeVehicle && activeVehicle.messageCount - anchors.verticalCenter: parent.verticalCenter - Item { - id: criticalMessage - anchors.fill: parent - visible: activeVehicle && activeVehicle.messageCount > 0 && isMessageImportant - Image { - source: "/qmlimages/Yield.svg" - height: mainWindow.tbCellHeight * 0.75 - sourceSize.height: height - fillMode: Image.PreserveAspectFit - cache: false - visible: isMessageImportant - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - } - } - Item { - anchors.fill: parent - visible: !criticalMessage.visible - QGCColoredImage { - id: messageIcon - source: "/qmlimages/Megaphone.svg" - height: mainWindow.tbCellHeight * 0.5 - width: height - sourceSize.height: height - fillMode: Image.PreserveAspectFit - color: getMessageColor() - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - } - } - MouseArea { - anchors.fill: parent - onClicked: { - mainWindow.showMessageArea() - } - } + Image { + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + visible: x > indicatorRow.width && !communicationLost + fillMode: Image.PreserveAspectFit + source: activeVehicle ? activeVehicle.brandImage : "" } - //------------------------------------------------------------------------- - //-- GPS Indicator - Item { - id: satelitte - width: (gpsValuesColumn.x + gpsValuesColumn.width) * 1.1 - height: mainWindow.tbCellHeight - - QGCColoredImage { - id: gpsIcon - source: "/qmlimages/Gps.svg" - fillMode: Image.PreserveAspectFit - width: mainWindow.tbCellHeight * 0.65 - height: mainWindow.tbCellHeight * 0.5 - sourceSize.height: height - opacity: (activeVehicle && activeVehicle.gps.count.value >= 0) ? 1 : 0.5 - color: qgcPal.buttonText - anchors.verticalCenter: parent.verticalCenter - } + Row { + anchors.fill: parent + layoutDirection: Qt.RightToLeft + spacing: ScreenTools.defaultFontPixelWidth + visible: communicationLost - Column { - id: gpsValuesColumn + QGCButton { + id: disconnectButton anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2 - anchors.left: gpsIcon.right - - QGCLabel { - anchors.horizontalCenter: hdopValue.horizontalCenter - visible: activeVehicle && !isNaN(activeVehicle.gps.hdop.value) - color: qgcPal.buttonText - text: activeVehicle ? activeVehicle.gps.count.valueString : "" - } - - QGCLabel { - id: hdopValue - visible: activeVehicle && !isNaN(activeVehicle.gps.hdop.value) - color: qgcPal.buttonText - text: activeVehicle ? activeVehicle.gps.hdop.value.toFixed(1) : "" - } - } // Column - - MouseArea { - anchors.fill: parent - onClicked: { - var centerX = mapToItem(toolBar, x, y).x + (width / 2) - mainWindow.showPopUp(gpsInfo, centerX) - } + text: qsTr("Disconnect") + primary: true + onClicked: activeVehicle.disconnectInactiveVehicle() } - } - //------------------------------------------------------------------------- - //-- RC RSSI - Item { - id: rcRssi - width: rssiRow.width * 1.1 - height: mainWindow.tbCellHeight - visible: activeVehicle ? activeVehicle.supportsRadio : true - Row { - id: rssiRow - height: parent.height - spacing: ScreenTools.defaultFontPixelWidth - QGCColoredImage { - width: mainWindow.tbCellHeight * 0.65 - height: width - sourceSize.height: height - source: "/qmlimages/RC.svg" - fillMode: Image.PreserveAspectFit - opacity: activeVehicle ? (((activeVehicle.rcRSSI < 0) || (activeVehicle.rcRSSI > 100)) ? 0.5 : 1) : 0.5 - color: qgcPal.buttonText - anchors.verticalCenter: parent.verticalCenter - } - SignalStrength { - size: mainWindow.tbCellHeight * 0.5 - percent: activeVehicle ? ((activeVehicle.rcRSSI > 100) ? 0 : activeVehicle.rcRSSI) : 0 - anchors.verticalCenter: parent.verticalCenter - } - } - MouseArea { - anchors.fill: parent - onClicked: { - var centerX = mapToItem(toolBar, x, y).x + (width / 2) - mainWindow.showPopUp(rcRSSIInfo, centerX) - } - } - } - - //------------------------------------------------------------------------- - //-- Telemetry RSSI - Item { - id: telemRssi - width: telemIcon.width - height: mainWindow.tbCellHeight - visible: _controller.telemetryLRSSI < 0 - QGCColoredImage { - id: telemIcon - height: parent.height * 0.5 - sourceSize.height: height - width: height * 1.5 - source: "/qmlimages/TelemRSSI.svg" - fillMode: Image.PreserveAspectFit - color: qgcPal.buttonText + QGCLabel { + id: connectionLost anchors.verticalCenter: parent.verticalCenter - } - MouseArea { - anchors.fill: parent - onClicked: { - var centerX = mapToItem(toolBar, x, y).x + (width / 2) - mainWindow.showPopUp(telemRSSIInfo, centerX) - } - } - } - - //------------------------------------------------------------------------- - //-- Battery Indicator - Item { - id: batteryStatus - width: battRow.width * 1.1 - height: mainWindow.tbCellHeight - opacity: (activeVehicle && activeVehicle.battery.voltage.value >= 0) ? 1 : 0.5 - Row { - id: battRow - height: mainWindow.tbCellHeight - anchors.horizontalCenter: parent.horizontalCenter - QGCColoredImage { - height: mainWindow.tbCellHeight * 0.65 - width: height - sourceSize.width: width - source: "/qmlimages/Battery.svg" - fillMode: Image.PreserveAspectFit - color: qgcPal.text - anchors.verticalCenter: parent.verticalCenter - } - QGCLabel { - text: getBatteryPercentageText() - font.pointSize: ScreenTools.mediumFontPointSize - color: getBatteryColor() - anchors.verticalCenter: parent.verticalCenter - } - } - MouseArea { - anchors.fill: parent - onClicked: { - if (activeVehicle) { - var centerX = mapToItem(toolBar, x, y).x + (width / 2) - mainWindow.showPopUp(batteryInfo, centerX) - } - } - } - } - - //------------------------------------------------------------------------- - //-- Vehicle Selector - QGCButton { - id: vehicleSelectorButton - width: ScreenTools.defaultFontPixelHeight * 8 - text: "Vehicle " + (activeVehicle ? activeVehicle.id : "None") - visible: QGroundControl.multiVehicleManager.vehicles.count > 1 - anchors.verticalCenter: parent.verticalCenter - - menu: vehicleMenu - - Menu { - id: vehicleMenu - } - - Component { - id: vehicleMenuItemComponent - - MenuItem { - checkable: true - onTriggered: QGroundControl.multiVehicleManager.activeVehicle = vehicle - - property int vehicleId: Number(text.split(" ")[1]) - property var vehicle: QGroundControl.multiVehicleManager.getVehicleById(vehicleId) - } - } - - property var vehicleMenuItems: [] - - function updateVehicleMenu() { - // Remove old menu items - for (var i = 0; i < vehicleMenuItems.length; i++) { - vehicleMenu.removeItem(vehicleMenuItems[i]) - } - vehicleMenuItems.length = 0 - - // Add new items - for (var i=0; i + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.MultiVehicleManager 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +//------------------------------------------------------------------------- +//-- GPS Indicator +Item { + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom + + function getMessageColor() { + if (activeVehicle) { + if (activeVehicle.messageTypeNone) + return colorGrey + if (activeVehicle.messageTypeNormal) + return colorBlue; + if (activeVehicle.messageTypeWarning) + return colorOrange; + if (activeVehicle.messageTypeError) + return colorRed; + // Cannot be so make make it obnoxious to show error + console.log("Invalid vehicle message type") + return "purple"; + } + //-- It can only get here when closing (vehicle gone while window active) + return "white"; + } + + Image { + id: criticalMessageIcon + anchors.fill: parent + source: "/qmlimages/Yield.svg" + sourceSize.height: height + fillMode: Image.PreserveAspectFit + cache: false + visible: activeVehicle && activeVehicle.messageCount > 0 && isMessageImportant + } + + QGCColoredImage { + anchors.fill: parent + source: "/qmlimages/Megaphone.svg" + sourceSize.height: height + fillMode: Image.PreserveAspectFit + color: getMessageColor() + visible: !criticalMessageIcon.visible + } + + MouseArea { + anchors.fill: parent + onClicked: mainWindow.showMessageArea() + } +} diff --git a/src/ui/toolbar/ModeIndicator.qml b/src/ui/toolbar/ModeIndicator.qml new file mode 100644 index 0000000000000000000000000000000000000000..2d8ba75259bfabbe1ed4493e54846963f4392880 --- /dev/null +++ b/src/ui/toolbar/ModeIndicator.qml @@ -0,0 +1,63 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.MultiVehicleManager 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +//------------------------------------------------------------------------- +//-- Mode Indicator +QGCLabel { + id: flightModeSelector + text: activeVehicle ? activeVehicle.flightMode : qsTr("N/A", "No data to display") + font.pointSize: ScreenTools.mediumFontPointSize + color: qgcPal.buttonText + anchors.verticalCenter: parent.verticalCenter + Menu { + id: flightModesMenu + } + Component { + id: flightModeMenuItemComponent + MenuItem { + onTriggered: activeVehicle.flightMode = text + } + } + property var flightModesMenuItems: [] + function updateFlightModesMenu() { + if (activeVehicle && activeVehicle.flightModeSetAvailable) { + // Remove old menu items + for (var i = 0; i < flightModesMenuItems.length; i++) { + flightModesMenu.removeItem(flightModesMenuItems[i]) + } + flightModesMenuItems.length = 0 + // Add new items + for (var i = 0; i < activeVehicle.flightModes.length; i++) { + var menuItem = flightModeMenuItemComponent.createObject(null, { "text": activeVehicle.flightModes[i] }) + flightModesMenuItems.push(menuItem) + flightModesMenu.insertItem(i, menuItem) + } + } + } + Component.onCompleted: flightModeSelector.updateFlightModesMenu() + Connections { + target: QGroundControl.multiVehicleManager + onActiveVehicleChanged: flightModeSelector.updateFlightModesMenu() + } + MouseArea { + visible: activeVehicle && activeVehicle.flightModeSetAvailable + anchors.fill: parent + onClicked: flightModesMenu.popup() + } +} diff --git a/src/ui/toolbar/RCRSSIIndicator.qml b/src/ui/toolbar/RCRSSIIndicator.qml new file mode 100644 index 0000000000000000000000000000000000000000..64471abf26ff99419c40a60c34b1e6c744e46412 --- /dev/null +++ b/src/ui/toolbar/RCRSSIIndicator.qml @@ -0,0 +1,105 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.MultiVehicleManager 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +//------------------------------------------------------------------------- +//-- GPS Indicator +Item { + width: rssiRow.width * 1.1 + anchors.top: parent.top + anchors.bottom: parent.bottom + visible: activeVehicle ? activeVehicle.supportsRadio : true + + Component { + id: rcRSSIInfo + + Rectangle { + width: rcrssiCol.width + ScreenTools.defaultFontPixelWidth * 3 + height: rcrssiCol.height + ScreenTools.defaultFontPixelHeight * 2 + radius: ScreenTools.defaultFontPixelHeight * 0.5 + color: qgcPal.window + border.color: qgcPal.text + + Column { + id: rcrssiCol + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + width: Math.max(rcrssiGrid.width, rssiLabel.width) + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.centerIn: parent + + QGCLabel { + id: rssiLabel + text: activeVehicle ? (activeVehicle.rcRSSI != 255 ? qsTr("RC RSSI Status") : qsTr("RC RSSI Data Unavailable")) : qsTr("N/A", "No data available") + font.family: ScreenTools.demiboldFontFamily + anchors.horizontalCenter: parent.horizontalCenter + } + + GridLayout { + id: rcrssiGrid + visible: activeVehicle && activeVehicle.rcRSSI != 255 + anchors.margins: ScreenTools.defaultFontPixelHeight + columnSpacing: ScreenTools.defaultFontPixelWidth + columns: 2 + anchors.horizontalCenter: parent.horizontalCenter + + QGCLabel { text: qsTr("RSSI:") } + QGCLabel { text: activeVehicle ? (activeVehicle.rcRSSI + "%") : 0 } + } + } + + Component.onCompleted: { + var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) + x = pos.x + y = pos.y + ScreenTools.defaultFontPixelHeight + } + } + } + + Row { + id: rssiRow + anchors.top: parent.top + anchors.bottom: parent.bottom + spacing: ScreenTools.defaultFontPixelWidth + + QGCColoredImage { + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom + sourceSize.height: height + source: "/qmlimages/RC.svg" + fillMode: Image.PreserveAspectFit + opacity: activeVehicle ? (((activeVehicle.rcRSSI < 0) || (activeVehicle.rcRSSI > 100)) ? 0.5 : 1) : 0.5 + color: qgcPal.buttonText + } + + SignalStrength { + anchors.verticalCenter: parent.verticalCenter + size: parent.height * 0.5 + percent: activeVehicle ? ((activeVehicle.rcRSSI > 100) ? 0 : activeVehicle.rcRSSI) : 0 + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + var centerX = mapToItem(toolBar, x, y).x + (width / 2) + mainWindow.showPopUp(rcRSSIInfo, centerX) + } + } +} diff --git a/src/ui/toolbar/TelemetryRSSIIndicator.qml b/src/ui/toolbar/TelemetryRSSIIndicator.qml new file mode 100644 index 0000000000000000000000000000000000000000..145fa6519c3165c73c8a7a14941842c28506363b --- /dev/null +++ b/src/ui/toolbar/TelemetryRSSIIndicator.qml @@ -0,0 +1,87 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.MultiVehicleManager 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +//------------------------------------------------------------------------- +//-- Telemetry RSSI +QGCColoredImage { + anchors.top: parent.top + anchors.bottom: parent.bottom + sourceSize.height: height + source: "/qmlimages/TelemRSSI.svg" + fillMode: Image.PreserveAspectFit + color: qgcPal.buttonText + visible: activeVehicle ? (activeVehicle.telemetryLRSSI < 0) : false + Component { + id: telemRSSIInfo + Rectangle { + width: telemCol.width + ScreenTools.defaultFontPixelWidth * 3 + height: telemCol.height + ScreenTools.defaultFontPixelHeight * 2 + radius: ScreenTools.defaultFontPixelHeight * 0.5 + color: qgcPal.window + border.color: qgcPal.text + Column { + id: telemCol + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + width: Math.max(telemGrid.width, telemLabel.width) + anchors.margins: ScreenTools.defaultFontPixelHeight + anchors.centerIn: parent + QGCLabel { + id: telemLabel + text: qsTr("Telemetry RSSI Status") + font.family: ScreenTools.demiboldFontFamily + anchors.horizontalCenter: parent.horizontalCenter + } + GridLayout { + id: telemGrid + anchors.margins: ScreenTools.defaultFontPixelHeight + columnSpacing: ScreenTools.defaultFontPixelWidth + columns: 2 + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { text: qsTr("Local RSSI:") } + QGCLabel { text: activeVehicle.telemetryLRSSI + " dBm" } + QGCLabel { text: qsTr("Remote RSSI:") } + QGCLabel { text: activeVehicle.telemetryRRSSI + " dBm" } + QGCLabel { text: qsTr("RX Errors:") } + QGCLabel { text: activeVehicle.telemetryRXErrors } + QGCLabel { text: qsTr("Errors Fixed:") } + QGCLabel { text: activeVehicle.telemetryFixed } + QGCLabel { text: qsTr("TX Buffer:") } + QGCLabel { text: activeVehicle.telemetryTXBuffer } + QGCLabel { text: qsTr("Local Noise:") } + QGCLabel { text: activeVehicle.telemetryLNoise } + QGCLabel { text: qsTr("Remote Noise:") } + QGCLabel { text: activeVehicle.telemetryRNoise } + } + } + Component.onCompleted: { + var pos = mapFromItem(toolBar, centerX - (width / 2), toolBar.height) + x = pos.x + y = pos.y + ScreenTools.defaultFontPixelHeight + } + } + } + MouseArea { + anchors.fill: parent + onClicked: { + var centerX = mapToItem(toolBar, x, y).x + (width / 2) + mainWindow.showPopUp(telemRSSIInfo, centerX) + } + } +} diff --git a/tools/StripAndTarQtForAndroidMin.sh b/tools/StripAndTarQtForAndroidMin.sh new file mode 100755 index 0000000000000000000000000000000000000000..548c74dfc317ef066d1f569b118da88c674bf5c6 --- /dev/null +++ b/tools/StripAndTarQtForAndroidMin.sh @@ -0,0 +1,19 @@ +#!/bin/bash +if [ $# -eq 0 ]; then + echo 'Qt directory must be specified as argument' + exit 1 +fi +if [ ! -d $1 ] ; then + echo 'Qt directory not found' + exit 1 +fi +cd $1 +rm * +find . ! -name '5.8' -maxdepth 1 -type d -exec rm -rf {} + +cd 5.8 +find . ! -name 'android_armv7' -maxdepth 1 -type d -exec rm -rf {} + +cd clang_64 +rm -rf doc +cd $1 +cd .. +tar -jcvf Qt5.8.0-android-min.tar.bz2 $1 diff --git a/tools/StripAndTarQtForLinuxMin.sh b/tools/StripAndTarQtForLinuxMin.sh new file mode 100755 index 0000000000000000000000000000000000000000..b813c5b77b3bb531277a31ba31a9d86289f6796d --- /dev/null +++ b/tools/StripAndTarQtForLinuxMin.sh @@ -0,0 +1,19 @@ +#!/bin/bash +if [ $# -eq 0 ]; then + echo 'Qt directory must be specified as argument' + exit 1 +fi +if [ ! -d $1 ] ; then + echo 'Qt directory not found' + exit 1 +fi +cd $1 +rm * +find . ! -name '5.8' -maxdepth 1 -type d -exec rm -rf {} + +cd 5.8 +find . ! -name 'gcc_64' -maxdepth 1 -type d -exec rm -rf {} + +cd clang_64 +rm -rf doc +cd $1 +cd .. +tar -jcvf Qt5.8.0-linux-min.tar.bz2 $1 diff --git a/tools/StripAndTarQtForOSXMin.sh b/tools/StripAndTarQtForOSXMin.sh new file mode 100755 index 0000000000000000000000000000000000000000..1e16db34ac1b14863d9dc07ade30d9493a207006 --- /dev/null +++ b/tools/StripAndTarQtForOSXMin.sh @@ -0,0 +1,21 @@ +#!/bin/bash +if [ $# -eq 0 ]; then + echo 'Qt directory must be specified as argument' + exit 1 +fi +if [ ! -d $1 ] ; then + echo 'Qt directory not found' + exit 1 +fi +cd $1 +rm * +find . ! -name '5.8' -maxdepth 1 -type d -exec rm -rf {} + +cd 5.8 +find . ! -name 'clang_64' -maxdepth 1 -type d -exec rm -rf {} + +cd clang_64 +rm -rf doc +cd lib +rm -rf *.dSYM +cd $1 +cd .. +tar -jcvf Qt5.8.0-mac-clang-min.tar.bz2 $1 diff --git a/tools/StripAndTarQtForiOSMin.sh b/tools/StripAndTarQtForiOSMin.sh new file mode 100755 index 0000000000000000000000000000000000000000..d50e537a2d51eb41c8140ecd5c1cfbf696d7c1f0 --- /dev/null +++ b/tools/StripAndTarQtForiOSMin.sh @@ -0,0 +1,23 @@ +#!/bin/bash +if [ $# -eq 0 ]; then + echo 'Qt directory must be specified as argument' + exit 1 +fi +if [ ! -d $1 ] ; then + echo 'Qt directory not found' + exit 1 +fi +cd $1 +rm * +find . ! -name '5.8' -maxdepth 1 -type d -exec rm -rf {} + +cd 5.8 +find . ! -name 'ios' -maxdepth 1 -type d -exec rm -rf {} + +cd ios +rm -rf doc +find . -type f -name 'lib*_debug.a' -delete +find . -type f -name 'lib*_debug.la' -delete +find . -type f -name 'lib*_debug.prl' -delete +cd .. +cd .. +cd .. +tar -jcvf Qt5.8.0-mac-ios-min.tar.bz2 $1