diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index 788b6aa60edae6cb15ff5961c453cb32fcdc7f18..86f057428863dbe6e4dfbc9ee1329942174a1278 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -70,6 +70,7 @@
src/FlightMap/Images/Help.svg
src/FlightMap/Images/MapCenter.svg
src/FlightMap/Images/MapSync.svg
+ src/FlightMap/Images/MapSyncChanged.svg
src/FlightMap/Images/MapType.svg
src/FlightMap/Images/MapHome.svg
src/FlightMap/Images/MapAddMission.svg
diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml
index 2731316e8f6198188cfdea4254736288339a4ae5..6565ef69804e94e42ae86cb8fc1e65d7dd9185e2 100644
--- a/src/FlightDisplay/FlightDisplayView.qml
+++ b/src/FlightDisplay/FlightDisplayView.qml
@@ -55,15 +55,14 @@ Item {
property var _activeVehicle: multiVehicleManager.activeVehicle
- readonly property real _defaultLatitude: 37.803784
- readonly property real _defaultLongitude: -122.462276
- readonly property real _defaultRoll: 0
- readonly property real _defaultPitch: 0
- readonly property real _defaultHeading: 0
- readonly property real _defaultAltitudeWGS84: 0
- readonly property real _defaultGroundSpeed: 0
- readonly property real _defaultAirSpeed: 0
- readonly property real _defaultClimbRate: 0
+ readonly property var _defaultVehicleCoordinate: QtPositioning.coordinate(37.803784, -122.462276)
+ readonly property real _defaultRoll: 0
+ readonly property real _defaultPitch: 0
+ readonly property real _defaultHeading: 0
+ readonly property real _defaultAltitudeWGS84: 0
+ readonly property real _defaultGroundSpeed: 0
+ readonly property real _defaultAirSpeed: 0
+ readonly property real _defaultClimbRate: 0
readonly property string _mapName: "FlightDisplayView"
readonly property string _showMapBackgroundKey: "/showMapBackground"
@@ -72,8 +71,7 @@ Item {
property real _pitch: _activeVehicle ? (isNaN(_activeVehicle.pitch) ? _defaultPitch : _activeVehicle.pitch) : _defaultPitch
property real _heading: _activeVehicle ? (isNaN(_activeVehicle.heading) ? _defaultHeading : _activeVehicle.heading) : _defaultHeading
- property real _latitude: _activeVehicle ? ((_activeVehicle.latitude === 0) ? _defaultLatitude : _activeVehicle.latitude) : _defaultLatitude
- property real _longitude: _activeVehicle ? ((_activeVehicle.longitude === 0) ? _defaultLongitude : _activeVehicle.longitude) : _defaultLongitude
+ property var _vehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : _defaultVehicleCoordinate
property real _altitudeWGS84: _activeVehicle ? _activeVehicle.altitudeWGS84 : _defaultAltitudeWGS84
property real _groundSpeed: _activeVehicle ? _activeVehicle.groundSpeed : _defaultGroundSpeed
@@ -82,14 +80,20 @@ Item {
property bool _showMap: getBool(QGroundControl.flightMapSettings.loadMapSetting(flightMap.mapName, _showMapBackgroundKey, "1"))
- FlightDisplayViewController { id: _controller; }
+ FlightDisplayViewController { id: _controller }
ExclusiveGroup {
id: _dropButtonsExclusiveGroup
}
// Validate _showMap setting
- Component.onCompleted: _setShowMap(_showMap)
+ Component.onCompleted: {
+ // We have to be careful to not reference root properties in a function which is in a subcomponent
+ // until the root component has completed loading. Otherwise you get undefined references.
+ flightMap.rootLoadCompleted = true
+ flightMap.updateMapPosition(true /* force */)
+ _setShowMap(_showMap)
+ }
function getBool(value) {
return value === '0' ? false : true;
@@ -104,24 +108,24 @@ Item {
QGroundControl.flightMapSettings.saveMapSetting(flightMap.mapName, _showMapBackgroundKey, setBool(_showMap))
}
+
FlightMap {
id: flightMap
anchors.fill: parent
mapName: _mapName
visible: _showMap
+ latitude: root._defaultCoordinate.latitude
+ longitude: root._defaultCoordinate.longitude
- property real rootLatitude: root._latitude
- property real rootLongitude: root._longitude
-
- Component.onCompleted: updateMapPosition(true /* force */)
+ property var rootVehicleCoordinate: _vehicleCoordinate
+ property bool rootLoadCompleted: false
- onRootLatitudeChanged: updateMapPosition(false /* force */)
- onRootLongitudeChanged: updateMapPosition(false /* force */)
+ onRootVehicleCoordinateChanged: updateMapPosition(false /* force */)
function updateMapPosition(force) {
- if (_followVehicle || force) {
- latitude = root._latitude
- longitude = root._longitude
+ if ((_followVehicle || force) && rootLoadCompleted) {
+ flightMap.latitude = root._vehicleCoordinate.latitude
+ flightMap.longitude = root._vehicleCoordinate.longitude
}
}
diff --git a/src/FlightMap/FlightMap.qml b/src/FlightMap/FlightMap.qml
index 3f1d1c028d756b1342cc680987c76ede5433452f..fa696a392fd9873e7969f4dd1186b089dbbac9c3 100644
--- a/src/FlightMap/FlightMap.qml
+++ b/src/FlightMap/FlightMap.qml
@@ -59,10 +59,13 @@ Map {
readonly property real zOrderWidgets: 100 ///< z order value to widgets, for example: zoom controls, hud widgetss
readonly property real zOrderMapItems: 50 ///< z order value for map items, for example: mission item indicators
- zoomLevel: 18
- center: QtPositioning.coordinate(lat, lon)
- gesture.flickDeceleration: 3000
- gesture.enabled: interactive
+ readonly property real maxZoomLevel: 20
+
+ zoomLevel: 18
+ center: QtPositioning.coordinate(lat, lon)
+ gesture.flickDeceleration: 3000
+ gesture.enabled: interactive
+ gesture.activeGestures: MapGestureArea.ZoomGesture | MapGestureArea.PanGesture | MapGestureArea.FlickGesture
plugin: Plugin { name: "QGroundControl" }
@@ -295,11 +298,4 @@ Map {
}
}
*/
-
- MouseArea {
- //-- TODO: Check if this is still needed when we switch to 5.5.1
- //-- Workaround for QTBUG-46388 (Pinch zoom doesn't work without it on mobile)
- anchors.fill: parent
- }
-
} // Map
diff --git a/src/MissionEditor/MissionEditor.qml b/src/MissionEditor/MissionEditor.qml
index 5107ef5ace2114a8951814ee379b239016db09e5..4002f7af3b9f260a12b8f614d86f7ee17e29245a 100644
--- a/src/MissionEditor/MissionEditor.qml
+++ b/src/MissionEditor/MissionEditor.qml
@@ -45,9 +45,13 @@ QGCView {
readonly property int _decimalPlaces: 7
readonly property real _horizontalMargin: ScreenTools.defaultFontPixelWidth / 2
- readonly property real _verticalMargin: ScreenTools.defaultFontPixelHeight / 2
+ readonly property real _margin: ScreenTools.defaultFontPixelHeight / 2
readonly property var _activeVehicle: multiVehicleManager.activeVehicle
readonly property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 16
+ readonly property real _rightPanelWidth: ScreenTools.defaultFontPixelWidth * 30
+ readonly property real _rightPanelOpacity: 0.8
+ readonly property int _toolButtonCount: 6
+ readonly property int _addMissionItemsButtonAutoOffTimeout: 10000
property var _missionItems: _controller.missionItems
@@ -59,9 +63,11 @@ QGCView {
property var liveHomePositionAvailable: _controller.liveHomePositionAvailable
property var homePosition: offlineHomePosition // live or offline depending on state
+ property bool _syncNeeded: _controller.missionItems.dirty
+
MissionEditorController { id: _controller }
- QGCPalette { id: _qgcPal; colorGroupEnabled: enabled }
+ QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
ExclusiveGroup {
id: _mapTypeButtonsExclusiveGroup
@@ -69,7 +75,6 @@ QGCView {
ExclusiveGroup {
id: _dropButtonsExclusiveGroup
- onCurrentChanged: console.log("Current button", current)
}
function setCurrentItem(index) {
@@ -107,10 +112,7 @@ QGCView {
FlightMap {
id: editorMap
- anchors.left: parent.left
- anchors.right: missionItemView.left
- anchors.top: parent.top
- anchors.bottom: parent.bottom
+ anchors.fill: parent
mapName: "MissionEditor"
Component.onCompleted: {
@@ -118,6 +120,29 @@ QGCView {
longitude = homePosition.longitude
}
+ readonly property real animationDuration: 500
+
+ Behavior on zoomLevel {
+ NumberAnimation {
+ duration: editorMap.animationDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ Behavior on latitude {
+ NumberAnimation {
+ duration: editorMap.animationDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ Behavior on longitude {
+ NumberAnimation {
+ duration: editorMap.animationDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
+
MouseArea {
anchors.fill: parent
@@ -130,245 +155,95 @@ QGCView {
offlineHomePosition = coordinate
} else if (addMissionItemsButton.checked) {
var index = _controller.addMissionItem(coordinate)
+ addMissionItemsButtonAutoOffTimer.start()
setCurrentItem(index)
+ } else {
+ editorMap.zoomLevel = editorMap.maxZoomLevel - 2
}
}
}
- Rectangle {
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- width: parent.width * 0.75
- height: syncNeededText.height + (ScreenTools.defaultFontPixelWidth * 2)
- border.width: 1
- border.color: "white"
- color: "black"
- opacity: 0.75
- visible: _controller.missionItems.dirty
-
- QGCLabel {
- id: syncNeededText
- anchors.margins: ScreenTools.defaultFontPixelWidth
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- wrapMode: Text.WordWrap
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- font.pixelSize: ScreenTools.mediumFontPixelSize
- text: "You have unsaved changes. Be sure to use the Sync tool to save when ready."
- }
- }
-
- RoundButton {
- id: addMissionItemsButton
- anchors.rightMargin: ScreenTools.defaultFontPixelWidth
- anchors.right: homePositionManagerButton.left
- anchors.top: helpButton.top
- buttonImage: "/qmlimages/MapAddMission.svg"
- exclusiveGroup: _dropButtonsExclusiveGroup
- }
-
- RoundButton {
- id: homePositionManagerButton
- anchors.rightMargin: ScreenTools.defaultFontPixelWidth
- anchors.right: centerMapButton.left
- anchors.top: helpButton.top
- buttonImage: "/qmlimages/MapHome.svg"
- exclusiveGroup: _dropButtonsExclusiveGroup
- }
-
- DropButton {
- id: centerMapButton
- anchors.rightMargin: ScreenTools.defaultFontPixelWidth
- anchors.right: syncButton.left
- anchors.top: helpButton.top
- dropDirection: dropDown
- buttonImage: "/qmlimages/MapCenter.svg"
- viewportMargins: ScreenTools.defaultFontPixelWidth / 2
- exclusiveGroup: _dropButtonsExclusiveGroup
-
- dropDownComponent: Component {
- Row {
- spacing: ScreenTools.defaultFontPixelWidth
-
- QGCButton {
- text: "Home"
-
- onClicked: {
- centerMapButton.hideDropDown()
- editorMap.center = QtPositioning.coordinate(homePosition.latitude, homePosition.longitude)
- }
- }
-
- QGCButton {
- text: "Vehicle"
- enabled: activeVehicle && activeVehicle.latitude != 0 && activeVehicle.longitude != 0
-
- property var activeVehicle: multiVehicleManager.activeVehicle
-
- onClicked: {
- centerMapButton.hideDropDown()
- editorMap.latitude = activeVehicle.latitude
- editorMap.longitude = activeVehicle.longitude
- }
- }
-
- /*
-
- This code will need to wait for Qml 5.5 support since Map.visibleRegion is only in Qt 5.5
-
- QGCButton {
- text: "All Items"
-
- onClicked: {
- centerMapButton.hideDropDown()
-
- // Begin with only the home position in the region
- var region = QtPositioning.rectangle(QtPositioning.coordinate(homePosition.latitude, homePosition.longitude),
- QtPositioning.coordinate(homePosition.latitude, homePosition.longitude))
-
- // Now expand the region to include all mission items
- for (var i=0; i<_missionItems.count; i++) {
- var missionItem = _missionItems.get(i)
-
- region.topLeft.latitude = Math.max(missionItem.coordinate.latitude, region.topLeft.latitude)
- region.topLeft.longitude = Math.min(missionItem.coordinate.longitude, region.topLeft.longitude)
-
- region.topRight.latitude = Math.max(missionItem.coordinate.latitude, region.topRight.latitude)
- region.topRight.longitude = Math.max(missionItem.coordinate.longitude, region.topRight.longitude)
-
- region.bottomLeft.latitude = Math.min(missionItem.coordinate.latitude, region.bottomLeft.latitude)
- region.bottomLeft.longitude = Math.min(missionItem.coordinate.longitude, region.bottomLeft.longitude)
-
- region.bottomRight.latitude = Math.min(missionItem.coordinate.latitude, region.bottomRight.latitude)
- region.bottomRight.longitude = Math.max(missionItem.coordinate.longitude, region.bottomRight.longitude)
- }
-
- editorMap.visibleRegion = region
- }
- }
- */
- }
- }
- }
-
- DropButton {
- id: syncButton
- anchors.rightMargin: ScreenTools.defaultFontPixelWidth
- anchors.right: mapTypeButton.left
- anchors.top: helpButton.top
- dropDirection: dropDown
- buttonImage: "/qmlimages/MapSync.svg"
- viewportMargins: ScreenTools.defaultFontPixelWidth / 2
- exclusiveGroup: _dropButtonsExclusiveGroup
-
- dropDownComponent: Component {
- Row {
- spacing: ScreenTools.defaultFontPixelWidth
-
- QGCButton {
- text: "Load from vehicle"
- enabled: _activeVehicle && !_activeVehicle.missionManager.inProgress
-
- onClicked: {
- syncButton.hideDropDown()
- _controller.getMissionItems()
- }
- }
-
- QGCButton {
- text: "Save to vehicle"
- enabled: _activeVehicle && !_activeVehicle.missionManager.inProgress
-
- onClicked: {
- syncButton.hideDropDown()
- _controller.setMissionItems()
- }
- }
-
- QGCButton {
- text: "Load from file..."
-
- onClicked: {
- syncButton.hideDropDown()
- _controller.loadMissionFromFile()
- }
- }
-
- QGCButton {
- text: "Save to file..."
-
- onClicked: {
- syncButton.hideDropDown()
- _controller.saveMissionToFile()
- }
- }
- }
+ // We use this item to support dragging since dragging a MapQuickItem just doesn't seem to work
+ Item {
+ id: itemEditor
+ x: missionItemIndicator ? (missionItemIndicator.x + missionItemIndicator.anchorPoint.x - (itemEditor.width / 2)) : 100
+ y: missionItemIndicator ? (missionItemIndicator.y + missionItemIndicator.anchorPoint.y - (itemEditor.height / 2)) : 100
+ width: ScreenTools.defaultFontPixelHeight * 7
+ height: ScreenTools.defaultFontPixelHeight * 7
+ visible: false
+ z: editorMap.zOrderMapItems + 1 // Above item icons
+
+ property var missionItem
+ property var missionItemIndicator
+ property real heading: missionItem ? missionItem.heading : 0
+
+ Drag.active: itemDrag.drag.active
+ Drag.hotSpot.x: width / 2
+ Drag.hotSpot.y: height / 2
+
+ MissionItemIndexLabel {
+ x: (itemEditor.width / 2) - (width / 2)
+ y: (itemEditor.height / 2) - (height / 2)
+ label: itemEditor.missionItemIndicator ? itemEditor.missionItemIndicator.label : ""
+ isCurrentItem: true
}
- }
-
- DropButton {
- id: mapTypeButton
- anchors.rightMargin: ScreenTools.defaultFontPixelWidth
- anchors.right: helpButton.left
- anchors.top: helpButton.top
- dropDirection: dropDown
- buttonImage: "/qmlimages/MapType.svg"
- viewportMargins: ScreenTools.defaultFontPixelWidth / 2
- exclusiveGroup: _dropButtonsExclusiveGroup
- dropDownComponent: Component {
- Row {
- spacing: ScreenTools.defaultFontPixelWidth
+ MouseArea {
+ id: itemDrag
+ anchors.fill: parent
+ drag.target: parent
- Repeater {
- model: QGroundControl.flightMapSettings.mapTypes
+ property bool dragActive: drag.active
- QGCButton {
- checkable: true
- checked: editorMap.mapType == text
- text: modelData
- exclusiveGroup: _mapTypeButtonsExclusiveGroup
-
- onClicked: {
- editorMap.mapType = text
- checked = true
- mapTypeButton.hideDropDown()
- }
- }
+ onDragActiveChanged: {
+ if (!drag.active) {
+ var point = Qt.point(itemEditor.x + (itemEditor.width / 2), itemEditor.y + (itemEditor.height / 2))
+ itemEditor.missionItem.coordinate = editorMap.toCoordinate(point)
}
}
}
}
- RoundButton {
- id: helpButton
- anchors.margins: ScreenTools.defaultFontPixelWidth
- anchors.right: parent.right
- anchors.top: parent.top
- buttonImage: "/qmlimages/Help.svg"
- exclusiveGroup: _dropButtonsExclusiveGroup
- }
-
// Add the mission items to the map
MapItemView {
model: _controller.missionItems
-
+
delegate:
MissionItemIndicator {
id: itemIndicator
label: object.sequenceNumber == 0 ? (liveHomePositionAvailable ? "H" : "F") : object.sequenceNumber
isCurrentItem: !homePositionManagerButton.checked && object.isCurrentItem
coordinate: object.coordinate
- z: 2
+ z: editorMap.zOrderMapItems
visible: object.specifiesCoordinate
- onClicked: {
- setCurrentItem(object.sequenceNumber)
- missionItemEditorButton.checked
+ onClicked: setCurrentItem(object.sequenceNumber)
+
+ Connections {
+ target: object
+
+ onIsCurrentItemChanged: {
+ if (isCurrentItem) {
+ // Setup our drag item
+ if (object.sequenceNumber != 0) {
+ itemEditor.visible = true
+ itemEditor.missionItem = Qt.binding(function() { return object })
+ itemEditor.missionItemIndicator = Qt.binding(function() { return itemIndicator })
+ } else {
+ itemEditor.visible = false
+ itemEditor.missionItem = undefined
+ itemEditor.missionItemIndicator = undefined
+ }
+
+ // Zoom the map and move to the new position
+ editorMap.zoomLevel = editorMap.maxZoomLevel
+ editorMap.latitude = object.coordinate.latitude
+ editorMap.longitude = object.coordinate.longitude
+ }
+ }
}
+ // These are the non-coordinate child mission items attached to this item
Row {
anchors.top: parent.top
anchors.left: parent.right
@@ -400,8 +275,8 @@ QGCView {
delegate:
MapPolyline {
line.width: 3
- line.color: _qgcPal.mapButtonHighlight
- z: 1
+ line.color: qgcPal.mapButtonHighlight
+ z: editorMap.zOrderMapItems - 1 // Under item indicators
path: [
{ latitude: object.coordinate1.latitude, longitude: object.coordinate1.longitude },
@@ -410,346 +285,341 @@ QGCView {
}
}
- Column {
- id: controlWidgets
- anchors.margins: ScreenTools.defaultFontPixelWidth
- anchors.right: parent.left
- anchors.bottom: parent.top
- spacing: ScreenTools.defaultFontPixelWidth / 2
-
- QGCButton {
- id: addMode
- text: "+"
- checkable: true
- }
- }
- } // FlightMap
-
- Rectangle {
- id: missionItemView
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- width: ScreenTools.defaultFontPixelWidth * 30
- color: _qgcPal.window
-
+ // Mission Item Editor
Item {
- anchors.margins: _verticalMargin
- anchors.fill: parent
-
- // Mission Item Editor
- Item {
- id: missionItemEditor
+ id: missionItemEditor
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ width: _rightPanelWidth
+ visible: !helpButton.checked && !homePositionManagerButton.checked && _missionItems.count > 1
+ opacity: _rightPanelOpacity
+ z: editorMap.zOrderTopMost
+
+ ListView {
+ id: missionItemSummaryList
anchors.fill: parent
- visible: !helpButton.checked && !homePositionManagerButton.checked && _missionItems.count > 1
-
- ListView {
- id: missionItemSummaryList
- anchors.fill: parent
- spacing: _verticalMargin
- orientation: ListView.Vertical
- model: _controller.canEdit ? _controller.missionItems : 0
-
- property real _maxItemHeight: 0
-
- delegate:
- MissionItemEditor {
- missionItem: object
- width: parent.width
- readOnly: object.sequenceNumber == 0 && liveHomePositionAvailable
-
- onClicked: setCurrentItem(object.sequenceNumber)
-
- onRemove: {
- var newCurrentItem = object.sequenceNumber - 1
- _controller.removeMissionItem(object.sequenceNumber)
- if (_missionItems.count > 1) {
- newCurrentItem = Math.min(_missionItems.count - 1, newCurrentItem)
- setCurrentItem(newCurrentItem)
- }
- }
+ spacing: _margin / 2
+ orientation: ListView.Vertical
+ model: _controller.canEdit ? _controller.missionItems : 0
+
+ property real _maxItemHeight: 0
+
+ delegate:
+ MissionItemEditor {
+ missionItem: object
+ width: parent.width
+ readOnly: object.sequenceNumber == 0 && liveHomePositionAvailable
+
+ onClicked: setCurrentItem(object.sequenceNumber)
+
+ onRemove: {
+ var newCurrentItem = object.sequenceNumber - 1
+ _controller.removeMissionItem(object.sequenceNumber)
+ if (_missionItems.count > 1) {
+ newCurrentItem = Math.min(_missionItems.count - 1, newCurrentItem)
+ setCurrentItem(newCurrentItem)
}
- } // ListView
-
- QGCLabel {
- anchors.fill: parent
- visible: !_controller.canEdit
- wrapMode: Text.WordWrap
- text: "The set of mission items you have loaded cannot be edited by QGroundControl. " +
- "You will only be able to save these to a file, or send them to a vehicle."
+ }
}
- } // Item - Mission Item editor
+ } // ListView
- // Home Position Manager
- Item {
- id: homePositionManager
+ QGCLabel {
anchors.fill: parent
- visible: homePositionManagerButton.checked
+ visible: !_controller.canEdit
+ wrapMode: Text.WordWrap
+ text: "The set of mission items you have loaded cannot be edited by QGroundControl. " +
+ "You will only be able to save these to a file, or send them to a vehicle."
+ }
+ } // Item - Mission Item editor
- Column {
- anchors.fill: parent
- visible: !liveHomePositionAvailable
+ // Home Position Manager
+ Rectangle {
+ id: homePositionManager
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ width: _rightPanelWidth
+ visible: homePositionManagerButton.checked
+ color: qgcPal.window
+ opacity: _rightPanelOpacity
+ z: editorMap.zOrderTopMost
+
+ Column {
+ anchors.margins: _margin
+ anchors.fill: parent
+ visible: !liveHomePositionAvailable
- QGCLabel {
- font.pixelSize: ScreenTools.mediumFontPixelSize
- text: "Flying Field Manager"
- }
+ QGCLabel {
+ font.pixelSize: ScreenTools.mediumFontPixelSize
+ text: "Flying Field Manager"
+ }
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight
- }
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight
+ }
- QGCLabel {
- width: parent.width
- wrapMode: Text.WordWrap
- text: "This is used to save locations associated with your flying field for use while creating missions with no vehicle connection."
- }
+ QGCLabel {
+ width: parent.width
+ wrapMode: Text.WordWrap
+ text: "This is used to save locations associated with your flying field for use while creating missions with no vehicle connection."
+ }
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight
- }
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight
+ }
- QGCLabel {
- text: "Select field to use:"
- }
+ QGCLabel {
+ text: "Select field to use:"
+ }
- QGCComboBox {
- id: homePosCombo
- width: parent.width
- textRole: "text"
- model: _homePositionManager.homePositions
-
- onCurrentIndexChanged: {
- if (currentIndex != -1) {
- var homePos = _homePositionManager.homePositions.get(currentIndex)
- _homePositionName = homePos.name
- offlineHomePosition = homePos.coordinate
- editorMap.latitude = offlineHomePosition.latitude
- editorMap.longitude = offlineHomePosition.longitude
- }
+ QGCComboBox {
+ id: homePosCombo
+ width: parent.width
+ textRole: "text"
+ model: _homePositionManager.homePositions
+
+ onCurrentIndexChanged: {
+ if (currentIndex != -1) {
+ var homePos = _homePositionManager.homePositions.get(currentIndex)
+ _homePositionName = homePos.name
+ offlineHomePosition = homePos.coordinate
+ editorMap.latitude = offlineHomePosition.latitude
+ editorMap.longitude = offlineHomePosition.longitude
}
}
+ }
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight
- }
-
- QGCLabel {
- width: parent.width
- wrapMode: Text.WordWrap
- text: "To add a new flying field, click on the Map to set the position. " +
- "Then give it a new name and click Add/Update. " +
- "To change the current field position, click on the Map to set the new position. " +
- "Then click Add/Update without changing the name."
- }
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight
+ }
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight / 3
- }
+ QGCLabel {
+ width: parent.width
+ wrapMode: Text.WordWrap
+ text: "To add a new flying field, click on the Map to set the position. " +
+ "Then give it a new name and click Add/Update. " +
+ "To change the current field position, click on the Map to set the new position. " +
+ "Then click Add/Update without changing the name."
+ }
- Item {
- width: parent.width
- height: nameField.height
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight / 3
+ }
- QGCLabel {
- anchors.baseline: nameField.baseline
- text: "Name:"
- }
+ Item {
+ width: parent.width
+ height: nameField.height
- QGCTextField {
- id: nameField
- anchors.right: parent.right
- width: _editFieldWidth
- text: _homePositionName
- }
+ QGCLabel {
+ anchors.baseline: nameField.baseline
+ text: "Name:"
}
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight / 3
+ QGCTextField {
+ id: nameField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ text: _homePositionName
}
+ }
- Item {
- width: parent.width
- height: offlineLatitudeField.height
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight / 3
+ }
- QGCLabel {
- anchors.baseline: offlineLatitudeField.baseline
- text: "Lat:"
- }
+ Item {
+ width: parent.width
+ height: offlineLatitudeField.height
- QGCTextField {
- id: offlineLatitudeField
- anchors.right: parent.right
- width: _editFieldWidth
- text: offlineHomePosition.latitude
- }
+ QGCLabel {
+ anchors.baseline: offlineLatitudeField.baseline
+ text: "Lat:"
}
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight / 3
+ QGCTextField {
+ id: offlineLatitudeField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ text: offlineHomePosition.latitude
}
+ }
- Item {
- width: parent.width
- height: offlineLongitudeField.height
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight / 3
+ }
- QGCLabel {
- anchors.baseline: offlineLongitudeField.baseline
- text: "Lon:"
- }
+ Item {
+ width: parent.width
+ height: offlineLongitudeField.height
- QGCTextField {
- id: offlineLongitudeField
- anchors.right: parent.right
- width: _editFieldWidth
- text: offlineHomePosition.longitude
- }
+ QGCLabel {
+ anchors.baseline: offlineLongitudeField.baseline
+ text: "Lon:"
}
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight / 3
+ QGCTextField {
+ id: offlineLongitudeField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ text: offlineHomePosition.longitude
}
+ }
- Item {
- width: parent.width
- height: offlineAltitudeField.height
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight / 3
+ }
- QGCLabel {
- anchors.baseline: offlineAltitudeField.baseline
- text: "Alt:"
- }
+ Item {
+ width: parent.width
+ height: offlineAltitudeField.height
- QGCTextField {
- id: offlineAltitudeField
- anchors.right: parent.right
- width: _editFieldWidth
- text: offlineHomePosition.altitude
- }
+ QGCLabel {
+ anchors.baseline: offlineAltitudeField.baseline
+ text: "Alt:"
}
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight
+ QGCTextField {
+ id: offlineAltitudeField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ text: offlineHomePosition.altitude
}
+ }
- Row {
- spacing: ScreenTools.defaultFontPixelWidth
-
- QGCButton {
- text: "Add/Update"
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight
+ }
- onClicked: {
- offlineHomePosition = QtPositioning.coordinate(latitudeField.text, longitudeField.text, altitudeField.text)
- _homePositionManager.updateHomePosition(nameField.text, offlineHomePosition)
- homePosCombo.currentIndex = homePosCombo.find(nameField.text)
- }
- }
+ Row {
+ spacing: ScreenTools.defaultFontPixelWidth
- QGCButton {
- text: "Delete"
+ QGCButton {
+ text: "Add/Update"
- onClicked: {
- homePosCombo.currentIndex = -1
- _homePositionManager.deleteHomePosition(nameField.text)
- homePosCombo.currentIndex = 0
- var homePos = _homePositionManager.homePositions.get(0)
- _homePositionName = homePos.name
- offlineHomePosition = homePos.coordinate
- }
+ onClicked: {
+ offlineHomePosition = QtPositioning.coordinate(latitudeField.text, longitudeField.text, altitudeField.text)
+ _homePositionManager.updateHomePosition(nameField.text, offlineHomePosition)
+ homePosCombo.currentIndex = homePosCombo.find(nameField.text)
}
}
- } // Column - Offline view
- Column {
- anchors.fill: parent
- visible: liveHomePositionAvailable
+ QGCButton {
+ text: "Delete"
- QGCLabel {
- font.pixelSize: ScreenTools.mediumFontPixelSize
- text: "Vehicle Home Position"
+ onClicked: {
+ homePosCombo.currentIndex = -1
+ _homePositionManager.deleteHomePosition(nameField.text)
+ homePosCombo.currentIndex = 0
+ var homePos = _homePositionManager.homePositions.get(0)
+ _homePositionName = homePos.name
+ offlineHomePosition = homePos.coordinate
+ }
}
+ }
+ } // Column - Offline view
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight
- }
+ Column {
+ anchors.margins: _margin
+ anchors.fill: parent
+ visible: liveHomePositionAvailable
- Item {
- width: parent.width
- height: liveLatitudeField.height
+ QGCLabel {
+ font.pixelSize: ScreenTools.mediumFontPixelSize
+ text: "Vehicle Home Position"
+ }
- QGCLabel {
- anchors.baseline: liveLatitudeField.baseline
- text: "Lat:"
- }
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight
+ }
- QGCLabel {
- id: liveLatitudeField
- anchors.right: parent.right
- width: _editFieldWidth
- text: liveHomePosition.latitude
- }
+ Item {
+ width: parent.width
+ height: liveLatitudeField.height
+
+ QGCLabel {
+ anchors.baseline: liveLatitudeField.baseline
+ text: "Lat:"
}
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight / 3
+ QGCLabel {
+ id: liveLatitudeField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ text: liveHomePosition.latitude
}
+ }
- Item {
- width: parent.width
- height: liveLongitudeField.height
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight / 3
+ }
- QGCLabel {
- anchors.baseline: liveLongitudeField.baseline
- text: "Lon:"
- }
+ Item {
+ width: parent.width
+ height: liveLongitudeField.height
- QGCLabel {
- id: liveLongitudeField
- anchors.right: parent.right
- width: _editFieldWidth
- text: liveHomePosition.longitude
- }
+ QGCLabel {
+ anchors.baseline: liveLongitudeField.baseline
+ text: "Lon:"
}
- Item {
- width: 10
- height: ScreenTools.defaultFontPixelHeight / 3
+ QGCLabel {
+ id: liveLongitudeField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ text: liveHomePosition.longitude
}
+ }
- Item {
- width: parent.width
- height: liveAltitudeField.height
+ Item {
+ width: 10
+ height: ScreenTools.defaultFontPixelHeight / 3
+ }
- QGCLabel {
- anchors.baseline: liveAltitudeField.baseline
- text: "Alt:"
- }
+ Item {
+ width: parent.width
+ height: liveAltitudeField.height
- QGCLabel {
- id: liveAltitudeField
- anchors.right: parent.right
- width: _editFieldWidth
- text: liveHomePosition.altitude
- }
+ QGCLabel {
+ anchors.baseline: liveAltitudeField.baseline
+ text: "Alt:"
}
- } // Column - Online view
- } // Item - Home Position Manager
+ QGCLabel {
+ id: liveAltitudeField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ text: liveHomePosition.altitude
+ }
+ }
+ } // Column - Online view
+ } // Item - Home Position Manager
+
+ // Help Panel
+ Rectangle {
+ id: helpPanel
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ width: _rightPanelWidth
+ visible: !homePositionManagerButton.checked && (_missionItems.count == 1 || helpButton.checked)
+ color: qgcPal.window
+ opacity: _rightPanelOpacity
+ z: editorMap.zOrderTopMost
- // Help Panel
Item {
- id: helpPanel
- anchors.fill: parent
- visible: !homePositionManagerButton.checked && (_missionItems.count == 1 || helpButton.checked)
+ anchors.margins: _margin
+ anchors.fill: parent
QGCLabel {
id: helpTitle
@@ -876,9 +746,210 @@ QGCView {
text: "Map Type
" +
"Map type options."
}
- } // Item - Help Panel
- } // Item
- } // Rectangle - mission item list
+ } // Item - margin
+ } // Item - Help Panel
+
+ RoundButton {
+ id: addMissionItemsButton
+ anchors.margins: _margin
+ anchors.left: parent.left
+ y: (parent.height - (_toolButtonCount * height) - ((_toolButtonCount - 1) * _margin)) / 2
+ buttonImage: "/qmlimages/MapAddMission.svg"
+ exclusiveGroup: _dropButtonsExclusiveGroup
+
+ onCheckedChanged: {
+ if (checked) {
+ addMissionItemsButtonAutoOffTimer.start()
+ } else {
+ addMissionItemsButtonAutoOffTimer.stop()
+ }
+ }
+
+ Timer {
+ id: addMissionItemsButtonAutoOffTimer
+ interval: _addMissionItemsButtonAutoOffTimeout
+ repeat: false
+
+ onTriggered: addMissionItemsButton.checked = false
+ }
+ }
+
+ RoundButton {
+ id: homePositionManagerButton
+ anchors.margins: _margin
+ anchors.left: parent.left
+ anchors.top: addMissionItemsButton.bottom
+ buttonImage: "/qmlimages/MapHome.svg"
+ exclusiveGroup: _dropButtonsExclusiveGroup
+ z: editorMap.zOrderWidgets
+ }
+
+ DropButton {
+ id: centerMapButton
+ anchors.margins: _margin
+ anchors.left: parent.left
+ anchors.top: homePositionManagerButton.bottom
+ dropDirection: dropRight
+ buttonImage: "/qmlimages/MapCenter.svg"
+ viewportMargins: ScreenTools.defaultFontPixelWidth / 2
+ exclusiveGroup: _dropButtonsExclusiveGroup
+ z: editorMap.zOrderWidgets
+
+ dropDownComponent: Component {
+ Column {
+ QGCLabel { text: "Center map:" }
+
+ Row {
+ spacing: ScreenTools.defaultFontPixelWidth
+
+ QGCButton {
+ text: "Home"
+
+ onClicked: {
+ centerMapButton.hideDropDown()
+ editorMap.center = QtPositioning.coordinate(homePosition.latitude, homePosition.longitude)
+ }
+ }
+
+ QGCButton {
+ text: "Vehicle"
+ enabled: activeVehicle && activeVehicle.latitude != 0 && activeVehicle.longitude != 0
+
+ property var activeVehicle: multiVehicleManager.activeVehicle
+
+ onClicked: {
+ centerMapButton.hideDropDown()
+ editorMap.latitude = activeVehicle.latitude
+ editorMap.longitude = activeVehicle.longitude
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DropButton {
+ id: syncButton
+ anchors.margins: _margin
+ anchors.left: parent.left
+ anchors.top: centerMapButton.bottom
+ dropDirection: dropRight
+ buttonImage: _syncNeeded ? "/qmlimages/MapSyncChanged.svg" : "/qmlimages/MapSync.svg"
+ viewportMargins: ScreenTools.defaultFontPixelWidth / 2
+ exclusiveGroup: _dropButtonsExclusiveGroup
+ z: editorMap.zOrderWidgets
+
+ dropDownComponent: Component {
+ Column {
+ id: columnHolder
+ spacing: _margin
+
+ QGCLabel {
+ width: columnHolder.width
+ wrapMode: Text.WordWrap
+ text: _syncNeeded ?
+ "You have unsaved changed to you mission. You should send to your vehicle, or save to a file:" :
+ "Sync:"
+ }
+
+ Row {
+ spacing: ScreenTools.defaultFontPixelWidth
+
+ QGCButton {
+ text: "Send to vehicle"
+ enabled: _activeVehicle && !_activeVehicle.missionManager.inProgress
+
+ onClicked: {
+ syncButton.hideDropDown()
+ _controller.setMissionItems()
+ }
+ }
+
+ QGCButton {
+ text: "Load from vehicle"
+ enabled: _activeVehicle && !_activeVehicle.missionManager.inProgress
+
+ onClicked: {
+ syncButton.hideDropDown()
+ _controller.getMissionItems()
+ }
+ }
+ }
+
+ Row {
+ spacing: ScreenTools.defaultFontPixelWidth
+
+ QGCButton {
+ text: "Save to file..."
+
+ onClicked: {
+ syncButton.hideDropDown()
+ _controller.saveMissionToFile()
+ }
+ }
+
+ QGCButton {
+ text: "Load from file..."
+
+ onClicked: {
+ syncButton.hideDropDown()
+ _controller.loadMissionFromFile()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DropButton {
+ id: mapTypeButton
+ anchors.margins: _margin
+ anchors.left: parent.left
+ anchors.top: syncButton.bottom
+ dropDirection: dropRight
+ buttonImage: "/qmlimages/MapType.svg"
+ viewportMargins: ScreenTools.defaultFontPixelWidth / 2
+ exclusiveGroup: _dropButtonsExclusiveGroup
+ z: editorMap.zOrderWidgets
+
+ dropDownComponent: Component {
+ Column {
+ QGCLabel { text: "Map type:" }
+
+ Row {
+ spacing: ScreenTools.defaultFontPixelWidth
+
+ Repeater {
+ model: QGroundControl.flightMapSettings.mapTypes
+
+ QGCButton {
+ checkable: true
+ checked: editorMap.mapType == text
+ text: modelData
+ exclusiveGroup: _mapTypeButtonsExclusiveGroup
+
+ onClicked: {
+ editorMap.mapType = text
+ checked = true
+ mapTypeButton.hideDropDown()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ RoundButton {
+ id: helpButton
+ anchors.margins: _margin
+ anchors.left: parent.left
+ anchors.top: mapTypeButton.bottom
+ buttonImage: "/qmlimages/Help.svg"
+ exclusiveGroup: _dropButtonsExclusiveGroup
+ z: editorMap.zOrderWidgets
+ }
+ } // FlightMap
} // Item - split view container
} // QGCViewPanel
} // QGCVIew
diff --git a/src/MissionEditor/MissionEditorController.cc b/src/MissionEditor/MissionEditorController.cc
index a15a7f24381a107bfd915cb6bdf6f3ab1ac25d5a..0f4691a01a7f71b001f7399931dead5f1c512505 100644
--- a/src/MissionEditor/MissionEditorController.cc
+++ b/src/MissionEditor/MissionEditorController.cc
@@ -103,14 +103,15 @@ int MissionEditorController::addMissionItem(QGeoCoordinate coordinate)
if (!_canEdit) {
qWarning() << "addMissionItem called with _canEdit == false";
}
+
+ // Coordinate will come through without altitude
+ coordinate.setAltitude(MissionItem::defaultAltitude);
MissionItem * newItem = new MissionItem(this, _missionItems->count(), coordinate, MAV_CMD_NAV_WAYPOINT);
_initMissionItem(newItem);
- newItem->setAltitude(30);
if (_missionItems->count() == 1) {
newItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF);
}
- qDebug() << "MissionItem" << newItem->coordinate();
_missionItems->append(newItem);
_recalcAll();
diff --git a/src/MissionItem.cc b/src/MissionItem.cc
index f3a02fa23df83d05d2cf22979a8930965f2f244e..4ce5e21524cc27e4dc9fa830f29c92b148646d7b 100644
--- a/src/MissionItem.cc
+++ b/src/MissionItem.cc
@@ -36,6 +36,13 @@ This file is part of the QGROUNDCONTROL project
QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog")
+const double MissionItem::defaultPitch = 15.0;
+const double MissionItem::defaultHeading = 0.0;
+const double MissionItem::defaultAltitude = 25.0;
+const double MissionItem::defaultAcceptanceRadius = 3.0;
+const double MissionItem::defaultLoiterOrbitRadius = 10.0;
+const double MissionItem::defaultLoiterTurns = 1.0;
+
QDebug operator<<(QDebug dbg, const MissionItem& missionItem)
{
QDebugStateSaver saver(dbg);
@@ -82,14 +89,14 @@ MissionItem::MissionItem(QObject* parent,
, _autocontinue(autocontinue)
, _isCurrentItem(isCurrentItem)
, _reachedTime(0)
- , _yawRadiansFact(NULL)
+ , _headingDegreesFact(NULL)
,_dirty(false)
, _homePositionSpecialCase(false)
{
_latitudeFact = new Fact(0, "Latitude:", FactMetaData::valueTypeDouble, this);
_longitudeFact = new Fact(0, "Longitude:", FactMetaData::valueTypeDouble, this);
_altitudeFact = new Fact(0, "Altitude:", FactMetaData::valueTypeDouble, this);
- _yawRadiansFact = new Fact(0, "Heading:", FactMetaData::valueTypeDouble, this);
+ _headingDegreesFact = new Fact(0, "Heading:", FactMetaData::valueTypeDouble, this);
_loiterOrbitRadiusFact = new Fact(0, "Radius:", FactMetaData::valueTypeDouble, this);
_param1Fact = new Fact(0, QString(), FactMetaData::valueTypeDouble, this);
_param2Fact = new Fact(0, QString(), FactMetaData::valueTypeDouble, this);
@@ -100,7 +107,7 @@ MissionItem::MissionItem(QObject* parent,
setCoordinate(coordinate);
setParam1(param1);
setParam2(param2);
- setYawRadians(param4);
+ _setYawRadians(param4);
setLoiterOrbitRadius(param3);
// FIXME: Need to fill out more meta data
@@ -114,8 +121,8 @@ MissionItem::MissionItem(QObject* parent,
FactMetaData* altitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _altitudeFact);
altitudeMetaData->setUnits("meters");
- FactMetaData* yawMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _yawRadiansFact);
- yawMetaData->setUnits("deg");
+ FactMetaData* headingMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _headingDegreesFact);
+ headingMetaData->setUnits("deg");
_pitchMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
_pitchMetaData->setUnits("deg");
@@ -147,23 +154,10 @@ MissionItem::MissionItem(QObject* parent,
_latitudeFact->setMetaData(latitudeMetaData);
_longitudeFact->setMetaData(longitudeMetaData);
_altitudeFact->setMetaData(altitudeMetaData);
- _yawRadiansFact->setMetaData(yawMetaData);
+ _headingDegreesFact->setMetaData(headingMetaData);
_loiterOrbitRadiusFact->setMetaData(loiterOrbitRadiusMetaData);
- // Connect to valueChanged to track dirty state
- connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_yawRadiansFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_loiterOrbitRadiusFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
-
- // Connect valueChanged signals so we can output coordinateChanged signal
- connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
- connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
- connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
+ _connectSignals();
}
MissionItem::MissionItem(const MissionItem& other, QObject* parent)
@@ -172,7 +166,7 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent)
_latitudeFact = new Fact(this);
_longitudeFact = new Fact(this);
_altitudeFact = new Fact(this);
- _yawRadiansFact = new Fact(this);
+ _headingDegreesFact = new Fact(this);
_loiterOrbitRadiusFact = new Fact(this);
_param1Fact = new Fact(this);
_param2Fact = new Fact(this);
@@ -188,26 +182,9 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent)
_jumpSequenceMetaData = new FactMetaData(this);
_jumpRepeatMetaData = new FactMetaData(this);
- // Connect to valueChanged to track dirty state
- connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_yawRadiansFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_loiterOrbitRadiusFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
- connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
-
- // Connect valueChanged signals so we can output coordinateChanged signal
- connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
- connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
- connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
-
- *this = other;
-}
+ _connectSignals();
-MissionItem::~MissionItem()
-{
+ *this = other;
}
const MissionItem& MissionItem::operator=(const MissionItem& other)
@@ -221,15 +198,15 @@ const MissionItem& MissionItem::operator=(const MissionItem& other)
_altitudeRelativeToHomeFact = other._altitudeRelativeToHomeFact;
_dirty = other._dirty;
_homePositionSpecialCase = other._homePositionSpecialCase;
-
+
*_latitudeFact = *other._latitudeFact;
*_longitudeFact = *other._longitudeFact;
*_altitudeFact = *other._altitudeFact;
- *_yawRadiansFact = *other._yawRadiansFact;
+ *_headingDegreesFact = *other._headingDegreesFact;
*_loiterOrbitRadiusFact = *other._loiterOrbitRadiusFact;
*_param1Fact = *other._param1Fact;
*_param2Fact = *other._param2Fact;
-
+
*_pitchMetaData = *other._pitchMetaData;
*_acceptanceRadiusMetaData = *other._acceptanceRadiusMetaData;
*_holdTimeMetaData = *other._holdTimeMetaData;
@@ -238,10 +215,34 @@ const MissionItem& MissionItem::operator=(const MissionItem& other)
*_delaySecondsMetaData = *other._delaySecondsMetaData;
*_jumpSequenceMetaData = *other._jumpSequenceMetaData;
*_jumpRepeatMetaData = *other._jumpRepeatMetaData;
-
+
return *this;
}
+void MissionItem::_connectSignals(void)
+{
+ // Connect to valueChanged to track dirty state
+ connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
+ connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
+ connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
+ connect(_headingDegreesFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
+ connect(_loiterOrbitRadiusFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
+ connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
+ connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
+ connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
+
+ // Connect valueChanged signals so we can output coordinateChanged signal
+ connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
+ connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
+ connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
+
+ connect(_headingDegreesFact, &Fact::valueChanged, this, &MissionItem::_headingDegreesFactChanged);
+}
+
+MissionItem::~MissionItem()
+{
+}
+
bool MissionItem::isNavigationType()
{
return (_command < MavlinkQmlSingleton::MAV_CMD_NAV_LAST);
@@ -254,7 +255,7 @@ void MissionItem::save(QTextStream &saveStream)
position = position.arg(y(), 0, 'g', 18);
position = position.arg(z(), 0, 'g', 18);
QString parameters("%1\t%2\t%3\t%4");
- parameters = parameters.arg(param1(), 0, 'g', 18).arg(param2(), 0, 'g', 18).arg(loiterOrbitRadius(), 0, 'g', 18).arg(yawRadians(), 0, 'g', 18);
+ parameters = parameters.arg(param1(), 0, 'g', 18).arg(param2(), 0, 'g', 18).arg(loiterOrbitRadius(), 0, 'g', 18).arg(_yawRadians(), 0, 'g', 18);
// FORMAT:
// as documented here: http://qgroundcontrol.org/waypoint_protocol
saveStream << this->sequenceNumber() << "\t" << this->isCurrentItem() << "\t" << this->frame() << "\t" << this->command() << "\t" << parameters << "\t" << position << "\t" << this->autoContinue() << "\r\n"; //"\t" << this->getDescription() << "\r\n";
@@ -271,7 +272,7 @@ bool MissionItem::load(QTextStream &loadStream)
setParam1(wpParams[4].toDouble());
setParam2(wpParams[5].toDouble());
setLoiterOrbitRadius(wpParams[6].toDouble());
- setYawRadians(wpParams[7].toDouble());
+ _setYawRadians(wpParams[7].toDouble());
setLatitude(wpParams[8].toDouble());
setLongitude(wpParams[9].toDouble());
setAltitude(wpParams[10].toDouble());
@@ -351,11 +352,27 @@ void MissionItem::setAction(int /*MAV_CMD*/ action)
// Fix defaults according to WP type
- if (_command == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) {
- // We default to 15 degrees minimum takeoff pitch
- setParam1(15.0);
+ switch (_command) {
+ case MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF:
+ setParam1(defaultPitch);
+ break;
+ case MavlinkQmlSingleton::MAV_CMD_NAV_WAYPOINT:
+ setAcceptanceRadius(defaultAcceptanceRadius);
+ break;
+ case MavlinkQmlSingleton::MAV_CMD_NAV_LOITER_UNLIM:
+ case MavlinkQmlSingleton::MAV_CMD_NAV_LOITER_TIME:
+ setLoiterOrbitRadius(defaultLoiterOrbitRadius);
+ break;
+ case MavlinkQmlSingleton::MAV_CMD_NAV_LOITER_TURNS:
+ setLoiterOrbitRadius(defaultLoiterOrbitRadius);
+ setParam1(defaultLoiterTurns);
+ break;
+ default:
+ break;
}
-
+ setHeadingDegrees(defaultHeading);
+ setAltitude(defaultAltitude);
+
if (specifiesCoordinate()) {
if (_frame != MAV_FRAME_GLOBAL && _frame != MAV_FRAME_GLOBAL_RELATIVE_ALT) {
setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
@@ -438,7 +455,7 @@ void MissionItem::setParam3(double param3)
void MissionItem::setParam4(double param4)
{
- setYawRadians(param4);
+ _setYawRadians(param4);
}
void MissionItem::setParam5(double param5)
@@ -526,6 +543,46 @@ QString MissionItem::commandName(void)
return type;
}
+QString MissionItem::commandDescription(void)
+{
+ QString description;
+
+ switch (_command) {
+ case MAV_CMD_NAV_WAYPOINT:
+ description = "Travel to a position in 3D space.";
+ break;
+ case MAV_CMD_NAV_LOITER_UNLIM:
+ description = "Travel to a position and Loiter around the specified radius indefinitely.";
+ break;
+ case MAV_CMD_NAV_LOITER_TURNS:
+ description = "Travel to a position and Loiter around the specified radius for a number of turns.";
+ break;
+ case MAV_CMD_NAV_LOITER_TIME:
+ description = "Travel to a position and Loiter around the specified radius for an amount of time.";
+ break;
+ case MAV_CMD_NAV_RETURN_TO_LAUNCH:
+ description = "Send the vehicle back to the home position.";
+ break;
+ case MAV_CMD_NAV_LAND:
+ description = "Land vehicle at the specified location.";
+ break;
+ case MAV_CMD_NAV_TAKEOFF:
+ description = "Take off from the ground and travel towards the specified position.";
+ break;
+ case MAV_CMD_CONDITION_DELAY:
+ description = "Delay";
+ break;
+ case MAV_CMD_DO_JUMP:
+ description = "Jump To Command";
+ break;
+ default:
+ description = QString("Unknown (%1)").arg(_command);
+ break;
+ }
+
+ return description;
+}
+
QStringList MissionItem::valueLabels(void)
{
QStringList labels;
@@ -590,24 +647,24 @@ QStringList MissionItem::valueStrings(void)
switch (_command) {
case MAV_CMD_NAV_WAYPOINT:
- list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawDegrees()) << _oneDecimalString(param2()) << _oneDecimalString(param1());
+ list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(headingDegrees()) << _oneDecimalString(param2()) << _oneDecimalString(param1());
break;
case MAV_CMD_NAV_LOITER_UNLIM:
- list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius());
+ list << _oneDecimalString(headingDegrees()) << _oneDecimalString(loiterOrbitRadius());
break;
case MAV_CMD_NAV_LOITER_TURNS:
- list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
+ list << _oneDecimalString(headingDegrees()) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
break;
case MAV_CMD_NAV_LOITER_TIME:
- list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
+ list << _oneDecimalString(headingDegrees()) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
break;
case MAV_CMD_NAV_RETURN_TO_LAUNCH:
break;
case MAV_CMD_NAV_LAND:
- list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawRadians() * (180.0 / M_PI));
+ list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(headingDegrees());
break;
case MAV_CMD_NAV_TAKEOFF:
- list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(param1());
+ list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(headingDegrees()) << _oneDecimalString(param1());
break;
case MAV_CMD_CONDITION_DELAY:
list << _oneDecimalString(param1());
@@ -659,59 +716,38 @@ QmlObjectListModel* MissionItem::textFieldFacts(void)
switch ((MAV_CMD)_command) {
case MAV_CMD_NAV_WAYPOINT:
- _param2Fact->_setName("Radius:");
- _param2Fact->setMetaData(_acceptanceRadiusMetaData);
_param1Fact->_setName("Hold:");
_param1Fact->setMetaData(_holdTimeMetaData);
- model->append(_latitudeFact);
- model->append(_longitudeFact);
model->append(_altitudeFact);
if (!_homePositionSpecialCase) {
- model->append(_yawRadiansFact);
- model->append(_param2Fact);
model->append(_param1Fact);
}
break;
case MAV_CMD_NAV_LOITER_UNLIM:
- model->append(_latitudeFact);
- model->append(_longitudeFact);
model->append(_altitudeFact);
- model->append(_yawRadiansFact);
model->append(_loiterOrbitRadiusFact);
break;
case MAV_CMD_NAV_LOITER_TURNS:
_param1Fact->_setName("Turns:");
_param1Fact->setMetaData(_loiterTurnsMetaData);
- model->append(_latitudeFact);
- model->append(_longitudeFact);
model->append(_altitudeFact);
- model->append(_yawRadiansFact);
model->append(_loiterOrbitRadiusFact);
model->append(_param1Fact);
break;
case MAV_CMD_NAV_LOITER_TIME:
_param1Fact->_setName("Seconds:");
_param1Fact->setMetaData(_loiterSecondsMetaData);
- model->append(_latitudeFact);
- model->append(_longitudeFact);
model->append(_altitudeFact);
- model->append(_yawRadiansFact);
model->append(_loiterOrbitRadiusFact);
model->append(_param1Fact);
break;
case MAV_CMD_NAV_LAND:
- model->append(_latitudeFact);
- model->append(_longitudeFact);
model->append(_altitudeFact);
- model->append(_yawRadiansFact);
break;
case MAV_CMD_NAV_TAKEOFF:
_param1Fact->_setName("Pitch:");
_param1Fact->setMetaData(_pitchMetaData);
- model->append(_latitudeFact);
- model->append(_longitudeFact);
model->append(_altitudeFact);
- model->append(_yawRadiansFact);
model->append(_param1Fact);
break;
case MAV_CMD_CONDITION_DELAY:
@@ -730,6 +766,11 @@ QmlObjectListModel* MissionItem::textFieldFacts(void)
default:
break;
}
+
+ if (specifiesHeading()) {
+ model->append(_headingDegreesFact);
+ }
+
return model;
}
@@ -768,30 +809,30 @@ QmlObjectListModel* MissionItem::checkboxFacts(void)
return model;
}
-double MissionItem::yawRadians(void) const
+double MissionItem::headingDegrees(void) const
{
- return _yawRadiansFact->value().toDouble();
+ return _headingDegreesFact->value().toDouble();
}
-void MissionItem::setYawRadians(double yaw)
+void MissionItem::setHeadingDegrees(double headingDegrees)
{
- if (yawRadians() != yaw)
- {
- _yawRadiansFact->setValue(yaw);
+ if (_headingDegreesFact->value().toDouble() != headingDegrees) {
+ _headingDegreesFact->setValue(headingDegrees);
emit changed(this);
emit valueStringsChanged(valueStrings());
+ emit headingDegreesChanged(headingDegrees);
}
}
-double MissionItem::yawDegrees(void) const
+double MissionItem::_yawRadians(void) const
{
- return yawRadians() * (180.0 / M_PI);
+ return _headingDegreesFact->value().toDouble() * (M_PI / 180.0);
}
-void MissionItem::setYawDegrees(double yaw)
+void MissionItem::_setYawRadians(double yawRadians)
{
- setYawRadians(yaw * (M_PI / 180.0));
+ setHeadingDegrees(yawRadians * (180 / M_PI));
}
QGeoCoordinate MissionItem::coordinate(void) const
@@ -854,3 +895,19 @@ void MissionItem::_coordinateFactChanged(QVariant value)
Q_UNUSED(value);
emit coordinateChanged(coordinate());
}
+
+bool MissionItem::specifiesHeading(void) const
+{
+ switch ((MAV_CMD)_command) {
+ case MAV_CMD_NAV_LAND:
+ case MAV_CMD_NAV_TAKEOFF:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void MissionItem::_headingDegreesFactChanged(QVariant value)
+{
+ emit headingDegreesChanged(value.toDouble());
+}
diff --git a/src/MissionItem.h b/src/MissionItem.h
index 09c57ade62aa1dec30b87fa42f664af39a48d450..382c3d8c48c0ab44bd4717e6089667c878933f3e 100644
--- a/src/MissionItem.h
+++ b/src/MissionItem.h
@@ -50,9 +50,9 @@ public:
QGeoCoordinate coordiante = QGeoCoordinate(),
int action = MAV_CMD_NAV_WAYPOINT,
double param1 = 0.0,
- double param2 = 0.0,
- double param3 = 0.0,
- double param4 = 0.0,
+ double param2 = defaultAcceptanceRadius,
+ double param3 = defaultLoiterOrbitRadius,
+ double param4 = defaultHeading,
bool autocontinue = true,
bool isCurrentItem = false,
int frame = MAV_FRAME_GLOBAL_RELATIVE_ALT);
@@ -67,10 +67,16 @@ public:
Q_PROPERTY(int sequenceNumber READ sequenceNumber WRITE setSequenceNumber NOTIFY sequenceNumberChanged)
Q_PROPERTY(bool isCurrentItem READ isCurrentItem WRITE setIsCurrentItem NOTIFY isCurrentItemChanged)
+
Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY commandChanged)
Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged)
+
+ Q_PROPERTY(bool specifiesHeading READ specifiesHeading NOTIFY commandChanged)
+ Q_PROPERTY(double heading READ headingDegrees WRITE setHeadingDegrees NOTIFY headingDegreesChanged)
+
Q_PROPERTY(QStringList commandNames READ commandNames CONSTANT)
Q_PROPERTY(QString commandName READ commandName NOTIFY commandChanged)
+ Q_PROPERTY(QString commandDescription READ commandDescription NOTIFY commandChanged)
Q_PROPERTY(QStringList valueLabels READ valueLabels NOTIFY commandChanged)
Q_PROPERTY(QStringList valueStrings READ valueStrings NOTIFY valueStringsChanged)
Q_PROPERTY(int commandByIndex READ commandByIndex WRITE setCommandByIndex NOTIFY commandChanged)
@@ -88,12 +94,19 @@ public:
void setIsCurrentItem(bool isCurrentItem);
bool specifiesCoordinate(void) const;
-
QGeoCoordinate coordinate(void) const;
void setCoordinate(const QGeoCoordinate& coordinate);
+ bool specifiesHeading(void) const;
+ double headingDegrees(void) const;
+ void setHeadingDegrees(double headingDegrees);
+
+ // This is public for unit testing
+ double _yawRadians(void) const;
+
QStringList commandNames(void);
QString commandName(void);
+ QString commandDescription(void);
int commandByIndex(void);
void setCommandByIndex(int index);
@@ -107,9 +120,6 @@ public:
QmlObjectListModel* textFieldFacts(void);
QmlObjectListModel* checkboxFacts(void);
- double yawDegrees(void) const;
- void setYawDegrees(double yaw);
-
bool dirty(void) { return _dirty; }
void setDirty(bool dirty);
@@ -136,9 +146,6 @@ public:
void setY(double y);
void setZ(double z);
- double yawRadians(void) const;
- void setYawRadians(double yaw);
-
bool autoContinue() const {
return _autocontinue;
}
@@ -161,7 +168,7 @@ public:
return loiterOrbitRadius();
}
double param4() const {
- return yawRadians();
+ return _yawRadians();
}
double param5() const {
return latitude();
@@ -189,11 +196,19 @@ public:
bool load(QTextStream &loadStream);
void setHomePositionSpecialCase(bool homePositionSpecialCase) { _homePositionSpecialCase = homePositionSpecialCase; }
-
+
+ static const double defaultPitch;
+ static const double defaultHeading;
+ static const double defaultAltitude;
+ static const double defaultAcceptanceRadius;
+ static const double defaultLoiterOrbitRadius;
+ static const double defaultLoiterTurns;
+
signals:
void sequenceNumberChanged(int sequenceNumber);
void isCurrentItemChanged(bool isCurrentItem);
void coordinateChanged(const QGeoCoordinate& coordinate);
+ void headingDegreesChanged(double heading);
void dirtyChanged(bool dirty);
/** @brief Announces a change to the waypoint data */
@@ -234,9 +249,12 @@ public:
private slots:
void _factValueChanged(QVariant value);
void _coordinateFactChanged(QVariant value);
+ void _headingDegreesFactChanged(QVariant value);
private:
QString _oneDecimalString(double value);
+ void _connectSignals(void);
+ void _setYawRadians(double yawRadians);
private:
typedef struct {
@@ -254,7 +272,7 @@ private:
Fact* _latitudeFact;
Fact* _longitudeFact;
Fact* _altitudeFact;
- Fact* _yawRadiansFact;
+ Fact* _headingDegreesFact;
Fact* _loiterOrbitRadiusFact;
Fact* _param1Fact;
Fact* _param2Fact;
diff --git a/src/MissionItemTest.cc b/src/MissionItemTest.cc
index 59d590450843b4997ad99b76c90af821dd15cf50..b19582b1a4c66f24d7786b5ecbe77c6ba3798716 100644
--- a/src/MissionItemTest.cc
+++ b/src/MissionItemTest.cc
@@ -27,63 +27,46 @@
UT_REGISTER_TEST(MissionItemTest)
const MissionItemTest::ItemInfo_t MissionItemTest::_rgItemInfo[] = {
- { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_WAYPOINT, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
- { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_LOITER_UNLIM, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
- { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_LOITER_TURNS, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
- { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_LOITER_TIME, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
- { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_LAND, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
- { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_TAKEOFF, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
- { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_CONDITION_DELAY, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_MISSION },
- { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_DO_JUMP, 10.0, 20.0, 30.0, 40.0, true, false, MAV_FRAME_MISSION },
+ { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_WAYPOINT, 10.0, 20.0, 30.0, 1.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
+ { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_LOITER_UNLIM, 10.0, 20.0, 30.0, 1.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
+ { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_LOITER_TURNS, 10.0, 20.0, 30.0, 1.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
+ { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_LOITER_TIME, 10.0, 20.0, 30.0, 1.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
+ { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_LAND, 10.0, 20.0, 30.0, 1.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
+ { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_NAV_TAKEOFF, 10.0, 20.0, 30.0, 1.0, true, false, MAV_FRAME_GLOBAL_RELATIVE_ALT },
+ { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_CONDITION_DELAY, 10.0, 20.0, 30.0, 1.0, true, false, MAV_FRAME_MISSION },
+ { 1, QGeoCoordinate(-10.0, -20.0, -30.0), MAV_CMD_DO_JUMP, 10.0, 20.0, 30.0, 1.0, true, false, MAV_FRAME_MISSION },
};
const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesWaypoint[] = {
- { "Latitude:", -10.0 },
- { "Longitude:", -20.0 },
{ "Altitude:", -30.0 },
- { "Heading:", 40.0 },
- { "Radius:", 20.0 },
{ "Hold:", 10.0 },
};
const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesLoiterUnlim[] = {
- { "Latitude:", -10.0 },
- { "Longitude:", -20.0 },
{ "Altitude:", -30.0 },
- { "Heading:", 40.0 },
{ "Radius:", 30.0 },
};
const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesLoiterTurns[] = {
- { "Latitude:", -10.0 },
- { "Longitude:", -20.0 },
{ "Altitude:", -30.0 },
- { "Heading:", 40.0 },
{ "Radius:", 30.0 },
{ "Turns:", 10.0 },
};
const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesLoiterTime[] = {
- { "Latitude:", -10.0 },
- { "Longitude:", -20.0 },
{ "Altitude:", -30.0 },
- { "Heading:", 40.0 },
{ "Radius:", 30.0 },
{ "Seconds:", 10.0 },
};
const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesLand[] = {
- { "Latitude:", -10.0 },
- { "Longitude:", -20.0 },
{ "Altitude:", -30.0 },
- { "Heading:", 40.0 },
+ { "Heading:", 1.0 },
};
const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesTakeoff[] = {
- { "Latitude:", -10.0 },
- { "Longitude:", -20.0 },
{ "Altitude:", -30.0 },
- { "Heading:", 40.0 },
+ { "Heading:", 1.0 },
{ "Pitch:", 10.0 },
};
@@ -97,14 +80,14 @@ const MissionItemTest::FactValue_t MissionItemTest::_rgFactValuesDoJump[] = {
};
const MissionItemTest::ItemExpected_t MissionItemTest::_rgItemExpected[] = {
- { "1\t0\t3\t16\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesWaypoint)/sizeof(MissionItemTest::_rgFactValuesWaypoint[0]), MissionItemTest::_rgFactValuesWaypoint },
- { "1\t0\t3\t17\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesLoiterUnlim)/sizeof(MissionItemTest::_rgFactValuesLoiterUnlim[0]), MissionItemTest::_rgFactValuesLoiterUnlim },
- { "1\t0\t3\t18\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesLoiterTurns)/sizeof(MissionItemTest::_rgFactValuesLoiterTurns[0]), MissionItemTest::_rgFactValuesLoiterTurns },
- { "1\t0\t3\t19\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesLoiterTime)/sizeof(MissionItemTest::_rgFactValuesLoiterTime[0]), MissionItemTest::_rgFactValuesLoiterTime },
- { "1\t0\t3\t21\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesLand)/sizeof(MissionItemTest::_rgFactValuesLand[0]), MissionItemTest::_rgFactValuesLand },
- { "1\t0\t3\t22\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesTakeoff)/sizeof(MissionItemTest::_rgFactValuesTakeoff[0]), MissionItemTest::_rgFactValuesTakeoff },
- { "1\t0\t2\t112\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesConditionDelay)/sizeof(MissionItemTest::_rgFactValuesConditionDelay[0]), MissionItemTest::_rgFactValuesConditionDelay },
- { "1\t0\t2\t177\t10\t20\t30\t40\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesDoJump)/sizeof(MissionItemTest::_rgFactValuesDoJump[0]), MissionItemTest::_rgFactValuesDoJump },
+ { "1\t0\t3\t16\t10\t20\t30\t1\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesWaypoint)/sizeof(MissionItemTest::_rgFactValuesWaypoint[0]), MissionItemTest::_rgFactValuesWaypoint },
+ { "1\t0\t3\t17\t10\t20\t30\t1\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesLoiterUnlim)/sizeof(MissionItemTest::_rgFactValuesLoiterUnlim[0]), MissionItemTest::_rgFactValuesLoiterUnlim },
+ { "1\t0\t3\t18\t10\t20\t30\t1\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesLoiterTurns)/sizeof(MissionItemTest::_rgFactValuesLoiterTurns[0]), MissionItemTest::_rgFactValuesLoiterTurns },
+ { "1\t0\t3\t19\t10\t20\t30\t1\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesLoiterTime)/sizeof(MissionItemTest::_rgFactValuesLoiterTime[0]), MissionItemTest::_rgFactValuesLoiterTime },
+ { "1\t0\t3\t21\t10\t20\t30\t1\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesLand)/sizeof(MissionItemTest::_rgFactValuesLand[0]), MissionItemTest::_rgFactValuesLand },
+ { "1\t0\t3\t22\t10\t20\t30\t1\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesTakeoff)/sizeof(MissionItemTest::_rgFactValuesTakeoff[0]), MissionItemTest::_rgFactValuesTakeoff },
+ { "1\t0\t2\t112\t10\t20\t30\t1\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesConditionDelay)/sizeof(MissionItemTest::_rgFactValuesConditionDelay[0]), MissionItemTest::_rgFactValuesConditionDelay },
+ { "1\t0\t2\t177\t10\t20\t30\t1\t-10\t-20\t-30\t1\r\n", sizeof(MissionItemTest::_rgFactValuesDoJump)/sizeof(MissionItemTest::_rgFactValuesDoJump[0]), MissionItemTest::_rgFactValuesDoJump },
};
MissionItemTest::MissionItemTest(void)
@@ -149,7 +132,11 @@ void MissionItemTest::_test(void)
if (factValue->name == fact->name()) {
qDebug() << factValue->name;
- QCOMPARE(fact->value().toDouble(), factValue->value);
+ if (strcmp(factValue->name, "Heading:") == 0) {
+ QCOMPARE(fact->value().toDouble() * (M_PI / 180.0), item->_yawRadians());
+ } else {
+ QCOMPARE(fact->value().toDouble(), factValue->value);
+ }
factCount ++;
found = true;
break;
@@ -158,6 +145,7 @@ void MissionItemTest::_test(void)
QVERIFY(found);
}
+ qDebug() << info->command;
QCOMPARE(factCount, expected->cFactValues);
// Validate that loading is working correctly
diff --git a/src/QmlControls/DropButton.qml b/src/QmlControls/DropButton.qml
index acd67352d94fdce6e426cdd80afec0f5ddfa455b..493f12a6a6724aa6d37424fe66a46d2c9f9a20ec 100644
--- a/src/QmlControls/DropButton.qml
+++ b/src/QmlControls/DropButton.qml
@@ -224,7 +224,7 @@ Item {
context.lineTo(dropItemHolderRect.x, dropItemHolderRect.y)
context.closePath()
- context.fillStyle = qgcPal.button
+ context.fillStyle = qgcPal.windowShade
context.fill()
}
} // Canvas - arrowCanvas
diff --git a/src/QmlControls/MissionItemEditor.qml b/src/QmlControls/MissionItemEditor.qml
index b4c6f0e828a3bd2f685d07004a018687ca1ca1e9..3c7cb04d84908410807040a5523522cd239665bd 100644
--- a/src/QmlControls/MissionItemEditor.qml
+++ b/src/QmlControls/MissionItemEditor.qml
@@ -19,34 +19,26 @@ Rectangle {
signal clicked
signal remove
- height: missionItem.isCurrentItem ?
- (missionItem.textFieldFacts.count * (measureTextField.height + _margin)) +
- (missionItem.checkboxFacts.count * (measureCheckbox.height + _margin)) +
- commandPicker.height + (deleteButton.visible ? deleteButton.height : 0) + (_margin * 9) :
- commandPicker.height + (_margin * 2)
+ height: innerItem.height + (_margin * 2)
color: missionItem.isCurrentItem ? qgcPal.buttonHighlight : qgcPal.windowShade
+ radius: _radius
readonly property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 16
- readonly property real _margin: ScreenTools.defaultFontPixelWidth / 3
+ readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2
+ readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2
QGCPalette {
id: qgcPal
colorGroupEnabled: enabled
}
- QGCTextField {
- id: measureTextField
- visible: false
- }
-
- QGCCheckBox {
- id: measureCheckbox
- visible: false
- }
-
Item {
+ id: innerItem
anchors.margins: _margin
- anchors.fill: parent
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: valuesRect.visible ? valuesRect.y + valuesRect.height : valuesRect.y
MissionItemIndexLabel {
id: label
@@ -69,7 +61,7 @@ Rectangle {
anchors.right: parent.right
currentIndex: missionItem.commandByIndex
model: missionItem.commandNames
- visible: missionItem.sequenceNumber != 0 // Item 0 is home position, can't change item type
+ visible: missionItem.sequenceNumber != 0 && missionItem.isCurrentItem
onActivated: missionItem.commandByIndex = index
}
@@ -77,30 +69,36 @@ Rectangle {
Rectangle {
anchors.fill: commandPicker
color: qgcPal.button
- visible: missionItem.sequenceNumber == 0 // Item 0 is home position, can't change item type
+ visible: !commandPicker.visible
QGCLabel {
id: homeLabel
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
- text: "Home"
+ text: missionItem.sequenceNumber == 0 ? "Home" : missionItem.commandName
color: qgcPal.buttonText
}
}
Rectangle {
+ id: valuesRect
anchors.topMargin: _margin
anchors.top: commandPicker.bottom
- anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
+ height: valuesItem.height
color: qgcPal.windowShadeDark
visible: missionItem.isCurrentItem
+ radius: _radius
Item {
+ id: valuesItem
anchors.margins: _margin
- anchors.fill: parent
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ height: valuesColumn.height + _margin
Column {
id: valuesColumn
@@ -109,6 +107,12 @@ Rectangle {
anchors.top: parent.top
spacing: _margin
+ QGCLabel {
+ width: parent.width
+ wrapMode: Text.WordWrap
+ text: missionItem.commandDescription
+ }
+
Repeater {
model: missionItem.textFieldFacts
@@ -140,11 +144,6 @@ Rectangle {
}
}
- Item {
- width: 10
- height: missionItem.textFieldFacts.count ? _margin : 0
- }
-
Repeater {
model: missionItem.checkboxFacts
@@ -154,28 +153,6 @@ Rectangle {
fact: object
}
}
-
- Item {
- width: 10
- height: missionItem.checkboxFacts.count ? _margin : 0
- }
-
- Row {
- width: parent.width
- spacing: _margin
-
- readonly property real buttonWidth: (width - (_margin * 2)) / 3
-
- QGCButton {
- id: deleteButton
- width: parent.buttonWidth
- text: "Delete"
- visible: !readOnly
-
- onClicked: _root.remove()
- }
- }
-
} // Column
} // Item
} // Rectangle
diff --git a/src/QmlControls/MissionItemIndexLabel.qml b/src/QmlControls/MissionItemIndexLabel.qml
index 1c6f6b03d93d39387c3b3b3f2bf80a4954e67ba3..dcbb577ad45ed9aae282c4a406b655d60333bc1b 100644
--- a/src/QmlControls/MissionItemIndexLabel.qml
+++ b/src/QmlControls/MissionItemIndexLabel.qml
@@ -13,7 +13,7 @@ Rectangle {
QGCPalette { id: qgcPal }
- width: ScreenTools.defaultFontPixelHeight * 1.5
+ width: ScreenTools.mediumFontPixelSize * 1.5
height: width
radius: width / 2
border.width: 2
@@ -32,5 +32,6 @@ Rectangle {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: "white"
+ font.pixelSize: ScreenTools.mediumFontPixelSize
}
}
diff --git a/src/ui/MainWindow.qml b/src/ui/MainWindow.qml
index 0fe81f924e419331162b5a8c6da50e6184f934ac..83bc3ff67f5d2a1b80acce2cdc499a68520001a8 100644
--- a/src/ui/MainWindow.qml
+++ b/src/ui/MainWindow.qml
@@ -72,7 +72,7 @@ FlightDisplayView {
onShowSetupFirmware: setupViewLoader.item.showFirmwarePanel()
onShowSetupParameters: setupViewLoader.item.showParametersPanel()
onShowSetupSummary: setupViewLoader.item.showSummaryPanel()
- onShowSetupVehicleComponent: setupViewLoader.item.showVehicleComponentPanel(vechicleComponent)
+ onShowSetupVehicleComponent: setupViewLoader.item.showVehicleComponentPanel(vehicleComponent)
}
MainToolBar {