Commit 319cf9c5 authored by DonLakeFlyer's avatar DonLakeFlyer

New MissionSettingsComplexItem

parent 019e06d4
...@@ -440,6 +440,7 @@ HEADERS += \ ...@@ -440,6 +440,7 @@ HEADERS += \
src/MissionManager/MissionController.h \ src/MissionManager/MissionController.h \
src/MissionManager/MissionItem.h \ src/MissionManager/MissionItem.h \
src/MissionManager/MissionManager.h \ src/MissionManager/MissionManager.h \
src/MissionManager/MissionSettingsComplexItem.h \
src/MissionManager/PlanElementController.h \ src/MissionManager/PlanElementController.h \
src/MissionManager/QGCMapPolygon.h \ src/MissionManager/QGCMapPolygon.h \
src/MissionManager/RallyPoint.h \ src/MissionManager/RallyPoint.h \
...@@ -610,6 +611,7 @@ SOURCES += \ ...@@ -610,6 +611,7 @@ SOURCES += \
src/MissionManager/MissionController.cc \ src/MissionManager/MissionController.cc \
src/MissionManager/MissionItem.cc \ src/MissionManager/MissionItem.cc \
src/MissionManager/MissionManager.cc \ src/MissionManager/MissionManager.cc \
src/MissionManager/MissionSettingsComplexItem.cc \
src/MissionManager/PlanElementController.cc \ src/MissionManager/PlanElementController.cc \
src/MissionManager/QGCMapPolygon.cc \ src/MissionManager/QGCMapPolygon.cc \
src/MissionManager/RallyPoint.cc \ src/MissionManager/RallyPoint.cc \
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
<file alias="MainWindowNative.qml">src/ui/MainWindowNative.qml</file> <file alias="MainWindowNative.qml">src/ui/MainWindowNative.qml</file>
<file alias="MavlinkSettings.qml">src/ui/preferences/MavlinkSettings.qml</file> <file alias="MavlinkSettings.qml">src/ui/preferences/MavlinkSettings.qml</file>
<file alias="MissionEditor.qml">src/MissionEditor/MissionEditor.qml</file> <file alias="MissionEditor.qml">src/MissionEditor/MissionEditor.qml</file>
<file alias="MissionSettingsEditor.qml">src/MissionEditor/MissionSettingsEditor.qml</file>
<file alias="MixersComponent.qml">src/AutoPilotPlugins/Common/MixersComponent.qml</file> <file alias="MixersComponent.qml">src/AutoPilotPlugins/Common/MixersComponent.qml</file>
<file alias="MockLink.qml">src/ui/preferences/MockLink.qml</file> <file alias="MockLink.qml">src/ui/preferences/MockLink.qml</file>
<file alias="MockLinkSettings.qml">src/ui/preferences/MockLinkSettings.qml</file> <file alias="MockLinkSettings.qml">src/ui/preferences/MockLinkSettings.qml</file>
...@@ -67,6 +66,7 @@ ...@@ -67,6 +66,7 @@
<file alias="QGroundControl/Controls/MissionItemIndexLabel.qml">src/QmlControls/MissionItemIndexLabel.qml</file> <file alias="QGroundControl/Controls/MissionItemIndexLabel.qml">src/QmlControls/MissionItemIndexLabel.qml</file>
<file alias="QGroundControl/Controls/MissionItemMapVisual.qml">src/MissionEditor/MissionItemMapVisual.qml</file> <file alias="QGroundControl/Controls/MissionItemMapVisual.qml">src/MissionEditor/MissionItemMapVisual.qml</file>
<file alias="QGroundControl/Controls/MissionItemStatus.qml">src/MissionEditor/MissionItemStatus.qml</file> <file alias="QGroundControl/Controls/MissionItemStatus.qml">src/MissionEditor/MissionItemStatus.qml</file>
<file alias="QGroundControl/Controls/MissionSettingsMapVisual.qml">src/MissionEditor/MissionSettingsMapVisual.qml</file>
<file alias="QGroundControl/Controls/ModeSwitchDisplay.qml">src/QmlControls/ModeSwitchDisplay.qml</file> <file alias="QGroundControl/Controls/ModeSwitchDisplay.qml">src/QmlControls/ModeSwitchDisplay.qml</file>
<file alias="QGroundControl/Controls/MultiRotorMotorDisplay.qml">src/QmlControls/MultiRotorMotorDisplay.qml</file> <file alias="QGroundControl/Controls/MultiRotorMotorDisplay.qml">src/QmlControls/MultiRotorMotorDisplay.qml</file>
<file alias="QGroundControl/Controls/OfflineMapButton.qml">src/QmlControls/OfflineMapButton.qml</file> <file alias="QGroundControl/Controls/OfflineMapButton.qml">src/QmlControls/OfflineMapButton.qml</file>
...@@ -170,6 +170,7 @@ ...@@ -170,6 +170,7 @@
<file alias="SimpleItemEditor.qml">src/MissionEditor/SimpleItemEditor.qml</file> <file alias="SimpleItemEditor.qml">src/MissionEditor/SimpleItemEditor.qml</file>
<file alias="SurveyItemEditor.qml">src/MissionEditor/SurveyItemEditor.qml</file> <file alias="SurveyItemEditor.qml">src/MissionEditor/SurveyItemEditor.qml</file>
<file alias="FWLandingPatternEditor.qml">src/MissionEditor/FWLandingPatternEditor.qml</file> <file alias="FWLandingPatternEditor.qml">src/MissionEditor/FWLandingPatternEditor.qml</file>
<file alias="MissionSettingsEditor.qml">src/MissionEditor/MissionSettingsEditor.qml</file>
<file alias="TcpSettings.qml">src/ui/preferences/TcpSettings.qml</file> <file alias="TcpSettings.qml">src/ui/preferences/TcpSettings.qml</file>
<file alias="test.qml">src/test.qml</file> <file alias="test.qml">src/test.qml</file>
<file alias="UdpSettings.qml">src/ui/preferences/UdpSettings.qml</file> <file alias="UdpSettings.qml">src/ui/preferences/UdpSettings.qml</file>
...@@ -183,11 +184,6 @@ ...@@ -183,11 +184,6 @@
<file alias="MavCmdInfoRover.json">src/MissionManager/MavCmdInfoRover.json</file> <file alias="MavCmdInfoRover.json">src/MissionManager/MavCmdInfoRover.json</file>
<file alias="MavCmdInfoSub.json">src/MissionManager/MavCmdInfoSub.json</file> <file alias="MavCmdInfoSub.json">src/MissionManager/MavCmdInfoSub.json</file>
<file alias="MavCmdInfoVTOL.json">src/MissionManager/MavCmdInfoVTOL.json</file> <file alias="MavCmdInfoVTOL.json">src/MissionManager/MavCmdInfoVTOL.json</file>
<file alias="Vehicle/VehicleFact.json">src/Vehicle/VehicleFact.json</file>
<file alias="Vehicle/BatteryFact.json">src/Vehicle/BatteryFact.json</file>
<file alias="Vehicle/GPSFact.json">src/Vehicle/GPSFact.json</file>
<file alias="Vehicle/WindFact.json">src/Vehicle/WindFact.json</file>
<file alias="Vehicle/VibrationFact.json">src/Vehicle/VibrationFact.json</file>
<file alias="App.SettingsGroup.json">src/Settings/App.SettingsGroup.json</file> <file alias="App.SettingsGroup.json">src/Settings/App.SettingsGroup.json</file>
<file alias="AutoConnect.SettingsGroup.json">src/Settings/AutoConnect.SettingsGroup.json</file> <file alias="AutoConnect.SettingsGroup.json">src/Settings/AutoConnect.SettingsGroup.json</file>
<file alias="Survey.SettingsGroup.json">src/MissionManager/Survey.SettingsGroup.json</file> <file alias="Survey.SettingsGroup.json">src/MissionManager/Survey.SettingsGroup.json</file>
...@@ -196,6 +192,12 @@ ...@@ -196,6 +192,12 @@
<file alias="RallyPoint.FactMetaData.json">src/MissionManager/RallyPoint.FactMetaData.json</file> <file alias="RallyPoint.FactMetaData.json">src/MissionManager/RallyPoint.FactMetaData.json</file>
<file alias="FWLandingPattern.FactMetaData.json">src/MissionManager/FWLandingPattern.FactMetaData.json</file> <file alias="FWLandingPattern.FactMetaData.json">src/MissionManager/FWLandingPattern.FactMetaData.json</file>
<file alias="USBBoardInfo.json">src/comm/USBBoardInfo.json</file> <file alias="USBBoardInfo.json">src/comm/USBBoardInfo.json</file>
<file alias="MissionSettings.FactMetaData.json">src/MissionManager/MissionSettings.FactMetaData.json</file>
<file alias="Vehicle/VehicleFact.json">src/Vehicle/VehicleFact.json</file>
<file alias="Vehicle/BatteryFact.json">src/Vehicle/BatteryFact.json</file>
<file alias="Vehicle/GPSFact.json">src/Vehicle/GPSFact.json</file>
<file alias="Vehicle/WindFact.json">src/Vehicle/WindFact.json</file>
<file alias="Vehicle/VibrationFact.json">src/Vehicle/VibrationFact.json</file>
<file alias="Vehicle/TemperatureFact.json">src/Vehicle/TemperatureFact.json</file> <file alias="Vehicle/TemperatureFact.json">src/Vehicle/TemperatureFact.json</file>
</qresource> </qresource>
<qresource prefix="/MockLink"> <qresource prefix="/MockLink">
......
...@@ -266,7 +266,8 @@ QList<MAV_CMD> PX4FirmwarePlugin::supportedMissionCommands(void) ...@@ -266,7 +266,8 @@ QList<MAV_CMD> PX4FirmwarePlugin::supportedMissionCommands(void)
<< MAV_CMD_DO_CHANGE_SPEED << MAV_CMD_DO_CHANGE_SPEED
<< MAV_CMD_DO_LAND_START << MAV_CMD_DO_LAND_START
<< MAV_CMD_DO_MOUNT_CONFIGURE << MAV_CMD_DO_MOUNT_CONFIGURE
<< MAV_CMD_DO_MOUNT_CONTROL; << MAV_CMD_DO_MOUNT_CONTROL
<< MAV_CMD_IMAGE_START_CAPTURE << MAV_CMD_IMAGE_STOP_CAPTURE << MAV_CMD_VIDEO_START_CAPTURE << MAV_CMD_VIDEO_STOP_CAPTURE;
return list; return list;
} }
......
...@@ -210,9 +210,13 @@ FlightMap { ...@@ -210,9 +210,13 @@ FlightMap {
} }
} }
// Add the mission items to the map // Add the mission item visuals to the map
MissionItemView { Repeater {
model: _mainIsMap ? missionController.visualItems : 0 model: _mainIsMap ? missionController.visualItems : 0
delegate: MissionItemMapVisual {
map: flightMap
}
} }
// Add lines between waypoints // Add lines between waypoints
......
...@@ -25,7 +25,7 @@ MapItemView { ...@@ -25,7 +25,7 @@ MapItemView {
delegate: MissionItemIndicator { delegate: MissionItemIndicator {
id: itemIndicator id: itemIndicator
coordinate: object.coordinate coordinate: object.coordinate
visible: object.specifiesCoordinate && (index != 0 || object.showHomePosition) visible: object.specifiesCoordinate
z: QGroundControl.zOrderMapItems z: QGroundControl.zOrderMapItems
missionItem: object missionItem: object
sequenceNumber: object.sequenceNumber sequenceNumber: object.sequenceNumber
......
...@@ -49,9 +49,9 @@ Rectangle { ...@@ -49,9 +49,9 @@ Rectangle {
text: qsTr("WIP (NOT FOR REAL FLIGHT!)") text: qsTr("WIP (NOT FOR REAL FLIGHT!)")
} }
Item { width: 1; height: _margin } SectionHeader {
text: qsTr("Loiter point")
SectionHeader { text: qsTr("Loiter point") } }
Item { width: 1; height: _spacer } Item { width: 1; height: _spacer }
...@@ -80,8 +80,6 @@ Rectangle { ...@@ -80,8 +80,6 @@ Rectangle {
onClicked: missionItem.loiterClockwise = checked onClicked: missionItem.loiterClockwise = checked
} }
Item { width: 1; height: ScreenTools.defaultFontPixelHeight / 2 }
SectionHeader { text: qsTr("Landing point") } SectionHeader { text: qsTr("Landing point") }
Item { width: 1; height: _spacer } Item { width: 1; height: _spacer }
......
...@@ -585,6 +585,7 @@ QGCView { ...@@ -585,6 +585,7 @@ QGCView {
highlightMoveDuration: 250 highlightMoveDuration: 250
delegate: MissionItemEditor { delegate: MissionItemEditor {
map: editorMap
missionItem: object missionItem: object
width: parent.width width: parent.width
readOnly: false readOnly: false
...@@ -601,8 +602,7 @@ QGCView { ...@@ -601,8 +602,7 @@ QGCView {
setCurrentItem(removeIndex) setCurrentItem(removeIndex)
} }
onInsert: insertSimpleMissionItem(editorMap.center, index) onInsert: insertSimpleMissionItem(editorMap.center, index)
onMoveHomeToMapCenter: _visualItems.get(0).coordinate = editorMap.center
} }
} // QGCListView } // QGCListView
} // Item - Mission Item editor } // Item - Mission Item editor
......
...@@ -18,13 +18,13 @@ Rectangle { ...@@ -18,13 +18,13 @@ Rectangle {
color: _currentItem ? qgcPal.buttonHighlight : qgcPal.windowShade color: _currentItem ? qgcPal.buttonHighlight : qgcPal.windowShade
radius: _radius radius: _radius
property var map ///< Map control
property var missionItem ///< MissionItem associated with this editor property var missionItem ///< MissionItem associated with this editor
property bool readOnly ///< true: read only view, false: full editing view property bool readOnly ///< true: read only view, false: full editing view
signal clicked signal clicked
signal remove signal remove
signal insert signal insert
signal moveHomeToMapCenter
property bool _currentItem: missionItem.isCurrentItem property bool _currentItem: missionItem.isCurrentItem
property color _outerTextColor: _currentItem ? "black" : qgcPal.text property color _outerTextColor: _currentItem ? "black" : qgcPal.text
...@@ -125,7 +125,7 @@ Rectangle { ...@@ -125,7 +125,7 @@ Rectangle {
anchors.rightMargin: ScreenTools.defaultFontPixelWidth anchors.rightMargin: ScreenTools.defaultFontPixelWidth
anchors.left: label.right anchors.left: label.right
anchors.top: parent.top anchors.top: parent.top
visible: missionItem.sequenceNumber != 0 && missionItem.isCurrentItem && !missionItem.rawEdit && missionItem.isSimpleItem visible: missionItem.isCurrentItem && !missionItem.rawEdit && missionItem.isSimpleItem
text: missionItem.commandName text: missionItem.commandName
Component { Component {
...@@ -141,9 +141,9 @@ Rectangle { ...@@ -141,9 +141,9 @@ Rectangle {
QGCLabel { QGCLabel {
anchors.fill: commandPicker anchors.fill: commandPicker
visible: missionItem.sequenceNumber == 0 || !missionItem.isCurrentItem || !missionItem.isSimpleItem visible: !missionItem.isCurrentItem || !missionItem.isSimpleItem
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
text: missionItem.sequenceNumber == 0 ? qsTr("Mission Settings") : missionItem.commandName text: missionItem.commandName
color: _outerTextColor color: _outerTextColor
} }
...@@ -154,7 +154,7 @@ Rectangle { ...@@ -154,7 +154,7 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.top: commandPicker.bottom anchors.top: commandPicker.bottom
height: item ? item.height : 0 height: item ? item.height : 0
source: missionItem.sequenceNumber == 0 ? "qrc:/qml/MissionSettingsEditor.qml" : missionItem.editorQml source: missionItem.editorQml
onLoaded: { onLoaded: {
item.visible = Qt.binding(function() { return _currentItem; }) item.visible = Qt.binding(function() { return _currentItem; })
......
...@@ -19,6 +19,12 @@ Rectangle { ...@@ -19,6 +19,12 @@ Rectangle {
visible: missionItem.isCurrentItem visible: missionItem.isCurrentItem
radius: _radius radius: _radius
ExclusiveGroup {
id: sectionHeaderExclusiverGroup
}
property ExclusiveGroup sectionHeaderGroup: ScreenTools.isShortScreen ? sectionHeaderExclusiverGroup : null
Loader { Loader {
id: deferedload id: deferedload
active: valuesRect.visible active: valuesRect.visible
...@@ -37,7 +43,7 @@ Rectangle { ...@@ -37,7 +43,7 @@ Rectangle {
property bool _offlineEditing: _missionVehicle.isOfflineEditingVehicle property bool _offlineEditing: _missionVehicle.isOfflineEditingVehicle
property bool _showOfflineEditingCombos: _offlineEditing && _noMissionItemsAdded property bool _showOfflineEditingCombos: _offlineEditing && _noMissionItemsAdded
property bool _showCruiseSpeed: !_missionVehicle.multiRotor property bool _showCruiseSpeed: !_missionVehicle.multiRotor
property bool _showHoverSpeed: _missionVehicle.multiRotor || missionController.vehicle.vtol property bool _showHoverSpeed: _missionVehicle.multiRotor || _missionVehicle.vtol
property bool _multipleFirmware: QGroundControl.supportedFirmwareCount > 2 property bool _multipleFirmware: QGroundControl.supportedFirmwareCount > 2
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 16 property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 16
property bool _mobile: ScreenTools.isMobile property bool _mobile: ScreenTools.isMobile
...@@ -54,54 +60,72 @@ Rectangle { ...@@ -54,54 +60,72 @@ Rectangle {
anchors.top: parent.top anchors.top: parent.top
spacing: _margin spacing: _margin
SectionHeader { text: qsTr("Planned Home Position") } SectionHeader {
id: plannedHomePositionSection
text: qsTr("Planned Home Position")
showSpacer: false
exclusiveGroup: sectionHeaderGroup
}
Repeater { Column {
model: missionItem.textFieldFacts anchors.left: parent.left
RowLayout { anchors.right: parent.right
spacing: _margin
visible: plannedHomePositionSection.checked
GridLayout {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
spacing: _margin columnSpacing: ScreenTools.defaultFontPixelWidth
visible: _mobile ? index == 2 : true // Cheating here since we known we only have Lat/Lon/Alt rowSpacing: columnSpacing
columns: 2
QGCLabel { text: object.name; Layout.fillWidth: true } QGCLabel {
text: qsTr("Latitude")
}
FactTextField { FactTextField {
Layout.preferredWidth: _fieldWidth fact: missionItem.plannedHomePositionLatitude
showUnits: true Layout.fillWidth: true
fact: object
visible: !_root.readOnly
} }
FactLabel {
Layout.preferredWidth: _fieldWidth QGCLabel {
fact: object text: qsTr("Longitude")
visible: _root.readOnly }
FactTextField {
fact: missionItem.plannedHomePositionLongitude
Layout.fillWidth: true
} }
}
}
QGCLabel { QGCLabel {
width: parent.width text: qsTr("Altitude")
wrapMode: Text.WordWrap }
font.pointSize: ScreenTools.smallFontPointSize FactTextField {
text: qsTr("Actual position set by vehicle at flight time.") fact: missionItem.plannedHomePositionAltitude
horizontalAlignment: Text.AlignHCenter Layout.fillWidth: true
} }
}
QGCButton { QGCLabel {
text: qsTr("Set Home To Map Center") width: parent.width
onClicked: editorRoot.moveHomeToMapCenter() wrapMode: Text.WordWrap
anchors.horizontalCenter: parent.horizontalCenter font.pointSize: ScreenTools.smallFontPointSize
} text: qsTr("Actual position set by vehicle at flight time.")
horizontalAlignment: Text.AlignHCenter
}
Item { QGCButton {
height: _sectionSpacer text: qsTr("Set Home To Map Center")
width: 1 onClicked: missionItem.coordinate = map.center
visible: !ScreenTools.isTinyScreen anchors.horizontalCenter: parent.horizontalCenter
}
} }
SectionHeader { SectionHeader {
id: vehicleInfoSectionHeader
text: qsTr("Vehicle Info") text: qsTr("Vehicle Info")
visible: _multipleFirmware visible: _multipleFirmware && _showOfflineEditingCombos
checked: false
exclusiveGroup: sectionHeaderGroup
} }
GridLayout { GridLayout {
...@@ -110,74 +134,197 @@ Rectangle { ...@@ -110,74 +134,197 @@ Rectangle {
columnSpacing: ScreenTools.defaultFontPixelWidth columnSpacing: ScreenTools.defaultFontPixelWidth
rowSpacing: columnSpacing rowSpacing: columnSpacing
columns: 2 columns: 2
visible: _multipleFirmware visible: vehicleInfoSectionHeader.visible && vehicleInfoSectionHeader.checked
QGCLabel { QGCLabel {
text: _firmwareLabel text: _firmwareLabel
visible: _showOfflineEditingCombos Layout.fillWidth: true
Layout.fillWidth: true
} }
FactComboBox { FactComboBox {
fact: QGroundControl.settingsManager.appSettings.offlineEditingFirmwareType fact: QGroundControl.settingsManager.appSettings.offlineEditingFirmwareType
indexModel: false indexModel: false
visible: _showOfflineEditingCombos
Layout.preferredWidth: _fieldWidth Layout.preferredWidth: _fieldWidth
} }
QGCLabel { QGCLabel {
text: _vehicleLabel text: _vehicleLabel
visible: _showOfflineEditingCombos Layout.fillWidth: true
Layout.fillWidth: true
} }
FactComboBox { FactComboBox {
id: offlineVehicleCombo fact: QGroundControl.settingsManager.appSettings.offlineEditingVehicleType
fact: QGroundControl.settingsManager.appSettings.offlineEditingVehicleType indexModel: false
indexModel: false
visible: _showOfflineEditingCombos
Layout.preferredWidth: _fieldWidth Layout.preferredWidth: _fieldWidth
} }
QGCLabel { QGCLabel {
text: qsTr("Cruise speed") text: qsTr("Cruise speed")
visible: _showCruiseSpeed visible: _showCruiseSpeed
Layout.fillWidth: true Layout.fillWidth: true
} }
FactTextField { FactTextField {
fact: QGroundControl.settingsManager.appSettings.offlineEditingCruiseSpeed fact: QGroundControl.settingsManager.appSettings.offlineEditingCruiseSpeed
visible: _showCruiseSpeed visible: _showCruiseSpeed
Layout.preferredWidth: _fieldWidth Layout.preferredWidth: _fieldWidth
} }
QGCLabel { QGCLabel {
text: qsTr("Hover speed") text: qsTr("Hover speed")
visible: _showHoverSpeed visible: _showHoverSpeed
Layout.fillWidth: true Layout.fillWidth: true
} }
FactTextField { FactTextField {
fact: QGroundControl.settingsManager.appSettings.offlineEditingHoverSpeed fact: QGroundControl.settingsManager.appSettings.offlineEditingHoverSpeed
visible: _showHoverSpeed visible: _showHoverSpeed
Layout.preferredWidth: _fieldWidth Layout.preferredWidth: _fieldWidth
} }
} // GridLayout } // GridLayout
RowLayout { SectionHeader {
id: missionDefaultsSectionHeader
text: qsTr("Mission Defaults")
checked: false
exclusiveGroup: sectionHeaderGroup
}
Column {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
spacing: _margin spacing: _margin
visible: !_multipleFirmware visible: missionDefaultsSectionHeader.checked
QGCLabel { text: qsTr("Hover speed"); Layout.fillWidth: true }
FactTextField { GridLayout {
Layout.preferredWidth: _fieldWidth anchors.left: parent.left
fact: QGroundControl.settingsManager.appSettings.offlineEditingHoverSpeed anchors.right: parent.right
columnSpacing: ScreenTools.defaultFontPixelWidth
rowSpacing: columnSpacing
columns: 2
QGCLabel {
text: qsTr("Altitude")
}
FactTextField {
fact: QGroundControl.settingsManager.appSettings.defaultMissionItemAltitude
Layout.fillWidth: true
}
QGCCheckBox {
id: flightSpeedCheckBox
text: qsTr("Flight speed")
visible: !_missionVehicle.vtol
checked: missionItem.specifyMissionFlightSpeed
onClicked: missionItem.specifyMissionFlightSpeed = checked
}
FactTextField {
Layout.fillWidth: true
fact: missionItem.missionFlightSpeed
visible: flightSpeedCheckBox.visible
enabled: flightSpeedCheckBox.checked
}
} // GridLayout
/*
FIXME: NYI
FactComboBox {
anchors.left: parent.left
anchors.right: parent.right
fact: missionItem.missionEndAction
indexModel: false
}
*/
}
SectionHeader {
id: cameraSectionHeader
text: qsTr("Camera")
checked: false
exclusiveGroup: sectionHeaderGroup
}
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: cameraSectionHeader.checked
FactComboBox {
id: cameraActionCombo
anchors.left: parent.left
anchors.right: parent.right
fact: missionItem.cameraAction
indexModel: false
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: cameraActionCombo.currentIndex == 1
QGCLabel {
text: qsTr("Time")
Layout.fillWidth: true
}
FactTextField {
fact: missionItem.cameraPhotoIntervalTime
Layout.preferredWidth: _fieldWidth
}
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelWidth
visible: cameraActionCombo.currentIndex == 2
QGCLabel {
text: qsTr("Distance")
Layout.fillWidth: true
}
FactTextField {
fact: missionItem.cameraPhotoIntervalDistance
Layout.preferredWidth: _fieldWidth
}
}
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: 0
rowSpacing: 0
columns: 3
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Pitch") }
QGCLabel { text: qsTr("Yaw") }
QGCCheckBox {
id: gimbalCheckBox
text: qsTr("Gimbal")
checked: missionItem.specifyGimbal
onClicked: missionItem.specifyGimbal = checked
Layout.fillWidth: true
}
FactTextField {
fact: missionItem.gimbalPitch
implicitWidth: ScreenTools.defaultFontPixelWidth * 9
enabled: gimbalCheckBox.checked
}
FactTextField {
fact: missionItem.gimbalYaw
implicitWidth: ScreenTools.defaultFontPixelWidth * 9
enabled: gimbalCheckBox.checked
}
} }
} }
QGCLabel { QGCLabel {
width: parent.width width: parent.width
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font.pointSize: ScreenTools.smallFontPointSize font.pointSize: ScreenTools.smallFontPointSize
text: qsTr("Speeds are only used for time calculations. Actual vehicle speed will not be affected.") text: qsTr("Speeds are only used for time calculations. Actual vehicle speed will not be affected.")
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
visible: _offlineEditing && _missionVehicle.vtol
} }
} // Column } // Column
} // Item } // Item
......
/****************************************************************************
*
* (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.
*
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtLocation 5.3
import QtPositioning 5.3
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightMap 1.0
/// Mission Settings map visuals
Item {
property var map ///< Map control to place item in
property var _missionItem: object
property var _itemVisual
property var _dragArea
property bool _itemVisualShowing: false
property bool _dragAreaShowing: false
function hideItemVisuals() {
if (_itemVisualShowing) {
_itemVisual.destroy()
_itemVisualShowing = false
}
}
function showItemVisuals() {
if (!_itemVisualShowing) {
_itemVisual = indicatorComponent.createObject(map)
map.addMapItem(_itemVisual)
_itemVisualShowing = true
}
}
function hideDragArea() {
if (_dragAreaShowing) {
_dragArea.destroy()
_dragAreaShowing = false
}
}
function showDragArea() {
if (!_dragAreaShowing && _missionItem.specifiesCoordinate) {
_dragArea = dragAreaComponent.createObject(map)
_dragAreaShowing = true
}
}
Component.onCompleted: {
showItemVisuals()
if (_missionItem.isCurrentItem) {
showDragArea()
}
}
Component.onDestruction: {
hideDragArea()
hideItemVisuals()
}
Connections {
target: _missionItem
onIsCurrentItemChanged: {
if (_missionItem.isCurrentItem) {
showDragArea()
} else {
hideDragArea()
}
}
}
// Control which is used to drag items
Component {
id: dragAreaComponent
MissionItemIndicatorDrag {
itemIndicator: _itemVisual
itemCoordinate: _missionItem.coordinate
onItemCoordinateChanged: _missionItem.coordinate = itemCoordinate
}
}
Component {
id: indicatorComponent
MissionItemIndicator {
coordinate: _missionItem.coordinate
visible: _missionItem.showHomePosition
z: QGroundControl.zOrderMapItems
missionItem: _missionItem
onClicked: setCurrentItem(_missionItem.sequenceNumber)
// These are the non-coordinate child mission items attached to this item
Row {
anchors.top: parent.top
anchors.left: parent.right
Repeater {
model: _missionItem.childItems
delegate: MissionItemIndexLabel {
label: object.abbreviation
checked: object.isCurrentItem
z: 2
specifiesCoordinate: false
onClicked: setCurrentItem(object.sequenceNumber)
}
}
}
}
}
}
...@@ -5,20 +5,55 @@ import QtQuick.Layouts 1.2 ...@@ -5,20 +5,55 @@ import QtQuick.Layouts 1.2
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0 import QGroundControl.Palette 1.0
Column { QGCMouseArea {
id: _root
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: column.height
onClicked: checked = !checked
property alias text: label.text property alias text: label.text
property bool checked: true
property bool showSpacer: true
property ExclusiveGroup exclusiveGroup: null
QGCPalette { id: qgcPal; colorGroupEnabled: true } property real _sectionSpacer: ScreenTools.defaultFontPixelWidth / 2 // spacing between section headings
onExclusiveGroupChanged: {
if (exclusiveGroup)
exclusiveGroup.bindCheckable(_root)
}
QGCLabel { id: label } QGCPalette { id: qgcPal; colorGroupEnabled: true }
Rectangle { ColumnLayout {
id: column
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: 1
color: qgcPal.text Item {
height: _sectionSpacer
width: 1
visible: showSpacer
}
QGCLabel {
id: label
Layout.fillWidth: true
Image {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
source: "/qmlimages/arrow-down.png"
visible: !_root.checked
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: qgcPal.text
}
} }
} }
...@@ -166,7 +166,10 @@ Rectangle { ...@@ -166,7 +166,10 @@ Rectangle {
anchors.right: parent.right anchors.right: parent.right
spacing: _margin spacing: _margin
SectionHeader { text: qsTr("Camera") } SectionHeader {
text: qsTr("Camera")
showSpacer: false
}
QGCComboBox { QGCComboBox {
id: gridTypeCombo id: gridTypeCombo
...@@ -327,8 +330,6 @@ Rectangle { ...@@ -327,8 +330,6 @@ Rectangle {
} }
} }
Item { height: _sectionSpacer; width: 1; visible: !ScreenTools.isTinyScreen }
SectionHeader { text: qsTr("Grid") } SectionHeader { text: qsTr("Grid") }
GridLayout { GridLayout {
...@@ -395,8 +396,6 @@ Rectangle { ...@@ -395,8 +396,6 @@ Rectangle {
spacing: _margin spacing: _margin
visible: gridTypeCombo.currentIndex == _gridTypeManual visible: gridTypeCombo.currentIndex == _gridTypeManual
Item { height: _sectionSpacer; width: 1; visible: !ScreenTools.isTinyScreen }
SectionHeader { text: qsTr("Grid") } SectionHeader { text: qsTr("Grid") }
FactTextFieldGrid { FactTextFieldGrid {
...@@ -447,8 +446,6 @@ Rectangle { ...@@ -447,8 +446,6 @@ Rectangle {
} }
} }
Item { height: _sectionSpacer; width: 1; visible: !ScreenTools.isTinyScreen }
SectionHeader { text: qsTr("Statistics") } SectionHeader { text: qsTr("Statistics") }
Grid { Grid {
......
...@@ -105,8 +105,10 @@ void FixedWingLandingComplexItem::setDirty(bool dirty) ...@@ -105,8 +105,10 @@ void FixedWingLandingComplexItem::setDirty(bool dirty)
} }
} }
void FixedWingLandingComplexItem::save(QJsonObject& saveObject) const void FixedWingLandingComplexItem::save(QJsonArray& missionItems) const
{ {
QJsonObject saveObject;
saveObject[JsonHelper::jsonVersionKey] = 1; saveObject[JsonHelper::jsonVersionKey] = 1;
saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue;
saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue;
...@@ -128,6 +130,8 @@ void FixedWingLandingComplexItem::save(QJsonObject& saveObject) const ...@@ -128,6 +130,8 @@ void FixedWingLandingComplexItem::save(QJsonObject& saveObject) const
saveObject[_jsonLoiterClockwiseKey] = _loiterClockwise; saveObject[_jsonLoiterClockwiseKey] = _loiterClockwise;
saveObject[_jsonLoiterAltitudeRelativeKey] = _loiterAltitudeRelative; saveObject[_jsonLoiterAltitudeRelativeKey] = _loiterAltitudeRelative;
saveObject[_jsonLandingAltitudeRelativeKey] = _landingAltitudeRelative; saveObject[_jsonLandingAltitudeRelativeKey] = _landingAltitudeRelative;
missionItems.append(saveObject);
} }
void FixedWingLandingComplexItem::setSequenceNumber(int sequenceNumber) void FixedWingLandingComplexItem::setSequenceNumber(int sequenceNumber)
...@@ -236,7 +240,7 @@ QmlObjectListModel* FixedWingLandingComplexItem::getMissionItems(void) const ...@@ -236,7 +240,7 @@ QmlObjectListModel* FixedWingLandingComplexItem::getMissionItems(void) const
0.0, 0.0, 0.0, 0.0, // param 1-4 0.0, 0.0, 0.0, 0.0, // param 1-4
_landingCoordinate.latitude(), _landingCoordinate.latitude(),
_landingCoordinate.longitude(), _landingCoordinate.longitude(),
0.0, // altitude _landingAltitudeFact.rawValue().toDouble(),
true, // autoContinue true, // autoContinue
false, // isCurrentItem false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing pMissionItems); // parent - allow delete on pMissionItems to delete everthing
......
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
void setDirty (bool dirty) final; void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final { setLoiterCoordinate(coordinate); } void setCoordinate (const QGeoCoordinate& coordinate) final { setLoiterCoordinate(coordinate); }
void setSequenceNumber (int sequenceNumber) final; void setSequenceNumber (int sequenceNumber) final;
void save (QJsonObject& saveObject) const final; void save (QJsonArray& missionItems) const final;
static const char* jsonComplexItemTypeValue; static const char* jsonComplexItemTypeValue;
......
...@@ -965,11 +965,58 @@ ...@@ -965,11 +965,58 @@
{ "id": 510, "rawName": "MAV_CMD_GET_MESSAGE_INTERVAL", "friendlyName": "Get message interval" }, { "id": 510, "rawName": "MAV_CMD_GET_MESSAGE_INTERVAL", "friendlyName": "Get message interval" },
{ "id": 511, "rawName": "MAV_CMD_SET_MESSAGE_INTERVAL", "friendlyName": "Set message interval" }, { "id": 511, "rawName": "MAV_CMD_SET_MESSAGE_INTERVAL", "friendlyName": "Set message interval" },
{ "id": 520, "rawName": "MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES", "friendlyName": "Get capabilities" }, { "id": 520, "rawName": "MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES", "friendlyName": "Get capabilities" },
{ "id": 2000, "rawName": "MAV_CMD_IMAGE_START_CAPTURE", "friendlyName": "Start image capture" }, {
"id": 2000,
"rawName": "MAV_CMD_IMAGE_START_CAPTURE",
"friendlyName": "Start image capture" ,
"description": "Start taking one or more photos.",
"category": "Camera",
"param1": {
"label": "Interval",
"default": 0,
"units": "secs",
"decimalPlaces": 0
},
"param2": {
"label": "Photo count",
"default": 1,
"decimalPlaces": 0
},
"param3": {
"label": "Resolution",
"default": -1,
"decimalPlaces": 0
},
"param6": {
"label": "Camera id",
"default": 0,
"decimalPlaces": 0
}
},
{ "id": 2001, "rawName": "MAV_CMD_IMAGE_STOP_CAPTURE", "friendlyName": "Stop image capture" }, { "id": 2001, "rawName": "MAV_CMD_IMAGE_STOP_CAPTURE", "friendlyName": "Stop image capture" },
{ "id": 2003, "rawName": "MAV_CMD_DO_TRIGGER_CONTROL", "friendlyName": "Trigger control" }, { "id": 2003, "rawName": "MAV_CMD_DO_TRIGGER_CONTROL", "friendlyName": "Trigger control" },
{ "id": 2500, "rawName": "MAV_CMD_VIDEO_START_CAPTURE", "friendlyName": "Start video capture" }, {
{ "id": 2501, "rawName": "MAV_CMD_VIDEO_STOP_CAPTURE", "friendlyName": "Stop video cpture" }, "id": 2500,
"rawName": "MAV_CMD_VIDEO_START_CAPTURE",
"friendlyName": "Start video capture",
"description": "Start taking video.",
"category": "Camera",
"param1": {
"label": "Camera id",
"default": 0,
"decimalPlaces": 0
},
"param2": {
"label": "FPS",
"default": -1,
"decimalPlaces": 0
},
"param3": {
"label": "Resolution",
"default": -1,
"decimalPlaces": 0
}
},
{ "id": 2800, "rawName": "MAV_CMD_PANORAMA_CREATE", "friendlyName": "Create panorama" }, { "id": 2800, "rawName": "MAV_CMD_PANORAMA_CREATE", "friendlyName": "Create panorama" },
{ {
"id": 3000, "id": 3000,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "ParameterManager.h" #include "ParameterManager.h"
#include "QGroundControlQmlGlobal.h" #include "QGroundControlQmlGlobal.h"
#include "SettingsManager.h" #include "SettingsManager.h"
#include "MissionSettingsComplexItem.h"
#ifndef __mobile__ #ifndef __mobile__
#include "MainWindow.h" #include "MainWindow.h"
...@@ -29,7 +30,6 @@ ...@@ -29,7 +30,6 @@
QGC_LOGGING_CATEGORY(MissionControllerLog, "MissionControllerLog") QGC_LOGGING_CATEGORY(MissionControllerLog, "MissionControllerLog")
const char* MissionController::_settingsGroup = "MissionController"; const char* MissionController::_settingsGroup = "MissionController";
const char* MissionController::_jsonFileTypeValue = "Mission"; const char* MissionController::_jsonFileTypeValue = "Mission";
const char* MissionController::_jsonItemsKey = "items"; const char* MissionController::_jsonItemsKey = "items";
...@@ -49,7 +49,6 @@ const int MissionController::_missionFileVersion = 2; ...@@ -49,7 +49,6 @@ const int MissionController::_missionFileVersion = 2;
MissionController::MissionController(QObject *parent) MissionController::MissionController(QObject *parent)
: PlanElementController(parent) : PlanElementController(parent)
, _visualItems(NULL) , _visualItems(NULL)
, _complexItems(NULL)
, _firstItemsFromVehicle(false) , _firstItemsFromVehicle(false)
, _missionItemsRequested(false) , _missionItemsRequested(false)
, _queuedSend(false) , _queuedSend(false)
...@@ -91,7 +90,7 @@ void MissionController::_init(void) ...@@ -91,7 +90,7 @@ void MissionController::_init(void)
{ {
// We start with an empty mission // We start with an empty mission
_visualItems = new QmlObjectListModel(this); _visualItems = new QmlObjectListModel(this);
_addPlannedHomePosition(_activeVehicle, _visualItems, false /* addToCenter */); _addMissionSettings(_activeVehicle, _visualItems, false /* addToCenter */);
_initAllVisualItems(); _initAllVisualItems();
} }
...@@ -121,11 +120,13 @@ void MissionController::_newMissionItemsAvailableFromVehicle(void) ...@@ -121,11 +120,13 @@ void MissionController::_newMissionItemsAvailableFromVehicle(void)
_visualItems = newControllerMissionItems; _visualItems = newControllerMissionItems;
if (!_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle() || _visualItems->count() == 0) { if (!_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle() || _visualItems->count() == 0) {
_addPlannedHomePosition(_activeVehicle, _visualItems,true /* addToCenter */); _addMissionSettings(_activeVehicle, _visualItems, true /* addToCenter */);
} }
_missionItemsRequested = false; _missionItemsRequested = false;
MissionSettingsComplexItem::scanForMissionSettings(_visualItems, _activeVehicle);
_initAllVisualItems(); _initAllVisualItems();
emit newItemsFromVehicle(); emit newItemsFromVehicle();
} }
...@@ -237,7 +238,6 @@ int MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate ...@@ -237,7 +238,6 @@ int MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate
_initVisualItem(newItem); _initVisualItem(newItem);
_visualItems->insert(i, newItem); _visualItems->insert(i, newItem);
_complexItems->append(newItem);
_recalcAll(); _recalcAll();
...@@ -249,12 +249,6 @@ void MissionController::removeMissionItem(int index) ...@@ -249,12 +249,6 @@ void MissionController::removeMissionItem(int index)
VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->removeAt(index)); VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->removeAt(index));
_deinitVisualItem(item); _deinitVisualItem(item);
if (!item->isSimpleItem()) {
ComplexMissionItem* complexItem = qobject_cast<ComplexMissionItem*>(_complexItems->removeOne(item));
if (!complexItem) {
qWarning() << "Complex item missing";
}
}
item->deleteLater(); item->deleteLater();
_recalcAll(); _recalcAll();
...@@ -267,13 +261,13 @@ void MissionController::removeAll(void) ...@@ -267,13 +261,13 @@ void MissionController::removeAll(void)
_deinitAllVisualItems(); _deinitAllVisualItems();
_visualItems->deleteLater(); _visualItems->deleteLater();
_visualItems = new QmlObjectListModel(this); _visualItems = new QmlObjectListModel(this);
_addPlannedHomePosition(_activeVehicle, _visualItems, false /* addToCenter */); _addMissionSettings(_activeVehicle, _visualItems, false /* addToCenter */);
_initAllVisualItems(); _initAllVisualItems();
_visualItems->setDirty(true); _visualItems->setDirty(true);
} }
} }
bool MissionController::_loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString) bool MissionController::_loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QString& errorString)
{ {
QJsonParseError jsonParseError; QJsonParseError jsonParseError;
QJsonDocument jsonDoc(QJsonDocument::fromJson(bytes, &jsonParseError)); QJsonDocument jsonDoc(QJsonDocument::fromJson(bytes, &jsonParseError));
...@@ -300,13 +294,13 @@ bool MissionController::_loadJsonMissionFile(Vehicle* vehicle, const QByteArray& ...@@ -300,13 +294,13 @@ bool MissionController::_loadJsonMissionFile(Vehicle* vehicle, const QByteArray&
} }
if (fileVersion == 1) { if (fileVersion == 1) {
return _loadJsonMissionFileV1(vehicle, json, visualItems, complexItems, errorString); return _loadJsonMissionFileV1(vehicle, json, visualItems, errorString);
} else { } else {
return _loadJsonMissionFileV2(vehicle, json, visualItems, complexItems, errorString); return _loadJsonMissionFileV2(vehicle, json, visualItems, errorString);
} }
} }
bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString) bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString)
{ {
// Validate root object keys // Validate root object keys
QList<JsonHelper::KeyValidateInfo> rootKeyInfoList = { QList<JsonHelper::KeyValidateInfo> rootKeyInfoList = {
...@@ -320,6 +314,7 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje ...@@ -320,6 +314,7 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
} }
// Read complex items // Read complex items
QList<SurveyMissionItem*> surveyItems;
QJsonArray complexArray(json[_jsonComplexItemsKey].toArray()); QJsonArray complexArray(json[_jsonComplexItemsKey].toArray());
qCDebug(MissionControllerLog) << "Json load: complex item count" << complexArray.count(); qCDebug(MissionControllerLog) << "Json load: complex item count" << complexArray.count();
for (int i=0; i<complexArray.count(); i++) { for (int i=0; i<complexArray.count(); i++) {
...@@ -333,7 +328,7 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje ...@@ -333,7 +328,7 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
SurveyMissionItem* item = new SurveyMissionItem(vehicle, visualItems); SurveyMissionItem* item = new SurveyMissionItem(vehicle, visualItems);
const QJsonObject itemObject = itemValue.toObject(); const QJsonObject itemObject = itemValue.toObject();
if (item->load(itemObject, itemObject["id"].toInt(), errorString)) { if (item->load(itemObject, itemObject["id"].toInt(), errorString)) {
complexItems->append(item); surveyItems.append(item);
} else { } else {
return false; return false;
} }
...@@ -346,13 +341,13 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje ...@@ -346,13 +341,13 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
int nextSequenceNumber = 1; // Start with 1 since home is in 0 int nextSequenceNumber = 1; // Start with 1 since home is in 0
QJsonArray itemArray(json[_jsonItemsKey].toArray()); QJsonArray itemArray(json[_jsonItemsKey].toArray());
qCDebug(MissionControllerLog) << "Json load: simple item loop start simpleItemCount:ComplexItemCount" << itemArray.count() << complexItems->count(); qCDebug(MissionControllerLog) << "Json load: simple item loop start simpleItemCount:ComplexItemCount" << itemArray.count() << surveyItems.count();
do { do {
qCDebug(MissionControllerLog) << "Json load: simple item loop nextSimpleItemIndex:nextComplexItemIndex:nextSequenceNumber" << nextSimpleItemIndex << nextComplexItemIndex << nextSequenceNumber; qCDebug(MissionControllerLog) << "Json load: simple item loop nextSimpleItemIndex:nextComplexItemIndex:nextSequenceNumber" << nextSimpleItemIndex << nextComplexItemIndex << nextSequenceNumber;
// If there is a complex item that should be next in sequence add it in // If there is a complex item that should be next in sequence add it in
if (nextComplexItemIndex < complexItems->count()) { if (nextComplexItemIndex < surveyItems.count()) {
SurveyMissionItem* complexItem = qobject_cast<SurveyMissionItem*>(complexItems->get(nextComplexItemIndex)); SurveyMissionItem* complexItem = surveyItems[nextComplexItemIndex];
if (complexItem->sequenceNumber() == nextSequenceNumber) { if (complexItem->sequenceNumber() == nextSequenceNumber) {
qCDebug(MissionControllerLog) << "Json load: injecting complex item expectedSequence:actualSequence:" << nextSequenceNumber << complexItem->sequenceNumber(); qCDebug(MissionControllerLog) << "Json load: injecting complex item expectedSequence:actualSequence:" << nextSequenceNumber << complexItem->sequenceNumber();
...@@ -383,24 +378,27 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje ...@@ -383,24 +378,27 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
nextSequenceNumber++; nextSequenceNumber++;
} }
} while (nextSimpleItemIndex < itemArray.count() || nextComplexItemIndex < complexItems->count()); } while (nextSimpleItemIndex < itemArray.count() || nextComplexItemIndex < surveyItems.count());
if (json.contains(_jsonPlannedHomePositionKey)) { if (json.contains(_jsonPlannedHomePositionKey)) {
SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems); SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems);
if (item->load(json[_jsonPlannedHomePositionKey].toObject(), 0, errorString)) { if (item->load(json[_jsonPlannedHomePositionKey].toObject(), 0, errorString)) {
visualItems->insert(0, item); MissionSettingsComplexItem* settingsItem = new MissionSettingsComplexItem(vehicle, visualItems);
settingsItem->setCoordinate(item->coordinate());
visualItems->insert(0, settingsItem);
item->deleteLater();
} else { } else {
return false; return false;
} }
} else { } else {
_addPlannedHomePosition(vehicle, visualItems, true /* addToCenter */); _addMissionSettings(vehicle, visualItems, true /* addToCenter */);
} }
return true; return true;
} }
bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString) bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString)
{ {
// Validate root object keys // Validate root object keys
QList<JsonHelper::KeyValidateInfo> rootKeyInfoList = { QList<JsonHelper::KeyValidateInfo> rootKeyInfoList = {
...@@ -433,9 +431,9 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje ...@@ -433,9 +431,9 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
settingsManager->appSettings()->offlineEditingHoverSpeed()->setRawValue(json[_jsonHoverSpeedKey].toDouble()); settingsManager->appSettings()->offlineEditingHoverSpeed()->setRawValue(json[_jsonHoverSpeedKey].toDouble());
} }
SimpleMissionItem* homeItem = new SimpleMissionItem(vehicle, visualItems); MissionSettingsComplexItem* settingsItem = new MissionSettingsComplexItem(vehicle, visualItems);
homeItem->setCoordinate(homeCoordinate); settingsItem->setCoordinate(homeCoordinate);
visualItems->insert(0, homeItem); visualItems->insert(0, settingsItem);
qCDebug(MissionControllerLog) << "plannedHomePosition" << homeCoordinate; qCDebug(MissionControllerLog) << "plannedHomePosition" << homeCoordinate;
// Read mission items // Read mission items
...@@ -487,7 +485,6 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje ...@@ -487,7 +485,6 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
nextSequenceNumber = surveyItem->lastSequenceNumber() + 1; nextSequenceNumber = surveyItem->lastSequenceNumber() + 1;
qCDebug(MissionControllerLog) << "Survey load complete: nextSequenceNumber" << nextSequenceNumber; qCDebug(MissionControllerLog) << "Survey load complete: nextSequenceNumber" << nextSequenceNumber;
visualItems->append(surveyItem); visualItems->append(surveyItem);
complexItems->append(surveyItem);
} else if (complexItemType == FixedWingLandingComplexItem::jsonComplexItemTypeValue) { } else if (complexItemType == FixedWingLandingComplexItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog) << "Loading Fixed Wing Landing Pattern: nextSequenceNumber" << nextSequenceNumber; qCDebug(MissionControllerLog) << "Loading Fixed Wing Landing Pattern: nextSequenceNumber" << nextSequenceNumber;
FixedWingLandingComplexItem* landingItem = new FixedWingLandingComplexItem(vehicle, visualItems); FixedWingLandingComplexItem* landingItem = new FixedWingLandingComplexItem(vehicle, visualItems);
...@@ -497,7 +494,15 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje ...@@ -497,7 +494,15 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
nextSequenceNumber = landingItem->lastSequenceNumber() + 1; nextSequenceNumber = landingItem->lastSequenceNumber() + 1;
qCDebug(MissionControllerLog) << "FW Landing Pattern load complete: nextSequenceNumber" << nextSequenceNumber; qCDebug(MissionControllerLog) << "FW Landing Pattern load complete: nextSequenceNumber" << nextSequenceNumber;
visualItems->append(landingItem); visualItems->append(landingItem);
complexItems->append(landingItem); } else if (complexItemType == MissionSettingsComplexItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog) << "Loading Mission Settings: nextSequenceNumber" << nextSequenceNumber;
MissionSettingsComplexItem* settingsItem = new MissionSettingsComplexItem(vehicle, visualItems);
if (!settingsItem->load(itemObject, nextSequenceNumber++, errorString)) {
return false;
}
nextSequenceNumber = settingsItem->lastSequenceNumber() + 1;
qCDebug(MissionControllerLog) << "Mission Settings load complete: nextSequenceNumber" << nextSequenceNumber;
visualItems->append(settingsItem);
} else { } else {
errorString = tr("Unsupported complex item type: %1").arg(complexItemType); errorString = tr("Unsupported complex item type: %1").arg(complexItemType);
} }
...@@ -571,7 +576,7 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre ...@@ -571,7 +576,7 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre
} }
if (addPlannedHomePosition || visualItems->count() == 0) { if (addPlannedHomePosition || visualItems->count() == 0) {
_addPlannedHomePosition(vehicle, visualItems, true /* addToCenter */); _addMissionSettings(vehicle, visualItems, true /* addToCenter */);
// Update sequence numbers in DO_JUMP commands to take into account added home position in index 0 // Update sequence numbers in DO_JUMP commands to take into account added home position in index 0
for (int i=1; i<visualItems->count(); i++) { for (int i=1; i<visualItems->count(); i++) {
...@@ -588,9 +593,8 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre ...@@ -588,9 +593,8 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre
void MissionController::loadFromFile(const QString& filename) void MissionController::loadFromFile(const QString& filename)
{ {
QmlObjectListModel* newVisualItems = NULL; QmlObjectListModel* newVisualItems = NULL;
QmlObjectListModel* newComplexItems = NULL;
if (!loadItemsFromFile(_activeVehicle, filename, &newVisualItems, &newComplexItems)) { if (!loadItemsFromFile(_activeVehicle, filename, &newVisualItems)) {
return; return;
} }
...@@ -598,24 +602,21 @@ void MissionController::loadFromFile(const QString& filename) ...@@ -598,24 +602,21 @@ void MissionController::loadFromFile(const QString& filename)
_deinitAllVisualItems(); _deinitAllVisualItems();
_visualItems->deleteLater(); _visualItems->deleteLater();
} }
if (_complexItems) {
_complexItems->deleteLater();
}
_visualItems = newVisualItems; _visualItems = newVisualItems;
_complexItems = newComplexItems;
if (_visualItems->count() == 0) { if (_visualItems->count() == 0) {
_addPlannedHomePosition(_activeVehicle, _visualItems, true /* addToCenter */); _addMissionSettings(_activeVehicle, _visualItems, true /* addToCenter */);
} }
MissionSettingsComplexItem::scanForMissionSettings(_visualItems, _activeVehicle);
_initAllVisualItems(); _initAllVisualItems();
} }
bool MissionController::loadItemsFromFile(Vehicle* vehicle, const QString& filename, QmlObjectListModel** visualItems, QmlObjectListModel** complexItems) bool MissionController::loadItemsFromFile(Vehicle* vehicle, const QString& filename, QmlObjectListModel** visualItems)
{ {
*visualItems = NULL; *visualItems = NULL;
*complexItems = NULL;
QString errorString; QString errorString;
...@@ -624,7 +625,6 @@ bool MissionController::loadItemsFromFile(Vehicle* vehicle, const QString& filen ...@@ -624,7 +625,6 @@ bool MissionController::loadItemsFromFile(Vehicle* vehicle, const QString& filen
} }
*visualItems = new QmlObjectListModel(); *visualItems = new QmlObjectListModel();
*complexItems = new QmlObjectListModel();
QFile file(filename); QFile file(filename);
...@@ -639,13 +639,12 @@ bool MissionController::loadItemsFromFile(Vehicle* vehicle, const QString& filen ...@@ -639,13 +639,12 @@ bool MissionController::loadItemsFromFile(Vehicle* vehicle, const QString& filen
stream.seek(0); stream.seek(0);
_loadTextMissionFile(vehicle, stream, *visualItems, errorString); _loadTextMissionFile(vehicle, stream, *visualItems, errorString);
} else { } else {
_loadJsonMissionFile(vehicle, bytes, *visualItems, *complexItems, errorString); _loadJsonMissionFile(vehicle, bytes, *visualItems, errorString);
} }
} }
if (!errorString.isEmpty()) { if (!errorString.isEmpty()) {
(*visualItems)->deleteLater(); (*visualItems)->deleteLater();
(*complexItems)->deleteLater();
qgcApp()->showMessage(errorString); qgcApp()->showMessage(errorString);
return false; return false;
...@@ -691,13 +690,13 @@ void MissionController::saveToFile(const QString& filename) ...@@ -691,13 +690,13 @@ void MissionController::saveToFile(const QString& filename)
// Mission settings // Mission settings
SimpleMissionItem* homeItem = qobject_cast<SimpleMissionItem*>(_visualItems->get(0)); MissionSettingsComplexItem* settingsItem = _visualItems->value<MissionSettingsComplexItem*>(0);
if (!homeItem) { if (!settingsItem) {
qgcApp()->showMessage(QStringLiteral("Internal error: VisualMissionItem at index 0 not SimpleMissionItem")); qWarning() << "First item is not MissionSettingsComplexItem";
return; return;
} }
QJsonValue coordinateValue; QJsonValue coordinateValue;
JsonHelper::saveGeoCoordinate(homeItem->coordinate(), true /* writeAltitude */, coordinateValue); JsonHelper::saveGeoCoordinate(settingsItem->coordinate(), true /* writeAltitude */, coordinateValue);
missionFileObject[_jsonPlannedHomePositionKey] = coordinateValue; missionFileObject[_jsonPlannedHomePositionKey] = coordinateValue;
missionFileObject[_jsonFirmwareTypeKey] = _activeVehicle->firmwareType(); missionFileObject[_jsonFirmwareTypeKey] = _activeVehicle->firmwareType();
missionFileObject[_jsonVehicleTypeKey] = _activeVehicle->vehicleType(); missionFileObject[_jsonVehicleTypeKey] = _activeVehicle->vehicleType();
...@@ -706,12 +705,9 @@ void MissionController::saveToFile(const QString& filename) ...@@ -706,12 +705,9 @@ void MissionController::saveToFile(const QString& filename)
// Save the visual items // Save the visual items
QJsonArray rgMissionItems; QJsonArray rgMissionItems;
for (int i=1; i<_visualItems->count(); i++) { for (int i=0; i<_visualItems->count(); i++) {
QJsonObject itemObject;
VisualMissionItem* visualItem = qobject_cast<VisualMissionItem*>(_visualItems->get(i)); VisualMissionItem* visualItem = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
visualItem->save(itemObject); visualItem->save(rgMissionItems);
rgMissionItems.append(itemObject);
} }
missionFileObject[_jsonItemsKey] = rgMissionItems; missionFileObject[_jsonItemsKey] = rgMissionItems;
...@@ -785,13 +781,13 @@ void MissionController::_recalcWaypointLines(void) ...@@ -785,13 +781,13 @@ void MissionController::_recalcWaypointLines(void)
bool firstCoordinateItem = true; bool firstCoordinateItem = true;
VisualMissionItem* lastCoordinateItem = qobject_cast<VisualMissionItem*>(_visualItems->get(0)); VisualMissionItem* lastCoordinateItem = qobject_cast<VisualMissionItem*>(_visualItems->get(0));
SimpleMissionItem* homeItem = qobject_cast<SimpleMissionItem*>(lastCoordinateItem); MissionSettingsComplexItem* settingsItem = qobject_cast<MissionSettingsComplexItem*>(lastCoordinateItem);
if (!homeItem) { if (!settingsItem) {
qWarning() << "Home item is not SimpleMissionItem"; qWarning() << "First item is not MissionSettingsComplexItem";
} }
bool showHomePosition = homeItem->showHomePosition(); bool showHomePosition = false; // FIXME: settingsItem->showHomePosition();
qCDebug(MissionControllerLog) << "_recalcWaypointLines"; qCDebug(MissionControllerLog) << "_recalcWaypointLines";
...@@ -816,7 +812,7 @@ void MissionController::_recalcWaypointLines(void) ...@@ -816,7 +812,7 @@ void MissionController::_recalcWaypointLines(void)
if (!item->isStandaloneCoordinate()) { if (!item->isStandaloneCoordinate()) {
firstCoordinateItem = false; firstCoordinateItem = false;
VisualItemPair pair(lastCoordinateItem, item); VisualItemPair pair(lastCoordinateItem, item);
if (lastCoordinateItem != homeItem || (showHomePosition && linkBackToHome)) { if (lastCoordinateItem != settingsItem || (showHomePosition && linkBackToHome)) {
if (old_table.contains(pair)) { if (old_table.contains(pair)) {
// Do nothing, this segment already exists and is wired up // Do nothing, this segment already exists and is wired up
_linesTable[pair] = old_table.take(pair); _linesTable[pair] = old_table.take(pair);
...@@ -840,7 +836,6 @@ void MissionController::_recalcWaypointLines(void) ...@@ -840,7 +836,6 @@ void MissionController::_recalcWaypointLines(void)
} }
} }
{ {
// Create a temporary QObjectList and replace the model data // Create a temporary QObjectList and replace the model data
QObjectList objs; QObjectList objs;
...@@ -853,7 +848,6 @@ void MissionController::_recalcWaypointLines(void) ...@@ -853,7 +848,6 @@ void MissionController::_recalcWaypointLines(void)
_waypointLines.swapObjectList(objs); _waypointLines.swapObjectList(objs);
} }
// Anything left in the old table is an obsolete line object that can go // Anything left in the old table is an obsolete line object that can go
qDeleteAll(old_table); qDeleteAll(old_table);
...@@ -864,18 +858,19 @@ void MissionController::_recalcWaypointLines(void) ...@@ -864,18 +858,19 @@ void MissionController::_recalcWaypointLines(void)
void MissionController::_recalcAltitudeRangeBearing() void MissionController::_recalcAltitudeRangeBearing()
{ {
if (!_visualItems->count()) if (!_visualItems->count()) {
return; return;
}
bool firstCoordinateItem = true; bool firstCoordinateItem = true;
VisualMissionItem* lastCoordinateItem = qobject_cast<VisualMissionItem*>(_visualItems->get(0)); VisualMissionItem* lastCoordinateItem = qobject_cast<VisualMissionItem*>(_visualItems->get(0));
SimpleMissionItem* homeItem = qobject_cast<SimpleMissionItem*>(lastCoordinateItem); MissionSettingsComplexItem* settingsItem = qobject_cast<MissionSettingsComplexItem*>(lastCoordinateItem);
if (!homeItem) { if (!settingsItem) {
qWarning() << "Home item is not SimpleMissionItem"; qWarning() << "First item is not MissionSettingsComplexItem";
} }
bool showHomePosition = homeItem->showHomePosition(); bool showHomePosition = settingsItem->showHomePosition();
qCDebug(MissionControllerLog) << "_recalcAltitudeRangeBearing"; qCDebug(MissionControllerLog) << "_recalcAltitudeRangeBearing";
...@@ -890,8 +885,8 @@ void MissionController::_recalcAltitudeRangeBearing() ...@@ -890,8 +885,8 @@ void MissionController::_recalcAltitudeRangeBearing()
double minAltSeen = 0.0; double minAltSeen = 0.0;
double maxAltSeen = 0.0; double maxAltSeen = 0.0;
const double homePositionAltitude = homeItem->coordinate().altitude(); const double homePositionAltitude = settingsItem->coordinate().altitude();
minAltSeen = maxAltSeen = homeItem->coordinate().altitude(); minAltSeen = maxAltSeen = settingsItem->coordinate().altitude();
double missionDistance = 0.0; double missionDistance = 0.0;
double missionMaxTelemetry = 0.0; double missionMaxTelemetry = 0.0;
...@@ -981,7 +976,7 @@ void MissionController::_recalcAltitudeRangeBearing() ...@@ -981,7 +976,7 @@ void MissionController::_recalcAltitudeRangeBearing()
if (!item->isStandaloneCoordinate()) { if (!item->isStandaloneCoordinate()) {
firstCoordinateItem = false; firstCoordinateItem = false;
if (lastCoordinateItem != homeItem || linkBackToHome) { if (lastCoordinateItem != settingsItem || linkBackToHome) {
// This is a subsequent waypoint or we are forcing the first waypoint back to home // This is a subsequent waypoint or we are forcing the first waypoint back to home
double azimuth, distance, altDifference; double azimuth, distance, altDifference;
...@@ -991,7 +986,7 @@ void MissionController::_recalcAltitudeRangeBearing() ...@@ -991,7 +986,7 @@ void MissionController::_recalcAltitudeRangeBearing()
item->setDistance(distance); item->setDistance(distance);
missionDistance += distance; missionDistance += distance;
missionMaxTelemetry = qMax(missionMaxTelemetry, _calcDistanceToHome(item, homeItem)); missionMaxTelemetry = qMax(missionMaxTelemetry, _calcDistanceToHome(item, settingsItem));
// Calculate mission time // Calculate mission time
if (vtolVehicle) { if (vtolVehicle) {
...@@ -1017,7 +1012,7 @@ void MissionController::_recalcAltitudeRangeBearing() ...@@ -1017,7 +1012,7 @@ void MissionController::_recalcAltitudeRangeBearing()
double cruiseSpeed = _activeVehicle->multiRotor() ? currentHoverSpeed : currentCruiseSpeed; double cruiseSpeed = _activeVehicle->multiRotor() ? currentHoverSpeed : currentCruiseSpeed;
missionDistance += complexDistance; missionDistance += complexDistance;
missionTime += complexDistance / cruiseSpeed; missionTime += complexDistance / cruiseSpeed;
missionMaxTelemetry = qMax(missionMaxTelemetry, complexItem->greatestDistanceTo(homeItem->exitCoordinate())); missionMaxTelemetry = qMax(missionMaxTelemetry, complexItem->greatestDistanceTo(settingsItem->exitCoordinate()));
// Let the complex item know the current cruise speed // Let the complex item know the current cruise speed
complexItem->setCruiseSpeed(cruiseSpeed); complexItem->setCruiseSpeed(cruiseSpeed);
...@@ -1107,57 +1102,36 @@ void MissionController::_recalcAll(void) ...@@ -1107,57 +1102,36 @@ void MissionController::_recalcAll(void)
/// Initializes a new set of mission items /// Initializes a new set of mission items
void MissionController::_initAllVisualItems(void) void MissionController::_initAllVisualItems(void)
{ {
SimpleMissionItem* homeItem = NULL; MissionSettingsComplexItem* settingsItem = NULL;
// Setup home position at index 0 // Setup home position at index 0
homeItem = qobject_cast<SimpleMissionItem*>(_visualItems->get(0)); settingsItem = qobject_cast<MissionSettingsComplexItem*>(_visualItems->get(0));
if (!homeItem) { if (!settingsItem) {
qWarning() << "homeItem not SimpleMissionItem"; qWarning() << "First item not MissionSettingsComplexItem";
return; return;
} }
homeItem->setHomePositionSpecialCase(true); settingsItem->setShowHomePosition(_editMode);
homeItem->setShowHomePosition(_editMode); settingsItem->setIsCurrentItem(true);
homeItem->missionItem().setCommand(MAV_CMD_NAV_WAYPOINT);
homeItem->missionItem().setFrame(MAV_FRAME_GLOBAL);
homeItem->setIsCurrentItem(true);
if (!_editMode && _activeVehicle && _activeVehicle->homePositionAvailable()) { if (!_editMode && _activeVehicle && _activeVehicle->homePositionAvailable()) {
homeItem->setCoordinate(_activeVehicle->homePosition()); settingsItem->setCoordinate(_activeVehicle->homePosition());
homeItem->setShowHomePosition(true); settingsItem->setShowHomePosition(true);
} }
emit plannedHomePositionChanged(plannedHomePosition()); emit plannedHomePositionChanged(plannedHomePosition());
connect(homeItem, &VisualMissionItem::coordinateChanged, this, &MissionController::_homeCoordinateChanged); connect(settingsItem, &VisualMissionItem::coordinateChanged, this, &MissionController::_homeCoordinateChanged);
QmlObjectListModel* newComplexItems = new QmlObjectListModel(this);
for (int i=0; i<_visualItems->count(); i++) { for (int i=0; i<_visualItems->count(); i++) {
VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->get(i)); VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
_initVisualItem(item); _initVisualItem(item);
// Set up complex item list
if (!item->isSimpleItem()) {
ComplexMissionItem* complexItem = qobject_cast<ComplexMissionItem*>(item);
if (complexItem) {
newComplexItems->append(item);
} else {
qWarning() << "isSimpleItem == false, but not ComplexMissionItem";
}
}
}
if (_complexItems) {
_complexItems->deleteLater();
} }
_complexItems = newComplexItems;
_recalcAll(); _recalcAll();
emit visualItemsChanged(); emit visualItemsChanged();
emit complexVisualItemsChanged();
connect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged); connect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged);
...@@ -1256,14 +1230,14 @@ void MissionController::_activeVehicleSet(void) ...@@ -1256,14 +1230,14 @@ void MissionController::_activeVehicleSet(void)
void MissionController::_activeVehicleHomePositionAvailableChanged(bool homePositionAvailable) void MissionController::_activeVehicleHomePositionAvailableChanged(bool homePositionAvailable)
{ {
if (!_editMode && _visualItems) { if (!_editMode && _visualItems) {
SimpleMissionItem* homeItem = qobject_cast<SimpleMissionItem*>(_visualItems->get(0)); MissionSettingsComplexItem* settingsItem = qobject_cast<MissionSettingsComplexItem*>(_visualItems->get(0));
if (homeItem) { if (settingsItem) {
homeItem->setShowHomePosition(homePositionAvailable); settingsItem->setShowHomePosition(homePositionAvailable);
emit plannedHomePositionChanged(plannedHomePosition()); emit plannedHomePositionChanged(plannedHomePosition());
_recalcWaypointLines(); _recalcWaypointLines();
} else { } else {
qWarning() << "Unabled to cast home item to SimpleMissionItem"; qWarning() << "First item is not MissionSettingsComplexItem";
} }
} }
} }
...@@ -1271,16 +1245,17 @@ void MissionController::_activeVehicleHomePositionAvailableChanged(bool homePosi ...@@ -1271,16 +1245,17 @@ void MissionController::_activeVehicleHomePositionAvailableChanged(bool homePosi
void MissionController::_activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition) void MissionController::_activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition)
{ {
if (!_editMode && _visualItems) { if (!_editMode && _visualItems) {
VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->get(0)); MissionSettingsComplexItem* settingsItem = qobject_cast<MissionSettingsComplexItem*>(_visualItems->get(0));
if (item) { if (settingsItem) {
if (item->coordinate() != homePosition) { if (settingsItem->coordinate() != homePosition) {
item->setCoordinate(homePosition); settingsItem->setCoordinate(homePosition);
settingsItem->setShowHomePosition(true);
qCDebug(MissionControllerLog) << "Home position update" << homePosition; qCDebug(MissionControllerLog) << "Home position update" << homePosition;
emit plannedHomePositionChanged(plannedHomePosition()); emit plannedHomePositionChanged(plannedHomePosition());
_recalcWaypointLines(); _recalcWaypointLines();
} }
} else { } else {
qWarning() << "Unabled to cast home item to VisualMissionItem"; qWarning() << "First item is not MissionSettingsComplexItem";
} }
} }
} }
...@@ -1393,13 +1368,13 @@ double MissionController::_normalizeLon(double lon) ...@@ -1393,13 +1368,13 @@ double MissionController::_normalizeLon(double lon)
return lon + 180.0; return lon + 180.0;
} }
/// Add the home position item to the front of the list /// Add the Mission Settings complex item to the front of the items
void MissionController::_addPlannedHomePosition(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter) void MissionController::_addMissionSettings(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter)
{ {
bool homePositionSet = false; bool homePositionSet = false;
SimpleMissionItem* homeItem = new SimpleMissionItem(vehicle, visualItems); MissionSettingsComplexItem* settingsItem = new MissionSettingsComplexItem(vehicle, visualItems);
visualItems->insert(0, homeItem); visualItems->insert(0, settingsItem);
if (visualItems->count() > 1 && addToCenter) { if (visualItems->count() > 1 && addToCenter) {
double north = 0.0; double north = 0.0;
...@@ -1430,12 +1405,12 @@ void MissionController::_addPlannedHomePosition(Vehicle* vehicle, QmlObjectListM ...@@ -1430,12 +1405,12 @@ void MissionController::_addPlannedHomePosition(Vehicle* vehicle, QmlObjectListM
if (firstCoordSet) { if (firstCoordSet) {
homePositionSet = true; homePositionSet = true;
homeItem->setCoordinate(QGeoCoordinate((south + ((north - south) / 2)) - 90.0, (west + ((east - west) / 2)) - 180.0, 0.0)); settingsItem->setCoordinate(QGeoCoordinate((south + ((north - south) / 2)) - 90.0, (west + ((east - west) / 2)) - 180.0, 0.0));
} }
} }
if (!homePositionSet) { if (!homePositionSet) {
homeItem->setCoordinate(qgcApp()->lastKnownHomePosition()); settingsItem->setCoordinate(qgcApp()->lastKnownHomePosition());
} }
} }
...@@ -1474,9 +1449,9 @@ void MissionController::setDirty(bool dirty) ...@@ -1474,9 +1449,9 @@ void MissionController::setDirty(bool dirty)
QGeoCoordinate MissionController::plannedHomePosition(void) QGeoCoordinate MissionController::plannedHomePosition(void)
{ {
if (_visualItems && _visualItems->count() > 0) { if (_visualItems && _visualItems->count() > 0) {
SimpleMissionItem* item = qobject_cast<SimpleMissionItem*>(_visualItems->get(0)); MissionSettingsComplexItem* settingsItem = qobject_cast<MissionSettingsComplexItem*>(_visualItems->get(0));
if (item && item->showHomePosition()) { if (settingsItem && settingsItem->showHomePosition()) {
return item->coordinate(); return settingsItem->coordinate();
} }
} }
......
...@@ -34,11 +34,10 @@ public: ...@@ -34,11 +34,10 @@ public:
MissionController(QObject* parent = NULL); MissionController(QObject* parent = NULL);
~MissionController(); ~MissionController();
Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged) // Mission settings
Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged) Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged)
Q_PROPERTY(QmlObjectListModel* complexVisualItems READ complexVisualItems NOTIFY complexVisualItemsChanged) Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged)
Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged) Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged)
Q_PROPERTY(QStringList complexMissionItemNames MEMBER _complexMissionItemNames CONSTANT) Q_PROPERTY(QStringList complexMissionItemNames MEMBER _complexMissionItemNames CONSTANT)
Q_PROPERTY(double missionDistance READ missionDistance NOTIFY missionDistanceChanged) Q_PROPERTY(double missionDistance READ missionDistance NOTIFY missionDistanceChanged)
...@@ -67,9 +66,8 @@ public: ...@@ -67,9 +66,8 @@ public:
/// @param[in] vehicle Vehicle we are loading items for /// @param[in] vehicle Vehicle we are loading items for
/// @param[in] filename File to load from /// @param[in] filename File to load from
/// @param[out] visualItems Visual items loaded, returns NULL if error /// @param[out] visualItems Visual items loaded, returns NULL if error
/// @param[out] complexItems Complex items loaded, returns NULL if error
/// @return success/fail /// @return success/fail
static bool loadItemsFromFile(Vehicle* vehicle, const QString& filename, QmlObjectListModel** visualItems, QmlObjectListModel** complexItems); static bool loadItemsFromFile(Vehicle* vehicle, const QString& filename, QmlObjectListModel** visualItems);
/// Sends the mission items to the specified vehicle /// Sends the mission items to the specified vehicle
static void sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel* visualMissionItems); static void sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel* visualMissionItems);
...@@ -94,7 +92,6 @@ public: ...@@ -94,7 +92,6 @@ public:
QGeoCoordinate plannedHomePosition (void); QGeoCoordinate plannedHomePosition (void);
QmlObjectListModel* visualItems (void) { return _visualItems; } QmlObjectListModel* visualItems (void) { return _visualItems; }
QmlObjectListModel* complexVisualItems (void) { return _complexItems; }
QmlObjectListModel* waypointLines (void) { return &_waypointLines; } QmlObjectListModel* waypointLines (void) { return &_waypointLines; }
double missionDistance (void) const { return _missionDistance; } double missionDistance (void) const { return _missionDistance; }
...@@ -110,7 +107,6 @@ public: ...@@ -110,7 +107,6 @@ public:
signals: signals:
void plannedHomePositionChanged(QGeoCoordinate plannedHomePosition); void plannedHomePositionChanged(QGeoCoordinate plannedHomePosition);
void visualItemsChanged(void); void visualItemsChanged(void);
void complexVisualItemsChanged(void);
void waypointLinesChanged(void); void waypointLinesChanged(void);
void newItemsFromVehicle(void); void newItemsFromVehicle(void);
void missionDistanceChanged(double missionDistance); void missionDistanceChanged(double missionDistance);
...@@ -151,10 +147,10 @@ private: ...@@ -151,10 +147,10 @@ private:
bool _findPreviousAltitude(int newIndex, double* prevAltitude, MAV_FRAME* prevFrame); bool _findPreviousAltitude(int newIndex, double* prevAltitude, MAV_FRAME* prevFrame);
static double _normalizeLat(double lat); static double _normalizeLat(double lat);
static double _normalizeLon(double lon); static double _normalizeLon(double lon);
static void _addPlannedHomePosition(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter); static void _addMissionSettings(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter);
static bool _loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); static bool _loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); static bool _loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString); static bool _loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString); static bool _loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString);
int _nextSequenceNumber(void); int _nextSequenceNumber(void);
void _setMissionDistance(double missionDistance); void _setMissionDistance(double missionDistance);
...@@ -171,7 +167,6 @@ private: ...@@ -171,7 +167,6 @@ private:
private: private:
QmlObjectListModel* _visualItems; QmlObjectListModel* _visualItems;
QmlObjectListModel* _complexItems;
QmlObjectListModel _waypointLines; QmlObjectListModel _waypointLines;
CoordVectHashTable _linesTable; CoordVectHashTable _linesTable;
bool _firstItemsFromVehicle; bool _firstItemsFromVehicle;
...@@ -189,6 +184,8 @@ private: ...@@ -189,6 +184,8 @@ private:
QStringList _complexMissionItemNames; QStringList _complexMissionItemNames;
static const char* _settingsGroup; static const char* _settingsGroup;
// Json file keys for persistence
static const char* _jsonFileTypeValue; static const char* _jsonFileTypeValue;
static const char* _jsonFirmwareTypeKey; static const char* _jsonFirmwareTypeKey;
static const char* _jsonVehicleTypeKey; static const char* _jsonVehicleTypeKey;
......
...@@ -91,7 +91,7 @@ void MissionManager::writeMissionItems(const QList<MissionItem*>& missionItems) ...@@ -91,7 +91,7 @@ void MissionManager::writeMissionItems(const QList<MissionItem*>& missionItems)
/// This begins the write sequence with the vehicle. This may be called during a retry. /// This begins the write sequence with the vehicle. This may be called during a retry.
void MissionManager::_writeMissionCount(void) void MissionManager::_writeMissionCount(void)
{ {
qCDebug(MissionManagerLog) << "_writeMissionCount retry count" << _retryCount; qCDebug(MissionManagerLog) << "_writeMissionCount count:_retryCount" << _missionItems.count() << _retryCount;
mavlink_message_t message; mavlink_message_t message;
mavlink_mission_count_t missionCount; mavlink_mission_count_t missionCount;
...@@ -427,7 +427,7 @@ void MissionManager::_handleMissionItem(const mavlink_message_t& message, bool m ...@@ -427,7 +427,7 @@ void MissionManager::_handleMissionItem(const mavlink_message_t& message, bool m
seq = missionItem.seq; seq = missionItem.seq;
} }
qCDebug(MissionManagerLog) << "_handleMissionItem sequenceNumber:" << seq; qCDebug(MissionManagerLog) << "_handleMissionItem sequenceNumber:" << seq << command;
if (_itemIndicesToRead.contains(seq)) { if (_itemIndicesToRead.contains(seq)) {
_itemIndicesToRead.removeOne(seq); _itemIndicesToRead.removeOne(seq);
...@@ -483,8 +483,6 @@ void MissionManager::_handleMissionRequest(const mavlink_message_t& message, boo ...@@ -483,8 +483,6 @@ void MissionManager::_handleMissionRequest(const mavlink_message_t& message, boo
mavlink_msg_mission_request_decode(&message, &missionRequest); mavlink_msg_mission_request_decode(&message, &missionRequest);
qCDebug(MissionManagerLog) << "_handleMissionRequest sequenceNumber:" << missionRequest.seq;
if (!_itemIndicesToWrite.contains(missionRequest.seq)) { if (!_itemIndicesToWrite.contains(missionRequest.seq)) {
if (missionRequest.seq > _missionItems.count()) { if (missionRequest.seq > _missionItems.count()) {
_sendError(RequestRangeError, QString("Vehicle requested item outside range, count:request %1:%2. Send to Vehicle failed.").arg(_missionItems.count()).arg(missionRequest.seq)); _sendError(RequestRangeError, QString("Vehicle requested item outside range, count:request %1:%2. Send to Vehicle failed.").arg(_missionItems.count()).arg(missionRequest.seq));
...@@ -497,11 +495,13 @@ void MissionManager::_handleMissionRequest(const mavlink_message_t& message, boo ...@@ -497,11 +495,13 @@ void MissionManager::_handleMissionRequest(const mavlink_message_t& message, boo
_itemIndicesToWrite.removeOne(missionRequest.seq); _itemIndicesToWrite.removeOne(missionRequest.seq);
} }
mavlink_message_t messageOut; MissionItem* item = _missionItems[missionRequest.seq];
qCDebug(MissionManagerLog) << "_handleMissionRequest sequenceNumber:" << missionRequest.seq << item->command();
mavlink_message_t messageOut;
if (missionItemInt) { if (missionItemInt) {
mavlink_mission_item_int_t missionItem; mavlink_mission_item_int_t missionItem;
MissionItem* item = _missionItems[missionRequest.seq];
missionItem.target_system = _vehicle->id(); missionItem.target_system = _vehicle->id();
missionItem.target_component = MAV_COMP_ID_MISSIONPLANNER; missionItem.target_component = MAV_COMP_ID_MISSIONPLANNER;
...@@ -526,8 +526,6 @@ void MissionManager::_handleMissionRequest(const mavlink_message_t& message, boo ...@@ -526,8 +526,6 @@ void MissionManager::_handleMissionRequest(const mavlink_message_t& message, boo
} else { } else {
mavlink_mission_item_t missionItem; mavlink_mission_item_t missionItem;
MissionItem* item = _missionItems[missionRequest.seq];
missionItem.target_system = _vehicle->id(); missionItem.target_system = _vehicle->id();
missionItem.target_component = MAV_COMP_ID_MISSIONPLANNER; missionItem.target_component = MAV_COMP_ID_MISSIONPLANNER;
missionItem.seq = missionRequest.seq; missionItem.seq = missionRequest.seq;
......
[
{
"name": "PlannedHomePositionLatitude",
"shortDescription": "Planned home position latitude",
"type": "double",
"decimalPlaces": 7,
"defaultValue": 37.803784
},
{
"name": "PlannedHomePositionLongitude",
"shortDescription": "Planned home position longitude",
"type": "double",
"decimalPlaces": 7,
"defaultValue": -122.462276
},
{
"name": "PlannedHomePositionAltitude",
"shortDescription": "Planned home position altitude",
"type": "double",
"units": "m",
"decimalPlaces": 1,
"defaultValue": 0
},
{
"name": "FlightSpeed",
"shortDescription": "Flight speed for mission.",
"type": "double",
"units": "m/s",
"min": 0,
"decimalPlaces": 1
},
{
"name": "CameraAction",
"shortDescription": "Specify whether the camera should take photos or video",
"type": "uint32",
"enumStrings": "No camera action,Take photos (time),Take photos (distance),Take video",
"enumValues": "0,1,2,3",
"defaultValue": 0
},
{
"name": "CameraPhotoIntervalDistance",
"shortDescription": "Specify the distance between each photo",
"type": "double",
"units": "m",
"min": 0,
"decimalPlaces": 1,
"defaultValue": 1
},
{
"name": "CameraPhotoIntervalTime",
"shortDescription": "Specify the time between each photo",
"type": "uint32",
"units": "secs",
"min": 1,
"decimalPlaces": 0,
"defaultValue": 10
},
{
"name": "GimbalPitch",
"shortDescription": "Gimbal pitch rotation.",
"type": "double",
"units": "deg",
"min": 0.0,
"max": 360.0,
"decimalPlaces": 0,
"defaultValue": 0
},
{
"name": "GimbalYaw",
"shortDescription": "Gimbal yaw rotation.",
"type": "double",
"units": "deg",
"min": 0.0,
"max": 360.0,
"decimalPlaces": 0,
"defaultValue": 0
},
{
"name": "MissionEndAction",
"shortDescription": "The action to take when the mission completed.",
"type": "uint32",
"enumStrings": "No action on mission completion,Loiter after mission completes,RTL after mission completes,Land after mission completes",
"enumValues": "0,1,2,3",
"defaultValue": 0
}
]
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "MissionSettingsComplexItem.h"
#include "JsonHelper.h"
#include "MissionController.h"
#include "QGCGeo.h"
#include "QGroundControlQmlGlobal.h"
#include "SimpleMissionItem.h"
#include "SettingsManager.h"
#include "AppSettings.h"
#include <QPolygonF>
QGC_LOGGING_CATEGORY(MissionSettingsComplexItemLog, "MissionSettingsComplexItemLog")
const char* MissionSettingsComplexItem::jsonComplexItemTypeValue = "MissionSettings";
const char* MissionSettingsComplexItem::_plannedHomePositionLatitudeName = "PlannedHomePositionLatitude";
const char* MissionSettingsComplexItem::_plannedHomePositionLongitudeName = "PlannedHomePositionLongitude";
const char* MissionSettingsComplexItem::_plannedHomePositionAltitudeName = "PlannedHomePositionAltitude";
const char* MissionSettingsComplexItem::_missionFlightSpeedName = "FlightSpeed";
const char* MissionSettingsComplexItem::_gimbalPitchName = "GimbalPitch";
const char* MissionSettingsComplexItem::_gimbalYawName = "GimbalYaw";
const char* MissionSettingsComplexItem::_cameraActionName = "CameraAction";
const char* MissionSettingsComplexItem::_cameraPhotoIntervalDistanceName = "CameraPhotoIntervalDistance";
const char* MissionSettingsComplexItem::_cameraPhotoIntervalTimeName = "CameraPhotoIntervalTime";
const char* MissionSettingsComplexItem::_missionEndActionName = "MissionEndAction";
QMap<QString, FactMetaData*> MissionSettingsComplexItem::_metaDataMap;
MissionSettingsComplexItem::MissionSettingsComplexItem(Vehicle* vehicle, QObject* parent)
: ComplexMissionItem(vehicle, parent)
, _specifyMissionFlightSpeed(false)
, _specifyGimbal(false)
, _plannedHomePositionLatitudeFact (0, _plannedHomePositionLatitudeName, FactMetaData::valueTypeDouble)
, _plannedHomePositionLongitudeFact (0, _plannedHomePositionLongitudeName, FactMetaData::valueTypeDouble)
, _plannedHomePositionAltitudeFact (0, _plannedHomePositionAltitudeName, FactMetaData::valueTypeDouble)
, _missionFlightSpeedFact (0, _missionFlightSpeedName, FactMetaData::valueTypeDouble)
, _gimbalYawFact (0, _gimbalYawName, FactMetaData::valueTypeDouble)
, _gimbalPitchFact (0, _gimbalPitchName, FactMetaData::valueTypeDouble)
, _cameraActionFact (0, _cameraActionName, FactMetaData::valueTypeDouble)
, _cameraPhotoIntervalDistanceFact (0, _cameraPhotoIntervalDistanceName, FactMetaData::valueTypeDouble)
, _cameraPhotoIntervalTimeFact (0, _cameraPhotoIntervalTimeName, FactMetaData::valueTypeUint32)
, _missionEndActionFact (0, _missionEndActionName, FactMetaData::valueTypeUint32)
, _sequenceNumber(0)
, _dirty(false)
{
_editorQml = "qrc:/qml/MissionSettingsEditor.qml";
if (_metaDataMap.isEmpty()) {
_metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/MissionSettings.FactMetaData.json"), NULL /* metaDataParent */);
}
_plannedHomePositionLatitudeFact.setMetaData (_metaDataMap[_plannedHomePositionLatitudeName]);
_plannedHomePositionLongitudeFact.setMetaData (_metaDataMap[_plannedHomePositionLongitudeName]);
_plannedHomePositionAltitudeFact.setMetaData (_metaDataMap[_plannedHomePositionAltitudeName]);
_missionFlightSpeedFact.setMetaData (_metaDataMap[_missionFlightSpeedName]);
_gimbalPitchFact.setMetaData (_metaDataMap[_gimbalPitchName]);
_gimbalYawFact.setMetaData (_metaDataMap[_gimbalYawName]);
_cameraActionFact.setMetaData (_metaDataMap[_cameraActionName]);
_cameraPhotoIntervalDistanceFact.setMetaData (_metaDataMap[_cameraPhotoIntervalDistanceName]);
_cameraPhotoIntervalTimeFact.setMetaData (_metaDataMap[_cameraPhotoIntervalTimeName]);
_missionEndActionFact.setMetaData (_metaDataMap[_missionEndActionName]);
_plannedHomePositionLatitudeFact.setRawValue (_plannedHomePositionLatitudeFact.rawDefaultValue());
_plannedHomePositionLongitudeFact.setRawValue (_plannedHomePositionLongitudeFact.rawDefaultValue());
_plannedHomePositionAltitudeFact.setRawValue (_plannedHomePositionAltitudeFact.rawDefaultValue());
_gimbalPitchFact.setRawValue (_gimbalPitchFact.rawDefaultValue());
_gimbalYawFact.setRawValue (_gimbalYawFact.rawDefaultValue());
_cameraActionFact.setRawValue (_cameraActionFact.rawDefaultValue());
_cameraPhotoIntervalDistanceFact.setRawValue (_cameraPhotoIntervalDistanceFact.rawDefaultValue());
_cameraPhotoIntervalTimeFact.setRawValue (_cameraPhotoIntervalTimeFact.rawDefaultValue());
_missionEndActionFact.setRawValue (_missionEndActionFact.rawDefaultValue());
// FIXME: Flight speed default value correctly based firmware parameter if online
AppSettings* appSettings = qgcApp()->toolbox()->settingsManager()->appSettings();
Fact* speedFact = vehicle->multiRotor() ? appSettings->offlineEditingHoverSpeed() : appSettings->offlineEditingCruiseSpeed();
_missionFlightSpeedFact.setRawValue(speedFact->rawValue().toDouble());
setHomePositionSpecialCase(true);
connect(this, &MissionSettingsComplexItem::specifyMissionFlightSpeedChanged, this, &MissionSettingsComplexItem::_setDirtyAndUpdateLastSequenceNumber);
connect(this, &MissionSettingsComplexItem::specifyGimbalChanged, this, &MissionSettingsComplexItem::_setDirtyAndUpdateLastSequenceNumber);
connect(&_plannedHomePositionLatitudeFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirtyAndUpdateCoordinate);
connect(&_plannedHomePositionLongitudeFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirtyAndUpdateCoordinate);
connect(&_plannedHomePositionAltitudeFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirtyAndUpdateCoordinate);
connect(&_missionFlightSpeedFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirty);
connect(&_gimbalPitchFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirty);
connect(&_gimbalYawFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirty);
connect(&_cameraActionFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirtyAndUpdateLastSequenceNumber);
connect(&_cameraPhotoIntervalDistanceFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirty);
connect(&_cameraPhotoIntervalTimeFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirty);
connect(&_missionEndActionFact, &Fact::valueChanged, this, &MissionSettingsComplexItem::_setDirty);
}
void MissionSettingsComplexItem::setSpecifyMissionFlightSpeed(bool specifyMissionFlightSpeed)
{
if (specifyMissionFlightSpeed != _specifyMissionFlightSpeed) {
_specifyMissionFlightSpeed = specifyMissionFlightSpeed;
emit specifyMissionFlightSpeedChanged(specifyMissionFlightSpeed);
}
}
void MissionSettingsComplexItem::setSpecifyGimbal(bool specifyGimbal)
{
if (specifyGimbal != _specifyGimbal) {
_specifyGimbal = specifyGimbal;
emit specifyGimbalChanged(specifyGimbal);
}
}
int MissionSettingsComplexItem::lastSequenceNumber(void) const
{
int lastSequenceNumber = _sequenceNumber + 1; // +1 for planned home position
if (_specifyMissionFlightSpeed) {
lastSequenceNumber++;
}
if (_specifyGimbal) {
lastSequenceNumber++;
}
if (_cameraActionFact.rawValue().toInt() != CameraActionNone) {
lastSequenceNumber++;
}
return lastSequenceNumber;
}
void MissionSettingsComplexItem::setDirty(bool dirty)
{
if (_dirty != dirty) {
_dirty = dirty;
emit dirtyChanged(_dirty);
}
}
void MissionSettingsComplexItem::save(QJsonArray& missionItems) const
{
QmlObjectListModel* items = getMissionItems();
// First item show be planned home position, we are not reponsible for save/load
// Remained we just output as is
for (int i=1; i<items->count(); i++) {
MissionItem* item = items->value<MissionItem*>(i);
QJsonObject saveObject;
item->save(saveObject);
missionItems.append(saveObject);
}
items->deleteLater();
}
void MissionSettingsComplexItem::setSequenceNumber(int sequenceNumber)
{
if (_sequenceNumber != sequenceNumber) {
_sequenceNumber = sequenceNumber;
emit sequenceNumberChanged(sequenceNumber);
emit lastSequenceNumberChanged(lastSequenceNumber());
}
}
bool MissionSettingsComplexItem::load(const QJsonObject& complexObject, int sequenceNumber, QString& errorString)
{
Q_UNUSED(complexObject);
Q_UNUSED(sequenceNumber);
Q_UNUSED(errorString);
#if 0
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true },
{ VisualMissionItem::jsonTypeKey, QJsonValue::String, true },
{ ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true },
{ _jsonLoiterCoordinateKey, QJsonValue::Array, true },
{ _jsonLoiterRadiusKey, QJsonValue::Double, true },
{ _jsonLoiterClockwiseKey, QJsonValue::Bool, true },
{ _jsonLoiterAltitudeRelativeKey, QJsonValue::Bool, true },
{ _jsonLandingCoordinateKey, QJsonValue::Array, true },
{ _jsonLandingAltitudeRelativeKey, QJsonValue::Bool, true },
};
if (!JsonHelper::validateKeys(complexObject, keyInfoList, errorString)) {
return false;
}
QString itemType = complexObject[VisualMissionItem::jsonTypeKey].toString();
QString complexType = complexObject[ComplexMissionItem::jsonComplexItemTypeKey].toString();
if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) {
errorString = tr("QGroundControl does not support loading this complex mission item type: %1:2").arg(itemType).arg(complexType);
return false;
}
setSequenceNumber(sequenceNumber);
QGeoCoordinate coordinate;
if (!JsonHelper::loadGeoCoordinate(complexObject[_jsonLoiterCoordinateKey], true /* altitudeRequired */, coordinate, errorString)) {
return false;
}
_loiterCoordinate = coordinate;
_loiterAltitudeFact.setRawValue(coordinate.altitude());
if (!JsonHelper::loadGeoCoordinate(complexObject[_jsonLandingCoordinateKey], true /* altitudeRequired */, coordinate, errorString)) {
return false;
}
_landingCoordinate = coordinate;
_landingAltitudeFact.setRawValue(coordinate.altitude());
_loiterRadiusFact.setRawValue(complexObject[_jsonLoiterRadiusKey].toDouble());
_loiterClockwise = complexObject[_jsonLoiterClockwiseKey].toBool();
_loiterAltitudeRelative = complexObject[_jsonLoiterAltitudeRelativeKey].toBool();
_landingAltitudeRelative = complexObject[_jsonLandingAltitudeRelativeKey].toBool();
_landingCoordSet = true;
_recalcFromHeadingAndDistanceChange();
#endif
return true;
}
double MissionSettingsComplexItem::greatestDistanceTo(const QGeoCoordinate &other) const
{
Q_UNUSED(other);
return 0;
}
bool MissionSettingsComplexItem::specifiesCoordinate(void) const
{
return false;
}
QmlObjectListModel* MissionSettingsComplexItem::getMissionItems(void) const
{
QmlObjectListModel* pMissionItems = new QmlObjectListModel;
int seqNum = _sequenceNumber;
// IMPORTANT NOTE: If anything changed here you just also change MissionSettingsComplexItem::scanForMissionSettings
// Planned home position
MissionItem* item = new MissionItem(seqNum++,
MAV_CMD_NAV_WAYPOINT,
MAV_FRAME_GLOBAL,
0, // Hold time
0, // Acceptance radius
0, // Not sure?
0, // Yaw
_plannedHomePositionLatitudeFact.rawValue().toDouble(),
_plannedHomePositionLongitudeFact.rawValue().toDouble(),
_plannedHomePositionAltitudeFact.rawValue().toDouble(),
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
if (_specifyGimbal) {
MissionItem* item = new MissionItem(seqNum++,
MAV_CMD_DO_MOUNT_CONTROL,
MAV_FRAME_MISSION,
_gimbalPitchFact.rawValue().toDouble(),
0, // Gimbal roll
_gimbalYawFact.rawValue().toDouble(),
0, 0, 0, // param 4-6 not used
MAV_MOUNT_MODE_MAVLINK_TARGETING,
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
}
if (_specifyMissionFlightSpeed) {
qDebug() << _missionFlightSpeedFact.rawValue().toDouble();
MissionItem* item = new MissionItem(seqNum++,
MAV_CMD_DO_CHANGE_SPEED,
MAV_FRAME_MISSION,
_vehicle->multiRotor() ? 1 /* groundspeed */ : 0 /* airspeed */, // Change airspeed or groundspeed
_missionFlightSpeedFact.rawValue().toDouble(),
-1, // No throttle change
0, // Absolute speed change
0, 0, 0, // param 5-7 not used
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
pMissionItems->append(item);
}
if (_cameraActionFact.rawValue().toInt() != CameraActionNone) {
MissionItem* item = NULL;
switch (_cameraActionFact.rawValue().toInt()) {
case TakePhotosIntervalTime:
item = new MissionItem(seqNum++,
MAV_CMD_IMAGE_START_CAPTURE,
MAV_FRAME_MISSION,
_cameraPhotoIntervalTimeFact.rawValue().toInt(), // Interval
0, // Unlimited photo count
-1, // Max resolution
0, 0, // param 4-5 not used
0, // Camera ID
0, // param 7 not used
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
break;
case TakePhotoIntervalDistance:
item = new MissionItem(seqNum++,
MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION,
_cameraPhotoIntervalDistanceFact.rawValue().toDouble(), // Trigger distance
0, 0, 0, 0, 0, 0, // param 2-7 not used
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
break;
case TakeVideo:
item = new MissionItem(seqNum++,
MAV_CMD_VIDEO_START_CAPTURE,
MAV_FRAME_MISSION,
0, // Camera ID
-1, // Max fps
-1, // Max resolution
0, 0, 0, 0, // param 5-7 not used
true, // autoContinue
false, // isCurrentItem
pMissionItems); // parent - allow delete on pMissionItems to delete everthing
break;
}
if (item) {
pMissionItems->append(item);
}
}
return pMissionItems;
}
void MissionSettingsComplexItem::scanForMissionSettings(QmlObjectListModel* visualItems, Vehicle* vehicle)
{
bool foundGimbal = false;
bool foundSpeed = false;
bool foundCameraAction = false;
MissionSettingsComplexItem* settingsItem = visualItems->value<MissionSettingsComplexItem*>(0);
if (!settingsItem) {
qWarning() << "First item is not MissionSettingsComplexItem";
return;
}
// Scan through the initial mission items for possible mission settings
while (visualItems->count()> 1) {
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(1);
if (!item) {
// We hit a complex item there can be no more possible mission settings
return;
}
MissionItem& missionItem = item->missionItem();
// See MissionSettingsComplexItem::getMissionItems for specs on what compomises a known mission settings
switch ((MAV_CMD)item->command()) {
case MAV_CMD_DO_MOUNT_CONTROL:
if (!foundGimbal && missionItem.param2() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == MAV_MOUNT_MODE_MAVLINK_TARGETING) {
foundGimbal = true;
settingsItem->setSpecifyGimbal(true);
settingsItem->gimbalPitch()->setRawValue(missionItem.param1());
settingsItem->gimbalYaw()->setRawValue(missionItem.param3());
visualItems->removeAt(1)->deleteLater();
} else {
return;
}
break;
case MAV_CMD_DO_CHANGE_SPEED:
if (!foundSpeed && missionItem.param3() == -1 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
if (vehicle->multiRotor()) {
if (missionItem.param1() != 1) {
return;
}
} else {
if (missionItem.param1() != 0) {
return;
}
}
foundSpeed = true;
settingsItem->setSpecifyMissionFlightSpeed(true);
settingsItem->missionFlightSpeed()->setRawValue(missionItem.param2());
visualItems->removeAt(1)->deleteLater();
} else {
return;
}
break;
case MAV_CMD_IMAGE_START_CAPTURE:
if (!foundCameraAction && missionItem.param1() != 0 && missionItem.param2() == 0 && missionItem.param3() == -1 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
foundCameraAction = true;
settingsItem->cameraAction()->setRawValue(TakePhotosIntervalTime);
settingsItem->cameraPhotoIntervalTime()->setRawValue(missionItem.param1());
visualItems->removeAt(1)->deleteLater();
} else {
return;
}
break;
case MAV_CMD_DO_SET_CAM_TRIGG_DIST:
if (!foundCameraAction && missionItem.param1() != 0 && missionItem.param2() == 0 && missionItem.param3() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
foundCameraAction = true;
settingsItem->cameraAction()->setRawValue(TakePhotoIntervalDistance);
settingsItem->cameraPhotoIntervalDistance()->setRawValue(missionItem.param1());
visualItems->removeAt(1)->deleteLater();
} else {
return;
}
break;
case MAV_CMD_VIDEO_START_CAPTURE:
if (!foundCameraAction && missionItem.param1() == 0 && missionItem.param2() == -1 && missionItem.param3() == -1 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
foundCameraAction = true;
settingsItem->cameraAction()->setRawValue(TakeVideo);
visualItems->removeAt(1)->deleteLater();
} else {
return;
}
break;
default:
return;
}
}
}
double MissionSettingsComplexItem::complexDistance(void) const
{
return 0;
}
void MissionSettingsComplexItem::setCruiseSpeed(double cruiseSpeed)
{
// We don't care about cruise speed
Q_UNUSED(cruiseSpeed);
}
void MissionSettingsComplexItem::_setDirty(void)
{
setDirty(true);
}
void MissionSettingsComplexItem::setCoordinate(const QGeoCoordinate& coordinate)
{
if (this->coordinate() != coordinate) {
_plannedHomePositionLatitudeFact.setRawValue(coordinate.latitude());
_plannedHomePositionLongitudeFact.setRawValue(coordinate.longitude());
_plannedHomePositionAltitudeFact.setRawValue(coordinate.altitude());
}
}
void MissionSettingsComplexItem::_setDirtyAndUpdateLastSequenceNumber(void)
{
emit lastSequenceNumberChanged(lastSequenceNumber());
setDirty(true);
}
void MissionSettingsComplexItem::_setDirtyAndUpdateCoordinate(void)
{
emit coordinateChanged(coordinate());
emit exitCoordinateChanged(coordinate());
setDirty(true);
}
QGeoCoordinate MissionSettingsComplexItem::coordinate(void) const
{
return QGeoCoordinate(_plannedHomePositionLatitudeFact.rawValue().toDouble(), _plannedHomePositionLongitudeFact.rawValue().toDouble(), _plannedHomePositionAltitudeFact.rawValue().toDouble());
}
/****************************************************************************
*
* (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.
*
****************************************************************************/
#ifndef MissionSettingsComplexItem_H
#define MissionSettingsComplexItem_H
#include "ComplexMissionItem.h"
#include "MissionItem.h"
#include "Fact.h"
#include "QGCLoggingCategory.h"
Q_DECLARE_LOGGING_CATEGORY(MissionSettingsComplexItemLog)
class MissionSettingsComplexItem : public ComplexMissionItem
{
Q_OBJECT
public:
MissionSettingsComplexItem(Vehicle* vehicle, QObject* parent = NULL);
enum MissionEndAction {
MissionEndNoAction,
MissionEndLoiter,
MissionEndRTL,
MissionEndLand
};
Q_ENUMS(MissionEndAction)
enum CameraAction {
CameraActionNone,
TakePhotosIntervalTime,
TakePhotoIntervalDistance,
TakeVideo
};
Q_ENUMS(CameraAction)
Q_PROPERTY(bool specifyMissionFlightSpeed READ specifyMissionFlightSpeed WRITE setSpecifyMissionFlightSpeed NOTIFY specifyMissionFlightSpeedChanged)
Q_PROPERTY(Fact* missionFlightSpeed READ missionFlightSpeed CONSTANT)
Q_PROPERTY(bool specifyGimbal READ specifyGimbal WRITE setSpecifyGimbal NOTIFY specifyGimbalChanged)
Q_PROPERTY(Fact* gimbalPitch READ gimbalPitch CONSTANT)
Q_PROPERTY(Fact* gimbalYaw READ gimbalYaw CONSTANT)
Q_PROPERTY(Fact* cameraAction READ cameraAction CONSTANT)
Q_PROPERTY(Fact* cameraPhotoIntervalTime READ cameraPhotoIntervalTime CONSTANT)
Q_PROPERTY(Fact* cameraPhotoIntervalDistance READ cameraPhotoIntervalDistance CONSTANT)
Q_PROPERTY(Fact* missionEndAction READ missionEndAction CONSTANT)
Q_PROPERTY(Fact* plannedHomePositionLatitude READ plannedHomePositionLatitude CONSTANT)
Q_PROPERTY(Fact* plannedHomePositionLongitude READ plannedHomePositionLongitude CONSTANT)
Q_PROPERTY(Fact* plannedHomePositionAltitude READ plannedHomePositionAltitude CONSTANT)
bool specifyMissionFlightSpeed (void) const { return _specifyMissionFlightSpeed; }
bool specifyGimbal (void) const { return _specifyGimbal; }
Fact* plannedHomePositionLatitude (void) { return &_plannedHomePositionLatitudeFact; }
Fact* plannedHomePositionLongitude(void) { return &_plannedHomePositionLongitudeFact; }
Fact* plannedHomePositionAltitude (void) { return &_plannedHomePositionAltitudeFact; }
Fact* missionFlightSpeed (void) { return &_missionFlightSpeedFact; }
Fact* gimbalYaw (void) { return &_gimbalYawFact; }
Fact* gimbalPitch (void) { return &_gimbalPitchFact; }
Fact* cameraAction (void) { return &_cameraActionFact; }
Fact* cameraPhotoIntervalTime (void) { return &_cameraPhotoIntervalTimeFact; }
Fact* cameraPhotoIntervalDistance (void) { return &_cameraPhotoIntervalDistanceFact; }
Fact* missionEndAction (void) { return &_missionEndActionFact; }
void setSpecifyMissionFlightSpeed (bool specifyMissionFlightSpeed);
void setSpecifyGimbal (bool specifyGimbal);
/// Scans the loaded items for the settings items
static void scanForMissionSettings(QmlObjectListModel* visualItems, Vehicle* vehicle);
// Overrides from ComplexMissionItem
double complexDistance (void) const final;
int lastSequenceNumber (void) const final;
QmlObjectListModel* getMissionItems (void) const final;
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final;
double greatestDistanceTo (const QGeoCoordinate &other) const final;
void setCruiseSpeed (double cruiseSpeed) final;
QString mapVisualQML (void) const final { return QStringLiteral("MissionSettingsMapVisual.qml"); }
// Overrides from VisualMissionItem
bool dirty (void) const final { return _dirty; }
bool isSimpleItem (void) const final { return false; }
bool isStandaloneCoordinate (void) const final { return false; }
bool specifiesCoordinate (void) const final;
QString commandDescription (void) const final { return "Mission Settings"; }
QString commandName (void) const final { return "Mission Settings"; }
QString abbreviation (void) const final { return "H"; }
QGeoCoordinate coordinate (void) const final;
QGeoCoordinate exitCoordinate (void) const final { return coordinate(); }
int sequenceNumber (void) const final { return _sequenceNumber; }
double flightSpeed (void) final { return std::numeric_limits<double>::quiet_NaN(); }
bool coordinateHasRelativeAltitude (void) const final { return true; }
bool exitCoordinateHasRelativeAltitude (void) const final { return true; }
bool exitCoordinateSameAsEntry (void) const final { return true; }
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final;
void setSequenceNumber (int sequenceNumber) final;
void save (QJsonArray& missionItems) const final;
static const char* jsonComplexItemTypeValue;
signals:
bool specifyMissionFlightSpeedChanged (bool specifyMissionFlightSpeed);
bool specifyGimbalChanged (bool specifyGimbal);
private slots:
void _setDirtyAndUpdateLastSequenceNumber(void);
void _setDirtyAndUpdateCoordinate(void);
void _setDirty(void);
private:
bool _specifyMissionFlightSpeed;
bool _specifyGimbal;
Fact _plannedHomePositionLatitudeFact;
Fact _plannedHomePositionLongitudeFact;
Fact _plannedHomePositionAltitudeFact;
Fact _missionFlightSpeedFact;
Fact _gimbalYawFact;
Fact _gimbalPitchFact;
Fact _cameraActionFact;
Fact _cameraPhotoIntervalDistanceFact;
Fact _cameraPhotoIntervalTimeFact;
Fact _missionEndActionFact;
int _sequenceNumber;
bool _dirty;
static QMap<QString, FactMetaData*> _metaDataMap;
static const char* _plannedHomePositionLatitudeName;
static const char* _plannedHomePositionLongitudeName;
static const char* _plannedHomePositionAltitudeName;
static const char* _missionFlightSpeedName;
static const char* _gimbalPitchName;
static const char* _gimbalYawName;
static const char* _cameraActionName;
static const char* _cameraPhotoIntervalDistanceName;
static const char* _cameraPhotoIntervalTimeName;
static const char* _missionEndActionName;
};
#endif
...@@ -50,8 +50,6 @@ static const struct EnumInfo_s _rgMavFrameInfo[] = { ...@@ -50,8 +50,6 @@ static const struct EnumInfo_s _rgMavFrameInfo[] = {
SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, QObject* parent) SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, QObject* parent)
: VisualMissionItem(vehicle, parent) : VisualMissionItem(vehicle, parent)
, _rawEdit(false) , _rawEdit(false)
, _homePositionSpecialCase(false)
, _showHomePosition(false)
, _commandTree(qgcApp()->toolbox()->missionCommandTree()) , _commandTree(qgcApp()->toolbox()->missionCommandTree())
, _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32) , _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32)
, _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32) , _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
...@@ -82,8 +80,6 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, const MissionItem& missio ...@@ -82,8 +80,6 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, const MissionItem& missio
, _missionItem(missionItem) , _missionItem(missionItem)
, _rawEdit(false) , _rawEdit(false)
, _dirty(false) , _dirty(false)
, _homePositionSpecialCase(false)
, _showHomePosition(false)
, _commandTree(qgcApp()->toolbox()->missionCommandTree()) , _commandTree(qgcApp()->toolbox()->missionCommandTree())
, _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32) , _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32)
, _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32) , _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
...@@ -112,8 +108,6 @@ SimpleMissionItem::SimpleMissionItem(const SimpleMissionItem& other, QObject* pa ...@@ -112,8 +108,6 @@ SimpleMissionItem::SimpleMissionItem(const SimpleMissionItem& other, QObject* pa
, _missionItem(other._vehicle) , _missionItem(other._vehicle)
, _rawEdit(false) , _rawEdit(false)
, _dirty(false) , _dirty(false)
, _homePositionSpecialCase(false)
, _showHomePosition(false)
, _commandTree(qgcApp()->toolbox()->missionCommandTree()) , _commandTree(qgcApp()->toolbox()->missionCommandTree())
, _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32) , _altitudeRelativeToHomeFact (0, "Altitude is relative to home", FactMetaData::valueTypeUint32)
, _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32) , _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
...@@ -246,9 +240,11 @@ SimpleMissionItem::~SimpleMissionItem() ...@@ -246,9 +240,11 @@ SimpleMissionItem::~SimpleMissionItem()
{ {
} }
void SimpleMissionItem::save(QJsonObject& saveObject) const void SimpleMissionItem::save(QJsonArray& missionItems) const
{ {
_missionItem.save(saveObject); QJsonObject itemObject;
_missionItem.save(itemObject);
missionItems.append(itemObject);
} }
bool SimpleMissionItem::load(QTextStream &loadStream) bool SimpleMissionItem::load(QTextStream &loadStream)
...@@ -584,14 +580,6 @@ QString SimpleMissionItem::category(void) const ...@@ -584,14 +580,6 @@ QString SimpleMissionItem::category(void) const
return _commandTree->getUIInfo(_vehicle, (MAV_CMD)command())->category(); return _commandTree->getUIInfo(_vehicle, (MAV_CMD)command())->category();
} }
void SimpleMissionItem::setShowHomePosition(bool showHomePosition)
{
if (showHomePosition != _showHomePosition) {
_showHomePosition = showHomePosition;
emit showHomePositionChanged(_showHomePosition);
}
}
void SimpleMissionItem::setCommand(MavlinkQmlSingleton::Qml_MAV_CMD command) void SimpleMissionItem::setCommand(MavlinkQmlSingleton::Qml_MAV_CMD command)
{ {
if ((MAV_CMD)command != _missionItem.command()) { if ((MAV_CMD)command != _missionItem.command()) {
......
...@@ -32,10 +32,8 @@ public: ...@@ -32,10 +32,8 @@ public:
Q_PROPERTY(QString category READ category NOTIFY commandChanged) Q_PROPERTY(QString category READ category NOTIFY commandChanged)
Q_PROPERTY(MavlinkQmlSingleton::Qml_MAV_CMD command READ command WRITE setCommand NOTIFY commandChanged) Q_PROPERTY(MavlinkQmlSingleton::Qml_MAV_CMD command READ command WRITE setCommand NOTIFY commandChanged)
Q_PROPERTY(bool friendlyEditAllowed READ friendlyEditAllowed NOTIFY friendlyEditAllowedChanged) Q_PROPERTY(bool friendlyEditAllowed READ friendlyEditAllowed NOTIFY friendlyEditAllowedChanged)
Q_PROPERTY(bool homePosition READ homePosition CONSTANT) ///< true: This item is being used as a home position indicator
Q_PROPERTY(bool rawEdit READ rawEdit WRITE setRawEdit NOTIFY rawEditChanged) ///< true: raw item editing with all params Q_PROPERTY(bool rawEdit READ rawEdit WRITE setRawEdit NOTIFY rawEditChanged) ///< true: raw item editing with all params
Q_PROPERTY(bool relativeAltitude READ relativeAltitude NOTIFY frameChanged) Q_PROPERTY(bool relativeAltitude READ relativeAltitude NOTIFY frameChanged)
Q_PROPERTY(bool showHomePosition READ showHomePosition WRITE setShowHomePosition NOTIFY showHomePositionChanged)
// These properties are used to display the editing ui // These properties are used to display the editing ui
Q_PROPERTY(QmlObjectListModel* checkboxFacts READ checkboxFacts NOTIFY uiModelChanged) Q_PROPERTY(QmlObjectListModel* checkboxFacts READ checkboxFacts NOTIFY uiModelChanged)
...@@ -47,9 +45,7 @@ public: ...@@ -47,9 +45,7 @@ public:
QString category (void) const; QString category (void) const;
MavlinkQmlSingleton::Qml_MAV_CMD command(void) const { return (MavlinkQmlSingleton::Qml_MAV_CMD)_missionItem._commandFact.cookedValue().toInt(); } MavlinkQmlSingleton::Qml_MAV_CMD command(void) const { return (MavlinkQmlSingleton::Qml_MAV_CMD)_missionItem._commandFact.cookedValue().toInt(); }
bool friendlyEditAllowed (void) const; bool friendlyEditAllowed (void) const;
bool homePosition (void) const { return _homePositionSpecialCase; }
bool rawEdit (void) const; bool rawEdit (void) const;
bool showHomePosition (void) const { return _showHomePosition; }
QmlObjectListModel* textFieldFacts (void); QmlObjectListModel* textFieldFacts (void);
...@@ -62,9 +58,6 @@ public: ...@@ -62,9 +58,6 @@ public:
void setCommand(MavlinkQmlSingleton::Qml_MAV_CMD command); void setCommand(MavlinkQmlSingleton::Qml_MAV_CMD command);
void setHomePositionSpecialCase(bool homePositionSpecialCase) { _homePositionSpecialCase = homePositionSpecialCase; }
void setShowHomePosition(bool showHomePosition);
void setAltDifference (double altDifference); void setAltDifference (double altDifference);
void setAltPercent (double altPercent); void setAltPercent (double altPercent);
void setAzimuth (double azimuth); void setAzimuth (double azimuth);
...@@ -99,7 +92,7 @@ public: ...@@ -99,7 +92,7 @@ public:
void setDirty (bool dirty) final; void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final; void setCoordinate (const QGeoCoordinate& coordinate) final;
void setSequenceNumber (int sequenceNumber) final; void setSequenceNumber (int sequenceNumber) final;
void save (QJsonObject& saveObject) const final; void save (QJsonArray& missionItems) const final;
public slots: public slots:
void setDefaultsForCommand(void); void setDefaultsForCommand(void);
...@@ -111,7 +104,6 @@ signals: ...@@ -111,7 +104,6 @@ signals:
void headingDegreesChanged (double heading); void headingDegreesChanged (double heading);
void rawEditChanged (bool rawEdit); void rawEditChanged (bool rawEdit);
void uiModelChanged (void); void uiModelChanged (void);
void showHomePositionChanged (bool showHomePosition);
private slots: private slots:
void _setDirtyFromSignal(void); void _setDirtyFromSignal(void);
...@@ -132,8 +124,6 @@ private: ...@@ -132,8 +124,6 @@ private:
MissionItem _missionItem; MissionItem _missionItem;
bool _rawEdit; bool _rawEdit;
bool _dirty; bool _dirty;
bool _homePositionSpecialCase; ///< true: This item is being used as a ui home position indicator
bool _showHomePosition;
MissionCommandTree* _commandTree; MissionCommandTree* _commandTree;
......
...@@ -293,8 +293,10 @@ void SurveyMissionItem::setDirty(bool dirty) ...@@ -293,8 +293,10 @@ void SurveyMissionItem::setDirty(bool dirty)
} }
} }
void SurveyMissionItem::save(QJsonObject& saveObject) const void SurveyMissionItem::save(QJsonArray& missionItems) const
{ {
QJsonObject saveObject;
saveObject[JsonHelper::jsonVersionKey] = 3; saveObject[JsonHelper::jsonVersionKey] = 3;
saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue;
saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue;
...@@ -344,6 +346,8 @@ void SurveyMissionItem::save(QJsonObject& saveObject) const ...@@ -344,6 +346,8 @@ void SurveyMissionItem::save(QJsonObject& saveObject) const
} }
saveObject[_jsonPolygonObjectKey] = polygonArray; saveObject[_jsonPolygonObjectKey] = polygonArray;
missionItems.append(saveObject);
} }
void SurveyMissionItem::setSequenceNumber(int sequenceNumber) void SurveyMissionItem::setSequenceNumber(int sequenceNumber)
......
...@@ -127,7 +127,7 @@ public: ...@@ -127,7 +127,7 @@ public:
void setCoordinate (const QGeoCoordinate& coordinate) final; void setCoordinate (const QGeoCoordinate& coordinate) final;
void setSequenceNumber (int sequenceNumber) final; void setSequenceNumber (int sequenceNumber) final;
void setTurnaroundDist (double dist) { _turnaroundDistFact.setRawValue(dist); } void setTurnaroundDist (double dist) { _turnaroundDistFact.setRawValue(dist); }
void save (QJsonObject& saveObject) const final; void save (QJsonArray& missionItems) const final;
static const char* jsonComplexItemTypeValue; static const char* jsonComplexItemTypeValue;
......
...@@ -25,6 +25,8 @@ VisualMissionItem::VisualMissionItem(Vehicle* vehicle, QObject* parent) ...@@ -25,6 +25,8 @@ VisualMissionItem::VisualMissionItem(Vehicle* vehicle, QObject* parent)
, _vehicle(vehicle) , _vehicle(vehicle)
, _isCurrentItem(false) , _isCurrentItem(false)
, _dirty(false) , _dirty(false)
, _homePositionSpecialCase(false)
, _showHomePosition(false)
, _altDifference(0.0) , _altDifference(0.0)
, _altPercent(0.0) , _altPercent(0.0)
, _azimuth(0.0) , _azimuth(0.0)
...@@ -38,6 +40,8 @@ VisualMissionItem::VisualMissionItem(const VisualMissionItem& other, QObject* pa ...@@ -38,6 +40,8 @@ VisualMissionItem::VisualMissionItem(const VisualMissionItem& other, QObject* pa
, _vehicle(NULL) , _vehicle(NULL)
, _isCurrentItem(false) , _isCurrentItem(false)
, _dirty(false) , _dirty(false)
, _homePositionSpecialCase(false)
, _showHomePosition(false)
, _altDifference(0.0) , _altDifference(0.0)
, _altPercent(0.0) , _altPercent(0.0)
, _azimuth(0.0) , _azimuth(0.0)
...@@ -52,6 +56,8 @@ const VisualMissionItem& VisualMissionItem::operator=(const VisualMissionItem& o ...@@ -52,6 +56,8 @@ const VisualMissionItem& VisualMissionItem::operator=(const VisualMissionItem& o
setIsCurrentItem(other._isCurrentItem); setIsCurrentItem(other._isCurrentItem);
setDirty(other._dirty); setDirty(other._dirty);
_homePositionSpecialCase = other._homePositionSpecialCase;
setShowHomePosition(other.showHomePosition());
setAltDifference(other._altDifference); setAltDifference(other._altDifference);
setAltPercent(other._altPercent); setAltPercent(other._altPercent);
setAzimuth(other._azimuth); setAzimuth(other._azimuth);
...@@ -103,3 +109,11 @@ void VisualMissionItem::setAzimuth(double azimuth) ...@@ -103,3 +109,11 @@ void VisualMissionItem::setAzimuth(double azimuth)
emit azimuthChanged(_azimuth); emit azimuthChanged(_azimuth);
} }
} }
void VisualMissionItem::setShowHomePosition(bool showHomePosition)
{
if (showHomePosition != _showHomePosition) {
_showHomePosition = showHomePosition;
emit showHomePositionChanged(_showHomePosition);
}
}
...@@ -40,6 +40,9 @@ public: ...@@ -40,6 +40,9 @@ public:
const VisualMissionItem& operator=(const VisualMissionItem& other); const VisualMissionItem& operator=(const VisualMissionItem& other);
Q_PROPERTY(bool homePosition READ homePosition CONSTANT) ///< true: This item is being used as a home position indicator
Q_PROPERTY(bool showHomePosition READ showHomePosition WRITE setShowHomePosition NOTIFY showHomePositionChanged)
// The following properties are calculated/set by the MissionController recalc methods // The following properties are calculated/set by the MissionController recalc methods
Q_PROPERTY(double altDifference READ altDifference WRITE setAltDifference NOTIFY altDifferenceChanged) ///< Change in altitude from previous waypoint Q_PROPERTY(double altDifference READ altDifference WRITE setAltDifference NOTIFY altDifferenceChanged) ///< Change in altitude from previous waypoint
...@@ -87,6 +90,11 @@ public: ...@@ -87,6 +90,11 @@ public:
// Property accesors // Property accesors
bool homePosition (void) const { return _homePositionSpecialCase; }
bool showHomePosition (void) const { return _showHomePosition; }
void setHomePositionSpecialCase (bool homePositionSpecialCase) { _homePositionSpecialCase = homePositionSpecialCase; }
void setShowHomePosition (bool showHomePosition);
double altDifference (void) const { return _altDifference; } double altDifference (void) const { return _altDifference; }
double altPercent (void) const { return _altPercent; } double altPercent (void) const { return _altPercent; }
double azimuth (void) const { return _azimuth; } double azimuth (void) const { return _azimuth; }
...@@ -126,8 +134,8 @@ public: ...@@ -126,8 +134,8 @@ public:
virtual void setSequenceNumber (int sequenceNumber) = 0; virtual void setSequenceNumber (int sequenceNumber) = 0;
/// Save the item(s) in Json format /// Save the item(s) in Json format
/// @param saveObject Save the item to this json object /// @param missionItems Current set of mission items, new items should be appended to the end
virtual void save(QJsonObject& saveObject) const = 0; virtual void save(QJsonArray& missionItems) const = 0;
/// @return The QML resource file which contains the control which visualizes the item on the map. /// @return The QML resource file which contains the control which visualizes the item on the map.
virtual QString mapVisualQML(void) const = 0; virtual QString mapVisualQML(void) const = 0;
...@@ -137,6 +145,7 @@ public: ...@@ -137,6 +145,7 @@ public:
static const char* jsonTypeComplexItemValue; ///< Item type is Complex Item static const char* jsonTypeComplexItemValue; ///< Item type is Complex Item
signals: signals:
void showHomePositionChanged (bool showHomePosition);
void altDifferenceChanged (double altDifference); void altDifferenceChanged (double altDifference);
void altPercentChanged (double altPercent); void altPercentChanged (double altPercent);
void azimuthChanged (double azimuth); void azimuthChanged (double azimuth);
...@@ -162,6 +171,8 @@ protected: ...@@ -162,6 +171,8 @@ protected:
Vehicle* _vehicle; Vehicle* _vehicle;
bool _isCurrentItem; bool _isCurrentItem;
bool _dirty; bool _dirty;
bool _homePositionSpecialCase; ///< true: This item is being used as a ui home position indicator
bool _showHomePosition;
double _altDifference; ///< Difference in altitude from previous waypoint double _altDifference; ///< Difference in altitude from previous waypoint
double _altPercent; ///< Percent of total altitude change in mission double _altPercent; ///< Percent of total altitude change in mission
double _azimuth; ///< Azimuth to previous waypoint double _azimuth; ///< Azimuth to previous waypoint
......
...@@ -1661,10 +1661,9 @@ void Vehicle::_startMissionRequest(void) ...@@ -1661,10 +1661,9 @@ void Vehicle::_startMissionRequest(void)
_missionManager->requestMissionItems(); _missionManager->requestMissionItems();
} else { } else {
QmlObjectListModel* visualItems = NULL; QmlObjectListModel* visualItems = NULL;
QmlObjectListModel* complexItems = NULL;
QDir missionAutoLoadDir(missionAutoLoadDirPath); QDir missionAutoLoadDir(missionAutoLoadDirPath);
QString autoloadFilename = missionAutoLoadDir.absoluteFilePath(tr("AutoLoad%1.mission").arg(_id)); QString autoloadFilename = missionAutoLoadDir.absoluteFilePath(tr("AutoLoad%1.mission").arg(_id));
if (MissionController::loadItemsFromFile(this, autoloadFilename, &visualItems, &complexItems)) { if (MissionController::loadItemsFromFile(this, autoloadFilename, &visualItems)) {
MissionController::sendItemsToVehicle(this, visualItems); MissionController::sendItemsToVehicle(this, visualItems);
} }
} }
......
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