Commit 79304384 authored by Valentin Platzgummer's avatar Valentin Platzgummer

after cleanup

parent 1add4096
/****************************************************************************
*
* (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 QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Airspace 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightDisplay 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
FlightMap {
id: flightMap
anchors.fill: parent
mapName: _mapName
allowGCSLocationCenter: !userPanned
allowVehicleLocationCenter: !_keepVehicleCentered
planView: false
property alias scaleState: mapScale.state
// The following properties must be set by the consumer
property var planMasterController
property var wimaController
property var guidedActionsController
property var flightWidgets
property var rightPanelWidth
property var qgcView ///< QGCView control which contains this map
property var multiVehicleView ///< true: multi-vehicle view, false: single vehicle view
property rect centerViewport: Qt.rect(0, 0, width, height)
property var _planMasterController: planMasterController
property var _missionController: _planMasterController.missionController
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2)
property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false
property bool _disableVehicleTracking: false
property bool _keepVehicleCentered: _mainIsMap ? false : true
property bool _wimaEnabled: wimaController.enableWimaController.value
property bool _showAllWimaItems: wimaController.showAllMissionItems.value
property bool _showCurrentWimaItems: wimaController.showCurrentMissionItems.value
function updateAirspace(reset) {
if(_airspaceEnabled) {
var coordinateNW = flightMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */)
var coordinateSE = flightMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */)
if(coordinateNW.isValid && coordinateSE.isValid) {
QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE, false /*planView*/, reset)
}
}
}
// Track last known map position and zoom from Fly view in settings
onZoomLevelChanged: {
QGroundControl.flightMapZoom = zoomLevel
updateAirspace(false)
}
onCenterChanged: {
QGroundControl.flightMapPosition = center
updateAirspace(false)
}
// When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires
onUserPannedChanged: {
if (userPanned) {
console.log("user panned")
userPanned = false
_disableVehicleTracking = true
panRecenterTimer.restart()
}
}
on_AirspaceEnabledChanged: {
updateAirspace(true)
}
function pointInRect(point, rect) {
return point.x > rect.x &&
point.x < rect.x + rect.width &&
point.y > rect.y &&
point.y < rect.y + rect.height;
}
property real _animatedLatitudeStart
property real _animatedLatitudeStop
property real _animatedLongitudeStart
property real _animatedLongitudeStop
property real animatedLatitude
property real animatedLongitude
onAnimatedLatitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
onAnimatedLongitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
NumberAnimation on animatedLatitude { id: animateLat; from: _animatedLatitudeStart; to: _animatedLatitudeStop; duration: 1000 }
NumberAnimation on animatedLongitude { id: animateLong; from: _animatedLongitudeStart; to: _animatedLongitudeStop; duration: 1000 }
function animatedMapRecenter(fromCoord, toCoord) {
_animatedLatitudeStart = fromCoord.latitude
_animatedLongitudeStart = fromCoord.longitude
_animatedLatitudeStop = toCoord.latitude
_animatedLongitudeStop = toCoord.longitude
animateLat.start()
animateLong.start()
}
function recenterNeeded() {
var vehiclePoint = flightMap.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
var toolStripRightEdge = mapFromItem(toolStrip, toolStrip.x, 0).x + toolStrip.width
var instrumentsWidth = 0
if (QGroundControl.corePlugin.options.instrumentWidget && QGroundControl.corePlugin.options.instrumentWidget.widgetPosition === CustomInstrumentWidget.POS_TOP_RIGHT) {
// Assume standard instruments
instrumentsWidth = flightDisplayViewWidgets.getPreferredInstrumentWidth()
}
var centerViewport = Qt.rect(toolStripRightEdge, 0, width - toolStripRightEdge - instrumentsWidth, height)
return !pointInRect(vehiclePoint, centerViewport)
}
function updateMapToVehiclePosition() {
// We let FlightMap handle first vehicle position
if (firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
if (_keepVehicleCentered) {
flightMap.center = _activeVehicleCoordinate
} else {
if (firstVehiclePositionReceived && recenterNeeded()) {
animatedMapRecenter(flightMap.center, _activeVehicleCoordinate)
}
}
}
}
Timer {
id: panRecenterTimer
interval: 10000
running: false
onTriggered: {
_disableVehicleTracking = false
updateMapToVehiclePosition()
}
}
Timer {
interval: 500
running: true
repeat: true
onTriggered: updateMapToVehiclePosition()
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Connections {
target: _missionController
onNewItemsFromVehicle: {
var visualItems = _missionController.visualItems
if (visualItems && visualItems.count !== 1) {
mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true
}
}
}
ExclusiveGroup {
id: _mapTypeButtonsExclusiveGroup
}
MapFitFunctions {
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
map: _flightMap
usePlannedHomePosition: false
planMasterController: _planMasterController
property real leftToolWidth: toolStrip.x + toolStrip.width
}
// Add wima Areas to the Map
MapItemView {
property bool _enableWima: wimaController.enableWimaController.value
model: _enableWima ? wimaController.visualItems : 0
delegate: MapPolygon{
path: object.path;
border.color: "black"
color: object.type === "WimaJoinedAreaData" ? "gray"
: object.type === "WimaServiceAreaData" ? "yellow"
: object.type === "WimaMeasurementAreaData" ? "green"
: "transparent"
opacity: 0.25
z: 0
}
}
// Add mission items generated by wima planer to the map
// all Items
WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.missionItems
path: wimaController.waypointPath
showItems: _wimaEnabled && _showAllWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-2
zOrderLines: QGroundControl.zOrderWaypointLines-2
color: "gray"
}
// current Items
/*WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.currentMissionItems
path: wimaController.currentWaypointPath
showItems: _wimaEnabled && _showCurrentWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-1
<<<<<<< HEAD
zOrderLines: QGroundControl.zOrderWaypointIndicators-2
color: "green" // gray with alpha 0.7
}*/
=======
zOrderLines: QGroundControl.zOrderWaypointLines-1
color: "green"
}
>>>>>>> temp
// Add trajectory points to the map
MapItemView {
model: _mainIsMap ? _activeVehicle ? _activeVehicle.trajectoryPoints : 0 : 0
delegate: MapPolyline {
line.width: 3
line.color: "red"
z: QGroundControl.zOrderTrajectoryLines
path: [
object.coordinate1,
object.coordinate2,
]
}
}
// Add the vehicles to the map
MapItemView {
model: QGroundControl.multiVehicleManager.vehicles
delegate: VehicleMapItem {
vehicle: object
coordinate: object.coordinate
map: flightMap
size: _mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight
z: QGroundControl.zOrderVehicles
}
}
// Add ADSB vehicles to the map
MapItemView {
model: _activeVehicle ? _activeVehicle.adsbVehicles : []
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
delegate: VehicleMapItem {
coordinate: object.coordinate
altitude: object.altitude
callsign: object.callsign
heading: object.heading
alert: object.alert
map: flightMap
z: QGroundControl.zOrderVehicles
}
}
// Add the items associated with each vehicles flight plan to the map
Repeater {
model: QGroundControl.multiVehicleManager.vehicles
PlanMapItems {
map: flightMap
largeMapView: _mainIsMap
masterController: masterController
isActiveVehicle: _vehicle.active
property var _vehicle: object
PlanMasterController {
id: masterController
Component.onCompleted: startStaticActiveVehicle(object)
}
}
}
// Allow custom builds to add map items
CustomMapItems {
map: flightMap
largeMapView: _mainIsMap
}
GeoFenceMapVisuals {
map: flightMap
myGeoFenceController: _geoFenceController
interactive: false
planView: false
homePosition: _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition : QtPositioning.coordinate()
}
// Rally points on map
MapItemView {
model: _rallyPointController.points
delegate: MapQuickItem {
id: itemIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: object.coordinate
z: QGroundControl.zOrderMapItems
sourceItem: MissionItemIndexLabel {
id: itemIndexLabel
label: qsTr("R", "rally point map item label")
}
}
}
// Camera trigger points
MapItemView {
model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
delegate: CameraTriggerIndicator {
coordinate: object.coordinate
z: QGroundControl.zOrderTopMost
}
}
// GoTo Location visuals
MapQuickItem {
id: gotoLocationItem
visible: false
z: QGroundControl.zOrderMapItems
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Goto here", "Goto here waypoint")
}
property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : false
property var activeVehicle: _activeVehicle
onInGotoFlightModeChanged: {
if (!inGotoFlightMode && visible) {
// Hide goto indicator when vehicle falls out of guided mode
visible = false
}
}
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
gotoLocationItem.coordinate = coord
gotoLocationItem.visible = true
}
function hide() {
gotoLocationItem.visible = false
}
function actionConfirmed() {
// We leave the indicator visible. The handling for onInGuidedModeChanged will hide it.
}
function actionCancelled() {
hide()
}
}
// Orbit editing visuals
QGCMapCircleVisuals {
id: orbitMapCircle
mapControl: parent
mapCircle: _mapCircle
visible: false
property alias center: _mapCircle.center
property alias clockwiseRotation: _mapCircle.clockwiseRotation
property var activeVehicle: _activeVehicle
readonly property real defaultRadius: 30
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
_mapCircle.radius.rawValue = defaultRadius
orbitMapCircle.center = coord
orbitMapCircle.visible = true
}
function hide() {
orbitMapCircle.visible = false
}
function actionConfirmed() {
// Live orbit status is handled by telemetry so we hide here and telemetry will show again.
hide()
}
function actionCancelled() {
hide()
}
function radius() {
return _mapCircle.radius.rawValue
}
Component.onCompleted: guidedActionsController.orbitMapCircle = orbitMapCircle
QGCMapCircle {
id: _mapCircle
interactive: true
radius.rawValue: 30
showRotation: true
clockwiseRotation: true
}
}
// Orbit telemetry visuals
QGCMapCircleVisuals {
id: orbitTelemetryCircle
mapControl: parent
mapCircle: _activeVehicle ? _activeVehicle.orbitMapCircle : null
visible: _activeVehicle ? _activeVehicle.orbitActive : false
}
MapQuickItem {
id: orbitCenterIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: _activeVehicle ? _activeVehicle.orbitMapCircle.center : QtPositioning.coordinate()
visible: orbitTelemetryCircle.visible
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Orbit", "Orbit waypoint")
}
}
// Handle guided mode clicks
MouseArea {
anchors.fill: parent
Menu {
id: clickMenu
property var coord
MenuItem {
text: qsTr("Go to location")
visible: guidedActionsController.showGotoLocation
onTriggered: {
gotoLocationItem.show(clickMenu.coord)
orbitMapCircle.hide()
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickMenu.coord, gotoLocationItem)
}
}
MenuItem {
text: qsTr("Orbit at location")
visible: guidedActionsController.showOrbit
onTriggered: {
orbitMapCircle.show(clickMenu.coord)
gotoLocationItem.hide()
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickMenu.coord, orbitMapCircle)
}
}
}
onClicked: {
if (guidedActionsController.guidedUIVisible || (!guidedActionsController.showGotoLocation && !guidedActionsController.showOrbit)) {
return
}
orbitMapCircle.hide()
gotoLocationItem.hide()
var clickCoord = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
if (guidedActionsController.showGotoLocation && guidedActionsController.showOrbit) {
clickMenu.coord = clickCoord
clickMenu.popup()
} else if (guidedActionsController.showGotoLocation) {
gotoLocationItem.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickCoord)
} else if (guidedActionsController.showOrbit) {
orbitMapCircle.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickCoord)
}
}
}
MapScale {
id: mapScale
anchors.right: parent.right
anchors.margins: ScreenTools.defaultFontPixelHeight * (0.33)
anchors.topMargin: ScreenTools.defaultFontPixelHeight * (0.33) + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * (0.33)
mapControl: flightMap
visible: !ScreenTools.isTinyScreen
state: "bottomMode"
states: [
State {
name: "topMode"
AnchorChanges {
target: mapScale
anchors.top: parent.top
anchors.bottom: undefined
}
},
State {
name: "bottomMode"
AnchorChanges {
target: mapScale
anchors.top: undefined
anchors.bottom: parent.bottom
}
}
]
}
// Airspace overlap support
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.circles : []
delegate: MapCircle {
center: object.center
radius: object.radius
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.polygons : []
delegate: MapPolygon {
path: object.polygon
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
}
/****************************************************************************
*
* (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 QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Airspace 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightDisplay 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
FlightMap {
id: flightMap
anchors.fill: parent
mapName: _mapName
allowGCSLocationCenter: !userPanned
allowVehicleLocationCenter: !_keepVehicleCentered
planView: false
property alias scaleState: mapScale.state
// The following properties must be set by the consumer
property var planMasterController
property var wimaController
property var guidedActionsController
property var flightWidgets
property var rightPanelWidth
property var qgcView ///< QGCView control which contains this map
property var multiVehicleView ///< true: multi-vehicle view, false: single vehicle view
property rect centerViewport: Qt.rect(0, 0, width, height)
property var _planMasterController: planMasterController
property var _missionController: _planMasterController.missionController
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2)
property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false
property bool _disableVehicleTracking: false
property bool _keepVehicleCentered: _mainIsMap ? false : true
property bool _wimaEnabled: wimaController.enableWimaController.value
property bool _showAllWimaItems: wimaController.showAllMissionItems.value
property bool _showCurrentWimaItems: wimaController.showCurrentMissionItems.value
function updateAirspace(reset) {
if(_airspaceEnabled) {
var coordinateNW = flightMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */)
var coordinateSE = flightMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */)
if(coordinateNW.isValid && coordinateSE.isValid) {
QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE, false /*planView*/, reset)
}
}
}
// Track last known map position and zoom from Fly view in settings
onZoomLevelChanged: {
QGroundControl.flightMapZoom = zoomLevel
updateAirspace(false)
}
onCenterChanged: {
QGroundControl.flightMapPosition = center
updateAirspace(false)
}
// When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires
onUserPannedChanged: {
if (userPanned) {
console.log("user panned")
userPanned = false
_disableVehicleTracking = true
panRecenterTimer.restart()
}
}
on_AirspaceEnabledChanged: {
updateAirspace(true)
}
function pointInRect(point, rect) {
return point.x > rect.x &&
point.x < rect.x + rect.width &&
point.y > rect.y &&
point.y < rect.y + rect.height;
}
property real _animatedLatitudeStart
property real _animatedLatitudeStop
property real _animatedLongitudeStart
property real _animatedLongitudeStop
property real animatedLatitude
property real animatedLongitude
onAnimatedLatitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
onAnimatedLongitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
NumberAnimation on animatedLatitude { id: animateLat; from: _animatedLatitudeStart; to: _animatedLatitudeStop; duration: 1000 }
NumberAnimation on animatedLongitude { id: animateLong; from: _animatedLongitudeStart; to: _animatedLongitudeStop; duration: 1000 }
function animatedMapRecenter(fromCoord, toCoord) {
_animatedLatitudeStart = fromCoord.latitude
_animatedLongitudeStart = fromCoord.longitude
_animatedLatitudeStop = toCoord.latitude
_animatedLongitudeStop = toCoord.longitude
animateLat.start()
animateLong.start()
}
function recenterNeeded() {
var vehiclePoint = flightMap.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
var toolStripRightEdge = mapFromItem(toolStrip, toolStrip.x, 0).x + toolStrip.width
var instrumentsWidth = 0
if (QGroundControl.corePlugin.options.instrumentWidget && QGroundControl.corePlugin.options.instrumentWidget.widgetPosition === CustomInstrumentWidget.POS_TOP_RIGHT) {
// Assume standard instruments
instrumentsWidth = flightDisplayViewWidgets.getPreferredInstrumentWidth()
}
var centerViewport = Qt.rect(toolStripRightEdge, 0, width - toolStripRightEdge - instrumentsWidth, height)
return !pointInRect(vehiclePoint, centerViewport)
}
function updateMapToVehiclePosition() {
// We let FlightMap handle first vehicle position
if (firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
if (_keepVehicleCentered) {
flightMap.center = _activeVehicleCoordinate
} else {
if (firstVehiclePositionReceived && recenterNeeded()) {
animatedMapRecenter(flightMap.center, _activeVehicleCoordinate)
}
}
}
}
Timer {
id: panRecenterTimer
interval: 10000
running: false
onTriggered: {
_disableVehicleTracking = false
updateMapToVehiclePosition()
}
}
Timer {
interval: 500
running: true
repeat: true
onTriggered: updateMapToVehiclePosition()
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Connections {
target: _missionController
onNewItemsFromVehicle: {
var visualItems = _missionController.visualItems
if (visualItems && visualItems.count !== 1) {
mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true
}
}
}
ExclusiveGroup {
id: _mapTypeButtonsExclusiveGroup
}
MapFitFunctions {
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
map: _flightMap
usePlannedHomePosition: false
planMasterController: _planMasterController
property real leftToolWidth: toolStrip.x + toolStrip.width
}
// Add wima Areas to the Map
MapItemView {
property bool _enableWima: wimaController.enableWimaController.value
model: _enableWima ? wimaController.visualItems : 0
delegate: MapPolygon{
path: object.path;
border.color: "black"
color: object.type === "WimaJoinedAreaData" ? "gray"
: object.type === "WimaServiceAreaData" ? "yellow"
: object.type === "WimaMeasurementAreaData" ? "green"
: "transparent"
opacity: 0.25
z: 0
}
}
// Add mission items generated by wima planer to the map
// all Items
WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.missionItems
path: wimaController.waypointPath
showItems: _wimaEnabled && _showAllWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-2
zOrderLines: QGroundControl.zOrderWaypointLines-2
color: "gray"
}
// current Items
/*WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.currentMissionItems
path: wimaController.currentWaypointPath
showItems: _wimaEnabled && _showCurrentWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-1
<<<<<<< HEAD
zOrderLines: QGroundControl.zOrderWaypointIndicators-2
color: "green" // gray with alpha 0.7
}*/
=======
zOrderLines: QGroundControl.zOrderWaypointLines-1
color: "green"
}
>>>>>>> temp
// Add trajectory points to the map
MapItemView {
model: _mainIsMap ? _activeVehicle ? _activeVehicle.trajectoryPoints : 0 : 0
delegate: MapPolyline {
line.width: 3
line.color: "red"
z: QGroundControl.zOrderTrajectoryLines
path: [
object.coordinate1,
object.coordinate2,
]
}
}
// Add the vehicles to the map
MapItemView {
model: QGroundControl.multiVehicleManager.vehicles
delegate: VehicleMapItem {
vehicle: object
coordinate: object.coordinate
map: flightMap
size: _mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight
z: QGroundControl.zOrderVehicles
}
}
// Add ADSB vehicles to the map
MapItemView {
model: _activeVehicle ? _activeVehicle.adsbVehicles : []
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
delegate: VehicleMapItem {
coordinate: object.coordinate
altitude: object.altitude
callsign: object.callsign
heading: object.heading
alert: object.alert
map: flightMap
z: QGroundControl.zOrderVehicles
}
}
// Add the items associated with each vehicles flight plan to the map
Repeater {
model: QGroundControl.multiVehicleManager.vehicles
PlanMapItems {
map: flightMap
largeMapView: _mainIsMap
masterController: masterController
isActiveVehicle: _vehicle.active
property var _vehicle: object
PlanMasterController {
id: masterController
Component.onCompleted: startStaticActiveVehicle(object)
}
}
}
// Allow custom builds to add map items
CustomMapItems {
map: flightMap
largeMapView: _mainIsMap
}
GeoFenceMapVisuals {
map: flightMap
myGeoFenceController: _geoFenceController
interactive: false
planView: false
homePosition: _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition : QtPositioning.coordinate()
}
// Rally points on map
MapItemView {
model: _rallyPointController.points
delegate: MapQuickItem {
id: itemIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: object.coordinate
z: QGroundControl.zOrderMapItems
sourceItem: MissionItemIndexLabel {
id: itemIndexLabel
label: qsTr("R", "rally point map item label")
}
}
}
// Camera trigger points
MapItemView {
model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
delegate: CameraTriggerIndicator {
coordinate: object.coordinate
z: QGroundControl.zOrderTopMost
}
}
// GoTo Location visuals
MapQuickItem {
id: gotoLocationItem
visible: false
z: QGroundControl.zOrderMapItems
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Goto here", "Goto here waypoint")
}
property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : false
property var activeVehicle: _activeVehicle
onInGotoFlightModeChanged: {
if (!inGotoFlightMode && visible) {
// Hide goto indicator when vehicle falls out of guided mode
visible = false
}
}
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
gotoLocationItem.coordinate = coord
gotoLocationItem.visible = true
}
function hide() {
gotoLocationItem.visible = false
}
function actionConfirmed() {
// We leave the indicator visible. The handling for onInGuidedModeChanged will hide it.
}
function actionCancelled() {
hide()
}
}
// Orbit editing visuals
QGCMapCircleVisuals {
id: orbitMapCircle
mapControl: parent
mapCircle: _mapCircle
visible: false
property alias center: _mapCircle.center
property alias clockwiseRotation: _mapCircle.clockwiseRotation
property var activeVehicle: _activeVehicle
readonly property real defaultRadius: 30
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
_mapCircle.radius.rawValue = defaultRadius
orbitMapCircle.center = coord
orbitMapCircle.visible = true
}
function hide() {
orbitMapCircle.visible = false
}
function actionConfirmed() {
// Live orbit status is handled by telemetry so we hide here and telemetry will show again.
hide()
}
function actionCancelled() {
hide()
}
function radius() {
return _mapCircle.radius.rawValue
}
Component.onCompleted: guidedActionsController.orbitMapCircle = orbitMapCircle
QGCMapCircle {
id: _mapCircle
interactive: true
radius.rawValue: 30
showRotation: true
clockwiseRotation: true
}
}
// Orbit telemetry visuals
QGCMapCircleVisuals {
id: orbitTelemetryCircle
mapControl: parent
mapCircle: _activeVehicle ? _activeVehicle.orbitMapCircle : null
visible: _activeVehicle ? _activeVehicle.orbitActive : false
}
MapQuickItem {
id: orbitCenterIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: _activeVehicle ? _activeVehicle.orbitMapCircle.center : QtPositioning.coordinate()
visible: orbitTelemetryCircle.visible
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Orbit", "Orbit waypoint")
}
}
// Handle guided mode clicks
MouseArea {
anchors.fill: parent
Menu {
id: clickMenu
property var coord
MenuItem {
text: qsTr("Go to location")
visible: guidedActionsController.showGotoLocation
onTriggered: {
gotoLocationItem.show(clickMenu.coord)
orbitMapCircle.hide()
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickMenu.coord, gotoLocationItem)
}
}
MenuItem {
text: qsTr("Orbit at location")
visible: guidedActionsController.showOrbit
onTriggered: {
orbitMapCircle.show(clickMenu.coord)
gotoLocationItem.hide()
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickMenu.coord, orbitMapCircle)
}
}
}
onClicked: {
if (guidedActionsController.guidedUIVisible || (!guidedActionsController.showGotoLocation && !guidedActionsController.showOrbit)) {
return
}
orbitMapCircle.hide()
gotoLocationItem.hide()
var clickCoord = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
if (guidedActionsController.showGotoLocation && guidedActionsController.showOrbit) {
clickMenu.coord = clickCoord
clickMenu.popup()
} else if (guidedActionsController.showGotoLocation) {
gotoLocationItem.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickCoord)
} else if (guidedActionsController.showOrbit) {
orbitMapCircle.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickCoord)
}
}
}
MapScale {
id: mapScale
anchors.right: parent.right
anchors.margins: ScreenTools.defaultFontPixelHeight * (0.33)
anchors.topMargin: ScreenTools.defaultFontPixelHeight * (0.33) + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * (0.33)
mapControl: flightMap
visible: !ScreenTools.isTinyScreen
state: "bottomMode"
states: [
State {
name: "topMode"
AnchorChanges {
target: mapScale
anchors.top: parent.top
anchors.bottom: undefined
}
},
State {
name: "bottomMode"
AnchorChanges {
target: mapScale
anchors.top: undefined
anchors.bottom: parent.bottom
}
}
]
}
// Airspace overlap support
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.circles : []
delegate: MapCircle {
center: object.center
radius: object.radius
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.polygons : []
delegate: MapPolygon {
path: object.polygon
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
}
/****************************************************************************
*
* (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 QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Airspace 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightDisplay 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
FlightMap {
id: flightMap
anchors.fill: parent
mapName: _mapName
allowGCSLocationCenter: !userPanned
allowVehicleLocationCenter: !_keepVehicleCentered
planView: false
property alias scaleState: mapScale.state
// The following properties must be set by the consumer
property var planMasterController
property var wimaController
property var guidedActionsController
property var flightWidgets
property var rightPanelWidth
property var qgcView ///< QGCView control which contains this map
property var multiVehicleView ///< true: multi-vehicle view, false: single vehicle view
property rect centerViewport: Qt.rect(0, 0, width, height)
property var _planMasterController: planMasterController
property var _missionController: _planMasterController.missionController
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2)
property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false
property bool _disableVehicleTracking: false
property bool _keepVehicleCentered: _mainIsMap ? false : true
property bool _wimaEnabled: wimaController.enableWimaController.value
property bool _showAllWimaItems: wimaController.showAllMissionItems.value
property bool _showCurrentWimaItems: wimaController.showCurrentMissionItems.value
function updateAirspace(reset) {
if(_airspaceEnabled) {
var coordinateNW = flightMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */)
var coordinateSE = flightMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */)
if(coordinateNW.isValid && coordinateSE.isValid) {
QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE, false /*planView*/, reset)
}
}
}
// Track last known map position and zoom from Fly view in settings
onZoomLevelChanged: {
QGroundControl.flightMapZoom = zoomLevel
updateAirspace(false)
}
onCenterChanged: {
QGroundControl.flightMapPosition = center
updateAirspace(false)
}
// When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires
onUserPannedChanged: {
if (userPanned) {
console.log("user panned")
userPanned = false
_disableVehicleTracking = true
panRecenterTimer.restart()
}
}
on_AirspaceEnabledChanged: {
updateAirspace(true)
}
function pointInRect(point, rect) {
return point.x > rect.x &&
point.x < rect.x + rect.width &&
point.y > rect.y &&
point.y < rect.y + rect.height;
}
property real _animatedLatitudeStart
property real _animatedLatitudeStop
property real _animatedLongitudeStart
property real _animatedLongitudeStop
property real animatedLatitude
property real animatedLongitude
onAnimatedLatitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
onAnimatedLongitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
NumberAnimation on animatedLatitude { id: animateLat; from: _animatedLatitudeStart; to: _animatedLatitudeStop; duration: 1000 }
NumberAnimation on animatedLongitude { id: animateLong; from: _animatedLongitudeStart; to: _animatedLongitudeStop; duration: 1000 }
function animatedMapRecenter(fromCoord, toCoord) {
_animatedLatitudeStart = fromCoord.latitude
_animatedLongitudeStart = fromCoord.longitude
_animatedLatitudeStop = toCoord.latitude
_animatedLongitudeStop = toCoord.longitude
animateLat.start()
animateLong.start()
}
function recenterNeeded() {
var vehiclePoint = flightMap.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
var toolStripRightEdge = mapFromItem(toolStrip, toolStrip.x, 0).x + toolStrip.width
var instrumentsWidth = 0
if (QGroundControl.corePlugin.options.instrumentWidget && QGroundControl.corePlugin.options.instrumentWidget.widgetPosition === CustomInstrumentWidget.POS_TOP_RIGHT) {
// Assume standard instruments
instrumentsWidth = flightDisplayViewWidgets.getPreferredInstrumentWidth()
}
var centerViewport = Qt.rect(toolStripRightEdge, 0, width - toolStripRightEdge - instrumentsWidth, height)
return !pointInRect(vehiclePoint, centerViewport)
}
function updateMapToVehiclePosition() {
// We let FlightMap handle first vehicle position
if (firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
if (_keepVehicleCentered) {
flightMap.center = _activeVehicleCoordinate
} else {
if (firstVehiclePositionReceived && recenterNeeded()) {
animatedMapRecenter(flightMap.center, _activeVehicleCoordinate)
}
}
}
}
Timer {
id: panRecenterTimer
interval: 10000
running: false
onTriggered: {
_disableVehicleTracking = false
updateMapToVehiclePosition()
}
}
Timer {
interval: 500
running: true
repeat: true
onTriggered: updateMapToVehiclePosition()
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Connections {
target: _missionController
onNewItemsFromVehicle: {
var visualItems = _missionController.visualItems
if (visualItems && visualItems.count !== 1) {
mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true
}
}
}
ExclusiveGroup {
id: _mapTypeButtonsExclusiveGroup
}
MapFitFunctions {
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
map: _flightMap
usePlannedHomePosition: false
planMasterController: _planMasterController
property real leftToolWidth: toolStrip.x + toolStrip.width
}
// Add wima Areas to the Map
MapItemView {
property bool _enableWima: wimaController.enableWimaController.value
model: _enableWima ? wimaController.visualItems : 0
delegate: MapPolygon{
path: object.path;
border.color: "black"
color: object.type === "WimaJoinedAreaData" ? "gray"
: object.type === "WimaServiceAreaData" ? "yellow"
: object.type === "WimaMeasurementAreaData" ? "green"
: "transparent"
opacity: 0.25
z: 0
}
}
// Add mission items generated by wima planer to the map
// all Items
WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.missionItems
path: wimaController.waypointPath
showItems: _wimaEnabled && _showAllWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-3
zOrderLines: QGroundControl.zOrderWaypointLines-1
color: "gray"
}
// current Items
WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.currentMissionItems
path: wimaController.currentWaypointPath
showItems: _wimaEnabled && _showCurrentWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-1
zOrderLines: QGroundControl.zOrderWaypointIndicators-2
color: "green" // gray with alpha 0.7
}
// Add trajectory points to the map
MapItemView {
model: _mainIsMap ? _activeVehicle ? _activeVehicle.trajectoryPoints : 0 : 0
delegate: MapPolyline {
line.width: 3
line.color: "red"
z: QGroundControl.zOrderTrajectoryLines
path: [
object.coordinate1,
object.coordinate2,
]
}
}
// Add the vehicles to the map
MapItemView {
model: QGroundControl.multiVehicleManager.vehicles
delegate: VehicleMapItem {
vehicle: object
coordinate: object.coordinate
map: flightMap
size: _mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight
z: QGroundControl.zOrderVehicles
}
}
// Add ADSB vehicles to the map
MapItemView {
model: _activeVehicle ? _activeVehicle.adsbVehicles : []
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
delegate: VehicleMapItem {
coordinate: object.coordinate
altitude: object.altitude
callsign: object.callsign
heading: object.heading
alert: object.alert
map: flightMap
z: QGroundControl.zOrderVehicles
}
}
// Add the items associated with each vehicles flight plan to the map
Repeater {
model: QGroundControl.multiVehicleManager.vehicles
PlanMapItems {
map: flightMap
largeMapView: _mainIsMap
masterController: masterController
isActiveVehicle: _vehicle.active
property var _vehicle: object
PlanMasterController {
id: masterController
Component.onCompleted: startStaticActiveVehicle(object)
}
}
}
// Allow custom builds to add map items
CustomMapItems {
map: flightMap
largeMapView: _mainIsMap
}
GeoFenceMapVisuals {
map: flightMap
myGeoFenceController: _geoFenceController
interactive: false
planView: false
homePosition: _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition : QtPositioning.coordinate()
}
// Rally points on map
MapItemView {
model: _rallyPointController.points
delegate: MapQuickItem {
id: itemIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: object.coordinate
z: QGroundControl.zOrderMapItems
sourceItem: MissionItemIndexLabel {
id: itemIndexLabel
label: qsTr("R", "rally point map item label")
}
}
}
// Camera trigger points
MapItemView {
model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
delegate: CameraTriggerIndicator {
coordinate: object.coordinate
z: QGroundControl.zOrderTopMost
}
}
// GoTo Location visuals
MapQuickItem {
id: gotoLocationItem
visible: false
z: QGroundControl.zOrderMapItems
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Goto here", "Goto here waypoint")
}
property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : false
property var activeVehicle: _activeVehicle
onInGotoFlightModeChanged: {
if (!inGotoFlightMode && visible) {
// Hide goto indicator when vehicle falls out of guided mode
visible = false
}
}
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
gotoLocationItem.coordinate = coord
gotoLocationItem.visible = true
}
function hide() {
gotoLocationItem.visible = false
}
function actionConfirmed() {
// We leave the indicator visible. The handling for onInGuidedModeChanged will hide it.
}
function actionCancelled() {
hide()
}
}
// Orbit editing visuals
QGCMapCircleVisuals {
id: orbitMapCircle
mapControl: parent
mapCircle: _mapCircle
visible: false
property alias center: _mapCircle.center
property alias clockwiseRotation: _mapCircle.clockwiseRotation
property var activeVehicle: _activeVehicle
readonly property real defaultRadius: 30
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
_mapCircle.radius.rawValue = defaultRadius
orbitMapCircle.center = coord
orbitMapCircle.visible = true
}
function hide() {
orbitMapCircle.visible = false
}
function actionConfirmed() {
// Live orbit status is handled by telemetry so we hide here and telemetry will show again.
hide()
}
function actionCancelled() {
hide()
}
function radius() {
return _mapCircle.radius.rawValue
}
Component.onCompleted: guidedActionsController.orbitMapCircle = orbitMapCircle
QGCMapCircle {
id: _mapCircle
interactive: true
radius.rawValue: 30
showRotation: true
clockwiseRotation: true
}
}
// Orbit telemetry visuals
QGCMapCircleVisuals {
id: orbitTelemetryCircle
mapControl: parent
mapCircle: _activeVehicle ? _activeVehicle.orbitMapCircle : null
visible: _activeVehicle ? _activeVehicle.orbitActive : false
}
MapQuickItem {
id: orbitCenterIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: _activeVehicle ? _activeVehicle.orbitMapCircle.center : QtPositioning.coordinate()
visible: orbitTelemetryCircle.visible
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Orbit", "Orbit waypoint")
}
}
// Handle guided mode clicks
MouseArea {
anchors.fill: parent
Menu {
id: clickMenu
property var coord
MenuItem {
text: qsTr("Go to location")
visible: guidedActionsController.showGotoLocation
onTriggered: {
gotoLocationItem.show(clickMenu.coord)
orbitMapCircle.hide()
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickMenu.coord, gotoLocationItem)
}
}
MenuItem {
text: qsTr("Orbit at location")
visible: guidedActionsController.showOrbit
onTriggered: {
orbitMapCircle.show(clickMenu.coord)
gotoLocationItem.hide()
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickMenu.coord, orbitMapCircle)
}
}
}
onClicked: {
if (guidedActionsController.guidedUIVisible || (!guidedActionsController.showGotoLocation && !guidedActionsController.showOrbit)) {
return
}
orbitMapCircle.hide()
gotoLocationItem.hide()
var clickCoord = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
if (guidedActionsController.showGotoLocation && guidedActionsController.showOrbit) {
clickMenu.coord = clickCoord
clickMenu.popup()
} else if (guidedActionsController.showGotoLocation) {
gotoLocationItem.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickCoord)
} else if (guidedActionsController.showOrbit) {
orbitMapCircle.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickCoord)
}
}
}
MapScale {
id: mapScale
anchors.right: parent.right
anchors.margins: ScreenTools.defaultFontPixelHeight * (0.33)
anchors.topMargin: ScreenTools.defaultFontPixelHeight * (0.33) + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * (0.33)
mapControl: flightMap
visible: !ScreenTools.isTinyScreen
state: "bottomMode"
states: [
State {
name: "topMode"
AnchorChanges {
target: mapScale
anchors.top: parent.top
anchors.bottom: undefined
}
},
State {
name: "bottomMode"
AnchorChanges {
target: mapScale
anchors.top: undefined
anchors.bottom: parent.bottom
}
}
]
}
// Airspace overlap support
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.circles : []
delegate: MapCircle {
center: object.center
radius: object.radius
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.polygons : []
delegate: MapPolygon {
path: object.polygon
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
}
/****************************************************************************
*
* (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 QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Airspace 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightDisplay 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
FlightMap {
id: flightMap
anchors.fill: parent
mapName: _mapName
allowGCSLocationCenter: !userPanned
allowVehicleLocationCenter: !_keepVehicleCentered
planView: false
property alias scaleState: mapScale.state
// The following properties must be set by the consumer
property var planMasterController
property var wimaController
property var guidedActionsController
property var flightWidgets
property var rightPanelWidth
property var qgcView ///< QGCView control which contains this map
property var multiVehicleView ///< true: multi-vehicle view, false: single vehicle view
property rect centerViewport: Qt.rect(0, 0, width, height)
property var _planMasterController: planMasterController
property var _missionController: _planMasterController.missionController
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2)
property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false
property bool _disableVehicleTracking: false
property bool _keepVehicleCentered: _mainIsMap ? false : true
property bool _wimaEnabled: wimaController.enableWimaController.value
property bool _showAllWimaItems: wimaController.showAllMissionItems.value
property bool _showCurrentWimaItems: wimaController.showCurrentMissionItems.value
function updateAirspace(reset) {
if(_airspaceEnabled) {
var coordinateNW = flightMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */)
var coordinateSE = flightMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */)
if(coordinateNW.isValid && coordinateSE.isValid) {
QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE, false /*planView*/, reset)
}
}
}
// Track last known map position and zoom from Fly view in settings
onZoomLevelChanged: {
QGroundControl.flightMapZoom = zoomLevel
updateAirspace(false)
}
onCenterChanged: {
QGroundControl.flightMapPosition = center
updateAirspace(false)
}
// When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires
onUserPannedChanged: {
if (userPanned) {
console.log("user panned")
userPanned = false
_disableVehicleTracking = true
panRecenterTimer.restart()
}
}
on_AirspaceEnabledChanged: {
updateAirspace(true)
}
function pointInRect(point, rect) {
return point.x > rect.x &&
point.x < rect.x + rect.width &&
point.y > rect.y &&
point.y < rect.y + rect.height;
}
property real _animatedLatitudeStart
property real _animatedLatitudeStop
property real _animatedLongitudeStart
property real _animatedLongitudeStop
property real animatedLatitude
property real animatedLongitude
onAnimatedLatitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
onAnimatedLongitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
NumberAnimation on animatedLatitude { id: animateLat; from: _animatedLatitudeStart; to: _animatedLatitudeStop; duration: 1000 }
NumberAnimation on animatedLongitude { id: animateLong; from: _animatedLongitudeStart; to: _animatedLongitudeStop; duration: 1000 }
function animatedMapRecenter(fromCoord, toCoord) {
_animatedLatitudeStart = fromCoord.latitude
_animatedLongitudeStart = fromCoord.longitude
_animatedLatitudeStop = toCoord.latitude
_animatedLongitudeStop = toCoord.longitude
animateLat.start()
animateLong.start()
}
function recenterNeeded() {
var vehiclePoint = flightMap.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
var toolStripRightEdge = mapFromItem(toolStrip, toolStrip.x, 0).x + toolStrip.width
var instrumentsWidth = 0
if (QGroundControl.corePlugin.options.instrumentWidget && QGroundControl.corePlugin.options.instrumentWidget.widgetPosition === CustomInstrumentWidget.POS_TOP_RIGHT) {
// Assume standard instruments
instrumentsWidth = flightDisplayViewWidgets.getPreferredInstrumentWidth()
}
var centerViewport = Qt.rect(toolStripRightEdge, 0, width - toolStripRightEdge - instrumentsWidth, height)
return !pointInRect(vehiclePoint, centerViewport)
}
function updateMapToVehiclePosition() {
// We let FlightMap handle first vehicle position
if (firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
if (_keepVehicleCentered) {
flightMap.center = _activeVehicleCoordinate
} else {
if (firstVehiclePositionReceived && recenterNeeded()) {
animatedMapRecenter(flightMap.center, _activeVehicleCoordinate)
}
}
}
}
Timer {
id: panRecenterTimer
interval: 10000
running: false
onTriggered: {
_disableVehicleTracking = false
updateMapToVehiclePosition()
}
}
Timer {
interval: 500
running: true
repeat: true
onTriggered: updateMapToVehiclePosition()
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Connections {
target: _missionController
onNewItemsFromVehicle: {
var visualItems = _missionController.visualItems
if (visualItems && visualItems.count !== 1) {
mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true
}
}
}
ExclusiveGroup {
id: _mapTypeButtonsExclusiveGroup
}
MapFitFunctions {
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
map: _flightMap
usePlannedHomePosition: false
planMasterController: _planMasterController
property real leftToolWidth: toolStrip.x + toolStrip.width
}
// Add wima Areas to the Map
MapItemView {
property bool _enableWima: wimaController.enableWimaController.value
model: _enableWima ? wimaController.visualItems : 0
delegate: MapPolygon{
path: object.path;
border.color: "black"
color: object.type === "WimaJoinedAreaData" ? "gray"
: object.type === "WimaServiceAreaData" ? "yellow"
: object.type === "WimaMeasurementAreaData" ? "green"
: "transparent"
opacity: 0.25
z: 0
}
}
// Add mission items generated by wima planer to the map
// all Items
WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.missionItems
path: wimaController.waypointPath
showItems: _wimaEnabled && _showAllWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-3
zOrderLines: QGroundControl.zOrderWaypointLines-1
color: "gray"
}
// current Items
/*WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.currentMissionItems
path: wimaController.currentWaypointPath
showItems: _wimaEnabled && _showCurrentWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-1
zOrderLines: QGroundControl.zOrderWaypointIndicators-2
color: "green" // gray with alpha 0.7
}*/
// Add trajectory points to the map
MapItemView {
model: _mainIsMap ? _activeVehicle ? _activeVehicle.trajectoryPoints : 0 : 0
delegate: MapPolyline {
line.width: 3
line.color: "red"
z: QGroundControl.zOrderTrajectoryLines
path: [
object.coordinate1,
object.coordinate2,
]
}
}
// Add the vehicles to the map
MapItemView {
model: QGroundControl.multiVehicleManager.vehicles
delegate: VehicleMapItem {
vehicle: object
coordinate: object.coordinate
map: flightMap
size: _mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight
z: QGroundControl.zOrderVehicles
}
}
// Add ADSB vehicles to the map
MapItemView {
model: _activeVehicle ? _activeVehicle.adsbVehicles : []
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
delegate: VehicleMapItem {
coordinate: object.coordinate
altitude: object.altitude
callsign: object.callsign
heading: object.heading
alert: object.alert
map: flightMap
z: QGroundControl.zOrderVehicles
}
}
// Add the items associated with each vehicles flight plan to the map
Repeater {
model: QGroundControl.multiVehicleManager.vehicles
PlanMapItems {
map: flightMap
largeMapView: _mainIsMap
masterController: masterController
isActiveVehicle: _vehicle.active
property var _vehicle: object
PlanMasterController {
id: masterController
Component.onCompleted: startStaticActiveVehicle(object)
}
}
}
// Allow custom builds to add map items
CustomMapItems {
map: flightMap
largeMapView: _mainIsMap
}
GeoFenceMapVisuals {
map: flightMap
myGeoFenceController: _geoFenceController
interactive: false
planView: false
homePosition: _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition : QtPositioning.coordinate()
}
// Rally points on map
MapItemView {
model: _rallyPointController.points
delegate: MapQuickItem {
id: itemIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: object.coordinate
z: QGroundControl.zOrderMapItems
sourceItem: MissionItemIndexLabel {
id: itemIndexLabel
label: qsTr("R", "rally point map item label")
}
}
}
// Camera trigger points
MapItemView {
model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
delegate: CameraTriggerIndicator {
coordinate: object.coordinate
z: QGroundControl.zOrderTopMost
}
}
// GoTo Location visuals
MapQuickItem {
id: gotoLocationItem
visible: false
z: QGroundControl.zOrderMapItems
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Goto here", "Goto here waypoint")
}
property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : false
property var activeVehicle: _activeVehicle
onInGotoFlightModeChanged: {
if (!inGotoFlightMode && visible) {
// Hide goto indicator when vehicle falls out of guided mode
visible = false
}
}
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
gotoLocationItem.coordinate = coord
gotoLocationItem.visible = true
}
function hide() {
gotoLocationItem.visible = false
}
function actionConfirmed() {
// We leave the indicator visible. The handling for onInGuidedModeChanged will hide it.
}
function actionCancelled() {
hide()
}
}
// Orbit editing visuals
QGCMapCircleVisuals {
id: orbitMapCircle
mapControl: parent
mapCircle: _mapCircle
visible: false
property alias center: _mapCircle.center
property alias clockwiseRotation: _mapCircle.clockwiseRotation
property var activeVehicle: _activeVehicle
readonly property real defaultRadius: 30
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
_mapCircle.radius.rawValue = defaultRadius
orbitMapCircle.center = coord
orbitMapCircle.visible = true
}
function hide() {
orbitMapCircle.visible = false
}
function actionConfirmed() {
// Live orbit status is handled by telemetry so we hide here and telemetry will show again.
hide()
}
function actionCancelled() {
hide()
}
function radius() {
return _mapCircle.radius.rawValue
}
Component.onCompleted: guidedActionsController.orbitMapCircle = orbitMapCircle
QGCMapCircle {
id: _mapCircle
interactive: true
radius.rawValue: 30
showRotation: true
clockwiseRotation: true
}
}
// Orbit telemetry visuals
QGCMapCircleVisuals {
id: orbitTelemetryCircle
mapControl: parent
mapCircle: _activeVehicle ? _activeVehicle.orbitMapCircle : null
visible: _activeVehicle ? _activeVehicle.orbitActive : false
}
MapQuickItem {
id: orbitCenterIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: _activeVehicle ? _activeVehicle.orbitMapCircle.center : QtPositioning.coordinate()
visible: orbitTelemetryCircle.visible
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Orbit", "Orbit waypoint")
}
}
// Handle guided mode clicks
MouseArea {
anchors.fill: parent
Menu {
id: clickMenu
property var coord
MenuItem {
text: qsTr("Go to location")
visible: guidedActionsController.showGotoLocation
onTriggered: {
gotoLocationItem.show(clickMenu.coord)
orbitMapCircle.hide()
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickMenu.coord, gotoLocationItem)
}
}
MenuItem {
text: qsTr("Orbit at location")
visible: guidedActionsController.showOrbit
onTriggered: {
orbitMapCircle.show(clickMenu.coord)
gotoLocationItem.hide()
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickMenu.coord, orbitMapCircle)
}
}
}
onClicked: {
if (guidedActionsController.guidedUIVisible || (!guidedActionsController.showGotoLocation && !guidedActionsController.showOrbit)) {
return
}
orbitMapCircle.hide()
gotoLocationItem.hide()
var clickCoord = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
if (guidedActionsController.showGotoLocation && guidedActionsController.showOrbit) {
clickMenu.coord = clickCoord
clickMenu.popup()
} else if (guidedActionsController.showGotoLocation) {
gotoLocationItem.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickCoord)
} else if (guidedActionsController.showOrbit) {
orbitMapCircle.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickCoord)
}
}
}
MapScale {
id: mapScale
anchors.right: parent.right
anchors.margins: ScreenTools.defaultFontPixelHeight * (0.33)
anchors.topMargin: ScreenTools.defaultFontPixelHeight * (0.33) + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * (0.33)
mapControl: flightMap
visible: !ScreenTools.isTinyScreen
state: "bottomMode"
states: [
State {
name: "topMode"
AnchorChanges {
target: mapScale
anchors.top: parent.top
anchors.bottom: undefined
}
},
State {
name: "bottomMode"
AnchorChanges {
target: mapScale
anchors.top: undefined
anchors.bottom: parent.bottom
}
}
]
}
// Airspace overlap support
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.circles : []
delegate: MapCircle {
center: object.center
radius: object.radius
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.polygons : []
delegate: MapPolygon {
path: object.polygon
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
}
/****************************************************************************
*
* (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 QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.Airspace 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightDisplay 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
FlightMap {
id: flightMap
anchors.fill: parent
mapName: _mapName
allowGCSLocationCenter: !userPanned
allowVehicleLocationCenter: !_keepVehicleCentered
planView: false
property alias scaleState: mapScale.state
// The following properties must be set by the consumer
property var planMasterController
property var wimaController
property var guidedActionsController
property var flightWidgets
property var rightPanelWidth
property var qgcView ///< QGCView control which contains this map
property var multiVehicleView ///< true: multi-vehicle view, false: single vehicle view
property rect centerViewport: Qt.rect(0, 0, width, height)
property var _planMasterController: planMasterController
property var _missionController: _planMasterController.missionController
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2)
property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false
property bool _disableVehicleTracking: false
property bool _keepVehicleCentered: _mainIsMap ? false : true
property bool _wimaEnabled: wimaController.enableWimaController.value
property bool _showAllWimaItems: wimaController.showAllMissionItems.value
property bool _showCurrentWimaItems: wimaController.showCurrentMissionItems.value
function updateAirspace(reset) {
if(_airspaceEnabled) {
var coordinateNW = flightMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */)
var coordinateSE = flightMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */)
if(coordinateNW.isValid && coordinateSE.isValid) {
QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE, false /*planView*/, reset)
}
}
}
// Track last known map position and zoom from Fly view in settings
onZoomLevelChanged: {
QGroundControl.flightMapZoom = zoomLevel
updateAirspace(false)
}
onCenterChanged: {
QGroundControl.flightMapPosition = center
updateAirspace(false)
}
// When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires
onUserPannedChanged: {
if (userPanned) {
console.log("user panned")
userPanned = false
_disableVehicleTracking = true
panRecenterTimer.restart()
}
}
on_AirspaceEnabledChanged: {
updateAirspace(true)
}
function pointInRect(point, rect) {
return point.x > rect.x &&
point.x < rect.x + rect.width &&
point.y > rect.y &&
point.y < rect.y + rect.height;
}
property real _animatedLatitudeStart
property real _animatedLatitudeStop
property real _animatedLongitudeStart
property real _animatedLongitudeStop
property real animatedLatitude
property real animatedLongitude
onAnimatedLatitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
onAnimatedLongitudeChanged: flightMap.center = QtPositioning.coordinate(animatedLatitude, animatedLongitude)
NumberAnimation on animatedLatitude { id: animateLat; from: _animatedLatitudeStart; to: _animatedLatitudeStop; duration: 1000 }
NumberAnimation on animatedLongitude { id: animateLong; from: _animatedLongitudeStart; to: _animatedLongitudeStop; duration: 1000 }
function animatedMapRecenter(fromCoord, toCoord) {
_animatedLatitudeStart = fromCoord.latitude
_animatedLongitudeStart = fromCoord.longitude
_animatedLatitudeStop = toCoord.latitude
_animatedLongitudeStop = toCoord.longitude
animateLat.start()
animateLong.start()
}
function recenterNeeded() {
var vehiclePoint = flightMap.fromCoordinate(_activeVehicleCoordinate, false /* clipToViewport */)
var toolStripRightEdge = mapFromItem(toolStrip, toolStrip.x, 0).x + toolStrip.width
var instrumentsWidth = 0
if (QGroundControl.corePlugin.options.instrumentWidget && QGroundControl.corePlugin.options.instrumentWidget.widgetPosition === CustomInstrumentWidget.POS_TOP_RIGHT) {
// Assume standard instruments
instrumentsWidth = flightDisplayViewWidgets.getPreferredInstrumentWidth()
}
var centerViewport = Qt.rect(toolStripRightEdge, 0, width - toolStripRightEdge - instrumentsWidth, height)
return !pointInRect(vehiclePoint, centerViewport)
}
function updateMapToVehiclePosition() {
// We let FlightMap handle first vehicle position
if (firstVehiclePositionReceived && _activeVehicleCoordinate.isValid && !_disableVehicleTracking) {
if (_keepVehicleCentered) {
flightMap.center = _activeVehicleCoordinate
} else {
if (firstVehiclePositionReceived && recenterNeeded()) {
animatedMapRecenter(flightMap.center, _activeVehicleCoordinate)
}
}
}
}
Timer {
id: panRecenterTimer
interval: 10000
running: false
onTriggered: {
_disableVehicleTracking = false
updateMapToVehiclePosition()
}
}
Timer {
interval: 500
running: true
repeat: true
onTriggered: updateMapToVehiclePosition()
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Connections {
target: _missionController
onNewItemsFromVehicle: {
var visualItems = _missionController.visualItems
if (visualItems && visualItems.count !== 1) {
mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true
}
}
}
ExclusiveGroup {
id: _mapTypeButtonsExclusiveGroup
}
MapFitFunctions {
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
map: _flightMap
usePlannedHomePosition: false
planMasterController: _planMasterController
property real leftToolWidth: toolStrip.x + toolStrip.width
}
// Add wima Areas to the Map
MapItemView {
property bool _enableWima: wimaController.enableWimaController.value
model: _enableWima ? wimaController.visualItems : 0
delegate: MapPolygon{
path: object.path;
border.color: "black"
color: object.type === "WimaJoinedAreaData" ? "gray"
: object.type === "WimaServiceAreaData" ? "yellow"
: object.type === "WimaMeasurementAreaData" ? "green"
: "transparent"
opacity: 0.25
z: 0
}
}
// Add mission items generated by wima planer to the map
// all Items
WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.missionItems
path: wimaController.waypointPath
showItems: _wimaEnabled && _showAllWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-2
zOrderLines: QGroundControl.zOrderWaypointLines-2
color: "gray"
}
// current Items
WimaPlanMapItems {
map: flightMap
largeMapView: _mainIsMap
missionItems: wimaController.currentMissionItems
path: wimaController.currentWaypointPath
showItems: _wimaEnabled && _showCurrentWimaItems
zOrderWP: QGroundControl.zOrderWaypointIndicators-1
zOrderLines: QGroundControl.zOrderWaypointLines-1
color: "green"
}
// Add trajectory points to the map
MapItemView {
model: _mainIsMap ? _activeVehicle ? _activeVehicle.trajectoryPoints : 0 : 0
delegate: MapPolyline {
line.width: 3
line.color: "red"
z: QGroundControl.zOrderTrajectoryLines
path: [
object.coordinate1,
object.coordinate2,
]
}
}
// Add the vehicles to the map
MapItemView {
model: QGroundControl.multiVehicleManager.vehicles
delegate: VehicleMapItem {
vehicle: object
coordinate: object.coordinate
map: flightMap
size: _mainIsMap ? ScreenTools.defaultFontPixelHeight * 3 : ScreenTools.defaultFontPixelHeight
z: QGroundControl.zOrderVehicles
}
}
// Add ADSB vehicles to the map
MapItemView {
model: _activeVehicle ? _activeVehicle.adsbVehicles : []
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
delegate: VehicleMapItem {
coordinate: object.coordinate
altitude: object.altitude
callsign: object.callsign
heading: object.heading
alert: object.alert
map: flightMap
z: QGroundControl.zOrderVehicles
}
}
// Add the items associated with each vehicles flight plan to the map
Repeater {
model: QGroundControl.multiVehicleManager.vehicles
PlanMapItems {
map: flightMap
largeMapView: _mainIsMap
masterController: masterController
isActiveVehicle: _vehicle.active
property var _vehicle: object
PlanMasterController {
id: masterController
Component.onCompleted: startStaticActiveVehicle(object)
}
}
}
// Allow custom builds to add map items
CustomMapItems {
map: flightMap
largeMapView: _mainIsMap
}
GeoFenceMapVisuals {
map: flightMap
myGeoFenceController: _geoFenceController
interactive: false
planView: false
homePosition: _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition : QtPositioning.coordinate()
}
// Rally points on map
MapItemView {
model: _rallyPointController.points
delegate: MapQuickItem {
id: itemIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: object.coordinate
z: QGroundControl.zOrderMapItems
sourceItem: MissionItemIndexLabel {
id: itemIndexLabel
label: qsTr("R", "rally point map item label")
}
}
}
// Camera trigger points
MapItemView {
model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
delegate: CameraTriggerIndicator {
coordinate: object.coordinate
z: QGroundControl.zOrderTopMost
}
}
// GoTo Location visuals
MapQuickItem {
id: gotoLocationItem
visible: false
z: QGroundControl.zOrderMapItems
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Goto here", "Goto here waypoint")
}
property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : false
property var activeVehicle: _activeVehicle
onInGotoFlightModeChanged: {
if (!inGotoFlightMode && visible) {
// Hide goto indicator when vehicle falls out of guided mode
visible = false
}
}
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
gotoLocationItem.coordinate = coord
gotoLocationItem.visible = true
}
function hide() {
gotoLocationItem.visible = false
}
function actionConfirmed() {
// We leave the indicator visible. The handling for onInGuidedModeChanged will hide it.
}
function actionCancelled() {
hide()
}
}
// Orbit editing visuals
QGCMapCircleVisuals {
id: orbitMapCircle
mapControl: parent
mapCircle: _mapCircle
visible: false
property alias center: _mapCircle.center
property alias clockwiseRotation: _mapCircle.clockwiseRotation
property var activeVehicle: _activeVehicle
readonly property real defaultRadius: 30
onActiveVehicleChanged: {
if (!_activeVehicle) {
visible = false
}
}
function show(coord) {
_mapCircle.radius.rawValue = defaultRadius
orbitMapCircle.center = coord
orbitMapCircle.visible = true
}
function hide() {
orbitMapCircle.visible = false
}
function actionConfirmed() {
// Live orbit status is handled by telemetry so we hide here and telemetry will show again.
hide()
}
function actionCancelled() {
hide()
}
function radius() {
return _mapCircle.radius.rawValue
}
Component.onCompleted: guidedActionsController.orbitMapCircle = orbitMapCircle
QGCMapCircle {
id: _mapCircle
interactive: true
radius.rawValue: 30
showRotation: true
clockwiseRotation: true
}
}
// Orbit telemetry visuals
QGCMapCircleVisuals {
id: orbitTelemetryCircle
mapControl: parent
mapCircle: _activeVehicle ? _activeVehicle.orbitMapCircle : null
visible: _activeVehicle ? _activeVehicle.orbitActive : false
}
MapQuickItem {
id: orbitCenterIndicator
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: _activeVehicle ? _activeVehicle.orbitMapCircle.center : QtPositioning.coordinate()
visible: orbitTelemetryCircle.visible
sourceItem: MissionItemIndexLabel {
checked: true
index: -1
label: qsTr("Orbit", "Orbit waypoint")
}
}
// Handle guided mode clicks
MouseArea {
anchors.fill: parent
Menu {
id: clickMenu
property var coord
MenuItem {
text: qsTr("Go to location")
visible: guidedActionsController.showGotoLocation
onTriggered: {
gotoLocationItem.show(clickMenu.coord)
orbitMapCircle.hide()
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickMenu.coord, gotoLocationItem)
}
}
MenuItem {
text: qsTr("Orbit at location")
visible: guidedActionsController.showOrbit
onTriggered: {
orbitMapCircle.show(clickMenu.coord)
gotoLocationItem.hide()
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickMenu.coord, orbitMapCircle)
}
}
}
onClicked: {
if (guidedActionsController.guidedUIVisible || (!guidedActionsController.showGotoLocation && !guidedActionsController.showOrbit)) {
return
}
orbitMapCircle.hide()
gotoLocationItem.hide()
var clickCoord = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
if (guidedActionsController.showGotoLocation && guidedActionsController.showOrbit) {
clickMenu.coord = clickCoord
clickMenu.popup()
} else if (guidedActionsController.showGotoLocation) {
gotoLocationItem.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickCoord)
} else if (guidedActionsController.showOrbit) {
orbitMapCircle.show(clickCoord)
guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickCoord)
}
}
}
MapScale {
id: mapScale
anchors.right: parent.right
anchors.margins: ScreenTools.defaultFontPixelHeight * (0.33)
anchors.topMargin: ScreenTools.defaultFontPixelHeight * (0.33) + state === "bottomMode" ? 0 : ScreenTools.toolbarHeight
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * (0.33)
mapControl: flightMap
visible: !ScreenTools.isTinyScreen
state: "bottomMode"
states: [
State {
name: "topMode"
AnchorChanges {
target: mapScale
anchors.top: parent.top
anchors.bottom: undefined
}
},
State {
name: "bottomMode"
AnchorChanges {
target: mapScale
anchors.top: undefined
anchors.bottom: parent.bottom
}
}
]
}
// Airspace overlap support
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.circles : []
delegate: MapCircle {
center: object.center
radius: object.radius
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
MapItemView {
model: _airspaceEnabled && QGroundControl.settingsManager.airMapSettings.enableAirspace && QGroundControl.airspaceManager.airspaceVisible ? QGroundControl.airspaceManager.airspaces.polygons : []
delegate: MapPolygon {
path: object.polygon
color: object.color
border.color: object.lineColor
border.width: object.lineWidth
}
}
}
#include "WimaController.h"
const char* WimaController::wimaFileExtension = "wima";
const char* WimaController::areaItemsName = "AreaItems";
const char* WimaController::missionItemsName = "MissionItems";
const char* WimaController::settingsGroup = "WimaController";
const char* WimaController::enableWimaControllerName = "EnableWimaController";
const char* WimaController::overlapWaypointsName = "OverlapWaypoints";
const char* WimaController::maxWaypointsPerPhaseName = "MaxWaypointsPerPhase";
const char* WimaController::startWaypointIndexName = "StartWaypointIndex";
const char* WimaController::showAllMissionItemsName = "ShowAllMissionItems";
const char* WimaController::showCurrentMissionItemsName = "ShowCurrentMissionItems";
const char* WimaController::flightSpeedName = "FlightSpeed";
const char* WimaController::arrivalReturnSpeedName = "ArrivalReturnSpeed";
const char* WimaController::altitudeName = "Altitude";
const char* WimaController::reverseName = "Reverse";
WimaController::WimaController(QObject *parent)
: QObject (parent)
, _container (nullptr)
, _joinedArea (this)
, _measurementArea (this)
, _serviceArea (this)
, _corridor (this)
, _localPlanDataValid (false)
, _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/WimaController.SettingsGroup.json"), this))
, _enableWimaController (settingsGroup, _metaDataMap[enableWimaControllerName])
, _overlapWaypoints (settingsGroup, _metaDataMap[overlapWaypointsName])
, _maxWaypointsPerPhase (settingsGroup, _metaDataMap[maxWaypointsPerPhaseName])
, _nextPhaseStartWaypointIndex (settingsGroup, _metaDataMap[startWaypointIndexName])
, _showAllMissionItems (settingsGroup, _metaDataMap[showAllMissionItemsName])
, _showCurrentMissionItems (settingsGroup, _metaDataMap[showCurrentMissionItemsName])
, _flightSpeed (settingsGroup, _metaDataMap[flightSpeedName])
, _arrivalReturnSpeed (settingsGroup, _metaDataMap[arrivalReturnSpeedName])
, _altitude (settingsGroup, _metaDataMap[altitudeName])
, _reverse (settingsGroup, _metaDataMap[reverseName])
, _endWaypointIndex (0)
, _startWaypointIndex (0)
, _uploadOverrideRequired (false)
, _measurementPathLength (-1)
, _arrivalPathLength (-1)
, _returnPathLength (-1)
, _phaseDistance (-1)
, _phaseDuration (-1)
, _vehicleHasLowBattery (false)
, _lowBatteryHandlingTriggered(false)
, _executingSmartRTL (false)
{
_showAllMissionItems.setRawValue(true);
_showCurrentMissionItems.setRawValue(true);
connect(&_overlapWaypoints, &Fact::rawValueChanged, this, &WimaController::updateNextWaypoint);
connect(&_maxWaypointsPerPhase, &Fact::rawValueChanged, this, &WimaController::recalcCurrentPhase);
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
connect(&_flightSpeed, &Fact::rawValueChanged, this, &WimaController::updateflightSpeed);
connect(&_arrivalReturnSpeed, &Fact::rawValueChanged, this, &WimaController::updateArrivalReturnSpeed);
connect(&_altitude, &Fact::rawValueChanged, this, &WimaController::updateAltitude);
connect(&_reverse, &Fact::rawValueChanged, this, &WimaController::reverseChangedHandler);
// setup low battery handling
connect(&_checkBatteryTimer, &QTimer::timeout, this, &WimaController::checkBatteryLevel);
_checkBatteryTimer.setInterval(500);
Fact *enableLowBatteryHandling = qgcApp()->toolbox()->settingsManager()->wimaSettings()->enableLowBatteryHandling();
connect(enableLowBatteryHandling, &Fact::rawValueChanged, this, &WimaController::enableDisableLowBatteryHandling);
enableDisableLowBatteryHandling(enableLowBatteryHandling->rawValue());
}
QmlObjectVectorModel* WimaController::visualItems()
{
return &_visualItems;
}
QStringList WimaController::loadNameFilters() const
{
QStringList filters;
filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension) <<
tr("All Files (*.*)");
return filters;
}
QStringList WimaController::saveNameFilters() const
{
QStringList filters;
filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension);
return filters;
}
WimaDataContainer *WimaController::dataContainer()
{
return _container;
}
QmlObjectVectorModel *WimaController::missionItems()
{
return &_missionItems;
}
QVariantList WimaController::waypointPath()
{
return _waypointPath;
}
Fact *WimaController::enableWimaController()
{
return &_enableWimaController;
}
Fact *WimaController::overlapWaypoints()
{
return &_overlapWaypoints;
}
Fact *WimaController::maxWaypointsPerPhase()
{
return &_maxWaypointsPerPhase;
}
Fact *WimaController::showAllMissionItems()
{
return &_showAllMissionItems;
}
Fact *WimaController::showCurrentMissionItems()
{
return &_showCurrentMissionItems;
}
Fact *WimaController::flightSpeed()
{
return &_flightSpeed;
}
Fact *WimaController::arrivalReturnSpeed()
{
return &_arrivalReturnSpeed;
}
Fact *WimaController::altitude()
{
return &_altitude;
}
Fact *WimaController::reverse()
{
return &_reverse;
}
bool WimaController::uploadOverrideRequired() const
{
return _uploadOverrideRequired;
}
double WimaController::phaseDistance() const
{
return _phaseDistance;
}
double WimaController::phaseDuration() const
{
return _phaseDuration;
}
bool WimaController::vehicleHasLowBattery() const
{
return _vehicleHasLowBattery;
}
Fact *WimaController::startWaypointIndex()
{
return &_nextPhaseStartWaypointIndex;
}
void WimaController::setMasterController(PlanMasterController *masterC)
{
_masterController = masterC;
emit masterControllerChanged();
}
void WimaController::setMissionController(MissionController *missionC)
{
_missionController = missionC;
emit missionControllerChanged();
}
/*!
* \fn void WimaController::setDataContainer(WimaDataContainer *container)
* Sets the pointer to the \c WimaDataContainer, which is meant to exchange data between the \c WimaController and the \c WimaPlaner.
*
* \sa WimaPlaner, WimaDataContainer, WimaPlanData
*/
void WimaController::setDataContainer(WimaDataContainer *container)
{
if (container != nullptr) {
if (_container != nullptr) {
disconnect(_container, &WimaDataContainer::newDataAvailable, this, &WimaController::fetchContainerData);
}
_container = container;
connect(_container, &WimaDataContainer::newDataAvailable, this, &WimaController::fetchContainerData);
emit dataContainerChanged();
}
}
void WimaController::setUploadOverrideRequired(bool overrideRequired)
{
if (_uploadOverrideRequired != overrideRequired) {
_uploadOverrideRequired = overrideRequired;
emit uploadOverrideRequiredChanged();
}
}
void WimaController::nextPhase()
{
calcNextPhase();
}
void WimaController::previousPhase()
{
bool reverseBool = _reverse.rawValue().toBool();
if (!reverseBool){
int startIndex = _nextPhaseStartWaypointIndex.rawValue().toInt();
if (startIndex > 0) {
_nextPhaseStartWaypointIndex.setRawValue(1+std::max(_startWaypointIndex
- _maxWaypointsPerPhase.rawValue().toInt()
+ _overlapWaypoints.rawValue().toInt(), 0));
}
}
else {
int startIndex = _nextPhaseStartWaypointIndex.rawValue().toInt();
if (startIndex <= _missionItems.count()) {
_nextPhaseStartWaypointIndex.setRawValue(1+std::min(_startWaypointIndex
+ _maxWaypointsPerPhase.rawValue().toInt()
- _overlapWaypoints.rawValue().toInt(), _missionItems.count()-1));
}
}
}
void WimaController::resetPhase()
{
bool reverseBool = _reverse.rawValue().toBool();
if (!reverseBool) {
_nextPhaseStartWaypointIndex.setRawValue(int(1));
}
else {
_nextPhaseStartWaypointIndex.setRawValue(_missionItems.count());
}
}
bool WimaController::uploadToVehicle()
{
if ( !_serviceArea.containsCoordinate(_masterController->managerVehicle()->coordinate())
&& _missionController->visualItems()->count() > 0) {
setUploadOverrideRequired(true);
return false;
}
return forceUploadToVehicle();
}
bool WimaController::forceUploadToVehicle()
{
setUploadOverrideRequired(false);
if (_missionController->visualItems()->count() < 1)
return false;
// set homeposition of settingsItem
QmlObjectListModel* visuals = _missionController->visualItems();
MissionSettingsItem* settingsItem = visuals->value<MissionSettingsItem *>(0);
if (settingsItem == nullptr) {
qWarning("WimaController::updateCurrentMissionItems(): nullptr");
return false;
}
settingsItem->setCoordinate(_takeoffLandPostion);
<<<<<<< HEAD
=======
// copy mission items from _currentMissionItems to _missionController
for (int i = 0; i < _currentMissionItems.count(); i++){
SimpleMissionItem *item = _currentMissionItems.value<SimpleMissionItem *>(i);
_missionController->insertSimpleMissionItem(*item, visuals->count());
if (item->command() == MAV_CMD_DO_CHANGE_SPEED) {
}
}
for (int i = 0; i < _missionController->visualItems()->count(); i++){
SimpleMissionItem *item = _missionController->visualItems()->value<SimpleMissionItem*>(i);
if (item == nullptr)
continue;
if (item->command() == MAV_CMD_DO_CHANGE_SPEED) {
}
}
for (int i = 0; i < _missionController->visualItems()->count(); i++){
SimpleMissionItem *item = _missionController->visualItems()->value<SimpleMissionItem*>(i);
if (item == nullptr)
continue;
}
>>>>>>> temp
_masterController->sendToVehicle();
return true;
}
void WimaController::removeFromVehicle()
{
_masterController->removeAllFromVehicle();
}
bool WimaController::checkSmartRTLPreCondition()
{
QString errorString;
bool retValue = _checkSmartRTLPreCondition(errorString);
if (retValue == false) {
qgcApp()->showMessage(errorString);
return false;
}
return true;
}
bool WimaController::calcReturnPath()
{
QString errorString;
bool retValue = _calcReturnPath(errorString);
if (retValue == false) {
qgcApp()->showMessage(errorString);
return false;
}
return true;
}
bool WimaController::executeSmartRTL()
{
QString errorString;
bool retValue = _executeSmartRTL(errorString);
if (!retValue) {
qgcApp()->showMessage(errorString);
}
return retValue;
}
bool WimaController::initSmartRTL()
{
masterController()->managerVehicle()->pauseVehicle();
QString errorString;
bool retValue = calcReturnPath();
if (!retValue)
return false;
emit uploadAndExecuteConfirmRequired();
return true;
}
void WimaController::removeVehicleTrajectoryHistory()
{
Vehicle *managerVehicle = masterController()->managerVehicle();
managerVehicle->trajectoryPoints()->clear();
}
void WimaController::saveToCurrent()
{
}
void WimaController::saveToFile(const QString& filename)
{
QString file = filename;
}
bool WimaController::loadFromCurrent()
{
return true;
}
bool WimaController::loadFromFile(const QString &filename)
{
QString file = filename;
return true;
}
QJsonDocument WimaController::saveToJson(FileType fileType)
{
if(fileType)
{
}
return QJsonDocument();
}
bool WimaController::calcShortestPath(const QGeoCoordinate &start, const QGeoCoordinate &destination, QVector<QGeoCoordinate> &path)
{
using namespace GeoUtilities;
using namespace PolygonCalculus;
QVector<QPointF> path2D;
bool retVal = PolygonCalculus::shortestPath(
toQPolygonF(toCartesian2D(_joinedArea.coordinateList(), /*origin*/ start)),
/*start point*/ QPointF(0,0),
/*destination*/ toCartesian2D(destination, start),
/*shortest path*/ path2D);
path.append(toGeo(path2D, /*origin*/ start));
return retVal;
}
bool WimaController::extractCoordinateList(QmlObjectVectorModel &missionItems, QVector<QGeoCoordinate> &coordinateList)
{
return extractCoordinateList(missionItems, coordinateList, 0, missionItems.count()-1);
}
bool WimaController::extractCoordinateList(QmlObjectVectorModel &missionItems, QVector<QGeoCoordinate> &coordinateList, int startIndex, int endIndex)
{
if ( startIndex >= 0
&& startIndex < missionItems.count()
&& endIndex >= 0
&& endIndex < missionItems.count()) {
if (startIndex > endIndex) {
if (!extractCoordinateList(missionItems, coordinateList, startIndex, missionItems.count()-1))
return false;
if (!extractCoordinateList(missionItems, coordinateList, 0, endIndex))
return false;
} else {
for (int i = startIndex; i <= endIndex; i++) {
SimpleMissionItem *mItem = missionItems.value<SimpleMissionItem *>(i);
if (mItem == nullptr) {
coordinateList.clear();
return false;
}
coordinateList.append(mItem->coordinate());
}
}
} else
return false;
return true;
}
bool WimaController::extractCoordinateList(QmlObjectVectorModel &missionItems, QVariantList &coordinateList)
{
return extractCoordinateList(missionItems, coordinateList, 0 , missionItems.count()-1);
}
bool WimaController::extractCoordinateList(QmlObjectVectorModel &missionItems, QVariantList &coordinateList, int startIndex, int endIndex)
{
QVector<QGeoCoordinate> geoCoordintateList;
bool retValue = extractCoordinateList(missionItems, geoCoordintateList, startIndex, endIndex);
if (!retValue)
return false;
for (int i = 0; i < geoCoordintateList.size(); i++) {
QGeoCoordinate vertex = geoCoordintateList[i];
if ( (qFuzzyIsNull(vertex.latitude()) && qFuzzyIsNull(vertex.longitude()))
|| !vertex.isValid())
geoCoordintateList.removeAt(i);
}
for (auto coordinate : geoCoordintateList)
coordinateList.append(QVariant::fromValue(coordinate));
return true;
}
/*!
* \fn void WimaController::containerDataValidChanged(bool valid)
* Pulls plan data generated by \c WimaPlaner from the \c _container if the data is valid (\a valid equals true).
* Is connected to the dataValidChanged() signal of the \c WimaDataContainer.
*
* \sa WimaDataContainer, WimaPlaner, WimaPlanData
*/
bool WimaController::fetchContainerData()
{
// fetch only if valid, return true on sucess
// reset visual items
_visualItems.clear();
_missionItems.clearAndDeleteContents();
_missionController->removeAll();
_localPlanDataValid = false;
// fetch data from container
QSharedPointer<const WimaPlanData> planData;
if (_container != nullptr) {
planData = _container->pull();
} else {
qWarning("WimaController::fetchContainerData(): No container assigned!");
return false;
}
// extract mission items
QList<QSharedPointer<const MissionItem>> tempMissionItems = planData->missionItems();
if (tempMissionItems.size() < 1)
return false;
// extract list with WimaAreas
QList<const WimaAreaData*> areaList = planData->areaList();
int areaCounter = 0;
int numAreas = 4; // extract only numAreas Areas, if there are more they are invalid and ignored
for (int i = 0; i < areaList.size(); i++) {
const WimaAreaData *areaData = areaList[i];
if (areaData->type() == WimaServiceAreaData::typeString) { // is it a service area?
_serviceArea = *qobject_cast<const WimaServiceAreaData*>(areaData);
areaCounter++;
_visualItems.append(&_serviceArea);
continue;
}
if (areaData->type() == WimaMeasurementAreaData::typeString) { // is it a measurement area?
_measurementArea = *qobject_cast<const WimaMeasurementAreaData*>(areaData);
areaCounter++;
_visualItems.append(&_measurementArea);
continue;
}
if (areaData->type() == WimaCorridorData::typeString) { // is it a corridor?
_corridor = *qobject_cast<const WimaCorridorData*>(areaData);
areaCounter++;
//_visualItems.append(&_corridor); // not needed
continue;
}
if (areaData->type() == WimaJoinedAreaData::typeString) { // is it a corridor?
_joinedArea = *qobject_cast<const WimaJoinedAreaData*>(areaData);
areaCounter++;
_visualItems.append(&_joinedArea);
continue;
}
if (areaCounter >= numAreas)
break;
}
if (areaCounter != numAreas) {
qWarning("WimaController::fetchContainerData(): areaCounter != numAreas");
return false;
}
// create SimpleMissionItems
for (auto item : tempMissionItems)
_missionItems.append(new SimpleMissionItem(
_masterController->managerVehicle(),
true /* flyView*/, *item, this));
setTakeoffLandPosition();
updateWaypointPath();
// set _nextPhaseStartWaypointIndex to 1
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
bool reverse = _reverse.rawValue().toBool();
_nextPhaseStartWaypointIndex.setRawValue(reverse? _missionItems.count() : int(1));
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
/*
if(!calcNextPhase())
return false;
*/
emit visualItemsChanged();
emit missionItemsChanged();
_localPlanDataValid = true;
return true;
}
bool WimaController::calcNextPhase()
{
auto start = std::chrono::high_resolution_clock::now();
if (_missionItems.count() < 1) {
_startWaypointIndex = 0;
_endWaypointIndex = 0;
return false;
}
qWarning() << "size QObject: " << sizeof (QObject);
qWarning() << "size MissionItem: " << sizeof (MissionItem); // 912
qWarning() << "size VisualMissionItem: " << sizeof (VisualMissionItem); //384
qWarning() << "size SimpleMissionItem: " << sizeof (SimpleMissionItem); // 3272
bool reverse = _reverse.rawValue().toBool(); // Reverses the phase direction. Phases go from high to low waypoint numbers, if true.
int startIndex = _nextPhaseStartWaypointIndex.rawValue().toInt()-1;
if (!reverse) {
if (startIndex > _missionItems.count()-1)
return false;
}
else {
if (startIndex < 0)
return false;
}
_startWaypointIndex = startIndex;
int maxWaypointsPerPhase = _maxWaypointsPerPhase.rawValue().toInt();
// determine end waypoint index
bool lastMissionPhaseReached = false;
if (!reverse) {
_endWaypointIndex = std::min(_startWaypointIndex + maxWaypointsPerPhase - 1, _missionItems.count()-1);
if (_endWaypointIndex == _missionItems.count() - 1)
lastMissionPhaseReached = true;
}
else {
_endWaypointIndex = std::max(_startWaypointIndex - maxWaypointsPerPhase + 1, 0);
if (_endWaypointIndex == 0)
lastMissionPhaseReached = true;
}
// extract waypoints
QVector<QGeoCoordinate> CSWpList; // list with potential waypoints (from _missionItems), for _currentMissionItems
if (!reverse) {
if (!extractCoordinateList(_missionItems, CSWpList, _startWaypointIndex, _endWaypointIndex)) {
qWarning("WimaController::calcNextPhase(): error on waypoint extraction.");
return false;
}
} else {
if (!extractCoordinateList(_missionItems, CSWpList, _endWaypointIndex, _startWaypointIndex)) {
qWarning("WimaController::calcNextPhase(): error on waypoint extraction.");
return false;
}
// reverse path
QVector<QGeoCoordinate> reversePath;
for (QGeoCoordinate c : CSWpList)
reversePath.prepend(c);
CSWpList.clear();
CSWpList.append(reversePath);
}
// calculate phase length
_measurementPathLength = 0;
for (int i = 0; i < CSWpList.size()-1; ++i)
_measurementPathLength += CSWpList[i].distanceTo(CSWpList[i+1]);
// set start waypoint index for next phase
if (!lastMissionPhaseReached) {
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
if (!reverse) {
int untruncated = std::max(_endWaypointIndex + 1 - _overlapWaypoints.rawValue().toInt(), 0);
int truncated = std::min(untruncated , _missionItems.count()-1);
_nextPhaseStartWaypointIndex.setRawValue(truncated + 1);
}
else {
int untruncated = std::min(_endWaypointIndex - 1 + _overlapWaypoints.rawValue().toInt(), _missionItems.count()-1);
int truncated = std::max(untruncated , 0);
_nextPhaseStartWaypointIndex.setRawValue(truncated + 1);
}
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
}
// calculate path from home to first waypoint
QVector<QGeoCoordinate> arrivalPath;
if (!_takeoffLandPostion.isValid()){
qWarning("WimaController::calcNextPhase(): _takeoffLandPostion not valid.");
return false;
}
if ( !calcShortestPath(_takeoffLandPostion, CSWpList.first(), arrivalPath) ) {
qWarning("WimaController::calcNextPhase(): Not able to calc path from home to first waypoint.");
return false;
}
// calculate arrival path length
_arrivalPathLength = 0;
for (int i = 0; i < arrivalPath.size()-1; ++i)
_arrivalPathLength += arrivalPath[i].distanceTo(arrivalPath[i+1]);
arrivalPath.removeFirst();
// calculate path from last waypoint to home
QVector<QGeoCoordinate> returnPath;
if ( !calcShortestPath(CSWpList.last(), _takeoffLandPostion, returnPath) ) {
qWarning("WimaController::calcNextPhase(): Not able to calc path from home to first waypoint.");
return false;
}
// calculate arrival path length
_returnPathLength = 0;
for (int i = 0; i < returnPath.size()-1; ++i)
_returnPathLength += returnPath[i].distanceTo(returnPath[i+1]);
returnPath.removeFirst();
returnPath.removeLast();
// create Mission Items
_missionController->removeAll();
QmlObjectListModel* missionControllerVisuals = _missionController->visualItems();
// set homeposition of settingsItem
MissionSettingsItem* settingsItem = missionControllerVisuals->value<MissionSettingsItem *>(0);
if (settingsItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
settingsItem->setCoordinate(_takeoffLandPostion);
// set takeoff position for first mission item (bug)
missionController()->insertSimpleMissionItem(_takeoffLandPostion, 1);
SimpleMissionItem *takeoffItem = missionControllerVisuals->value<SimpleMissionItem*>(1);
if (takeoffItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
takeoffItem->setCoordinate(_takeoffLandPostion);
// create change speed item, after take off
_missionController->insertSimpleMissionItem(_takeoffLandPostion, 2);
SimpleMissionItem *speedItem = missionControllerVisuals->value<SimpleMissionItem*>(2);
if (speedItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
speedItem->setCommand(MAV_CMD_DO_CHANGE_SPEED);// set coordinate must be after setCommand (setCommand sets coordinate to zero)
speedItem->setCoordinate(_takeoffLandPostion);
speedItem->missionItem().setParam2(_arrivalReturnSpeed.rawValue().toDouble());
// insert arrival path
for (auto coordinate : arrivalPath)
_missionController->insertSimpleMissionItem(coordinate, missionControllerVisuals->count());
// create change speed item, after arrival path
int index = missionControllerVisuals->count();
_missionController->insertSimpleMissionItem(CSWpList.first(), index);
speedItem = missionControllerVisuals->value<SimpleMissionItem*>(index);
if (speedItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
speedItem->setCommand(MAV_CMD_DO_CHANGE_SPEED); // set coordinate must be after setCommand (setCommand sets coordinate to zero)
speedItem->setCoordinate(CSWpList.first());
speedItem->missionItem().setParam2(_flightSpeed.rawValue().toDouble());
// insert Circular Survey coordinates
for (auto coordinate : CSWpList)
_missionController->insertSimpleMissionItem(coordinate, missionControllerVisuals->count());
// create change speed item, after circular survey
index = missionControllerVisuals->count();
_missionController->insertSimpleMissionItem(CSWpList.last(), index);
speedItem = missionControllerVisuals->value<SimpleMissionItem*>(index);
if (speedItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
speedItem->setCommand(MAV_CMD_DO_CHANGE_SPEED); // set coordinate must be after setCommand (setCommand sets coordinate to zero)
speedItem->setCoordinate(CSWpList.last());
speedItem->missionItem().setParam2(_arrivalReturnSpeed.rawValue().toDouble());
// insert return path coordinates
for (auto coordinate : returnPath)
_missionController->insertSimpleMissionItem(coordinate, missionControllerVisuals->count());
// set land command for last mission item
index = missionControllerVisuals->count();
_missionController->insertSimpleMissionItem(_takeoffLandPostion, index);
SimpleMissionItem *landItem = missionControllerVisuals->value<SimpleMissionItem*>(index);
if (landItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
_missionController->setLandCommand(*landItem);
_setPhaseDistance(_measurementPathLength + _arrivalPathLength + _returnPathLength);
_setPhaseDuration(_measurementPathLength/_flightSpeed.rawValue().toDouble()
+ (_arrivalPathLength + _returnPathLength)
/ _arrivalReturnSpeed.rawValue().toDouble());
updateAltitude();
qWarning() << "WimaController::calcNextPhase() exec time: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start).count() << " ms";
return true;
}
void WimaController::updateWaypointPath()
{
_waypointPath.clear();
extractCoordinateList(_missionItems, _waypointPath, 0, _missionItems.count()-1);
emit waypointPathChanged();
}
void WimaController::updateNextWaypoint()
{
if (_endWaypointIndex < _missionItems.count()-2) {
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
_nextPhaseStartWaypointIndex.setRawValue(1 + std::max(_endWaypointIndex + 1 - _overlapWaypoints.rawValue().toInt(), 0));
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
}
}
void WimaController::recalcCurrentPhase()
{
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
_nextPhaseStartWaypointIndex.setRawValue(_startWaypointIndex + 1);
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
calcNextPhase();
}
bool WimaController::setTakeoffLandPosition()
{
_takeoffLandPostion.setAltitude(0);
_takeoffLandPostion.setLongitude(_serviceArea.center().longitude());
_takeoffLandPostion.setLatitude(_serviceArea.center().latitude());
return true;
}
void WimaController::updateflightSpeed()
{
int speedItemCounter = 0;
QmlObjectListModel *visualMissionItems = _missionController->visualItems();
for (int i = 0; i < visualMissionItems->count(); i++) {
SimpleMissionItem *item = visualMissionItems->value<SimpleMissionItem *>(i);
if (item != nullptr && item->command() == MAV_CMD_DO_CHANGE_SPEED) {
speedItemCounter++;
if (speedItemCounter == 2) {
item->missionItem().setParam2(_flightSpeed.rawValue().toDouble());
}
}
}
_setPhaseDuration(_phaseDistance/_flightSpeed.rawValue().toDouble()
+ (_arrivalPathLength + _returnPathLength)
/ _arrivalReturnSpeed.rawValue().toDouble());
if (speedItemCounter != 3)
qWarning("WimaController::updateflightSpeed(): internal error.");
}
void WimaController::updateArrivalReturnSpeed()
{
int speedItemCounter = 0;
QmlObjectListModel *visualMissionItems = _missionController->visualItems();
for (int i = 0; i < visualMissionItems->count(); i++) {
SimpleMissionItem *item = visualMissionItems->value<SimpleMissionItem *>(i);
if (item != nullptr && item->command() == MAV_CMD_DO_CHANGE_SPEED) {
speedItemCounter++;
if (speedItemCounter != 2) {
item->missionItem().setParam2(_arrivalReturnSpeed.rawValue().toDouble());
}
}
}
_setPhaseDuration(_phaseDistance/_flightSpeed.rawValue().toDouble()
+ (_arrivalPathLength + _returnPathLength)
/ _arrivalReturnSpeed.rawValue().toDouble());
if (speedItemCounter != 3)
qWarning("WimaController::updateArrivalReturnSpeed(): internal error.");
}
void WimaController::updateAltitude()
{
QmlObjectListModel *visualMissionItems = _missionController->visualItems();
for (int i = 0; i < visualMissionItems->count(); i++) {
SimpleMissionItem *item = visualMissionItems->value<SimpleMissionItem *>(i);
if (item == nullptr) {
qWarning("WimaController::updateAltitude(): nullptr");
return;
}
item->altitude()->setRawValue(_altitude.rawValue().toDouble());
}
}
void WimaController::checkBatteryLevel()
{
Vehicle *managerVehicle = masterController()->managerVehicle();
WimaSettings* wimaSettings = qgcApp()->toolbox()->settingsManager()->wimaSettings();
int batteryThreshold = wimaSettings->lowBatteryThreshold()->rawValue().toInt();
bool enabled = _enableWimaController.rawValue().toBool();
static long attemptCounter = 0;
if (managerVehicle != nullptr && enabled == true) {
Fact *battery1percentRemaining = managerVehicle->battery1FactGroup()->getFact(VehicleBatteryFactGroup::_percentRemainingFactName);
Fact *battery2percentRemaining = managerVehicle->battery2FactGroup()->getFact(VehicleBatteryFactGroup::_percentRemainingFactName);
if (battery1percentRemaining->rawValue().toDouble() < batteryThreshold
&& battery2percentRemaining->rawValue().toDouble() < batteryThreshold) {
_setVehicleHasLowBattery(true);
if (!_lowBatteryHandlingTriggered) {
QString errorString;
attemptCounter++;
if (_checkSmartRTLPreCondition(errorString) == true) {
managerVehicle->pauseVehicle();
if (_calcReturnPath(errorString)) {
_lowBatteryHandlingTriggered = true;
attemptCounter = 0;
emit returnBatteryLowConfirmRequired();
} else {
if (attemptCounter > 3) {
qgcApp()->showMessage(tr("Battery level is low. Smart RTL not possible."));
qgcApp()->showMessage(errorString);
}
}
}
if (attemptCounter > 3) { // try 3 times, somtimes vehicle is outside joined area
_lowBatteryHandlingTriggered = true;
attemptCounter = 0;
}
}
}
else {
_setVehicleHasLowBattery(false);
_lowBatteryHandlingTriggered = false;
}
}
}
void WimaController::smartRTLCleanUp(bool flying)
{
if ( !flying) { // vehicle has landed
if (_executingSmartRTL) {
_executingSmartRTL = false;
_loadCurrentMissionItemsFromBuffer();
_showAllMissionItems.setRawValue(true);
_missionController->removeAllFromVehicle();
_missionController->removeAll();
disconnect(masterController()->managerVehicle(), &Vehicle::flyingChanged, this, &WimaController::smartRTLCleanUp);
}
}
}
void WimaController::enableDisableLowBatteryHandling(QVariant enable)
{
if (enable.toBool()) {
_checkBatteryTimer.start();
} else {
_checkBatteryTimer.stop();
}
}
void WimaController::reverseChangedHandler()
{
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
_nextPhaseStartWaypointIndex.setRawValue(_endWaypointIndex+1);
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::calcNextPhase);
calcNextPhase();
}
void WimaController::_setPhaseDistance(double distance)
{
if (!qFuzzyCompare(distance, _phaseDistance)) {
_phaseDistance = distance;
emit phaseDistanceChanged();
}
}
void WimaController::_setPhaseDuration(double duration)
{
if (!qFuzzyCompare(duration, _phaseDuration)) {
_phaseDuration = duration;
emit phaseDurationChanged();
}
}
bool WimaController::_checkSmartRTLPreCondition(QString &errorString)
{
if (!_localPlanDataValid) {
errorString.append(tr("No WiMA data available. Please define at least a measurement and a service area."));
return false;
}
Vehicle *managerVehicle = masterController()->managerVehicle();
if (!managerVehicle->flying()) {
errorString.append(tr("Vehicle is not flying. Smart RTL not available."));
return false;
}
return true;
}
bool WimaController::_calcReturnPath(QString &errorSring)
{
// it is assumed that checkSmartRTLPreCondition() was called first and true was returned
Vehicle *managerVehicle = masterController()->managerVehicle();
QGeoCoordinate currentVehiclePosition = managerVehicle->coordinate();
// check if vehicle inside _joinedArea, this statement is not inside checkSmartRTLPreCondition() because during checkSmartRTLPreCondition() vehicle is not paused yet
if (!_joinedArea.containsCoordinate(currentVehiclePosition)) {
errorSring.append(tr("Vehicle not inside joined area. Action not supported."));
return false;
}
// calculate return path
QVector<QGeoCoordinate> returnPath;
calcShortestPath(currentVehiclePosition, _takeoffLandPostion, returnPath);
// successful?
if (returnPath.isEmpty()) {
errorSring.append(tr("Not able to calculate return path."));
return false;
}
// qWarning() << "returnPath.size()" << returnPath.size();
_saveCurrentMissionItemsToBuffer();
// create Mission Items
removeFromVehicle();
QmlObjectListModel* missionControllerVisuals = _missionController->visualItems();
// set homeposition of settingsItem
MissionSettingsItem* settingsItem = missionControllerVisuals->value<MissionSettingsItem *>(0);
if (settingsItem == nullptr) {
qWarning("WimaController: nullptr");
return false;
}
settingsItem->setCoordinate(_takeoffLandPostion);
// copy from returnPath to _missionController
QGeoCoordinate speedItemCoordinate = returnPath.first();
for (auto coordinate : returnPath) {
_missionController->insertSimpleMissionItem(coordinate, missionControllerVisuals->count());
}
//qWarning() << "missionControllerVisuals->count()" << missionControllerVisuals->count();
// create speed item
int speedItemIndex = 1;
_missionController->insertSimpleMissionItem(speedItemCoordinate, speedItemIndex);
SimpleMissionItem *speedItem = missionControllerVisuals->value<SimpleMissionItem*>(speedItemIndex);
if (speedItem == nullptr) {
qWarning("WimaController: nullptr");
return false;
}
speedItem->setCommand(MAV_CMD_DO_CHANGE_SPEED);
speedItem->setCoordinate(speedItemCoordinate);
speedItem->missionItem().setParam2(_arrivalReturnSpeed.rawValue().toDouble());
// set second item command to ordinary waypoint (is takeoff)
SimpleMissionItem *secondItem = missionControllerVisuals->value<SimpleMissionItem*>(2);
if (secondItem == nullptr) {
qWarning("WimaController: nullptr");
return false;
}
secondItem->setCoordinate(speedItemCoordinate);
secondItem->setCommand(MAV_CMD_NAV_WAYPOINT);
// set land command for last mission item
SimpleMissionItem *landItem = missionControllerVisuals->value<SimpleMissionItem*>(missionControllerVisuals->count()-1);
if (landItem == nullptr) {
qWarning("WimaController: nullptr");
return false;
}
_missionController->setLandCommand(*landItem);
_setPhaseDistance(_phaseDistance + _arrivalPathLength + _returnPathLength);
_setPhaseDuration(_phaseDistance/_flightSpeed.rawValue().toDouble()
+ (_arrivalPathLength + _returnPathLength)
/ _arrivalReturnSpeed.rawValue().toDouble());
updateAltitude();
_showAllMissionItems.setRawValue(false);
managerVehicle->trajectoryPoints()->clear();
return true;
}
void WimaController::_setVehicleHasLowBattery(bool batteryLow)
{
if (_vehicleHasLowBattery != batteryLow) {
_vehicleHasLowBattery = batteryLow;
emit vehicleHasLowBatteryChanged();
}
}
bool WimaController::_executeSmartRTL(QString &errorSring)
{
Q_UNUSED(errorSring)
_executingSmartRTL = true;
connect(masterController()->managerVehicle(), &Vehicle::flyingChanged, this, &WimaController::smartRTLCleanUp);
forceUploadToVehicle();
masterController()->managerVehicle()->startMission();
return true;
}
void WimaController::_loadCurrentMissionItemsFromBuffer()
{
_missionController->removeAll();
int numItems = _missionItemsBuffer.count();
<<<<<<< HEAD
for (int i = 0; i < numItems; i++) {
SimpleMissionItem *item = _missionItemsBuffer.value<SimpleMissionItem *>(i);
if (item != nullptr)
_missionController->insertSimpleMissionItem(item->missionItem(), i+1);
else {
qWarning("WimaController::_loadCurrentMissionItemsFromBuffer(): internal error");
return;
}
}
_missionItems.clearAndDeleteContents();
=======
qWarning() << "WimaController::_loadCurrentMissionItemsFromBuffer: numItems" << numItems;
for (int i = 0; i < numItems; i++)
_currentMissionItems.append(_missionItemsBuffer.removeAt(0));
updateCurrentPath();
>>>>>>> temp
}
void WimaController::_saveCurrentMissionItemsToBuffer()
{
_missionItemsBuffer.clear();
<<<<<<< HEAD
int numItems = _missionController->visualItems()->count();
for (int i = 0; i < numItems; i++) {
SimpleMissionItem *item = _missionController->visualItems()->value<SimpleMissionItem *>(i);
if (item != nullptr)
_missionItems.append(new SimpleMissionItem(*item, true /* flyView */, this));
else {
qWarning("WimaController::_loadCurrentMissionItemsFromBuffer(): internal error");
return;
}
}
=======
int numItems = _currentMissionItems.count();
qWarning() << "WimaController::_saveCurrentMissionItemsToBuffer: numItems" << numItems;
for (int i = 0; i < numItems; i++)
_missionItemsBuffer.append(_currentMissionItems.removeAt(0));
>>>>>>> temp
}
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