Commit 0790eb2a authored by Gus Grubba's avatar Gus Grubba

Merge branch 'master' of https://github.com/mavlink/qgroundcontrol into pr-plugin-control

parents a954332b 67118103
......@@ -3,6 +3,74 @@ pipeline {
stages {
stage('build') {
parallel {
stage('Linux Debug') {
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'debug'
QMAKE_VER = "5.9.2/gcc_64/bin/qmake"
}
agent {
docker {
image 'mavlink/qgc-build-linux'
args '-v ${CCACHE_DIR}:${CCACHE_DIR}:rw'
}
}
steps {
sh 'export'
sh 'ccache -z'
sh 'git submodule deinit -f .'
sh 'git clean -ff -x -d .'
sh 'git submodule update --init --recursive --force'
sh 'mkdir build; cd build; ${QT_PATH}/${QMAKE_VER} -r ${WORKSPACE}/qgroundcontrol.pro CONFIG+=${QGC_CONFIG} CONFIG+=WarningsAsErrorsOn'
sh 'cd build; make -j`nproc --all`'
sh 'ccache -s'
}
}
stage('Linux Release') {
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'release'
QMAKE_VER = "5.9.2/gcc_64/bin/qmake"
}
agent {
docker {
image 'mavlink/qgc-build-linux'
args '-v ${CCACHE_DIR}:${CCACHE_DIR}:rw'
}
}
steps {
sh 'export'
sh 'ccache -z'
sh 'git submodule deinit -f .'
sh 'git clean -ff -x -d .'
sh 'git submodule update --init --recursive --force'
sh 'mkdir build; cd build; ${QT_PATH}/${QMAKE_VER} -r ${WORKSPACE}/qgroundcontrol.pro CONFIG+=${QGC_CONFIG} CONFIG+=WarningsAsErrorsOn'
sh 'cd build; make -j`nproc --all`'
sh 'ccache -s'
}
}
stage('OSX Debug') {
agent {
node {
label 'mac'
}
}
environment {
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'debug'
QMAKE_VER = "5.9.3/clang_64/bin/qmake"
}
steps {
sh 'export'
sh 'ccache -z'
sh 'git submodule deinit -f .'
sh 'git clean -ff -x -d .'
sh 'git submodule update --init --recursive --force'
sh 'mkdir build; cd build; ${QT_PATH}/${QMAKE_VER} -r ${WORKSPACE}/qgroundcontrol.pro CONFIG+=${QGC_CONFIG} CONFIG+=WarningsAsErrorsOn'
sh 'cd build; make -j`sysctl -n hw.ncpu`'
sh 'ccache -s'
}
}
stage('OSX Release') {
agent {
node {
......@@ -10,16 +78,18 @@ pipeline {
}
}
environment {
QT_FATAL_WARNINGS = '1'
QMAKESPEC = 'macx-clang'
CCACHE_BASEDIR = "${env.WORKSPACE}"
QGC_CONFIG = 'release'
QMAKE_VER = "5.9.3/clang_64/bin/qmake"
}
steps {
sh 'export'
sh 'ccache -z'
sh 'git submodule deinit -f .'
sh 'git clean -ff -x -d .'
sh 'git submodule update --init --recursive --force'
sh 'rm -rf ${SHADOW_BUILD_DIR}; mkdir -p ${SHADOW_BUILD_DIR}'
sh 'cd ${SHADOW_BUILD_DIR}; ${QT_PATH}/5.9.3/clang_64/bin/qmake -r ${WORKSPACE}/qgroundcontrol.pro CONFIG+=release CONFIG+=WarningsAsErrorsOn'
sh 'cd ${SHADOW_BUILD_DIR}; make -j`sysctl -n hw.ncpu`'
sh 'mkdir build; cd build; ${QT_PATH}/${QMAKE_VER} -r ${WORKSPACE}/qgroundcontrol.pro CONFIG+=${QGC_CONFIG} CONFIG+=WarningsAsErrorsOn'
sh 'cd build; make -j`sysctl -n hw.ncpu`'
sh 'ccache -s'
}
}
......@@ -27,8 +97,8 @@ pipeline {
}
}
environment {
SHADOW_BUILD_DIR = '/tmp/jenkins/shadow_build_dir'
CCACHE_CPP2 = '1'
CCACHE_BASEDIR = '${WORKSPACE}'
CCACHE_DIR = '/tmp/ccache'
QT_FATAL_WARNINGS = '1'
}
}
\ No newline at end of file
}
......@@ -146,7 +146,8 @@ LinuxBuild {
platforminputcontexts \
platforms \
position \
sqldrivers
sqldrivers \
texttospeech
!contains(DEFINES, __rasp_pi2__) {
QT_PLUGIN_LIST += xcbglintegrations
......
......@@ -34,10 +34,9 @@ mkdir -p ${APPDIR}
cd ${TMPDIR}
wget -c --quiet http://ftp.us.debian.org/debian/pool/main/u/udev/udev_175-7.2_amd64.deb
wget -c --quiet http://ftp.us.debian.org/debian/pool/main/e/espeak/espeak_1.46.02-2_amd64.deb
wget -c --quiet http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/speech-dispatcher_0.8.8-1_amd64.deb
wget -c --quiet http://ftp.us.debian.org/debian/pool/main/libs/libsdl2/libsdl2-2.0-0_2.0.2%2bdfsg1-6_amd64.deb
cd ${APPDIR}
find ../ -name *.deb -exec dpkg -x {} . \;
......
Subproject commit 5db5e944048cd6126a3e58c67c9c4dcdb4d4e0ff
Subproject commit f36b9c4c5c0c9b6d33621779469de0c1e7eea457
......@@ -7,14 +7,16 @@
# License terms set in COPYING.md
# -------------------------------------------------
QMAKE_PROJECT_DEPTH = 0 # undocumented qmake flag to force absolute paths in make files
exists($${OUT_PWD}/qgroundcontrol.pro) {
error("You must use shadow build (e.g. mkdir build; cd build; qmake ../qgroundcontrol.pro).")
}
message(Qt version $$[QT_VERSION])
!equals(QT_MAJOR_VERSION, 5) | !greaterThan(QT_MINOR_VERSION, 6) {
error("Unsupported Qt version, 5.7+ is required")
!equals(QT_MAJOR_VERSION, 5) | !greaterThan(QT_MINOR_VERSION, 8) {
error("Unsupported Qt version, 5.9+ is required")
}
include(QGCCommon.pri)
......@@ -207,8 +209,7 @@ contains(DEFINES, ENABLE_VERBOSE_OUTPUT) {
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, ENABLE_VERBOSE_OUTPUT) {
message("Enable verbose compiler output (manual override from user_config.pri)")
} else {
CONFIG += \
silent
CONFIG += silent
}
QT += \
......@@ -414,6 +415,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/FactSystem/FactSystemTestGeneric.h \
src/FactSystem/FactSystemTestPX4.h \
src/FactSystem/ParameterManagerTest.h \
src/MissionManager/CameraCalcTest.h \
src/MissionManager/CameraSectionTest.h \
src/MissionManager/CorridorScanComplexItemTest.h \
src/MissionManager/MissionCommandTreeTest.h \
......@@ -430,6 +432,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/SpeedSectionTest.h \
src/MissionManager/StructureScanComplexItemTest.h \
src/MissionManager/SurveyMissionItemTest.h \
src/MissionManager/TransectStyleComplexItemTest.h \
src/MissionManager/VisualMissionItemTest.h \
src/qgcunittest/FileDialogTest.h \
src/qgcunittest/FileManagerTest.h \
......@@ -453,6 +456,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/FactSystem/FactSystemTestGeneric.cc \
src/FactSystem/FactSystemTestPX4.cc \
src/FactSystem/ParameterManagerTest.cc \
src/MissionManager/CameraCalcTest.cc \
src/MissionManager/CameraSectionTest.cc \
src/MissionManager/CorridorScanComplexItemTest.cc \
src/MissionManager/MissionCommandTreeTest.cc \
......@@ -469,6 +473,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/SpeedSectionTest.cc \
src/MissionManager/StructureScanComplexItemTest.cc \
src/MissionManager/SurveyMissionItemTest.cc \
src/MissionManager/TransectStyleComplexItemTest.cc \
src/MissionManager/VisualMissionItemTest.cc \
src/qgcunittest/FileDialogTest.cc \
src/qgcunittest/FileManagerTest.cc \
......@@ -540,6 +545,7 @@ HEADERS += \
src/MissionManager/SpeedSection.h \
src/MissionManager/StructureScanComplexItem.h \
src/MissionManager/SurveyMissionItem.h \
src/MissionManager/TransectStyleComplexItem.h \
src/MissionManager/VisualMissionItem.h \
src/PositionManager/PositionManager.h \
src/PositionManager/SimulatedPosition.h \
......@@ -733,6 +739,7 @@ SOURCES += \
src/MissionManager/SpeedSection.cc \
src/MissionManager/StructureScanComplexItem.cc \
src/MissionManager/SurveyMissionItem.cc \
src/MissionManager/TransectStyleComplexItem.cc \
src/MissionManager/VisualMissionItem.cc \
src/PositionManager/PositionManager.cpp \
src/PositionManager/SimulatedPosition.cc \
......
This diff is collapsed.
......@@ -110,7 +110,7 @@ AnalyzePage {
}
QGCLabel {
text: geoController.saveDirectory != "" ? geoController.saveDirectory : "/TAGGED folder in your image folder"
text: geoController.saveDirectory !== "" ? geoController.saveDirectory : "/TAGGED folder in your image folder"
anchors.verticalCenter: parent.verticalCenter
}
}
......
......@@ -55,7 +55,7 @@ SetupPage {
property real _lastValue: 0
onTriggered: {
if (_lastValue != slider.value) {
if (_lastValue !== slider.value) {
controller.vehicle.motorTest(index + 1, slider.value, 1)
}
}
......
......@@ -379,7 +379,7 @@ SetupPage {
text: qsTr("Calibrate")
onClicked: {
if (text == qsTr("Calibrate")) {
if (text === qsTr("Calibrate")) {
showDialog(zeroTrimsDialogComponent, dialogTitle, radioPage.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel)
} else {
controller.nextButtonClicked()
......
......@@ -123,23 +123,23 @@ RadioComponentController::~RadioComponentController()
/// @brief Returns the state machine entry for the specified state.
const RadioComponentController::stateMachineEntry* RadioComponentController::_getStateMachineEntry(int step) const
{
static const char* msgBeginPX4 = "Lower the Throttle stick all the way down as shown in diagram.\n\n"
static const char* msgBeginPX4 = QT_TR_NOOP("Lower the Throttle stick all the way down as shown in diagram.\n\n"
"It is recommended to disconnect all motors for additional safety, however, the system is designed to not arm during the calibration.\n\n"
"Click Next to continue";
static const char* msgBeginAPM = "Lower the Throttle stick all the way down as shown in diagram.\nReset all transmitter trims to center.\n\n"
"Click Next to continue");
static const char* msgBeginAPM = QT_TR_NOOP("Lower the Throttle stick all the way down as shown in diagram.\nReset all transmitter trims to center.\n\n"
"Please ensure all motor power is disconnected AND all props are removed from the vehicle.\n\n"
"Click Next to continue";
static const char* msgThrottleUp = "Move the Throttle stick all the way up and hold it there...";
static const char* msgThrottleDown = "Move the Throttle stick all the way down and leave it there...";
static const char* msgYawLeft = "Move the Yaw stick all the way to the left and hold it there...";
static const char* msgYawRight = "Move the Yaw stick all the way to the right and hold it there...";
static const char* msgRollLeft = "Move the Roll stick all the way to the left and hold it there...";
static const char* msgRollRight = "Move the Roll stick all the way to the right and hold it there...";
static const char* msgPitchDown = "Move the Pitch stick all the way down and hold it there...";
static const char* msgPitchUp = "Move the Pitch stick all the way up and hold it there...";
static const char* msgPitchCenter = "Allow the Pitch stick to move back to center...";
static const char* msgSwitchMinMax = "Move all the transmitter switches and/or dials back and forth to their extreme positions.";
static const char* msgComplete = "All settings have been captured. Click Next to write the new parameters to your board.";
"Click Next to continue");
static const char* msgThrottleUp = QT_TR_NOOP("Move the Throttle stick all the way up and hold it there...");
static const char* msgThrottleDown = QT_TR_NOOP("Move the Throttle stick all the way down and leave it there...");
static const char* msgYawLeft = QT_TR_NOOP("Move the Yaw stick all the way to the left and hold it there...");
static const char* msgYawRight = QT_TR_NOOP("Move the Yaw stick all the way to the right and hold it there...");
static const char* msgRollLeft = QT_TR_NOOP("Move the Roll stick all the way to the left and hold it there...");
static const char* msgRollRight = QT_TR_NOOP("Move the Roll stick all the way to the right and hold it there...");
static const char* msgPitchDown = QT_TR_NOOP("Move the Pitch stick all the way down and hold it there...");
static const char* msgPitchUp = QT_TR_NOOP("Move the Pitch stick all the way up and hold it there...");
static const char* msgPitchCenter = QT_TR_NOOP("Allow the Pitch stick to move back to center...");
static const char* msgSwitchMinMax = QT_TR_NOOP("Move all the transmitter switches and/or dials back and forth to their extreme positions.");
static const char* msgComplete = QT_TR_NOOP("All settings have been captured. Click Next to write the new parameters to your board.");
static const stateMachineEntry rgStateMachinePX4[] = {
//Function
......@@ -206,9 +206,9 @@ void RadioComponentController::_advanceState(void)
/// @brief Sets up the state machine according to the current step from _currentStep.
void RadioComponentController::_setupCurrentState(void)
{
static const char* msgBeginAPMRover = "Center the Throttle stick as shown in diagram.\nReset all transmitter trims to center.\n\n"
static const char* msgBeginAPMRover = QT_TR_NOOP("Center the Throttle stick as shown in diagram.\nReset all transmitter trims to center.\n\n"
"Please ensure all motor power is disconnected from the vehicle.\n\n"
"Click Next to continue";
"Click Next to continue");
const stateMachineEntry* state = _getStateMachineEntry(_currentStep);
const char* instructions = state->instructions;
......
......@@ -202,12 +202,12 @@ Your vehicle will also be restarted in order to complete the process.")
QGCCheckBox {
// Although this item is invisible we still use it to manage state
id: airframeCheckBox
checked: modelData.name == controller.currentAirframeType
checked: modelData.name === controller.currentAirframeType
exclusiveGroup: airframeTypeExclusive
visible: false
onCheckedChanged: {
if (checked && combo.currentIndex != -1) {
if (checked && combo.currentIndex !== -1) {
console.log("check box change", combo.currentIndex)
controller.autostartId = modelData.airframes[combo.currentIndex].autostartId
}
......
......@@ -37,7 +37,7 @@ FactPanel {
VehicleSummaryRow {
labelText: qsTr("Firmware Version:")
valueText: activeVehicle.firmwareMajorVersion == -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + activeVehicle.firmwareVersionTypeString
valueText: activeVehicle.firmwareMajorVersion === -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + activeVehicle.firmwareVersionTypeString
}
}
}
......@@ -18,7 +18,7 @@ FactPanel {
property Fact _nullFact
property Fact _rcMapFltmode: controller.parameterExists(-1, "RC_MAP_FLTMODE") ? controller.getParameterFact(-1, "RC_MAP_FLTMODE") : _nullFact
property Fact _rcMapModeSw: controller.getParameterFact(-1, "RC_MAP_MODE_SW")
property bool _simpleMode: _rcMapFltmode.value > 0 || _rcMapModeSw.value == 0
property bool _simpleMode: _rcMapFltmode.value > 0 || _rcMapModeSw.value === 0
Loader {
anchors.fill: parent
......
......@@ -39,7 +39,7 @@ SetupPage {
property bool _rcMapFltmodeExists: controller.parameterExists(-1, "RC_MAP_FLTMODE")
property Fact _rcMapFltmode: _rcMapFltmodeExists ? controller.getParameterFact(-1, "RC_MAP_FLTMODE") : _nullFact
property Fact _rcMapModeSw: controller.getParameterFact(-1, "RC_MAP_MODE_SW")
property bool _simpleMode: _rcMapFltmodeExists ? _rcMapFltmode.value > 0 || _rcMapModeSw.value == 0 : false
property bool _simpleMode: _rcMapFltmodeExists ? _rcMapFltmode.value > 0 || _rcMapModeSw.value === 0 : false
FactPanelController {
id: controller
......
......@@ -145,7 +145,7 @@ Item {
QGCLabel {
anchors.baseline: returnCombo.baseline
text: qsTr("Return switch:")
color: parent.fact.value == 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
color: parent.fact.value === 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
}
FactComboBox {
......@@ -164,7 +164,7 @@ Item {
QGCLabel {
anchors.baseline: killCombo.baseline
text: qsTr("Kill switch:")
color: parent.fact.value == 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
color: parent.fact.value === 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
}
FactComboBox {
......@@ -183,7 +183,7 @@ Item {
QGCLabel {
anchors.baseline: offboardCombo.baseline
text: qsTr("Offboard switch:")
color: parent.fact.value == 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
color: parent.fact.value === 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
}
FactComboBox {
......@@ -203,7 +203,7 @@ Item {
QGCLabel {
anchors.baseline: vtolCombo.baseline
text: qsTr("VTOL mode switch:")
color: parent.fact.value == 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
color: parent.fact.value === 0 ? qgcPal.text : (controller.rcChannelValues[parent.fact.value - 1] >= 1500 ? "yellow" : qgcPal.text)
}
FactComboBox {
......
......@@ -143,7 +143,7 @@ SetupPage {
onClicked: {
var measuredVoltageValue = parseFloat(measuredVoltage.text)
if (measuredVoltageValue == 0 || isNaN(measuredVoltageValue)) {
if (measuredVoltageValue === 0 || isNaN(measuredVoltageValue)) {
return
}
var newVoltageDivider = (measuredVoltageValue * battVoltageDivider.value) / controller.vehicle.battery.voltage.value
......@@ -201,7 +201,7 @@ SetupPage {
onClicked: {
var measuredCurrentValue = parseFloat(measuredCurrent.text)
if (measuredCurrentValue == 0) {
if (measuredCurrentValue === 0) {
return
}
var newAmpsPerVolt = (measuredCurrentValue * battAmpsPerVolt.value) / controller.vehicle.battery.current.value
......@@ -379,7 +379,7 @@ SetupPage {
QGCCheckBox {
id: showUAVCAN
text: qsTr("Show UAVCAN Settings")
checked: uavcanEnable.rawValue != 0
checked: uavcanEnable ? uavcanEnable.rawValue !== 0 : false
}
QGCGroupBox {
......
......@@ -25,8 +25,8 @@ FactPanel {
property Fact airspeedDisabledFact: controller.getParameterFact(-1, "FW_ARSP_MODE")
property Fact airspeedBreakerFact: controller.getParameterFact(-1, "CBRK_AIRSPD_CHK")
property bool _airspeedVisible: airspeedDisabledFact.value == false && airspeedBreakerFact.value != 162128
property bool _airspeedCalRequired: _airspeedVisible && dpressOffFact.value == 0
property bool _airspeedVisible: airspeedDisabledFact.value === false && airspeedBreakerFact.value !== 162128
property bool _airspeedCalRequired: _airspeedVisible && dpressOffFact.value === 0
Column {
anchors.fill: parent
......
......@@ -352,7 +352,7 @@ Item {
id: compassButton
width: _buttonWidth
text: qsTr("Compass")
indicatorGreen: cal_mag0_id.value != 0
indicatorGreen: cal_mag0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationCompass && showSensorCalibrationCompass
onClicked: {
......@@ -366,7 +366,7 @@ Item {
id: gyroButton
width: _buttonWidth
text: qsTr("Gyroscope")
indicatorGreen: cal_gyro0_id.value != 0
indicatorGreen: cal_gyro0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationGyro && showSensorCalibrationGyro
onClicked: {
......@@ -380,7 +380,7 @@ Item {
id: accelButton
width: _buttonWidth
text: qsTr("Accelerometer")
indicatorGreen: cal_acc0_id.value != 0
indicatorGreen: cal_acc0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationAccel && showSensorCalibrationAccel
onClicked: {
......@@ -394,8 +394,8 @@ Item {
id: levelButton
width: _buttonWidth
text: qsTr("Level Horizon")
indicatorGreen: sens_board_x_off.value != 0 || sens_board_y_off.value != 0 | sens_board_z_off.value != 0
enabled: cal_acc0_id.value != 0 && cal_gyro0_id.value != 0
indicatorGreen: sens_board_x_off.value !== 0 || sens_board_y_off.value !== 0 | sens_board_z_off.value !== 0
enabled: cal_acc0_id.value !== 0 && cal_gyro0_id.value !== 0
visible: QGroundControl.corePlugin.options.showSensorCalibrationLevel && showSensorCalibrationLevel
onClicked: {
......@@ -410,11 +410,11 @@ Item {
width: _buttonWidth
text: qsTr("Airspeed")
visible: (controller.vehicle.fixedWing || controller.vehicle.vtol) &&
controller.getParameterFact(-1, "FW_ARSP_MODE").value == false &&
controller.getParameterFact(-1, "CBRK_AIRSPD_CHK").value != 162128 &&
controller.getParameterFact(-1, "FW_ARSP_MODE").value === false &&
controller.getParameterFact(-1, "CBRK_AIRSPD_CHK").value !== 162128 &&
QGroundControl.corePlugin.options.showSensorCalibrationAirspeed &&
showSensorCalibrationAirspeed
indicatorGreen: sens_dpres_off.value != 0
indicatorGreen: sens_dpres_off.value !== 0
onClicked: {
preCalibrationDialogType = "airspeed"
......
......@@ -57,9 +57,18 @@ QGCCameraParamIO::QGCCameraParamIO(QGCCameraControl *control, Fact* fact, Vehicl
case FactMetaData::valueTypeUint32:
_mavParamType = MAV_PARAM_EXT_TYPE_UINT32;
break;
case FactMetaData::valueTypeUint64:
_mavParamType = MAV_PARAM_EXT_TYPE_UINT64;
break;
case FactMetaData::valueTypeInt64:
_mavParamType = MAV_PARAM_EXT_TYPE_INT64;
break;
case FactMetaData::valueTypeFloat:
_mavParamType = MAV_PARAM_EXT_TYPE_REAL32;
break;
case FactMetaData::valueTypeDouble:
_mavParamType = MAV_PARAM_EXT_TYPE_REAL64;
break;
//-- String and custom are the same for now
case FactMetaData::valueTypeString:
case FactMetaData::valueTypeCustom:
......@@ -145,9 +154,18 @@ QGCCameraParamIO::_sendParameter()
case FactMetaData::valueTypeUint32:
union_value.param_uint32 = (uint32_t)_fact->rawValue().toUInt();
break;
case FactMetaData::valueTypeInt64:
union_value.param_int64 = (int64_t)_fact->rawValue().toLongLong();
break;
case FactMetaData::valueTypeUint64:
union_value.param_uint64 = (uint64_t)_fact->rawValue().toULongLong();
break;
case FactMetaData::valueTypeFloat:
union_value.param_float = _fact->rawValue().toFloat();
break;
case FactMetaData::valueTypeDouble:
union_value.param_double = _fact->rawValue().toDouble();
break;
//-- String and custom are the same for now
case FactMetaData::valueTypeString:
case FactMetaData::valueTypeCustom:
......@@ -282,6 +300,12 @@ QGCCameraParamIO::_valueFromMessage(const char* value, uint8_t param_type)
case MAV_PARAM_EXT_TYPE_INT32:
var = QVariant(u.param_int32);
break;
case MAV_PARAM_EXT_TYPE_UINT64:
var = QVariant((qulonglong)u.param_uint64);
break;
case MAV_PARAM_EXT_TYPE_INT64:
var = QVariant((qlonglong)u.param_int64);
break;
case MAV_PARAM_EXT_TYPE_CUSTOM:
var = QVariant(QByteArray(value, MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN));
break;
......
......@@ -19,6 +19,9 @@ MAVPACKED(
typedef struct {
union {
float param_float;
double param_double;
int64_t param_int64;
uint64_t param_uint64;
int32_t param_int32;
uint32_t param_uint32;
int16_t param_int16;
......
......@@ -33,10 +33,12 @@ Flow {
checked: fact.value & fact.bitmaskValues[index]
onClicked: {
var i;
var otherCheckbox;
if (checked) {
if (firstEntryIsAll && index == 0) {
for (var i=1; i<repeater.count; i++) {
var otherCheckbox = repeater.itemAt(i)
for (i = 1; i < repeater.count; i++) {
otherCheckbox = repeater.itemAt(i)
fact.value &= ~fact.bitmaskValues[i]
otherCheckbox.checked = false
otherCheckbox.enabled = false
......@@ -45,8 +47,8 @@ Flow {
fact.value |= fact.bitmaskValues[index]
} else {
if (firstEntryIsAll && index == 0) {
for (var i=1; i<repeater.count; i++) {
var otherCheckbox = repeater.itemAt(i)
for (i = 1; i < repeater.count; i++) {
otherCheckbox = repeater.itemAt(i)
otherCheckbox.enabled = true
}
}
......
......@@ -8,16 +8,14 @@ import QGroundControl.Controls 1.0
QGCCheckBox {
property Fact fact: Fact { }
property variant checkedValue: 1
property variant uncheckedValue: 0
checkedState: fact ?
(fact.typeIsBool ?
(fact.value === true ? Qt.Checked : Qt.Unchecked) :
(fact.value === checkedValue ? Qt.Checked : Qt.Unchecked)) :
(fact.value === false ? Qt.Unchecked : Qt.Checked) :
(fact.value === 0 ? Qt.Unchecked : Qt.Checked)) :
Qt.Unchecked
text: qsTr("Label")
onClicked: fact.value = checked ? checkedValue : uncheckedValue
onClicked: fact.value = checked ? 1 : 0
}
......@@ -12,7 +12,7 @@ QGCComboBox {
model: fact ? fact.enumStrings : null
currentIndex: indexModel ? fact.value : fact.enumIndex
currentIndex: fact ? (indexModel ? fact.value : fact.enumIndex) : 0
onActivated: {
if (indexModel) {
......
......@@ -32,7 +32,7 @@ QGCTextField {
}
if (typeof qgcView !== 'undefined' && qgcView) {
var errorString = fact.validate(text, false /* convertOnly */)
if (errorString == "") {
if (errorString === "") {
fact.value = text
} else {
_validateString = text
......
......@@ -254,9 +254,13 @@ QVariant FactMetaData::_minForType(void) const
case valueTypeInt16:
return QVariant(std::numeric_limits<short int>::min());
case valueTypeUint32:
return QVariant(std::numeric_limits<unsigned int>::min());
return QVariant(std::numeric_limits<uint32_t>::min());
case valueTypeInt32:
return QVariant(std::numeric_limits<int>::min());
return QVariant(std::numeric_limits<int32_t>::min());
case valueTypeUint64:
return QVariant((qulonglong)std::numeric_limits<uint64_t>::min());
case valueTypeInt64:
return QVariant((qlonglong)std::numeric_limits<int64_t>::min());
case valueTypeFloat:
return QVariant(-std::numeric_limits<float>::max());
case valueTypeDouble:
......@@ -287,9 +291,13 @@ QVariant FactMetaData::_maxForType(void) const
case valueTypeInt16:
return QVariant(std::numeric_limits<short int>::max());
case valueTypeUint32:
return QVariant(std::numeric_limits<unsigned int>::max());
return QVariant(std::numeric_limits<uint32_t>::max());
case valueTypeInt32:
return QVariant(std::numeric_limits<int>::max());
return QVariant(std::numeric_limits<int32_t>::max());
case valueTypeUint64:
return QVariant((qulonglong)std::numeric_limits<uint64_t>::max());
case valueTypeInt64:
return QVariant((qlonglong)std::numeric_limits<int64_t>::max());
case valueTypeFloat:
return QVariant(std::numeric_limits<float>::max());
case valueTypeElapsedTimeInSeconds:
......@@ -324,6 +332,14 @@ bool FactMetaData::convertAndValidateRaw(const QVariant& rawValue, bool convertO
}
}
break;
case FactMetaData::valueTypeInt64:
typedValue = QVariant(rawValue.toLongLong(&convertOk));
if (!convertOnly && convertOk) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = tr("Value must be within %1 and %2").arg(rawMin().toInt()).arg(rawMax().toInt());
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
......@@ -334,6 +350,14 @@ bool FactMetaData::convertAndValidateRaw(const QVariant& rawValue, bool convertO
}
}
break;
case FactMetaData::valueTypeUint64:
typedValue = QVariant(rawValue.toULongLong(&convertOk));
if (!convertOnly && convertOk) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = tr("Value must be within %1 and %2").arg(rawMin().toUInt()).arg(rawMax().toUInt());
}
}
break;
case FactMetaData::valueTypeFloat:
typedValue = QVariant(rawValue.toFloat(&convertOk));
if (!convertOnly && convertOk) {
......@@ -389,6 +413,14 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co
}
}
break;
case FactMetaData::valueTypeInt64:
typedValue = QVariant(cookedValue.toLongLong(&convertOk));
if (!convertOnly && convertOk) {
if (cookedMin() > typedValue || typedValue > cookedMax()) {
errorString = tr("Value must be within %1 and %2").arg(cookedMin().toInt()).arg(cookedMax().toInt());
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
......@@ -399,6 +431,14 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co
}
}
break;
case FactMetaData::valueTypeUint64:
typedValue = QVariant(cookedValue.toULongLong(&convertOk));
if (!convertOnly && convertOk) {
if (cookedMin() > typedValue || typedValue > cookedMax()) {
errorString = tr("Value must be within %1 and %2").arg(cookedMin().toUInt()).arg(cookedMax().toUInt());
}
}
break;
case FactMetaData::valueTypeFloat:
typedValue = QVariant(cookedValue.toFloat(&convertOk));
if (!convertOnly && convertOk) {
......@@ -453,6 +493,16 @@ bool FactMetaData::clampValue(const QVariant& cookedValue, QVariant& typedValue)
}
}
break;
case FactMetaData::valueTypeInt64:
typedValue = QVariant(cookedValue.toLongLong(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
......@@ -465,6 +515,16 @@ bool FactMetaData::clampValue(const QVariant& cookedValue, QVariant& typedValue)
}
}
break;
case FactMetaData::valueTypeUint64:
typedValue = QVariant(cookedValue.toULongLong(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeFloat:
typedValue = QVariant(cookedValue.toFloat(&convertOk));
if (convertOk) {
......@@ -742,6 +802,8 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString,
<< QStringLiteral("Int16")
<< QStringLiteral("Uint32")
<< QStringLiteral("Int32")
<< QStringLiteral("Uint64")
<< QStringLiteral("Int64")
<< QStringLiteral("Float")
<< QStringLiteral("Double")
<< QStringLiteral("String")
......@@ -755,6 +817,8 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString,
<< valueTypeInt16
<< valueTypeUint32
<< valueTypeInt32
<< valueTypeUint64
<< valueTypeInt64
<< valueTypeFloat
<< valueTypeDouble
<< valueTypeString
......@@ -789,6 +853,8 @@ size_t FactMetaData::typeToSize(ValueType_t type)
case valueTypeFloat:
return 4;
case valueTypeUint64:
case valueTypeInt64:
case valueTypeDouble:
return 8;
......
......@@ -36,6 +36,8 @@ public:
valueTypeInt16,
valueTypeUint32,
valueTypeInt32,
valueTypeUint64,
valueTypeInt64,
valueTypeFloat,
valueTypeDouble,
valueTypeString,
......
......@@ -289,6 +289,12 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
case MAV_PARAM_TYPE_INT32:
factType = FactMetaData::valueTypeInt32;
break;
case MAV_PARAM_TYPE_UINT64:
factType = FactMetaData::valueTypeUint64;
break;
case MAV_PARAM_TYPE_INT64:
factType = FactMetaData::valueTypeInt64;
break;
case MAV_PARAM_TYPE_REAL32:
factType = FactMetaData::valueTypeFloat;
break;
......@@ -983,9 +989,18 @@ MAV_PARAM_TYPE ParameterManager::_factTypeToMavType(FactMetaData::ValueType_t fa
case FactMetaData::valueTypeUint32:
return MAV_PARAM_TYPE_UINT32;
case FactMetaData::valueTypeUint64:
return MAV_PARAM_TYPE_UINT64;
case FactMetaData::valueTypeInt64:
return MAV_PARAM_TYPE_INT64;
case FactMetaData::valueTypeFloat:
return MAV_PARAM_TYPE_REAL32;
case FactMetaData::valueTypeDouble:
return MAV_PARAM_TYPE_REAL64;
default:
qWarning() << "Unsupported fact type" << factType;
// fall through
......@@ -1013,9 +1028,18 @@ FactMetaData::ValueType_t ParameterManager::_mavTypeToFactType(MAV_PARAM_TYPE ma
case MAV_PARAM_TYPE_UINT32:
return FactMetaData::valueTypeUint32;
case MAV_PARAM_TYPE_UINT64:
return FactMetaData::valueTypeUint64;
case MAV_PARAM_TYPE_INT64:
return FactMetaData::valueTypeInt64;
case MAV_PARAM_TYPE_REAL32:
return FactMetaData::valueTypeFloat;
case MAV_PARAM_TYPE_REAL64:
return FactMetaData::valueTypeDouble;
default:
qWarning() << "Unsupported mav param type" << mavType;
// fall through
......
......@@ -44,11 +44,13 @@ QVariant APMParameterMetaData::_stringToTypedVariant(const QString& string,
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
case FactMetaData::valueTypeUint64:
convertTo = QVariant::UInt;
break;
case FactMetaData::valueTypeInt8:
case FactMetaData::valueTypeInt16:
case FactMetaData::valueTypeInt32:
case FactMetaData::valueTypeInt64:
convertTo = QVariant::Int;
break;
case FactMetaData::valueTypeFloat:
......@@ -531,12 +533,14 @@ void APMParameterMetaData::addMetaDataToFact(Fact* fact, MAV_TYPE vehicleType)
break;
case FactMetaData::valueTypeInt32:
case FactMetaData::valueTypeInt64:
typedBitSet = QVariant((int)bitSet);
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
case FactMetaData::valueTypeUint64:
typedBitSet = QVariant(bitSet);
break;
......
......@@ -492,6 +492,18 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
0.8, // minTriggerInterval
this);
_cameraList.append(QVariant::fromValue(metaData));
metaData = new CameraMetaData(tr("GoPro Hero 4"),
6.17, // sensorWidth
4.55, // sendsorHeight
4000, // imageWidth
3000, // imageHeight
2.98, // focalLength
true, // landscape
false, // fixedOrientation
0, // minTriggerInterval
this);
_cameraList.append(QVariant::fromValue(metaData));
}
return _cameraList;
......@@ -620,4 +632,9 @@ QGCCameraControl* FirmwarePlugin::createCameraControl(const mavlink_camera_infor
return NULL;
}
uint32_t FirmwarePlugin::highLatencyCustomModeTo32Bits(uint16_t hlCustomMode)
{
// Standard implementation assumes no special handling. Upper part of 32 bit value is not used.
return hlCustomMode;
}
......@@ -304,6 +304,9 @@ public:
/// Returns true if the vehicle is a VTOL
virtual bool isVtol(const Vehicle* vehicle) const;
/// Convert from HIGH_LATENCY2.custom_mode value to correct 32 bit value.
virtual uint32_t highLatencyCustomModeTo32Bits(uint16_t hlCustomMode);
// FIXME: Hack workaround for non pluginize FollowMe support
static const QString px4FollowMeFlightMode;
......
......@@ -589,3 +589,12 @@ QGCCameraControl* PX4FirmwarePlugin::createCameraControl(const mavlink_camera_in
{
return new QGCCameraControl(info, vehicle, compID, parent);
}
uint32_t PX4FirmwarePlugin::highLatencyCustomModeTo32Bits(uint16_t hlCustomMode)
{
union px4_custom_mode px4_cm;
px4_cm.data = 0;
px4_cm.custom_mode_hl = hlCustomMode;
return px4_cm.data;
}
......@@ -70,6 +70,7 @@ public:
QString autoDisarmParameter (Vehicle* vehicle) override { Q_UNUSED(vehicle); return QStringLiteral("COM_DISARM_LAND"); }
QGCCameraManager* createCameraManager (Vehicle* vehicle) override;
QGCCameraControl* createCameraControl (const mavlink_camera_information_t* info, Vehicle* vehicle, int compID, QObject* parent = NULL) override;
uint32_t highLatencyCustomModeTo32Bits (uint16_t hlCustomMode) override;
protected:
typedef struct {
......
......@@ -44,11 +44,13 @@ QVariant PX4ParameterMetaData::_stringToTypedVariant(const QString& string, Fact
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
case FactMetaData::valueTypeUint64:
convertTo = QVariant::UInt;
break;
case FactMetaData::valueTypeInt8:
case FactMetaData::valueTypeInt16:
case FactMetaData::valueTypeInt32:
case FactMetaData::valueTypeInt64:
convertTo = QVariant::Int;
break;
case FactMetaData::valueTypeFloat:
......
......@@ -71,7 +71,11 @@ union px4_custom_mode {
uint8_t main_mode;
uint8_t sub_mode;
};
uint32_t data;
struct {
uint16_t reserved_hl;
uint16_t custom_mode_hl;
};
uint32_t data;
float data_float;
};
......
......@@ -143,7 +143,7 @@ FlightMap {
onNewItemsFromVehicle: {
var visualItems = _missionController.visualItems
if (visualItems && visualItems.count != 1) {
if (visualItems && visualItems.count !== 1) {
mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true
}
......
......@@ -72,7 +72,7 @@ Item {
instrumentsLoader.state = "topMode"
} else {
instrumentsLoader.source = "qrc:/qml/QGCInstrumentWidget.qml"
instrumentsLoader.state = QGroundControl.settingsManager.appSettings.showLargeCompass.value == 1 ? "centerMode" : "topMode"
instrumentsLoader.state = QGroundControl.settingsManager.appSettings.showLargeCompass.value === 1 ? "centerMode" : "topMode"
}
}
} else {
......
......@@ -16,7 +16,7 @@ import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
/// Guided actions confirmation dialog
NoMouseThroughRectangle {
Rectangle {
id: _root
border.color: qgcPal.alertBorder
border.width: 1
......@@ -48,6 +48,10 @@ NoMouseThroughRectangle {
QGCPalette { id: qgcPal }
DeadMouseArea {
anchors.fill: parent
}
Column {
id: confirmColumn
anchors.margins: _margins
......
......@@ -17,7 +17,7 @@ import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
/// Dialog showing list of available guided actions
NoMouseThroughRectangle {
Rectangle {
id: _root
width: actionColumn.width + (_margins * 4)
height: actionColumn.height + (_margins * 4)
......@@ -35,6 +35,10 @@ NoMouseThroughRectangle {
QGCPalette { id: qgcPal }
DeadMouseArea {
anchors.fill: parent
}
ColumnLayout {
id: actionColumn
anchors.margins: _root._margins
......
......@@ -101,13 +101,15 @@ Item {
property bool showLand: _activeVehicle && _activeVehicle.guidedModeSupported && _vehicleArmed && !_activeVehicle.fixedWing && !_vehicleInLandMode
property bool showStartMission: _activeVehicle && _missionAvailable && !_missionActive && !_vehicleFlying
property bool showContinueMission: _activeVehicle && _missionAvailable && !_missionActive && _vehicleFlying && (_currentMissionIndex < missionController.visualItems.count - 1)
property bool showResumeMission: _activeVehicle && !_vehicleArmed && _vehicleWasFlying && _missionAvailable && _resumeMissionIndex > 0 && (_resumeMissionIndex < missionController.visualItems.count - 2)
property bool showPause: _activeVehicle && _vehicleArmed && _activeVehicle.pauseVehicleSupported && _vehicleFlying && !_vehiclePaused
property bool showChangeAlt: (_activeVehicle && _vehicleFlying) && _activeVehicle.guidedModeSupported && _vehicleArmed && !_missionActive
property bool showOrbit: !_hideOrbit && _activeVehicle && _vehicleFlying && _activeVehicle.orbitModeSupported && _vehicleArmed && !_missionActive
property bool showLandAbort: _activeVehicle && _vehicleFlying && _activeVehicle.fixedWing && _vehicleLanding
property bool showGotoLocation: _activeVehicle && _vehicleFlying
// Note: The 'missionController.visualItems.count - 3' is a hack to not trigger resume mission when a mission ends with an RTL item
property bool showResumeMission: _activeVehicle && !_vehicleArmed && _vehicleWasFlying && _missionAvailable && _resumeMissionIndex > 0 && (_resumeMissionIndex < missionController.visualItems.count - 3)
property bool guidedUIVisible: guidedActionConfirm.visible || guidedActionList.visible
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
......@@ -311,6 +313,8 @@ Item {
// Executes the specified action
function executeAction(actionCode, actionData) {
var i;
var rgVehicle;
switch (actionCode) {
case actionRTL:
_activeVehicle.guidedModeRTL()
......@@ -334,10 +338,9 @@ Item {
_activeVehicle.startMission()
break
case actionMVStartMission:
var rgVehicle = QGroundControl.multiVehicleManager.vehicles
for (var i=0; i<rgVehicle.count; i++) {
var vehicle = rgVehicle.get(i)
vehicle.startMission()
rgVehicle = QGroundControl.multiVehicleManager.vehicles
for (i = 0; i < rgVehicle.count; i++) {
rgVehicle.get(i).startMission()
}
break
case actionArm:
......@@ -368,10 +371,9 @@ Item {
_activeVehicle.pauseVehicle()
break
case actionMVPause:
var rgVehicle = QGroundControl.multiVehicleManager.vehicles
for (var i=0; i<rgVehicle.count; i++) {
var vehicle = rgVehicle.get(i)
vehicle.pauseVehicle()
rgVehicle = QGroundControl.multiVehicleManager.vehicles
for (i = 0; i < rgVehicle.count; i++) {
rgVehicle.get(i).pauseVehicle()
}
break
case actionVtolTransitionToFwdFlight:
......
......@@ -28,7 +28,7 @@ Item {
QGCPalette { id: qgcPal }
NoMouseThroughRectangle {
Rectangle {
id: mvCommands
anchors.left: parent.left
anchors.right: parent.right
......@@ -37,6 +37,10 @@ Item {
opacity: _rectOpacity
radius: _margin
DeadMouseArea {
anchors.fill: parent
}
Column {
id: mvCommandsColumn
anchors.margins: _margin
......@@ -152,7 +156,7 @@ Item {
QGCButton {
text: "Start Mission"
visible: _vehicle.armed && _vehicle.flightMode != _vehicle.missionFlightMode
visible: _vehicle.armed && _vehicle.flightMode !== _vehicle.missionFlightMode
onClicked: _vehicle.startMission()
}
......@@ -164,13 +168,13 @@ Item {
QGCButton {
text: "RTL"
visible: _vehicle.armed && _vehicle.flightMode != _vehicle.rtlFlightMode
visible: _vehicle.armed && _vehicle.flightMode !== _vehicle.rtlFlightMode
onClicked: _vehicle.flightMode = _vehicle.rtlFlightMode
}
QGCButton {
text: "Take control"
visible: _vehicle.armed && _vehicle.flightMode != _vehicle.takeControlFlightMode
visible: _vehicle.armed && _vehicle.flightMode !== _vehicle.takeControlFlightMode
onClicked: _vehicle.flightMode = _vehicle.takeControlFlightMode
}
} // Row
......
......@@ -29,9 +29,9 @@ Item {
Component.onCompleted: {
var controlUrl = object.url
if (controlUrl != "") {
if (controlUrl !== "") {
var component = Qt.createComponent(controlUrl);
if (component.status == Component.Ready) {
if (component.status === Component.Ready) {
_customObject = component.createObject(map, { "customMapObject": object })
if (_customObject) {
map.addMapItem(_customObject)
......
......@@ -233,7 +233,7 @@ Item {
var clickCoordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
var polygonPath = _newPolygon.path
if (polygonPath.length == 0) {
if (polygonPath.length === 0) {
// Add first coordinate
polygonPath.push(clickCoordinate)
} else {
......@@ -252,10 +252,10 @@ Item {
_currentPolygon.path = polygonPath
_newPolygon.path = polygonPath
if (_mobile && _currentPolygon.path.length == 1) {
if (_mobile && _currentPolygon.path.length === 1) {
_mobilePoint.coordinate = _currentPolygon.path[0]
_mobilePoint.visible = true
} else if (_mobile && _currentPolygon.path.length == 2) {
} else if (_mobile && _currentPolygon.path.length === 2) {
// Show initial line segment on mobile
_mobileSegment.path = [ _currentPolygon.path[0], _currentPolygon.path[1] ]
_mobileSegment.visible = true
......
......@@ -115,7 +115,7 @@ Item {
var rightCoord = mapControl.toCoordinate(Qt.point(scaleLinePixelLength, scale.y), false /* clipToViewPort */)
var scaleLineMeters = Math.round(leftCoord.distanceTo(rightCoord))
if (QGroundControl.settingsManager.unitsSettings.distanceUnits.value == UnitsSettings.DistanceUnitsFeet) {
if (QGroundControl.settingsManager.unitsSettings.distanceUnits.value === UnitsSettings.DistanceUnitsFeet) {
calculateFeetRatio(scaleLineMeters, scaleLinePixelLength)
} else {
calculateMetersRatio(scaleLineMeters, scaleLinePixelLength)
......
......@@ -26,23 +26,26 @@ import QGroundControl.FactControls 1.0
/// Camera page for Instrument Panel PageView
Column {
width: pageWidth
spacing: ScreenTools.defaultFontPixelHeight
spacing: ScreenTools.defaultFontPixelHeight * 0.25
property bool showSettingsIcon: _camera !== null
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _dynamicCameras: _activeVehicle ? _activeVehicle.dynamicCameras : null
property bool _isCamera: _dynamicCameras ? _dynamicCameras.cameras.count > 0 : false
property var _camera: _isCamera ? _dynamicCameras.cameras.get(0) : null // Single camera support for the time being
property bool _cameraModeUndefined: _isCamera ? _dynamicCameras.cameras.get(0).cameraMode === QGCCameraControl.CAMERA_MODE_UNDEFINED : true
property bool _cameraVideoMode: _isCamera ? _dynamicCameras.cameras.get(0).cameraMode === 1 : false
property bool _cameraPhotoMode: _isCamera ? _dynamicCameras.cameras.get(0).cameraMode === 0 : false
property var _camera: _isCamera ? _dynamicCameras.cameras.get(0) : null // Single camera support for the time being
property bool _cameraPhotoIdle: _isCamera && _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_IDLE
property bool _cameraElapsedMode: _isCamera && _camera.cameraMode === QGCCameraControl.CAM_MODE_PHOTO && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE
property real _spacers: ScreenTools.defaultFontPixelHeight * 0.5
property real _labelFieldWidth: ScreenTools.defaultFontPixelWidth * 30
property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30
property bool _communicationLost: _activeVehicle ? _activeVehicle.connectionLost : false
property bool _hasModes: _isCamera && _camera && _camera.hasModes
property bool _videoRecording: _camera && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING
property bool _noStorage: _camera && _camera.storageTotal === 0
function showSettings() {
qgcView.showDialog(cameraSettings, _cameraVideoMode ? qsTr("Video Settings") : qsTr("Camera Settings"), 70, StandardButton.Ok)
......@@ -60,13 +63,21 @@ Column {
//-- Actual controller
QGCLabel {
id: cameraLabel
text: _isCamera ? _dynamicCameras.cameras.get(0).modelName : qsTr("Camera")
text: _isCamera ? _camera.modelName : qsTr("Camera")
visible: _isCamera
font.pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: _camera ? qsTr("Free Space: ") + _camera.storageFreeStr : ""
font.pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
visible: _camera && !_noStorage
}
//-- Camera Mode (visible only if camera has modes)
Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.75; visible: camMode.visible; }
Rectangle {
id: camMode
width: _hasModes ? ScreenTools.defaultFontPixelWidth * 8 : 0
height: _hasModes ? ScreenTools.defaultFontPixelWidth * 4 : 0
color: qgcPal.button
......@@ -129,19 +140,21 @@ Column {
}
}
//-- Shutter
Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.75; visible: camShutter.visible; }
Rectangle {
id: camShutter
color: Qt.rgba(0,0,0,0)
width: ScreenTools.defaultFontPixelWidth * 6
height: width
radius: width * 0.5
visible: _isCamera
visible: _isCamera
border.color: qgcPal.buttonText
border.width: 3
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
width: parent.width * (_videoRecording ? 0.5 : 0.75)
width: parent.width * (_videoRecording || (_cameraPhotoMode && !_cameraPhotoIdle && _cameraElapsedMode) ? 0.5 : 0.75)
height: width
radius: _videoRecording ? 0 : width * 0.5
radius: _videoRecording || (_cameraPhotoMode && !_cameraPhotoIdle && _cameraElapsedMode) ? 0 : width * 0.5
color: _cameraModeUndefined ? qgcPal.colorGrey : qgcPal.colorRed
anchors.centerIn: parent
}
......@@ -152,11 +165,28 @@ Column {
if(_cameraVideoMode) {
_camera.toggleVideo()
} else {
_camera.takePhoto()
if(_cameraPhotoMode && !_cameraPhotoIdle && _cameraElapsedMode) {
_camera.stopTakePhoto()
} else {
_camera.takePhoto()
}
}
}
}
}
Item { width: 1; height: ScreenTools.defaultFontPixelHeight * 0.75; visible: _isCamera; }
QGCLabel {
text: (_cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) ? _camera.recordTimeStr : "00:00:00"
font.pointSize: ScreenTools.smallFontPointSize
visible: _cameraVideoMode
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: _activeVehicle && _cameraPhotoMode ? ('00000' + _activeVehicle.cameraTriggerPoints.count).slice(-5) : "00000"
font.pointSize: ScreenTools.smallFontPointSize
visible: _cameraPhotoMode
anchors.horizontalCenter: parent.horizontalCenter
}
Item { width: 1; height: ScreenTools.defaultFontPixelHeight; visible: _isCamera; }
Component {
id: cameraSettings
......@@ -232,6 +262,54 @@ Column {
}
}
//-------------------------------------------
//-- Time Lapse
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _cameraPhotoMode
property var photoModes: [qsTr("Single"), qsTr("Time Lapse")]
QGCLabel {
text: qsTr("Photo Mode")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
id: photoModeCombo
width: _editFieldWidth
model: parent.photoModes
currentIndex: _camera ? _camera.photoMode : 0
onActivated: _camera.photoMode = index
}
}
//-------------------------------------------
//-- Time Lapse Interval
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _cameraPhotoMode && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE
QGCLabel {
text: qsTr("Photo Interval (seconds)")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
Item {
height: photoModeCombo.height
width: _editFieldWidth
QGCSlider {
maximumValue: 60
minimumValue: 1
stepSize: 1
value: _camera ? _camera.photoLapse : 5
displayValue: true
updateValueWhileDragging: true
anchors.fill: parent
onValueChanged: {
_camera.photoLapse = value
}
}
}
}
//-------------------------------------------
//-- Reset Camera
Row {
spacing: ScreenTools.defaultFontPixelWidth
......
......@@ -61,7 +61,7 @@ DropButton {
/// 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) {
if (coordList.length === 0) {
map.center = fitHomePosition()
return
}
......@@ -115,16 +115,17 @@ DropButton {
}
function addFenceItemCoordsForFit(coordList) {
var i
var homePosition = fitHomePosition()
if (homePosition.isValid && geoFenceController.circleEnabled) {
var azimuthList = [ 0, 180, 90, 270 ]
for (var i=0; i<azimuthList.length; i++) {
for (i = 0; i < azimuthList.length; i++) {
var edgeCoordinate = homePosition.atDistanceAndAzimuth(geoFenceController.circleRadius, azimuthList[i])
coordList.push(edgeCoordinate)
}
}
if (geoFenceController.polygonEnabled && geoFenceController.polygon.count() > 2) {
for (var i=0; i<geoFenceController.polygon.count(); i++) {
for (i = 0; i < geoFenceController.polygon.count(); i++) {
coordList.push(geoFenceController.polygon.path[i])
}
}
......
......@@ -49,7 +49,7 @@ Item {
/// are specified the map will center to fitHomePosition()
function fitMapViewportToAllCoordinates(coordList) {
var mapFitViewport = Qt.rect(0, 0, map.width, map.height)
if (coordList.length == 0) {
if (coordList.length === 0) {
var homeCoord = fitHomePosition()
if (homeCoord.isValid) {
map.center = homeCoord
......@@ -113,16 +113,17 @@ Item {
}
function addFenceItemCoordsForFit(coordList) {
var i
var homePosition = fitHomePosition()
if (homePosition.isValid && _geoFenceController.circleEnabled) {
var azimuthList = [ 0, 180, 90, 270 ]
for (var i=0; i<azimuthList.length; i++) {
for (i = 0; i < azimuthList.length; i++) {
var edgeCoordinate = homePosition.atDistanceAndAzimuth(_geoFenceController.circleRadius, azimuthList[i])
coordList.push(edgeCoordinate)
}
}
if (_geoFenceController.polygonEnabled && _geoFenceController.mapPolygon.path.count > 2) {
for (var i=0; i<_geoFenceController.mapPolygon.path.count; i++) {
for (i = 0; i < _geoFenceController.mapPolygon.path.count; i++) {
coordList.push(_geoFenceController.mapPolygon.path[i])
}
}
......
......@@ -174,8 +174,8 @@ Column {
anchors.right: parent.right
sourceComponent: factGroupList
property var factGroup: _activeVehicle
property var factGroupName: "Vehicle"
property var factGroup: _activeVehicle
property string factGroupName: "Vehicle"
}
}
}
......
......@@ -49,7 +49,7 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatC
, _hatCount(hatCount)
, _hatButtonCount(4*hatCount)
, _totalButtonCount(_buttonCount+_hatButtonCount)
, _calibrationMode(CalibrationModeOff)
, _calibrationMode(false)
, _rgAxisValues(NULL)
, _rgCalibration(NULL)
, _rgButtonValues(NULL)
......@@ -431,7 +431,7 @@ void Joystick::run(void)
}
}
if (_calibrationMode != CalibrationModeCalibrating && _calibrated) {
if (_outputEnabled && _calibrated) {
int axis = _rgFunctionAxis[rollFunction];
float roll = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis], _deadband);
......@@ -757,36 +757,28 @@ void Joystick::setDeadband(bool deadband)
_saveSettings();
}
void Joystick::startCalibrationMode(CalibrationMode_t mode)
void Joystick::setCalibrationMode(bool calibrating)
{
if (mode == CalibrationModeOff) {
qWarning() << "Incorrect mode CalibrationModeOff";
return;
}
_calibrationMode = calibrating;
_calibrationMode = mode;
if (!isRunning()) {
if (calibrating && !isRunning()) {
_pollingStartedForCalibration = true;
startPolling(_multiVehicleManager->activeVehicle());
}
}
void Joystick::stopCalibrationMode(CalibrationMode_t mode)
{
if (mode == CalibrationModeOff) {
qWarning() << "Incorrect mode: CalibrationModeOff";
return;
else if (_pollingStartedForCalibration) {
stopPolling();
}
if (mode == CalibrationModeCalibrating) {
_calibrationMode = CalibrationModeMonitor;
} else {
_calibrationMode = CalibrationModeOff;
if (_pollingStartedForCalibration) {
stopPolling();
}
if (calibrating){
setOutputEnabled(false); //Disable the joystick output before calibrating
}
else if (!calibrating && _calibrated){
setOutputEnabled(true); //Enable joystick output after calibration
}
}
void Joystick::setOutputEnabled(bool enabled){
_outputEnabled = enabled;
emit outputEnabledChanged(_outputEnabled);
}
void Joystick::_buttonAction(const QString& action)
......
......@@ -61,6 +61,7 @@ public:
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(bool calibrated MEMBER _calibrated NOTIFY calibratedChanged)
Q_PROPERTY(bool outputEnabled MEMBER _outputEnabled WRITE setOutputEnabled NOTIFY outputEnabledChanged)
Q_PROPERTY(int totalButtonCount READ totalButtonCount CONSTANT)
Q_PROPERTY(int axisCount READ axisCount CONSTANT)
......@@ -122,20 +123,13 @@ public:
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
CalibrationModeCalibrating, // Calibrating, stop sending joystick to vehicle
} CalibrationMode_t;
/// Set the current calibration mode
void startCalibrationMode(CalibrationMode_t mode);
/// Clear the current calibration mode
void stopCalibrationMode(CalibrationMode_t mode);
void setCalibrationMode(bool calibrating);
void setOutputEnabled(bool enabled);
signals:
void calibratedChanged(bool calibrated);
void outputEnabledChanged(bool enabled);
// The raw signals are only meant for use by calibration
void rawAxisValueChanged(int index, int value);
......@@ -201,7 +195,8 @@ protected:
int _totalButtonCount;
static int _transmitterMode;
CalibrationMode_t _calibrationMode;
bool _calibrationMode;
bool _outputEnabled;
int* _rgAxisValues;
Calibration_t* _rgCalibration;
......
......@@ -14,15 +14,16 @@
#include <QQmlEngine>
const char* CameraCalc::_valueSetIsDistanceName = "ValueSetIsDistance";
const char* CameraCalc::_distanceToSurfaceName = "DistanceToSurface";
const char* CameraCalc::_imageDensityName = "ImageDensity";
const char* CameraCalc::_frontalOverlapName = "FrontalOverlap";
const char* CameraCalc::_sideOverlapName = "SideOverlap";
const char* CameraCalc::_adjustedFootprintFrontalName = "AdjustedFootprintFrontal";
const char* CameraCalc::_adjustedFootprintSideName = "AdjustedFootprintSide";
const char* CameraCalc::_jsonCameraNameKey = "CameraName";
const char* CameraCalc::_jsonCameraSpecTypeKey = "CameraSpecType";
const char* CameraCalc::_valueSetIsDistanceName = "ValueSetIsDistance";
const char* CameraCalc::_distanceToSurfaceName = "DistanceToSurface";
const char* CameraCalc::_distanceToSurfaceRelativeName = "DistanceToSurfaceRelative";
const char* CameraCalc::_imageDensityName = "ImageDensity";
const char* CameraCalc::_frontalOverlapName = "FrontalOverlap";
const char* CameraCalc::_sideOverlapName = "SideOverlap";
const char* CameraCalc::_adjustedFootprintFrontalName = "AdjustedFootprintFrontal";
const char* CameraCalc::_adjustedFootprintSideName = "AdjustedFootprintSide";
const char* CameraCalc::_jsonCameraNameKey = "CameraName";
const char* CameraCalc::_jsonCameraSpecTypeKey = "CameraSpecType";
CameraCalc::CameraCalc(Vehicle* vehicle, QObject* parent)
: CameraSpec (parent)
......@@ -30,6 +31,7 @@ CameraCalc::CameraCalc(Vehicle* vehicle, QObject* parent)
, _dirty (false)
, _cameraName (manualCameraName())
, _disableRecalc (false)
, _distanceToSurfaceRelative (true)
, _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraCalc.FactMetaData.json"), this))
, _valueSetIsDistanceFact (0, _valueSetIsDistanceName, FactMetaData::valueTypeBool)
, _distanceToSurfaceFact (0, _distanceToSurfaceName, FactMetaData::valueTypeDouble)
......@@ -52,7 +54,18 @@ CameraCalc::CameraCalc(Vehicle* vehicle, QObject* parent)
_adjustedFootprintSideFact.setMetaData (_metaDataMap[_adjustedFootprintSideName], true);
_adjustedFootprintFrontalFact.setMetaData (_metaDataMap[_adjustedFootprintFrontalName], true);
connect(&_valueSetIsDistanceFact, &Fact::valueChanged, this, &CameraCalc::_setDirty);
connect(&_distanceToSurfaceFact, &Fact::valueChanged, this, &CameraCalc::_setDirty);
connect(&_imageDensityFact, &Fact::valueChanged, this, &CameraCalc::_setDirty);
connect(&_frontalOverlapFact, &Fact::valueChanged, this, &CameraCalc::_setDirty);
connect(&_sideOverlapFact, &Fact::valueChanged, this, &CameraCalc::_setDirty);
connect(&_adjustedFootprintSideFact, &Fact::valueChanged, this, &CameraCalc::_setDirty);
connect(&_adjustedFootprintFrontalFact, &Fact::valueChanged, this, &CameraCalc::_setDirty);
connect(this, &CameraCalc::cameraNameChanged, this, &CameraCalc::_setDirty);
connect(this, &CameraCalc::distanceToSurfaceRelativeChanged, this, &CameraCalc::_setDirty);
connect(this, &CameraCalc::cameraNameChanged, this, &CameraCalc::_recalcTriggerDistance);
connect(this, &CameraCalc::cameraNameChanged, this, &CameraCalc::_adjustDistanceToSurfaceRelative);
connect(&_distanceToSurfaceFact, &Fact::rawValueChanged, this, &CameraCalc::_recalcTriggerDistance);
connect(&_imageDensityFact, &Fact::rawValueChanged, this, &CameraCalc::_recalcTriggerDistance);
......@@ -167,8 +180,9 @@ void CameraCalc::save(QJsonObject& json) const
json[JsonHelper::jsonVersionKey] = 1;
json[_adjustedFootprintSideName] = _adjustedFootprintSideFact.rawValue().toDouble();
json[_adjustedFootprintFrontalName] = _adjustedFootprintFrontalFact.rawValue().toDouble();
json[_distanceToSurfaceName] = _distanceToSurfaceFact.rawValue().toDouble();
json[_jsonCameraNameKey] = _cameraName;
json[_distanceToSurfaceName] = _distanceToSurfaceFact.rawValue().toDouble();
json[_distanceToSurfaceRelativeName] = _distanceToSurfaceRelative;
json[_jsonCameraNameKey] = _cameraName;
if (_cameraName != manualCameraName()) {
CameraSpec::save(json);
......@@ -209,6 +223,7 @@ bool CameraCalc::load(const QJsonObject& json, QString& errorString)
{ _adjustedFootprintSideName, QJsonValue::Double, true },
{ _adjustedFootprintFrontalName, QJsonValue::Double, true },
{ _distanceToSurfaceName, QJsonValue::Double, true },
{ _distanceToSurfaceRelativeName, QJsonValue::Bool, true },
};
if (!JsonHelper::validateKeys(v1Json, keyInfoList1, errorString)) {
return false;
......@@ -221,6 +236,8 @@ bool CameraCalc::load(const QJsonObject& json, QString& errorString)
_adjustedFootprintFrontalFact.setRawValue (v1Json[_adjustedFootprintFrontalName].toDouble());
_distanceToSurfaceFact.setRawValue (v1Json[_distanceToSurfaceName].toDouble());
_distanceToSurfaceRelative = v1Json[_distanceToSurfaceRelativeName].toBool();
if (_cameraName != manualCameraName()) {
QList<JsonHelper::KeyValidateInfo> keyInfoList2 = {
{ _valueSetIsDistanceName, QJsonValue::Bool, true },
......@@ -257,3 +274,23 @@ QString CameraCalc::manualCameraName(void)
{
return tr("Manual (no camera specs)");
}
void CameraCalc::_adjustDistanceToSurfaceRelative(void)
{
if (!isManualCamera()) {
setDistanceToSurfaceRelative(true);
}
}
void CameraCalc::setDistanceToSurfaceRelative(bool distanceToSurfaceRelative)
{
if (distanceToSurfaceRelative != _distanceToSurfaceRelative) {
_distanceToSurfaceRelative = distanceToSurfaceRelative;
emit distanceToSurfaceRelativeChanged(distanceToSurfaceRelative);
}
}
void CameraCalc::_setDirty(void)
{
setDirty(true);
}
......@@ -20,17 +20,18 @@ class CameraCalc : public CameraSpec
public:
CameraCalc(Vehicle* vehicle, QObject* parent = NULL);
Q_PROPERTY(QString cameraName READ cameraName WRITE setCameraName NOTIFY cameraNameChanged)
Q_PROPERTY(QString customCameraName READ customCameraName CONSTANT) ///< Camera name for custom camera setting
Q_PROPERTY(QString manualCameraName READ manualCameraName CONSTANT) ///< Camera name for manual camera setting
Q_PROPERTY(bool isManualCamera READ isManualCamera NOTIFY cameraNameChanged) ///< true: using manual camera
Q_PROPERTY(Fact* valueSetIsDistance READ valueSetIsDistance CONSTANT) ///< true: distance specified, resolution calculated
Q_PROPERTY(Fact* distanceToSurface READ distanceToSurface CONSTANT) ///< Distance to surface for image foot print calculation
Q_PROPERTY(Fact* imageDensity READ imageDensity CONSTANT) ///< Image density on surface (cm/px)
Q_PROPERTY(Fact* frontalOverlap READ frontalOverlap CONSTANT)
Q_PROPERTY(Fact* sideOverlap READ sideOverlap CONSTANT)
Q_PROPERTY(Fact* adjustedFootprintSide READ adjustedFootprintSide CONSTANT) ///< Side footprint adjusted down for overlap
Q_PROPERTY(Fact* adjustedFootprintFrontal READ adjustedFootprintFrontal CONSTANT) ///< Frontal footprint adjusted down for overlap
Q_PROPERTY(QString cameraName READ cameraName WRITE setCameraName NOTIFY cameraNameChanged)
Q_PROPERTY(QString customCameraName READ customCameraName CONSTANT) ///< Camera name for custom camera setting
Q_PROPERTY(QString manualCameraName READ manualCameraName CONSTANT) ///< Camera name for manual camera setting
Q_PROPERTY(bool isManualCamera READ isManualCamera NOTIFY cameraNameChanged) ///< true: using manual camera
Q_PROPERTY(Fact* valueSetIsDistance READ valueSetIsDistance CONSTANT) ///< true: distance specified, resolution calculated
Q_PROPERTY(Fact* distanceToSurface READ distanceToSurface CONSTANT) ///< Distance to surface for image foot print calculation
Q_PROPERTY(Fact* imageDensity READ imageDensity CONSTANT) ///< Image density on surface (cm/px)
Q_PROPERTY(Fact* frontalOverlap READ frontalOverlap CONSTANT)
Q_PROPERTY(Fact* sideOverlap READ sideOverlap CONSTANT)
Q_PROPERTY(Fact* adjustedFootprintSide READ adjustedFootprintSide CONSTANT) ///< Side footprint adjusted down for overlap
Q_PROPERTY(Fact* adjustedFootprintFrontal READ adjustedFootprintFrontal CONSTANT) ///< Frontal footprint adjusted down for overlap
Q_PROPERTY(bool distanceToSurfaceRelative READ distanceToSurfaceRelative WRITE setDistanceToSurfaceRelative NOTIFY distanceToSurfaceRelativeChanged)
// The following values are calculated from the camera properties
Q_PROPERTY(double imageFootprintSide READ imageFootprintSide NOTIFY imageFootprintSideChanged) ///< Size of image size side in meters
......@@ -57,30 +58,36 @@ public:
const Fact* adjustedFootprintSide (void) const { return &_adjustedFootprintSideFact; }
const Fact* adjustedFootprintFrontal (void) const { return &_adjustedFootprintFrontalFact; }
bool isManualCamera (void) { return cameraName() == manualCameraName(); }
double imageFootprintSide (void) const { return _imageFootprintSide; }
double imageFootprintFrontal (void) const { return _imageFootprintFrontal; }
bool dirty (void) const { return _dirty; }
bool isManualCamera (void) { return cameraName() == manualCameraName(); }
double imageFootprintSide (void) const { return _imageFootprintSide; }
double imageFootprintFrontal (void) const { return _imageFootprintFrontal; }
bool distanceToSurfaceRelative (void) const { return _distanceToSurfaceRelative; }
bool dirty (void) const { return _dirty; }
void setDirty (bool dirty);
void setDirty (bool dirty);
void setDistanceToSurfaceRelative (bool distanceToSurfaceRelative);
void save(QJsonObject& json) const;
bool load(const QJsonObject& json, QString& errorString);
signals:
void cameraNameChanged (QString cameraName);
void dirtyChanged (bool dirty);
void imageFootprintSideChanged (double imageFootprintSide);
void imageFootprintFrontalChanged (double imageFootprintFrontal);
void cameraNameChanged (QString cameraName);
void dirtyChanged (bool dirty);
void imageFootprintSideChanged (double imageFootprintSide);
void imageFootprintFrontalChanged (double imageFootprintFrontal);
void distanceToSurfaceRelativeChanged (bool distanceToSurfaceRelative);
private slots:
void _recalcTriggerDistance(void);
void _recalcTriggerDistance (void);
void _adjustDistanceToSurfaceRelative (void);
void _setDirty (void);
private:
Vehicle* _vehicle;
bool _dirty;
QString _cameraName;
bool _disableRecalc;
bool _distanceToSurfaceRelative;
QMap<QString, FactMetaData*> _metaDataMap;
......@@ -99,6 +106,7 @@ private:
static const char* _valueSetIsDistanceName;
static const char* _distanceToSurfaceName;
static const char* _distanceToSurfaceRelativeName;
static const char* _imageDensityName;
static const char* _frontalOverlapName;
static const char* _sideOverlapName;
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "CameraCalcTest.h"
#include "QGCApplication.h"
CameraCalcTest::CameraCalcTest(void)
: _offlineVehicle(NULL)
{
}
void CameraCalcTest::init(void)
{
UnitTest::init();
_offlineVehicle = new Vehicle(MAV_AUTOPILOT_PX4, MAV_TYPE_QUADROTOR, qgcApp()->toolbox()->firmwarePluginManager(), this);
_cameraCalc = new CameraCalc(_offlineVehicle, this);
_rgSignals[cameraNameChangedIndex] = SIGNAL(cameraNameChanged(QString));
_rgSignals[dirtyChangedIndex] = SIGNAL(dirtyChanged(bool));
_rgSignals[imageFootprintSideChangedIndex] = SIGNAL(imageFootprintSideChanged(double));
_rgSignals[imageFootprintFrontalChangedIndex] = SIGNAL(imageFootprintFrontalChanged(double));
_rgSignals[distanceToSurfaceRelativeChangedIndex] = SIGNAL(distanceToSurfaceRelativeChanged(bool));
_multiSpy = new MultiSignalSpy();
QCOMPARE(_multiSpy->init(_cameraCalc, _rgSignals, _cSignals), true);
}
void CameraCalcTest::cleanup(void)
{
delete _cameraCalc;
delete _offlineVehicle;
delete _multiSpy;
}
void CameraCalcTest::_testDirty(void)
{
QVERIFY(!_cameraCalc->dirty());
_cameraCalc->setDirty(false);
QVERIFY(!_cameraCalc->dirty());
QVERIFY(_multiSpy->checkNoSignals());
_cameraCalc->setDirty(true);
QVERIFY(_cameraCalc->dirty());
QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_multiSpy->clearAllSignals();
_cameraCalc->setDirty(false);
QVERIFY(!_cameraCalc->dirty());
QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask));
_multiSpy->clearAllSignals();
// These facts should set dirty when changed
QList<Fact*> rgFacts;
rgFacts << _cameraCalc->valueSetIsDistance()
<< _cameraCalc->distanceToSurface()
<< _cameraCalc->imageDensity()
<< _cameraCalc->frontalOverlap ()
<< _cameraCalc->sideOverlap ()
<< _cameraCalc->adjustedFootprintSide()
<< _cameraCalc->adjustedFootprintFrontal();
foreach(Fact* fact, rgFacts) {
qDebug() << fact->name();
QVERIFY(!_cameraCalc->dirty());
if (fact->typeIsBool()) {
fact->setRawValue(!fact->rawValue().toBool());
} else {
fact->setRawValue(fact->rawValue().toDouble() + 1);
}
QVERIFY(_multiSpy->checkSignalByMask(dirtyChangedMask));
_cameraCalc->setDirty(false);
_multiSpy->clearAllSignals();
}
rgFacts.clear();
_cameraCalc->setCameraName(_cameraCalc->customCameraName());
QVERIFY(_cameraCalc->dirty());
_multiSpy->clearAllSignals();
_cameraCalc->setDistanceToSurfaceRelative(!_cameraCalc->distanceToSurfaceRelative());
QVERIFY(_cameraCalc->dirty());
_multiSpy->clearAllSignals();
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "UnitTest.h"
#include "MultiSignalSpy.h"
#include "CameraCalc.h"
#include <QGeoCoordinate>
class CameraCalcTest : public UnitTest
{
Q_OBJECT
public:
CameraCalcTest(void);
protected:
void init(void) final;
void cleanup(void) final;
private slots:
void _testDirty(void);
private:
enum {
cameraNameChangedIndex = 0,
dirtyChangedIndex,
imageFootprintSideChangedIndex,
imageFootprintFrontalChangedIndex,
distanceToSurfaceRelativeChangedIndex,
maxSignalIndex
};
enum {
cameraNameChangedMask = 1 << cameraNameChangedIndex,
dirtyChangedMask = 1 << dirtyChangedIndex,
imageFootprintSideChangedMask = 1 << imageFootprintSideChangedIndex,
imageFootprintFrontalChangedMask = 1 << imageFootprintFrontalChangedIndex,
distanceToSurfaceRelativeChangedMask = 1 << distanceToSurfaceRelativeChangedIndex,
};
static const size_t _cSignals = maxSignalIndex;
const char* _rgSignals[_cSignals];
Vehicle* _offlineVehicle;
MultiSignalSpy* _multiSpy;
CameraCalc* _cameraCalc;
};
......@@ -35,8 +35,8 @@
"defaultValue": 30
},
{
"name": "TurnaroundDist",
"shortDescription": "Amount of additional distance to add outside the grid area for vehicle turnaround.",
"name": "TurnaroundDistance",
"shortDescription": "Amount of additional distance to add outside the survey area for vehicle turnaround.",
"type": "double",
"decimalPlaces": 2,
"min": 0,
......
......@@ -9,7 +9,7 @@
#pragma once
#include "ComplexMissionItem.h"
#include "TransectStyleComplexItem.h"
#include "MissionItem.h"
#include "SettingsFact.h"
#include "QGCLoggingCategory.h"
......@@ -19,120 +19,61 @@
Q_DECLARE_LOGGING_CATEGORY(CorridorScanComplexItemLog)
class CorridorScanComplexItem : public ComplexMissionItem
class CorridorScanComplexItem : public TransectStyleComplexItem
{
Q_OBJECT
public:
CorridorScanComplexItem(Vehicle* vehicle, QObject* parent = NULL);
Q_PROPERTY(CameraCalc* cameraCalc READ cameraCalc CONSTANT)
Q_PROPERTY(QGCMapPolyline* corridorPolyline READ corridorPolyline CONSTANT)
Q_PROPERTY(QGCMapPolygon* corridorPolygon READ corridorPolygon CONSTANT)
Q_PROPERTY(Fact* corridorWidth READ corridorWidth CONSTANT)
Q_PROPERTY(int cameraShots READ cameraShots NOTIFY cameraShotsChanged)
Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged)
Q_PROPERTY(double coveredArea READ coveredArea NOTIFY coveredAreaChanged)
Q_PROPERTY(double cameraMinTriggerInterval MEMBER _cameraMinTriggerInterval NOTIFY cameraMinTriggerIntervalChanged)
Q_PROPERTY(QVariantList transectPoints READ transectPoints NOTIFY transectPointsChanged)
CameraCalc* cameraCalc (void) { return &_cameraCalc; }
QGCMapPolyline* corridorPolyline(void) { return &_corridorPolyline; }
QGCMapPolygon* corridorPolygon (void) { return &_corridorPolygon; }
Fact* corridorWidth (void) { return &_corridorWidthFact; }
QVariantList transectPoints (void) { return _transectPoints; }
Q_PROPERTY(CameraCalc* cameraCalc READ cameraCalc CONSTANT)
Q_PROPERTY(QGCMapPolyline* corridorPolyline READ corridorPolyline CONSTANT)
Q_PROPERTY(Fact* corridorWidth READ corridorWidth CONSTANT)
int cameraShots (void) const { return _cameraShots; }
double timeBetweenShots (void);
double coveredArea (void) const;
Fact* corridorWidth (void) { return &_corridorWidthFact; }
QGCMapPolyline* corridorPolyline(void) { return &_corridorPolyline; }
Q_INVOKABLE void rotateEntryPoint(void);
// Overrides from ComplexMissionItem
double complexDistance (void) const final { return _scanDistance; }
int lastSequenceNumber (void) const final;
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final;
double greatestDistanceTo (const QGeoCoordinate &other) const final;
QString mapVisualQML (void) const final { return QStringLiteral("CorridorScanMapVisual.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;
bool specifiesAltitudeOnly (void) const final { return false; }
QString commandDescription (void) const final { return tr("Corridor Scan"); }
QString commandName (void) const final { return tr("Corridor Scan"); }
QString abbreviation (void) const final { return "S"; }
QGeoCoordinate coordinate (void) const final { return _coordinate; }
QGeoCoordinate exitCoordinate (void) const final { return _exitCoordinate; }
int sequenceNumber (void) const final { return _sequenceNumber; }
double specifiedFlightSpeed (void) final { return std::numeric_limits<double>::quiet_NaN(); }
double specifiedGimbalYaw (void) final { return std::numeric_limits<double>::quiet_NaN(); }
double specifiedGimbalPitch (void) final { return std::numeric_limits<double>::quiet_NaN(); }
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
void setMissionFlightStatus (MissionController::MissionFlightStatus_t& missionFlightStatus) final;
void applyNewAltitude (double newAltitude) final;
bool coordinateHasRelativeAltitude (void) const final { return true /*_altitudeRelative*/; }
bool exitCoordinateHasRelativeAltitude (void) const final { return true /*_altitudeRelative*/; }
bool exitCoordinateSameAsEntry (void) const final { return false; }
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final { Q_UNUSED(coordinate); }
void setSequenceNumber (int sequenceNumber) final;
void save (QJsonArray& missionItems) final;
int lastSequenceNumber (void) const final;
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final;
QString mapVisualQML (void) const final { return QStringLiteral("CorridorScanMapVisual.qml"); }
// Overrides from TransectStyleComplexItem
void save (QJsonArray& missionItems) final;
bool specifiesCoordinate (void) const final;
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
void applyNewAltitude (double newAltitude) final;
static const char* jsonComplexItemTypeValue;
signals:
void cameraShotsChanged (void);
void timeBetweenShotsChanged (void);
void cameraMinTriggerIntervalChanged(double cameraMinTriggerInterval);
void altitudeRelativeChanged (bool altitudeRelative);
void transectPointsChanged (void);
void coveredAreaChanged (void);
static const char* settingsGroup;
static const char* corridorWidthName;
private slots:
void _setDirty (void);
void _polylineDirtyChanged (bool dirty);
void _polylineCountChanged (int count);
void _clearInternal (void);
void _updateCoordinateAltitudes (void);
void _signalLastSequenceNumberChanged (void);
void _rebuildCorridor (void);
void _rebuildTransects (void);
// Overrides from TransectStyleComplexItem
virtual void _rebuildTransects (void) final;
private:
void _setExitCoordinate (const QGeoCoordinate& coordinate);
void _setScanDistance (double scanDistance);
void _setCameraShots (int cameraShots);
double _triggerDistance (void) const;
int _transectCount (void) const;
void _rebuildCorridorPolygon(void);
int _sequenceNumber;
bool _dirty;
QGeoCoordinate _coordinate;
QGeoCoordinate _exitCoordinate;
QGCMapPolyline _corridorPolyline;
QGCMapPolygon _corridorPolygon;
Fact _corridorWidthFact;
QVariantList _transectPoints;
bool _ignoreRecalc;
double _scanDistance;
int _cameraShots;
double _timeBetweenShots;
double _cameraMinTriggerInterval;
double _cruiseSpeed;
CameraCalc _cameraCalc;
QGCMapPolyline _corridorPolyline;
QList<QList<QGeoCoordinate>> _transectSegments; ///< Internal transect segments including grid exit, turnaround and internal camera points
static QMap<QString, FactMetaData*> _metaDataMap;
bool _ignoreRecalc;
int _entryPoint;
static const char* _corridorWidthFactName;
QMap<QString, FactMetaData*> _metaDataMap;
SettingsFact _corridorWidthFact;
static const char* _jsonCameraCalcKey;
static const char* _entryPointName;
};
......@@ -25,94 +25,37 @@ void CorridorScanComplexItemTest::init(void)
_offlineVehicle = new Vehicle(MAV_AUTOPILOT_PX4, MAV_TYPE_QUADROTOR, qgcApp()->toolbox()->firmwarePluginManager(), this);
_corridorItem = new CorridorScanComplexItem(_offlineVehicle, this);
// _corridorItem->setTurnaroundDist(0); // Unit test written for no turnaround distance
_setPolyline();
_corridorItem->setDirty(false);
_mapPolyline = _corridorItem->corridorPolyline();
_rgSignals[complexDistanceChangedIndex] = SIGNAL(complexDistanceChanged());
_rgSignals[greatestDistanceToChangedIndex] = SIGNAL(greatestDistanceToChanged());
_rgSignals[additionalTimeDelayChangedIndex] = SIGNAL(additionalTimeDelayChanged());
_rgSignals[transectPointsChangedIndex] = SIGNAL(transectPointsChanged());
_rgSignals[cameraShotsChangedIndex] = SIGNAL(cameraShotsChanged());
_rgSignals[coveredAreaChangedIndex] = SIGNAL(coveredAreaChanged());
_rgSignals[timeBetweenShotsChangedIndex] = SIGNAL(timeBetweenShotsChanged());
_rgSignals[dirtyChangedIndex] = SIGNAL(dirtyChanged(bool));
_multiSpy = new MultiSignalSpy();
QCOMPARE(_multiSpy->init(_corridorItem, _rgSignals, _cSignals), true);
_rgCorridorPolygonSignals[corridorPolygonPathChangedIndex] = SIGNAL(pathChanged());
_multiSpyCorridorPolygon = new MultiSignalSpy();
QCOMPARE(_multiSpyCorridorPolygon->init(_corridorItem->corridorPolygon(), _rgCorridorPolygonSignals, _cCorridorPolygonSignals), true);
QCOMPARE(_multiSpyCorridorPolygon->init(_corridorItem->surveyAreaPolygon(), _rgCorridorPolygonSignals, _cCorridorPolygonSignals), true);
}
void CorridorScanComplexItemTest::cleanup(void)
{
delete _corridorItem;
delete _offlineVehicle;
delete _multiSpy;
}
void CorridorScanComplexItemTest::_testDirty(void)
{
QVERIFY(!_corridorItem->dirty());
Fact* fact = _corridorItem->corridorWidth();
fact->setRawValue(fact->rawValue().toDouble() + 1);
QVERIFY(_corridorItem->dirty());
_corridorItem->setDirty(false);
QVERIFY(!_corridorItem->dirty());
QVERIFY(_multiSpy->checkNoSignals());
_corridorItem->setDirty(true);
changeFactValue(_corridorItem->cameraCalc()->distanceToSurface());
QVERIFY(_corridorItem->dirty());
QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_multiSpy->clearAllSignals();
_corridorItem->setDirty(false);
QVERIFY(!_corridorItem->dirty());
QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask));
QVERIFY(!_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_multiSpy->clearAllSignals();
// These facts should set dirty when changed
QList<Fact*> rgFacts;
#if 0
rgFacts << _corridorItem->gridAltitude() << _corridorItem->gridAngle() << _corridorItem->gridSpacing() << _corridorItem->turnaroundDist() << _corridorItem->cameraTriggerDistance() <<
_corridorItem->gridAltitudeRelative() << _corridorItem->cameraTriggerInTurnaround() << _corridorItem->hoverAndCapture();
#endif
rgFacts << _corridorItem->corridorWidth();
foreach(Fact* fact, rgFacts) {
qDebug() << fact->name();
QVERIFY(!_corridorItem->dirty());
if (fact->typeIsBool()) {
fact->setRawValue(!fact->rawValue().toBool());
} else {
fact->setRawValue(fact->rawValue().toDouble() + 1);
}
QVERIFY(_multiSpy->checkSignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_corridorItem->setDirty(false);
_multiSpy->clearAllSignals();
}
rgFacts.clear();
// These facts should not change dirty bit
#if 0
rgFacts << _corridorItem->groundResolution() << _corridorItem->frontalOverlap() << _corridorItem->sideOverlap() << _corridorItem->cameraSensorWidth() << _corridorItem->cameraSensorHeight() <<
_corridorItem->cameraResolutionWidth() << _corridorItem->cameraResolutionHeight() << _corridorItem->cameraFocalLength() << _corridorItem->cameraOrientationLandscape() <<
_corridorItem->fixedValueIsAltitude() << _corridorItem->camera() << _corridorItem->manualGrid();
#endif
foreach(Fact* fact, rgFacts) {
qDebug() << fact->name();
QVERIFY(!_corridorItem->dirty());
if (fact->typeIsBool()) {
fact->setRawValue(!fact->rawValue().toBool());
} else {
fact->setRawValue(fact->rawValue().toDouble() + 1);
}
QVERIFY(_multiSpy->checkNoSignalByMask(dirtyChangedMask));
QVERIFY(!_corridorItem->dirty());
_multiSpy->clearAllSignals();
}
rgFacts.clear();
QGeoCoordinate coord = _corridorItem->corridorPolyline()->vertexCoordinate(0);
coord.setLatitude(coord.latitude() + 1);
_corridorItem->corridorPolyline()->adjustVertex(1, coord);
QVERIFY(_corridorItem->dirty());
_corridorItem->setDirty(false);
}
void CorridorScanComplexItemTest::_testCameraTrigger(void)
......@@ -155,7 +98,7 @@ void CorridorScanComplexItemTest::_setPolyline(void)
{
for (int i=0; i<_linePoints.count(); i++) {
QGeoCoordinate& vertex = _linePoints[i];
_mapPolyline->appendVertex(vertex);
_corridorItem->corridorPolyline()->appendVertex(vertex);
}
}
......@@ -191,27 +134,24 @@ void CorridorScanComplexItemTest::_testItemCount(void)
{
QList<MissionItem*> items;
_setPolyline();
_corridorItem->turnAroundDistance()->setRawValue(20);
// _corridorItem->cameraTriggerInTurnaround()->setRawValue(false);
_corridorItem->cameraTriggerInTurnAround()->setRawValue(false);
_corridorItem->appendMissionItems(items, this);
QCOMPARE(items.count(), _corridorItem->lastSequenceNumber());
QCOMPARE(items.count() - 1, _corridorItem->lastSequenceNumber());
items.clear();
_corridorItem->cameraTriggerInTurnAround()->setRawValue(true);
_corridorItem->appendMissionItems(items, this);
QCOMPARE(items.count() - 1, _corridorItem->lastSequenceNumber());
items.clear();
}
void CorridorScanComplexItemTest::_testPathChanges(void)
{
_setPolyline();
_corridorItem->setDirty(false);
_multiSpy->clearAllSignals();
_multiSpyCorridorPolygon->clearAllSignals();
QGeoCoordinate vertex = _mapPolyline->vertexCoordinate(1);
QGeoCoordinate vertex = _corridorItem->corridorPolyline()->vertexCoordinate(1);
vertex.setLatitude(vertex.latitude() + 0.01);
_mapPolyline->adjustVertex(1, vertex);
_corridorItem->corridorPolyline()->adjustVertex(1, vertex);
QVERIFY(_corridorItem->dirty());
QVERIFY(_multiSpy->checkOnlySignalsByMask(dirtyChangedMask | transectPointsChangedMask | cameraShotsChangedMask | coveredAreaChangedMask | complexDistanceChangedMask | greatestDistanceToChangedMask));
QVERIFY(_multiSpyCorridorPolygon->checkSignalsByMask(corridorPolygonPathChangedMask));
_multiSpy->clearAllSignals();
}
......@@ -37,32 +37,6 @@ private slots:
private:
void _setPolyline(void);
enum {
complexDistanceChangedIndex = 0,
greatestDistanceToChangedIndex,
additionalTimeDelayChangedIndex,
transectPointsChangedIndex,
cameraShotsChangedIndex,
coveredAreaChangedIndex,
timeBetweenShotsChangedIndex,
dirtyChangedIndex,
maxSignalIndex
};
enum {
complexDistanceChangedMask = 1 << complexDistanceChangedIndex,
greatestDistanceToChangedMask = 1 << greatestDistanceToChangedIndex,
additionalTimeDelayChangedMask = 1 << additionalTimeDelayChangedIndex,
transectPointsChangedMask = 1 << transectPointsChangedIndex,
cameraShotsChangedMask = 1 << cameraShotsChangedIndex,
coveredAreaChangedMask = 1 << coveredAreaChangedIndex,
timeBetweenShotsChangedMask = 1 << timeBetweenShotsChangedIndex,
dirtyChangedMask = 1 << dirtyChangedIndex
};
static const size_t _cSignals = maxSignalIndex;
const char* _rgSignals[_cSignals];
enum {
corridorPolygonPathChangedIndex = 0,
maxCorridorPolygonSignalIndex
......@@ -76,9 +50,7 @@ private:
const char* _rgCorridorPolygonSignals[_cCorridorPolygonSignals];
Vehicle* _offlineVehicle;
MultiSignalSpy* _multiSpy;
MultiSignalSpy* _multiSpyCorridorPolygon;
CorridorScanComplexItem* _corridorItem;
QGCMapPolyline* _mapPolyline;
QList<QGeoCoordinate> _linePoints;
};
......@@ -493,6 +493,7 @@ void MissionController::removeAll(void)
{
if (_visualItems) {
_deinitAllVisualItems();
_visualItems->clearAndDeleteContents();
_visualItems->deleteLater();
_settingsItem = NULL;
_visualItems = new QmlObjectListModel(this);
......
......@@ -242,7 +242,7 @@ void MissionManager::_handleMissionCurrent(const mavlink_message_t& message)
emit currentIndexChanged(_currentMissionIndex);
}
if (_currentMissionIndex != _lastCurrentIndex) {
if (_currentMissionIndex != _lastCurrentIndex && _cachedLastCurrentIndex != _currentMissionIndex) {
// We have to be careful of an RTL sequence causing a change of index to the DO_LAND_START sequence. This also triggers
// a flight mode change away from mission flight mode. So we only update _lastCurrentIndex when the flight mode is mission.
// But we can run into problems where we may get the MISSION_CURRENT message for the RTL/DO_LAND_START sequenc change prior
......
......@@ -30,13 +30,13 @@ PlanManager::PlanManager(Vehicle* vehicle, MAV_MISSION_TYPE planType)
, _transactionInProgress(TransactionNone)
, _resumeMission(false)
, _lastMissionRequest(-1)
, _missionItemCountToRead(-1)
, _currentMissionIndex(-1)
, _lastCurrentIndex(-1)
{
_ackTimeoutTimer = new QTimer(this);
_ackTimeoutTimer->setSingleShot(true);
_ackTimeoutTimer->setInterval(_ackTimeoutMilliseconds);
connect(_ackTimeoutTimer, &QTimer::timeout, this, &PlanManager::_ackTimeout);
}
......@@ -244,6 +244,24 @@ void PlanManager::_ackTimeout(void)
void PlanManager::_startAckTimeout(AckType_t ack)
{
switch (ack) {
case AckMissionItem:
// We are actively trying to get the mission item, so we don't want to wait as long.
_ackTimeoutTimer->setInterval(_retryTimeoutMilliseconds);
break;
case AckNone:
// FALLTHROUGH
case AckMissionCount:
// FALLTHROUGH
case AckMissionRequest:
// FALLTHROUGH
case AckMissionClearAll:
// FALLTHROUGH
case AckGuidedItem:
_ackTimeoutTimer->setInterval(_ackTimeoutMilliseconds);
break;
}
_expectedAck = ack;
_ackTimeoutTimer->start();
}
......@@ -317,6 +335,7 @@ void PlanManager::_handleMissionCount(const mavlink_message_t& message)
for (int i=0; i<missionCount.count; i++) {
_itemIndicesToRead << i;
}
_missionItemCountToRead = missionCount.count;
_requestNextMissionItem();
}
}
......@@ -460,7 +479,7 @@ void PlanManager::_handleMissionItem(const mavlink_message_t& message, bool miss
return;
}
emit progressPct((double)seq / (double)_missionItems.count());
emit progressPct((double)seq / (double)_missionItemCountToRead);
_retryCount = 0;
if (_itemIndicesToRead.count() == 0) {
......
......@@ -28,11 +28,11 @@ Q_DECLARE_LOGGING_CATEGORY(PlanManagerLog)
class PlanManager : public QObject
{
Q_OBJECT
public:
PlanManager(Vehicle* vehicle, MAV_MISSION_TYPE planType);
~PlanManager();
bool inProgress(void) const;
const QList<MissionItem*>& missionItems(void) { return _missionItems; }
......@@ -41,11 +41,11 @@ public:
/// Last current mission item reported while in Mission flight mode
int lastCurrentIndex(void) const { return _lastCurrentIndex; }
/// Load the mission items from the vehicle
/// Signals newMissionItemsAvailable when done
void loadFromVehicle(void);
/// Writes the specified set of mission items to the vehicle
/// IMPORTANT NOTE: PlanManager will take control of the MissionItem objects with the missionItems list. It will free them when done.
/// @param missionItems Items to send to vehicle
......@@ -70,9 +70,12 @@ public:
} ErrorCode_t;
// These values are public so the unit test can set appropriate signal wait times
// When passively waiting for a mission process, use a longer timeout.
static const int _ackTimeoutMilliseconds = 1000;
// When actively retrying to request mission items, use a shorter timeout instead.
static const int _retryTimeoutMilliseconds = 250;
static const int _maxRetryCount = 5;
signals:
void newMissionItemsAvailable (bool removeAllRequested);
void inProgressChanged (bool inProgress);
......@@ -88,7 +91,7 @@ signals:
private slots:
void _mavlinkMessageReceived(const mavlink_message_t& message);
void _ackTimeout(void);
protected:
typedef enum {
AckNone, ///< State machine is idle
......@@ -134,17 +137,18 @@ protected:
Vehicle* _vehicle;
MAV_MISSION_TYPE _planType;
LinkInterface* _dedicatedLink;
QTimer* _ackTimeoutTimer;
AckType_t _expectedAck;
int _retryCount;
TransactionType_t _transactionInProgress;
bool _resumeMission;
QList<int> _itemIndicesToWrite; ///< List of mission items which still need to be written to vehicle
QList<int> _itemIndicesToRead; ///< List of mission items which still need to be requested from vehicle
int _lastMissionRequest; ///< Index of item last requested by MISSION_REQUEST
int _missionItemCountToRead;///< Count of all mission items to read
QList<MissionItem*> _missionItems; ///< Set of mission items on vehicle
QList<MissionItem*> _writeMissionItems; ///< Set of mission items currently being written to vehicle
int _currentMissionIndex;
......
......@@ -296,7 +296,7 @@ private:
static const char* _jsonFixedValueIsAltitudeKey;
static const char* _jsonRefly90DegreesKey;
static const int _hoverAndCaptureDelaySeconds = 1;
static const int _hoverAndCaptureDelaySeconds = 2;
};
#endif
[
{
"name": "TurnAroundDistance",
"shortDescription": "Amount of additional distance to add outside the survey area for vehicle turn around.",
"type": "double",
"decimalPlaces": 2,
"min": 0,
"units": "m",
"defaultValue": 30
},
{
"name": "TurnAroundDistanceMultiRotor",
"shortDescription": "Amount of additional distance to add outside the survey area for vehicle turn around.",
"type": "double",
"decimalPlaces": 2,
"min": 0,
"units": "m",
"defaultValue": 10
},
{
"name": "CameraTriggerInTurnAround",
"shortDescription": "Camera continues taking images in turn arounds.",
"type": "bool",
"defaultValue": true
},
{
"name": "HoverAndCapture",
"shortDescription": "Stop and Hover at each image point before taking image",
"type": "bool",
"defaultValue": false
},
{
"name": "Refly90Degrees",
"shortDescription": "Refly the pattern at a 90 degree angle",
"type": "bool",
"defaultValue": false
}
]
This diff is collapsed.
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "ComplexMissionItem.h"
#include "MissionItem.h"
#include "SettingsFact.h"
#include "QGCLoggingCategory.h"
#include "QGCMapPolyline.h"
#include "QGCMapPolygon.h"
#include "CameraCalc.h"
Q_DECLARE_LOGGING_CATEGORY(TransectStyleComplexItemLog)
class TransectStyleComplexItem : public ComplexMissionItem
{
Q_OBJECT
public:
TransectStyleComplexItem(Vehicle* vehicle, QString settignsGroup, QObject* parent = NULL);
Q_PROPERTY(QGCMapPolygon* surveyAreaPolygon READ surveyAreaPolygon CONSTANT)
Q_PROPERTY(CameraCalc* cameraCalc READ cameraCalc CONSTANT)
Q_PROPERTY(Fact* turnAroundDistance READ turnAroundDistance CONSTANT)
Q_PROPERTY(Fact* cameraTriggerInTurnAround READ cameraTriggerInTurnAround CONSTANT)
Q_PROPERTY(Fact* hoverAndCapture READ hoverAndCapture CONSTANT)
Q_PROPERTY(Fact* refly90Degrees READ refly90Degrees CONSTANT)
Q_PROPERTY(int cameraShots READ cameraShots NOTIFY cameraShotsChanged)
Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged)
Q_PROPERTY(double coveredArea READ coveredArea NOTIFY coveredAreaChanged)
Q_PROPERTY(double cameraMinTriggerInterval READ cameraMinTriggerInterval NOTIFY cameraMinTriggerIntervalChanged)
Q_PROPERTY(bool hoverAndCaptureAllowed READ hoverAndCaptureAllowed CONSTANT)
Q_PROPERTY(QVariantList transectPoints READ transectPoints NOTIFY transectPointsChanged)
QGCMapPolygon* surveyAreaPolygon (void) { return &_surveyAreaPolygon; }
CameraCalc* cameraCalc (void) { return &_cameraCalc; }
QVariantList transectPoints (void) { return _transectPoints; }
Fact* turnAroundDistance (void) { return &_turnAroundDistanceFact; }
Fact* cameraTriggerInTurnAround (void) { return &_cameraTriggerInTurnAroundFact; }
Fact* hoverAndCapture (void) { return &_hoverAndCaptureFact; }
Fact* refly90Degrees (void) { return &_refly90DegreesFact; }
int cameraShots (void) const { return _cameraShots; }
double timeBetweenShots (void);
double coveredArea (void) const;
double cameraMinTriggerInterval(void) const { return _cameraMinTriggerInterval; }
bool hoverAndCaptureAllowed (void) const;
// Overrides from ComplexMissionItem
int lastSequenceNumber (void) const override = 0;
QString mapVisualQML (void) const override = 0;
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) override = 0;
double complexDistance (void) const final { return _complexDistance; }
double greatestDistanceTo (const QGeoCoordinate &other) const final;
// Overrides from VisualMissionItem
void save (QJsonArray& missionItems) override = 0;
bool specifiesCoordinate (void) const override = 0;
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) override = 0;
void applyNewAltitude (double newAltitude) override = 0;
bool dirty (void) const final { return _dirty; }
bool isSimpleItem (void) const final { return false; }
bool isStandaloneCoordinate (void) const final { return false; }
bool specifiesAltitudeOnly (void) const final { return false; }
QString commandDescription (void) const final { return tr("Corridor Scan"); }
QString commandName (void) const final { return tr("Corridor Scan"); }
QString abbreviation (void) const final { return "S"; }
QGeoCoordinate coordinate (void) const final { return _coordinate; }
QGeoCoordinate exitCoordinate (void) const final { return _exitCoordinate; }
int sequenceNumber (void) const final { return _sequenceNumber; }
double specifiedFlightSpeed (void) final { return std::numeric_limits<double>::quiet_NaN(); }
double specifiedGimbalYaw (void) final { return std::numeric_limits<double>::quiet_NaN(); }
double specifiedGimbalPitch (void) final { return std::numeric_limits<double>::quiet_NaN(); }
void setMissionFlightStatus (MissionController::MissionFlightStatus_t& missionFlightStatus) final;
bool coordinateHasRelativeAltitude (void) const final { return true /*_altitudeRelative*/; }
bool exitCoordinateHasRelativeAltitude (void) const final { return true /*_altitudeRelative*/; }
bool exitCoordinateSameAsEntry (void) const final { return false; }
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final { Q_UNUSED(coordinate); }
void setSequenceNumber (int sequenceNumber) final;
static const char* turnAroundDistanceName;
static const char* turnAroundDistanceMultiRotorName;
static const char* cameraTriggerInTurnAroundName;
static const char* hoverAndCaptureName;
static const char* refly90DegreesName;
signals:
void cameraShotsChanged (void);
void timeBetweenShotsChanged (void);
void cameraMinTriggerIntervalChanged(double cameraMinTriggerInterval);
void transectPointsChanged (void);
void coveredAreaChanged (void);
protected slots:
virtual void _rebuildTransects (void) = 0;
void _setDirty (void);
void _setIfDirty (bool dirty);
void _updateCoordinateAltitudes (void);
void _signalLastSequenceNumberChanged (void);
protected:
void _save (QJsonObject& saveObject);
bool _load (const QJsonObject& complexObject, QString& errorString);
void _setExitCoordinate (const QGeoCoordinate& coordinate);
void _setCameraShots (int cameraShots);
double _triggerDistance (void) const;
int _transectCount (void) const;
bool _hasTurnaround (void) const;
double _turnaroundDistance (void) const;
QString _settingsGroup;
int _sequenceNumber;
bool _dirty;
QGeoCoordinate _coordinate;
QGeoCoordinate _exitCoordinate;
QVariantList _transectPoints;
QGCMapPolygon _surveyAreaPolygon;
bool _ignoreRecalc;
double _complexDistance;
int _cameraShots;
double _timeBetweenShots;
double _cameraMinTriggerInterval;
double _cruiseSpeed;
CameraCalc _cameraCalc;
QMap<QString, FactMetaData*> _metaDataMap;
SettingsFact _turnAroundDistanceFact;
SettingsFact _cameraTriggerInTurnAroundFact;
SettingsFact _hoverAndCaptureFact;
SettingsFact _refly90DegreesFact;
static const char* _jsonCameraCalcKey;
};
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "TransectStyleComplexItemTest.h"
#include "QGCApplication.h"
TransectStyleComplexItemTest::TransectStyleComplexItemTest(void)
: _offlineVehicle(NULL)
{
_polygonVertices << QGeoCoordinate(47.633550640000003, -122.08982199)
<< QGeoCoordinate(47.634129020000003, -122.08887249)
<< QGeoCoordinate(47.633619320000001, -122.08811074)
<< QGeoCoordinate(47.633189139999999, -122.08900124);
}
void TransectStyleComplexItemTest::init(void)
{
UnitTest::init();
_offlineVehicle = new Vehicle(MAV_AUTOPILOT_PX4, MAV_TYPE_QUADROTOR, qgcApp()->toolbox()->firmwarePluginManager(), this);
_transectStyleItem = new TransectStyleItem(_offlineVehicle, this);
_setSurveyAreaPolygon();
_transectStyleItem->setDirty(false);
_rgSignals[cameraShotsChangedIndex] = SIGNAL(cameraShotsChanged());
_rgSignals[timeBetweenShotsChangedIndex] = SIGNAL(timeBetweenShotsChanged());
_rgSignals[cameraMinTriggerIntervalChangedIndex] = SIGNAL(cameraMinTriggerIntervalChanged(double));
_rgSignals[transectPointsChangedIndex] = SIGNAL(transectPointsChanged());
_rgSignals[coveredAreaChangedIndex] = SIGNAL(coveredAreaChanged());
_rgSignals[dirtyChangedIndex] = SIGNAL(dirtyChanged(bool));
_rgSignals[complexDistanceChangedIndex] = SIGNAL(complexDistanceChanged());
_rgSignals[greatestDistanceToChangedIndex] = SIGNAL(greatestDistanceToChanged());
_rgSignals[additionalTimeDelayChangedIndex] = SIGNAL(additionalTimeDelayChanged());
_rgSignals[lastSequenceNumberChangedIndex] = SIGNAL(lastSequenceNumberChanged(int));
_multiSpy = new MultiSignalSpy();
QCOMPARE(_multiSpy->init(_transectStyleItem, _rgSignals, _cSignals), true);
}
void TransectStyleComplexItemTest::cleanup(void)
{
delete _transectStyleItem;
delete _offlineVehicle;
delete _multiSpy;
}
void TransectStyleComplexItemTest::_testDirty(void)
{
QVERIFY(!_transectStyleItem->dirty());
_transectStyleItem->setDirty(false);
QVERIFY(!_transectStyleItem->dirty());
QVERIFY(_multiSpy->checkNoSignals());
_transectStyleItem->setDirty(true);
QVERIFY(_transectStyleItem->dirty());
QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_multiSpy->clearAllSignals();
_transectStyleItem->setDirty(false);
QVERIFY(!_transectStyleItem->dirty());
QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask));
_multiSpy->clearAllSignals();
// These facts should set dirty when changed
QList<Fact*> rgFacts;
rgFacts << _transectStyleItem->turnAroundDistance()
<< _transectStyleItem->cameraTriggerInTurnAround()
<< _transectStyleItem->hoverAndCapture()
<< _transectStyleItem->refly90Degrees();
foreach(Fact* fact, rgFacts) {
qDebug() << fact->name();
QVERIFY(!_transectStyleItem->dirty());
changeFactValue(fact);
QVERIFY(_multiSpy->checkSignalByMask(dirtyChangedMask));
_transectStyleItem->setDirty(false);
_multiSpy->clearAllSignals();
}
rgFacts.clear();
_adjustSurveAreaPolygon();
QVERIFY(_transectStyleItem->dirty());
_transectStyleItem->setDirty(false);
QVERIFY(!_transectStyleItem->surveyAreaPolygon()->dirty());
_multiSpy->clearAllSignals();
changeFactValue(_transectStyleItem->cameraCalc()->distanceToSurface());
QVERIFY(_transectStyleItem->dirty());
_transectStyleItem->setDirty(false);
QVERIFY(!_transectStyleItem->cameraCalc()->dirty());
_multiSpy->clearAllSignals();
}
void TransectStyleComplexItemTest::_setSurveyAreaPolygon(void)
{
foreach (const QGeoCoordinate vertex, _polygonVertices) {
_transectStyleItem->surveyAreaPolygon()->appendVertex(vertex);
}
}
void TransectStyleComplexItemTest::_testRebuildTransects(void)
{
// Changing the survey polygon should trigger:
// _rebuildTransects call
// coveredAreaChanged signal
// lastSequenceNumberChanged signal
_adjustSurveAreaPolygon();
QVERIFY(_transectStyleItem->rebuildTransectsCalled);
QVERIFY(_multiSpy->checkSignalsByMask(coveredAreaChangedMask | lastSequenceNumberChangedMask));
_transectStyleItem->rebuildTransectsCalled = false;
_transectStyleItem->setDirty(false);
_multiSpy->clearAllSignals();
// Changes to these facts should trigger:
// _rebuildTransects call
// lastSequenceNumberChanged signal
QList<Fact*> rgFacts;
rgFacts << _transectStyleItem->turnAroundDistance()
<< _transectStyleItem->cameraTriggerInTurnAround()
<< _transectStyleItem->hoverAndCapture()
<< _transectStyleItem->refly90Degrees()
<< _transectStyleItem->cameraCalc()->adjustedFootprintSide()
<< _transectStyleItem->cameraCalc()->adjustedFootprintFrontal();
foreach(Fact* fact, rgFacts) {
qDebug() << fact->name();
changeFactValue(fact);
QVERIFY(_transectStyleItem->rebuildTransectsCalled);
QVERIFY(_multiSpy->checkSignalsByMask(lastSequenceNumberChangedMask));
_transectStyleItem->setDirty(false);
_multiSpy->clearAllSignals();
_transectStyleItem->rebuildTransectsCalled = false;
}
rgFacts.clear();
}
void TransectStyleComplexItemTest::_testDistanceSignalling(void)
{
_adjustSurveAreaPolygon();
QVERIFY(_multiSpy->checkSignalsByMask(complexDistanceChangedMask | greatestDistanceToChangedMask));
_transectStyleItem->setDirty(false);
_multiSpy->clearAllSignals();
QList<Fact*> rgFacts;
rgFacts << _transectStyleItem->turnAroundDistance()
<< _transectStyleItem->hoverAndCapture()
<< _transectStyleItem->refly90Degrees();
foreach(Fact* fact, rgFacts) {
qDebug() << fact->name();
changeFactValue(fact);
QVERIFY(_multiSpy->checkSignalsByMask(complexDistanceChangedMask | greatestDistanceToChangedMask));
_transectStyleItem->setDirty(false);
_multiSpy->clearAllSignals();
}
rgFacts.clear();
}
void TransectStyleComplexItemTest::_adjustSurveAreaPolygon(void)
{
QGeoCoordinate vertex = _transectStyleItem->surveyAreaPolygon()->vertexCoordinate(0);
vertex.setLatitude(vertex.latitude() + 1);
_transectStyleItem->surveyAreaPolygon()->adjustVertex(0, vertex);
}
TransectStyleItem::TransectStyleItem(Vehicle* vehicle, QObject* parent)
: TransectStyleComplexItem (vehicle, QStringLiteral("UnitTestTransect"), parent)
, rebuildTransectsCalled (false)
{
}
void TransectStyleItem::_rebuildTransects(void)
{
rebuildTransectsCalled = true;
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "UnitTest.h"
#include "MultiSignalSpy.h"
#include "CorridorScanComplexItem.h"
#include <QGeoCoordinate>
class TransectStyleItem;
class TransectStyleComplexItemTest : public UnitTest
{
Q_OBJECT
public:
TransectStyleComplexItemTest(void);
protected:
void init(void) final;
void cleanup(void) final;
private slots:
void _testDirty (void);
void _testRebuildTransects (void);
void _testDistanceSignalling (void);
private:
void _setSurveyAreaPolygon (void);
void _adjustSurveAreaPolygon(void);
enum {
// These signals are from TransectStyleComplexItem
cameraShotsChangedIndex = 0,
timeBetweenShotsChangedIndex,
cameraMinTriggerIntervalChangedIndex,
transectPointsChangedIndex,
coveredAreaChangedIndex,
// These signals are from ComplexItem
dirtyChangedIndex,
complexDistanceChangedIndex,
greatestDistanceToChangedIndex,
additionalTimeDelayChangedIndex,
// These signals are from VisualMissionItem
lastSequenceNumberChangedIndex,
maxSignalIndex
};
enum {
// These signals are from TransectStyleComplexItem
cameraShotsChangedMask = 1 << cameraShotsChangedIndex,
timeBetweenShotsChangedMask = 1 << timeBetweenShotsChangedIndex,
cameraMinTriggerIntervalChangedMask = 1 << cameraMinTriggerIntervalChangedIndex,
transectPointsChangedMask = 1 << transectPointsChangedIndex,
coveredAreaChangedMask = 1 << coveredAreaChangedIndex,
// These signals are from ComplexItem
dirtyChangedMask = 1 << dirtyChangedIndex,
complexDistanceChangedMask = 1 << complexDistanceChangedIndex,
greatestDistanceToChangedMask = 1 << greatestDistanceToChangedIndex,
additionalTimeDelayChangedMask = 1 << additionalTimeDelayChangedIndex,
// These signals are from VisualMissionItem
lastSequenceNumberChangedMask = 1 << lastSequenceNumberChangedIndex,
};
static const size_t _cSignals = maxSignalIndex;
const char* _rgSignals[_cSignals];
Vehicle* _offlineVehicle;
MultiSignalSpy* _multiSpy;
QList<QGeoCoordinate> _polygonVertices;
TransectStyleItem* _transectStyleItem;
};
class TransectStyleItem : public TransectStyleComplexItem
{
Q_OBJECT
public:
TransectStyleItem(Vehicle* vehicle, QObject* parent = NULL);
// Overrides from ComplexMissionItem
int lastSequenceNumber (void) const final { return _sequenceNumber; }
QString mapVisualQML (void) const final { return QString(); }
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final { Q_UNUSED(complexObject); Q_UNUSED(sequenceNumber); Q_UNUSED(errorString); return false; }
// Overrides from VisualMissionItem
void save (QJsonArray& missionItems) final { Q_UNUSED(missionItems); }
bool specifiesCoordinate (void) const final { return true; }
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final { Q_UNUSED(items); Q_UNUSED(missionItemParent); }
void applyNewAltitude (double newAltitude) final { Q_UNUSED(newAltitude); }
bool rebuildTransectsCalled;
private slots:
// Overrides from TransectStyleComplexItem
void _rebuildTransects (void) final;
};
......@@ -39,7 +39,7 @@ Column {
}
gridTypeCombo.model = _cameraList
var knownCameraIndex = gridTypeCombo.find(cameraCalc.cameraName)
if (knownCameraIndex != -1) {
if (knownCameraIndex !== -1) {
gridTypeCombo.currentIndex = knownCameraIndex
} else {
console.log("Internal error: Known camera not found", cameraCalc.cameraName)
......
......@@ -46,7 +46,7 @@ Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: _camera.cameraAction.rawValue == 1
visible: _camera.cameraAction.rawValue === 1
QGCLabel {
text: qsTr("Time")
......@@ -62,7 +62,7 @@ Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: _camera.cameraAction.rawValue == 2
visible: _camera.cameraAction.rawValue === 2
QGCLabel {
text: qsTr("Distance")
......
......@@ -56,15 +56,6 @@ Rectangle {
anchors.right: parent.right
spacing: _margin
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("WARNING WORK IN PROGRESS: BE VERY CAREFUL WHEN FLYING")
wrapMode: Text.WordWrap
color: qgcPal.warningText
font.pointSize: ScreenTools.smallFontPointSize
}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
......@@ -100,6 +91,39 @@ Rectangle {
fact: missionItem.corridorWidth
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Turnaround dist") }
FactTextField {
fact: missionItem.turnAroundDistance
Layout.fillWidth: true
}
FactCheckBox {
text: qsTr("Take images in turnarounds")
fact: missionItem.cameraTriggerInTurnAround
enabled: missionItem.hoverAndCaptureAllowed ? !missionItem.hoverAndCapture.rawValue : true
Layout.columnSpan: 2
}
QGCCheckBox {
id: relAlt
anchors.left: parent.left
text: qsTr("Relative altitude")
checked: missionItem.cameraCalc.distanceToSurfaceRelative
enabled: missionItem.cameraCalc.isManualCamera
Layout.columnSpan: 2
onClicked: missionItem.cameraCalc.distanceToSurfaceRelative = checked
Connections {
target: missionItem.cameraCalc
onDistanceToSurfaceRelativeChanged: relAlt.checked = missionItem.cameraCalc.distanceToSurfaceRelative
}
}
}
QGCButton {
text: qsTr("Rotate Entry Point")
onClicked: missionItem.rotateEntryPoint()
}
SectionHeader {
......
......@@ -56,7 +56,7 @@ Item {
QGCMapPolygonVisuals {
qgcView: _root.qgcView
mapControl: map
mapPolygon: object.corridorPolygon
mapPolygon: object.surveyAreaPolygon
interactive: false
interiorColor: "green"
interiorOpacity: 0.25
......
......@@ -154,7 +154,7 @@ QGCFlickable {
QGCLabel {
text: qsTr("None")
visible: polygonSection.checked && myGeoFenceController.polygons.count == 0
visible: polygonSection.checked && myGeoFenceController.polygons.count === 0
}
GridLayout {
......@@ -239,7 +239,7 @@ QGCFlickable {
QGCLabel {
text: qsTr("None")
visible: circleSection.checked && myGeoFenceController.circles.count == 0
visible: circleSection.checked && myGeoFenceController.circles.count === 0
}
GridLayout {
......
......@@ -89,7 +89,7 @@ Rectangle {
height: _hamburgerSize
sourceSize.height: _hamburgerSize
source: "qrc:/qmlimages/Hamburger.svg"
visible: missionItem.isCurrentItem && missionItem.sequenceNumber != 0
visible: missionItem.isCurrentItem && missionItem.sequenceNumber !== 0
color: qgcPal.windowShade
}
......
......@@ -32,13 +32,13 @@ Rectangle {
property real missionMaxTelemetry: _controllerValid ? planMasterController.missionController.missionMaxTelemetry : NaN
property bool missionDirty: _controllerValid ? planMasterController.missionController.dirty : false
property bool _controllerValid: planMasterController != undefined
property bool _controllerValid: planMasterController !== undefined
property bool _controllerOffline: _controllerValid ? planMasterController.offline : true
property var _controllerDirty: _controllerValid ? planMasterController.dirty : false
property var _controllerSyncInProgress: _controllerValid ? planMasterController.syncInProgress : false
property bool _statusValid: currentMissionItem != undefined
property bool _missionValid: missionItems != undefined
property bool _statusValid: currentMissionItem !== undefined
property bool _missionValid: missionItems !== undefined
property real _dataFontSize: ScreenTools.defaultFontPointSize
property real _largeValueWidth: ScreenTools.defaultFontPixelWidth * 8
......@@ -84,11 +84,8 @@ Rectangle {
}
//-- Eat mouse events, preventing them from reaching toolbar, which is underneath us.
MouseArea {
anchors.fill: parent
onWheel: { wheel.accepted = true; }
onPressed: { mouse.accepted = true; }
onReleased: { mouse.accepted = true; }
DeadMouseArea {
anchors.fill: parent
}
//-- The reason for this Row to be here is so the Logo (Home) button is in the same
......
......@@ -238,7 +238,7 @@ QGCView {
QGCFileDialog {
id: fileDialog
qgcView: _qgcView
property var plan: true
property bool plan: true
folder: QGroundControl.settingsManager.appSettings.missionSavePath
fileExtension: QGroundControl.settingsManager.appSettings.planFileExtension
fileExtension2: QGroundControl.settingsManager.appSettings.missionFileExtension
......@@ -263,7 +263,7 @@ QGCView {
function accept() {
var toIndex = toCombo.currentIndex
if (toIndex == 0) {
if (toIndex === 0) {
toIndex = 1
}
_missionController.moveMissionItem(_moveDialogMissionItemIndex, toIndex)
......
......@@ -17,7 +17,7 @@ Rectangle {
property var rallyPoint ///< RallyPoint object associated with editor
property var controller ///< RallyPointController
property bool _currentItem: rallyPoint ? rallyPoint == controller.currentRallyPoint : false
property bool _currentItem: rallyPoint ? rallyPoint === controller.currentRallyPoint : false
property color _outerTextColor: _currentItem ? "black" : qgcPal.text
readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2
......
......@@ -45,7 +45,7 @@ Item {
MissionItemIndicatorDrag {
itemCoordinate: rallyPointObject.coordinate
visible: rallyPointObject == myRallyPointController.currentRallyPoint
visible: rallyPointObject === myRallyPointController.currentRallyPoint
property var rallyPointObject
......@@ -67,7 +67,7 @@ Item {
sourceItem: MissionItemIndexLabel {
id: itemIndexLabel
label: qsTr("R", "rally point map item label")
checked: _editingLayer == _layerRallyPoints ? rallyPointObject == myRallyPointController.currentRallyPoint : false
checked: _editingLayer == _layerRallyPoints ? rallyPointObject === myRallyPointController.currentRallyPoint : false
onClicked: myRallyPointController.currentRallyPoint = rallyPointObject
}
......
......@@ -44,7 +44,7 @@ Rectangle {
QGCLabel {
text: object.name
visible: object.name != ""
visible: object.name !== ""
Layout.column: 0
Layout.row: index
}
......
......@@ -46,7 +46,7 @@ Rectangle {
} else {
var index = -1
for (index=0; index<_cameraList.length; index++) {
if (_cameraList[index] == missionItem.camera.value) {
if (_cameraList[index] === missionItem.camera.value) {
break;
}
}
......@@ -243,7 +243,7 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: missionItem.manualGrid.value == true
visible: missionItem.manualGrid.value
QGCCheckBox {
id: cameraTriggerDistanceCheckBox
......@@ -273,7 +273,7 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: gridTypeCombo.currentIndex != _gridTypeManual
visible: gridTypeCombo.currentIndex !== _gridTypeManual
Row {
spacing: _margin
......@@ -443,7 +443,7 @@ Rectangle {
id: windRoseButton
anchors.verticalCenter: angleText.verticalCenter
iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
visible: _vehicle.fixedWing
visible: _vehicle ? _vehicle.fixedWing : false
onClicked: {
windRosePie.angle = Number(gridAngleText.text)
......@@ -522,7 +522,7 @@ Rectangle {
SectionHeader {
id: manualGridHeader
text: qsTr("Grid")
visible: gridTypeCombo.currentIndex == _gridTypeManual
visible: gridTypeCombo.currentIndex === _gridTypeManual
}
GridLayout {
......@@ -547,7 +547,7 @@ Rectangle {
anchors.verticalCenter: manualAngleText.verticalCenter
Layout.columnSpan: 1
iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
visible: _vehicle.fixedWing
visible: _vehicle ? _vehicle.fixedWing : false
onClicked: {
var cords = manualWindRoseButton.mapToItem(_root, 0, 0)
......
......@@ -90,6 +90,7 @@ Item {
QGCMapPolygonVisuals {
id: mapPolygonVisuals
qgcView: _root.qgcView
mapControl: map
mapPolygon: _mapPolygon
interactive: _missionItem.isCurrentItem
......
......@@ -61,14 +61,14 @@ double limitAngleToPMPId(double angle)
{
while (angle < -M_PI)
{
angle += M_PI;
angle += 2.0f * M_PI;
}
}
else if (angle > M_PI)
{
while (angle > M_PI)
{
angle -= M_PI;
angle -= 2.0f * M_PI;
}
}
}
......
import QtQuick 2.3
import QtQuick.Controls 1.2
MouseArea {
preventStealing:true
hoverEnabled: true
onWheel: { wheel.accepted = true; }
onPressed: { mouse.accepted = true; }
onReleased: { mouse.accepted = true; }
}
......@@ -175,9 +175,9 @@ Item {
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)
property point arrowPoint: Qt.point(0, 0)
property point arrowBase1: Qt.point(0, 0)
property point arrowBase2: Qt.point(0, 0)
onPaint: {
var context = getContext("2d")
......
......@@ -124,9 +124,9 @@ Item {
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)
property point arrowPoint: Qt.point(0, 0)
property point arrowBase1: Qt.point(0, 0)
property point arrowBase2: Qt.point(0, 0)
onPaint: {
var context = getContext("2d")
......
......@@ -37,13 +37,14 @@ QGCLabel {
function updateFlightModesMenu() {
if (activeVehicle && activeVehicle.flightModeSetAvailable) {
var i;
// Remove old menu items
for (var i = 0; i < flightModesMenuItems.length; i++) {
for (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++) {
for (i = 0; i < activeVehicle.flightModes.length; i++) {
var menuItem = flightModeMenuItemComponent.createObject(null, { "text": activeVehicle.flightModes[i] })
flightModesMenuItems.push(menuItem)
flightModesMenu.insertItem(i, menuItem)
......
......@@ -68,7 +68,7 @@ QGCViewDialog {
color: qgcPal.button
property var mavCmdInfo: modelData
property var textColor: qgcPal.buttonText
property color textColor: qgcPal.buttonText
Column {
id: commandColumn
......
import QtQuick 2.3
import QtQuick.Controls 1.2
/// This control is used to create a Rectangle control which does not allow mouse events to bleed through to the control
/// which is beneath it.
Rectangle {
MouseArea {
anchors.fill: parent
preventStealing: true
onWheel: { wheel.accepted = true; }
onPressed: { mouse.accepted = true; }
onReleased: { mouse.accepted = true; }
}
}
......@@ -20,6 +20,8 @@ Rectangle {
border.width: _showBorder ? 1: 0
border.color: qgcPal.buttonText
property var tileSet: null
property var currentSet: null
property bool checked: false
property bool complete: false
property alias text: nameLabel.text
......@@ -37,6 +39,19 @@ Rectangle {
signal clicked()
property ExclusiveGroup exclusiveGroup: null
onExclusiveGroupChanged: {
if (exclusiveGroup) {
checked = false
exclusiveGroup.bindCheckable(mapButton)
}
}
onCheckedChanged: {
if(checked) {
currentSet = tileSet
}
}
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
Row {
......@@ -85,26 +100,53 @@ Rectangle {
MouseArea {
anchors.fill: parent
hoverEnabled: true
hoverEnabled: !ScreenTools.isMobile
onMouseXChanged: {
_lastGlobalMouseX = ScreenTools.mouseX()
_lastGlobalMouseY = ScreenTools.mouseY()
if(!ScreenTools.isMobile) {
_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()
if(!ScreenTools.isMobile) {
_lastGlobalMouseX = ScreenTools.mouseX()
_lastGlobalMouseY = ScreenTools.mouseY()
}
}
onEntered: {
if(!ScreenTools.isMobile) {
_hovered = true
_forceHoverOff = false
hoverTimer.start()
}
}
onExited: {
if(!ScreenTools.isMobile) {
_hovered = false
_forceHoverOff = false
hoverTimer.stop()
}
}
onPressed: {
if(!ScreenTools.isMobile) {
_pressed = true
}
}
onReleased: {
if(!ScreenTools.isMobile) {
_pressed = false
}
}
onClicked: {
checked = true
mapButton.clicked()
}
}
Timer {
id: hoverTimer
interval: 250
repeat: true
repeat: !ScreenTools.isMobile
onTriggered: {
if (_lastGlobalMouseX !== ScreenTools.mouseX() || _lastGlobalMouseY !== ScreenTools.mouseY()) {
_forceHoverOff = true
......
......@@ -253,7 +253,7 @@ QGCView {
id: valueLabel
width: ScreenTools.defaultFontPixelWidth * 20
color: factRow.modelFact.defaultValueAvailable ? (factRow.modelFact.valueEqualsDefault ? __qgcPal.text : __qgcPal.warningText) : __qgcPal.text
text: factRow.modelFact.enumStrings.length == 0 ? factRow.modelFact.valueString + " " + factRow.modelFact.units : factRow.modelFact.enumStringValue
text: factRow.modelFact.enumStrings.length === 0 ? factRow.modelFact.valueString + " " + factRow.modelFact.units : factRow.modelFact.enumStringValue
clip: true
}
......
......@@ -116,7 +116,7 @@ QGCViewDialog {
QGCTextField {
id: valueField
text: validate ? validateValue : fact.valueString
visible: fact.enumStrings.length == 0 || validate || manualEntry.checked
visible: fact.enumStrings.length === 0 || validate || manualEntry.checked
unitsLabel: fact.units
showUnits: fact.units != ""
Layout.fillWidth: true
......@@ -145,7 +145,7 @@ QGCViewDialog {
visible: _showCombo
model: fact.enumStrings
property bool _showCombo: fact.enumStrings.length != 0 && fact.bitmaskStrings.length == 0 && !validate
property bool _showCombo: fact.enumStrings.length !== 0 && fact.bitmaskStrings.length === 0 && !validate
Component.onCompleted: {
// We can't bind directly to fact.enumIndex since that would add an unknown value
......
......@@ -144,7 +144,7 @@ Item {
QGCLabel {
text: qsTr("No files")
visible: fileList.model.length == 0
visible: fileList.model.length === 0
}
}
}
......
......@@ -11,9 +11,9 @@ Rectangle {
color: parent.indicatorColor
visible: showIndicator
property bool showIndicator: (parent.flickableDirection == Flickable.AutoFlickDirection ||
parent.flickableDirection == Flickable.HorizontalFlick ||
parent.flickableDirection == Flickable.HorizontalAndVerticalFlick) &&
property bool showIndicator: (parent.flickableDirection === Flickable.AutoFlickDirection ||
parent.flickableDirection === Flickable.HorizontalFlick ||
parent.flickableDirection === Flickable.HorizontalAndVerticalFlick) &&
(parent.contentWidth > parent.width)
Component.onCompleted: animateOpacity.restart()
......
......@@ -11,9 +11,9 @@ Rectangle {
color: parent.indicatorColor
visible: showIndicator
property bool showIndicator: (parent.flickableDirection == Flickable.AutoFlickDirection ||
parent.flickableDirection == Flickable.VerticalFlick ||
parent.flickableDirection == Flickable.HorizontalAndVerticalFlick) &&
property bool showIndicator: (parent.flickableDirection === Flickable.AutoFlickDirection ||
parent.flickableDirection === Flickable.VerticalFlick ||
parent.flickableDirection === Flickable.HorizontalAndVerticalFlick) &&
(parent.contentHeight > parent.height)
Component.onCompleted: animateOpacity.restart()
......
......@@ -51,8 +51,8 @@ Item {
anchors.right: parent.right
height: ScreenTools.minTouchPixels
width: height
property var initialX: 0
property var initialWidth: 0
property real initialX: 0
property real initialWidth: 0
onClicked: {
// TODO propagate
......@@ -98,7 +98,7 @@ Item {
}
// Resize pip window if necessary when main window is resized
property var pipLock: 2
property int pipLock: 2
Connections {
target: pip.parent
......
......@@ -21,6 +21,7 @@ Slider {
// Value indicator starts display from zero instead of min value
property bool zeroCentered: false
property bool displayValue: false
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
......@@ -67,8 +68,15 @@ Slider {
implicitWidth: _radius * 2
implicitHeight: _radius * 2
radius: _radius
property real _radius: Math.round(ScreenTools.defaultFontPixelHeight * 0.75)
Label {
text: _root.value.toFixed(0)
visible: _root.displayValue
anchors.centerIn: parent
font.family: ScreenTools.normalFontFamily
font.pointSize: ScreenTools.smallFontPointSize
color: qgcPal.buttonText
}
}
}
}
......@@ -58,7 +58,7 @@ FactPanel {
console.log("Error loading QGCViewDialogContainer.qml: ", dialogComponent.errorString())
return
}
var dialogWidth = charWidth == showDialogFullWidth ? parent.width : ScreenTools.defaultFontPixelWidth * charWidth
var dialogWidth = charWidth === showDialogFullWidth ? parent.width : ScreenTools.defaultFontPixelWidth * charWidth
var dialog = dialogComponent.createObject(_rootItem,
{
"anchors.fill": _rootItem,
......
......@@ -27,10 +27,10 @@ FactPanel {
signal hideDialog
Keys.onReleased: {
if (event.key == Qt.Key_Escape) {
if (event.key === Qt.Key_Escape) {
reject()
event.accepted = true
} else if (event.key == Qt.Key_Return || event.key == Qt.Key_Enter) {
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
accept()
event.accepted = true
}
......
......@@ -5,6 +5,7 @@ AppMessages 1.0 AppMessages.qml
CameraCalc 1.0 CameraCalc.qml
CameraSection 1.0 CameraSection.qml
ClickableColor 1.0 ClickableColor.qml
DeadMouseArea 1.0 DeadMouseArea.qml
DropButton 1.0 DropButton.qml
DropPanel 1.0 DropPanel.qml
EditPositionDialog 1.0 EditPositionDialog.qml
......@@ -27,15 +28,11 @@ MissionItemMapVisual 1.0 MissionItemMapVisual.qml
MissionItemStatus 1.0 MissionItemStatus.qml
ModeSwitchDisplay 1.0 ModeSwitchDisplay.qml
MultiRotorMotorDisplay 1.0 MultiRotorMotorDisplay.qml
NoMouseThroughRectangle 1.0 NoMouseThroughRectangle.qml
OfflineMapButton 1.0 OfflineMapButton.qml
PageView 1.0 PageView.qml
ParameterEditor 1.0 ParameterEditor.qml
ParameterEditorDialog 1.0 ParameterEditorDialog.qml
PlanToolBar 1.0 PlanToolBar.qml
RallyPointEditorHeader 1.0 RallyPointEditorHeader.qml
RallyPointItemEditor 1.0 RallyPointItemEditor.qml
RallyPointMapVisuals 1.0 RallyPointMapVisuals.qml
RCChannelMonitor 1.0 RCChannelMonitor.qml
QGCButton 1.0 QGCButton.qml
QGCCheckBox 1.0 QGCCheckBox.qml
QGCColoredImage 1.0 QGCColoredImage.qml
......@@ -45,8 +42,8 @@ QGCFlickable 1.0 QGCFlickable.qml
QGCGroupBox 1.0 QGCGroupBox.qml
QGCLabel 1.0 QGCLabel.qml
QGCListView 1.0 QGCListView.qml
QGCMapLabel 1.0 QGCMapLabel.qml
QGCMapCircleVisuals 1.0 QGCMapCircleVisuals.qml
QGCMapLabel 1.0 QGCMapLabel.qml
QGCMapPolygonVisuals 1.0 QGCMapPolygonVisuals.qml
QGCMapPolylineVisuals 1.0 QGCMapPolylineVisuals.qml
QGCMouseArea 1.0 QGCMouseArea.qml
......@@ -62,6 +59,10 @@ QGCViewDialog 1.0 QGCViewDialog.qml
QGCViewDialogContainer 1.0 QGCViewDialogContainer.qml
QGCViewMessage 1.0 QGCViewMessage.qml
QGCViewPanel 1.0 QGCViewPanel.qml
RallyPointEditorHeader 1.0 RallyPointEditorHeader.qml
RallyPointItemEditor 1.0 RallyPointItemEditor.qml
RallyPointMapVisuals 1.0 RallyPointMapVisuals.qml
RCChannelMonitor 1.0 RCChannelMonitor.qml
RoundButton 1.0 RoundButton.qml
SectionHeader 1.0 SectionHeader.qml
SetupPage 1.0 SetupPage.qml
......@@ -74,4 +75,3 @@ ToolStrip 1.0 ToolStrip.qml
VehicleRotationCal 1.0 VehicleRotationCal.qml
VehicleSummaryRow 1.0 VehicleSummaryRow.qml
ViewWidget 1.0 ViewWidget.qml
OfflineMapButton 1.0 OfflineMapButton.qml
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment