Commit fd28bf03 authored by Don Gagne's avatar Don Gagne

Major rework of Survey ui

parent 23e95926
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
......@@ -21,127 +22,165 @@ Rectangle {
//property real availableWidth ///< Width for control
//property var missionItem ///< Mission Item for editor
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property int cameraIndex: 1
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property int _cameraIndex: 1
readonly property int _gridTypeManual: 0
readonly property int _gridTypeCustomCamera: 1
readonly property int _gridTypeCamera: 2
Component.onCompleted: {
console.log("gridAltitude", missionItem.gridAltitude.value)
console.log("gridAltitudeRelative", missionItem.gridAltitudeRelative)
console.log("gridAngle", missionItem.gridAngle.value)
console.log("gridSpacing", missionItem.gridSpacing.value)
console.log("turnaroundDist", missionItem.turnaroundDist.value)
console.log("cameraTrigger", missionItem.cameraTrigger)
console.log("cameraTriggerDistance", missionItem.cameraTriggerDistance.value)
console.log("groundResolution", missionItem.groundResolution.value)
console.log("frontalOverlap", missionItem.frontalOverlap.value)
console.log("sideOverlap", missionItem.sideOverlap.value)
console.log("cameraSensorWidth", missionItem.cameraSensorWidth.value)
console.log("cameraSensorHeight", missionItem.cameraSensorHeight.value)
console.log("cameraResolutionWidth", missionItem.cameraResolutionWidth.value)
console.log("cameraResolutionHeight", missionItem.cameraResolutionHeight.value)
console.log("cameraFocalLength", missionItem.cameraFocalLength.value)
console.log("fixedValueIsAltitude", missionItem.fixedValueIsAltitude)
console.log("cameraOrientationLandscape", missionItem.cameraOrientationLandscape)
console.log("manualGrid", missionItem.manualGrid)
console.log("camera", missionItem.camera)
}
ListModel {
id: cameraModelList
ListElement {
text: qsTr("Custom")
sensorWidth: 0
sensorHeight: 0
imageWidth: 0
imageHeight: 0
focalLength: 0
}
ListElement {
text: qsTr("Sony ILCE-QX1") //http://www.sony.co.uk/electronics/interchangeable-lens-cameras/ilce-qx1-body-kit/specifications
sensorWidth: 23.2 //http://www.sony.com/electronics/camera-lenses/sel16f28/specifications
sensorHeight: 15.4
imageWidth: 5456
imageHeight: 3632
focalLength: 16
}
ListElement {
text: qsTr("Canon S100 PowerShot")
sensorWidth: 7.6
sensorHeight: 5.7
imageWidth: 4000
imageHeight: 3000
focalLength: 5.2
}
ListElement {
text: qsTr("Canon SX260 HS PowerShot")
sensorWidth: 6.17
sensorHeight: 4.55
imageWidth: 4000
imageHeight: 3000
focalLength: 4.5
}
ListElement {
text: qsTr("Canon EOS-M 22mm")
sensorWidth: 22.3
sensorHeight: 14.9
imageWidth: 5184
imageHeight: 3456
focalLength: 22
}
ListElement {
text: qsTr("Sony a6000 16mm") //http://www.sony.co.uk/electronics/interchangeable-lens-cameras/ilce-6000-body-kit#product_details_default
sensorWidth: 23.5
sensorHeight: 15.6
imageWidth: 6000
imageHeight: 4000
focalLength: 16
}
}
id: cameraModelList
Component.onCompleted: {
cameraModelList.setProperty(_gridTypeCustomCamera, "sensorWidth", missionItem.cameraSensorWidth.rawValue)
cameraModelList.setProperty(_gridTypeCustomCamera, "sensorHeight", missionItem.cameraSensorHeight.rawValue)
cameraModelList.setProperty(_gridTypeCustomCamera, "imageWidth", missionItem.cameraResolutionWidth.rawValue)
cameraModelList.setProperty(_gridTypeCustomCamera, "imageHeight", missionItem.cameraResolutionHeight.rawValue)
cameraModelList.setProperty(_gridTypeCustomCamera, "focalLength", missionItem.cameraFocalLength.rawValue)
}
ListElement {
text: qsTr("Manual Grid (no camera specs)")
}
ListElement {
text: qsTr("Custom Camera Grid")
}
ListElement {
text: qsTr("Sony ILCE-QX1") //http://www.sony.co.uk/electronics/interchangeable-lens-cameras/ilce-qx1-body-kit/specifications
sensorWidth: 23.2 //http://www.sony.com/electronics/camera-lenses/sel16f28/specifications
sensorHeight: 15.4
imageWidth: 5456
imageHeight: 3632
focalLength: 16
}
ListElement {
text: qsTr("Canon S100 PowerShot")
sensorWidth: 7.6
sensorHeight: 5.7
imageWidth: 4000
imageHeight: 3000
focalLength: 5.2
}
ListElement {
text: qsTr("Canon SX260 HS PowerShot")
sensorWidth: 6.17
sensorHeight: 4.55
imageWidth: 4000
imageHeight: 3000
focalLength: 4.5
}
ListElement {
text: qsTr("Canon EOS-M 22mm")
sensorWidth: 22.3
sensorHeight: 14.9
imageWidth: 5184
imageHeight: 3456
focalLength: 22
}
ListElement {
text: qsTr("Sony a6000 16mm") //http://www.sony.co.uk/electronics/interchangeable-lens-cameras/ilce-6000-body-kit#product_details_default
sensorWidth: 23.5
sensorHeight: 15.6
imageWidth: 6000
imageHeight: 4000
focalLength: 16
}
}
function recalcFromCameraValues() {
var focalLength = cameraModelList.get(cameraIndex).focalLength
var sensorWidth = cameraModelList.get(cameraIndex).sensorWidth
var sensorHeight = cameraModelList.get(cameraIndex).sensorHeight
var imageWidth = cameraModelList.get(cameraIndex).imageWidth
var imageHeight = cameraModelList.get(cameraIndex).imageHeight
var gsd = Number(gsdField.text)
var frontalOverlap = Number(frontalOverlapField.text)
var sideOverlap = Number(sideOverlapField.text)
if (focalLength <= 0.0 || sensorWidth <= 0.0 || sensorHeight <= 0.0 || imageWidth < 0 || imageHeight < 0 || gsd < 0.0 || frontalOverlap < 0 || sideOverlap < 0) {
missionItem.gridAltitude.rawValue = 0
missionItem.gridSpacing.rawValue = 0
missionItem.cameraTriggerDistance.rawValue = 0
var focalLength = missionItem.cameraFocalLength.rawValue
var sensorWidth = missionItem.cameraSensorWidth.rawValue
var sensorHeight = missionItem.cameraSensorHeight.rawValue
var imageWidth = missionItem.cameraResolutionWidth.rawValue
var imageHeight = missionItem.cameraResolutionHeight.rawValue
var altitude = missionItem.gridAltitude.rawValue
var groundResolution = missionItem.groundResolution.rawValue
var frontalOverlap = missionItem.frontalOverlap.rawValue
var sideOverlap = missionItem.sideOverlap.rawValue
if (focalLength <= 0 || sensorWidth <= 0 || sensorHeight <= 0 || imageWidth <= 0 || imageHeight <= 0 || groundResolution <= 0) {
return
}
var altitude
var imageSizeSideGround //size in side (non flying) direction of the image on the ground
var imageSizeFrontGround //size in front (flying) direction of the image on the ground
var imageSizeSideGround //size in side (non flying) direction of the image on the ground
var imageSizeFrontGround //size in front (flying) direction of the image on the ground
var gridSpacing
var cameraTriggerDistance
altitude = (imageWidth * gsd * focalLength) / (sensorWidth * 100)
if (missionItem.fixedValueIsAltitude) {
groundResolution = (altitude * sensorWidth * 100) / (imageWidth * focalLength)
} else {
altitude = (imageWidth * groundResolution * focalLength) / (sensorWidth * 100)
}
if (cameraOrientationLandscape.checked) {
imageSizeSideGround = (imageWidth * gsd) / 100
imageSizeFrontGround = (imageHeight * gsd) / 100
imageSizeSideGround = (imageWidth * groundResolution) / 100
imageSizeFrontGround = (imageHeight * groundResolution) / 100
} else {
imageSizeSideGround = (imageHeight * gsd) / 100
imageSizeFrontGround = (imageWidth * gsd) / 100
imageSizeSideGround = (imageHeight * groundResolution) / 100
imageSizeFrontGround = (imageWidth * groundResolution) / 100
}
gridSpacing = imageSizeSideGround * ( (100-sideOverlap) / 100 )
cameraTriggerDistance = imageSizeFrontGround * ( (100-frontalOverlap) / 100 )
missionItem.gridAltitude.rawValue = altitude
if (missionItem.fixedValueIsAltitude) {
missionItem.groundResolution.rawValue = groundResolution
} else {
missionItem.gridAltitude.rawValue = altitude
}
missionItem.gridSpacing.rawValue = gridSpacing
missionItem.cameraTriggerDistance.rawValue = cameraTriggerDistance
}
/*
function recalcFromMissionValues() {
var focalLength = cameraModelList.get(cameraIndex).focalLength
var sensorWidth = cameraModelList.get(cameraIndex).sensorWidth
var sensorHeight = cameraModelList.get(cameraIndex).sensorHeight
var imageWidth = cameraModelList.get(cameraIndex).imageWidth
var imageHeight = cameraModelList.get(cameraIndex).imageHeight
var focalLength = missionItem.cameraFocalLength.rawValue
var sensorWidth = missionItem.cameraSensorWidth.rawValue
var sensorHeight = missionItem.cameraSensorHeight.rawValue
var imageWidth = missionItem.cameraResolutionWidth.rawValue
var imageHeight = missionItem.cameraResolutionHeight.rawValue
var altitude = missionItem.gridAltitude.rawValue
var gridSpacing = missionItem.gridSpacing.rawValue
var cameraTriggerDistance = missionItem.cameraTriggerDistance.rawValue
if (focalLength <= 0.0 || sensorWidth <= 0.0 || sensorHeight <= 0.0 || imageWidth < 0 || imageHeight < 0 || altitude < 0.0 || gridSpacing < 0.0 || cameraTriggerDistance < 0.0) {
gsdField.text = "0.0"
sideOverlapField.text = "0"
frontalOverlapField.text = "0"
missionItem.groundResolution.rawValue = 0
missionItem.sideOverlap = 0
missionItem.frontalOverlap = 0
return
}
var gsd
var imageSizeSideGround //size in side (non flying) direction of the image on the ground
var imageSizeFrontGround //size in front (flying) direction of the image on the ground
var groundResolution
var imageSizeSideGround //size in side (non flying) direction of the image on the ground
var imageSizeFrontGround //size in front (flying) direction of the image on the ground
gsd = (altitude * sensorWidth * 100) / (imageWidth * focalLength)
groundResolution = (altitude * sensorWidth * 100) / (imageWidth * focalLength)
if (cameraOrientationLandscape.checked) {
imageSizeSideGround = (imageWidth * gsd) / 100
......@@ -154,13 +193,14 @@ Rectangle {
var sideOverlap = (imageSizeSideGround == 0 ? 0 : 100 - (gridSpacing*100 / imageSizeSideGround))
var frontOverlap = (imageSizeFrontGround == 0 ? 0 : 100 - (cameraTriggerDistance*100 / imageSizeFrontGround))
gsdField.text = gsd.toFixed(1)
sideOverlapField.text = sideOverlap.toFixed(0)
frontalOverlapField.text = frontOverlap.toFixed(0)
missionItem.groundResolution.rawValue = groundResolution
missionItem.sideOverlap.rawValue = sideOverlap
missionItem.frontalOverlap.rawValue = frontOverlap
}
*/
function polygonCaptureStarted() {
missionItem.clearPolygon()
missionItem.clearPolygon()
}
function polygonCaptureFinished(coordinates) {
......@@ -176,15 +216,42 @@ Rectangle {
function polygonAdjustStarted() { }
function polygonAdjustFinished() { }
property bool _noCameraValueRecalc: false ///< Prevents uneeded recalcs
Connections {
target: missionItem
onCameraValueChanged: {
if (gridTypeCombo.currentIndex >= _gridTypeCustomCamera && !_noCameraValueRecalc) {
recalcFromCameraValues()
}
}
}
Connections {
target: missionItem.gridAltitude
onValueChanged: {
if (gridTypeCombo.currentIndex >= _gridTypeCustomCamera && missionItem.fixedValueIsAltitude && !_noCameraValueRecalc) {
recalcFromCameraValues()
}
}
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
ExclusiveGroup {
id: cameraOrientationGroup
onCurrentChanged: {
recalcFromMissionValues()
id: cameraOrientationGroup
onCurrentChanged: {
if (gridTypeCombo.currentIndex >= _gridTypeCustomCamera) {
recalcFromCameraValues()
}
}
}
ExclusiveGroup { id: fixedValueGroup }
Column {
id: editorColumn
anchors.margins: _margin
......@@ -198,307 +265,292 @@ Rectangle {
anchors.right: parent.right
wrapMode: Text.WordWrap
font.pointSize: ScreenTools.smallFontPointSize
text: qsTr("Create a flight path to fully cover a polygonal area with a camera.")
text: gridTypeCombo.currentIndex == 0 ?
qsTr("Create a flight path which covers a polygonal area by specifying all grid parameters.") :
qsTr("Create a flight path which fully covers a polygonal area using camera specifications.")
}
Repeater {
model: [ missionItem.gridAngle, missionItem.gridSpacing, missionItem.gridAltitude, missionItem.turnaroundDist ]
QGCLabel { text: qsTr("Camera:") }
Item {
anchors.left: parent.left
anchors.right: parent.right
height: textField.height
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: qgcPal.text
}
QGCLabel {
anchors.baseline: textField.baseline
anchors.left: parent.left
text: modelData.name + ":"
QGCComboBox {
id: gridTypeCombo
anchors.left: parent.left
anchors.right: parent.right
model: cameraModelList
currentIndex: -1
Component.onCompleted: {
if (missionItem.manualGrid) {
gridTypeCombo.currentIndex = _gridTypeManual
} else {
var index = gridTypeCombo.find(missionItem.camera)
if (index == -1) {
console.log("Couldn't find camera", missionItem.camera)
gridTypeCombo.currentIndex = _gridTypeManual
} else {
gridTypeCombo.currentIndex = index
}
}
}
FactTextField {
id: textField
anchors.right: parent.right
width: _editFieldWidth
showUnits: true
fact: modelData
onEditingFinished: recalcFromMissionValues()
validator: DoubleValidator{bottom:0.0; decimals:2}
onActivated: {
if (index == _gridTypeManual) {
missionItem.manualGrid = true
} else {
missionItem.manualGrid = false
missionItem.camera = gridTypeCombo.textAt(index)
_noCameraValueRecalc = true
missionItem.cameraSensorWidth.rawValue = cameraModelList.get(index).sensorWidth
missionItem.cameraSensorHeight.rawValue = cameraModelList.get(index).sensorHeight
missionItem.cameraResolutionWidth.rawValue = cameraModelList.get(index).imageWidth
missionItem.cameraResolutionHeight.rawValue = cameraModelList.get(index).imageHeight
missionItem.cameraFocalLength.rawValue = cameraModelList.get(index).focalLength
_noCameraValueRecalc = false
recalcFromCameraValues()
}
}
}
QGCCheckBox {
// Camera based grid ui
Column {
anchors.left: parent.left
text: qsTr("Relative altitude")
checked: missionItem.gridAltitudeRelative
onClicked: missionItem.gridAltitudeRelative = checked
}
anchors.right: parent.right
spacing: _margin
visible: gridTypeCombo.currentIndex != _gridTypeManual
Grid {
columns: 2
columnSpacing: ScreenTools.defaultFontPixelWidth
rowSpacing: _margin
verticalItemAlignment: Grid.AlignVCenter
Row {
spacing: _margin
QGCLabel {
text: qsTr("GSD:")
width: _editFieldWidth
}
QGCTextField {
id: gsdField
width: _editFieldWidth
unitsLabel: "cm/px"
showUnits: true
onEditingFinished: recalcFromCameraValues()
validator: DoubleValidator{bottom:0.0; decimals:2}
}
QGCRadioButton {
id: cameraOrientationLandscape
width: _editFieldWidth
text: "Landscape"
checked: true
exclusiveGroup: cameraOrientationGroup
}
QGCLabel { text: qsTr("Frontal Overlap:") }
QGCTextField {
id: frontalOverlapField
width: _editFieldWidth
unitsLabel: "%"
showUnits: true
onEditingFinished: recalcFromCameraValues()
validator: IntValidator {bottom:0}
QGCRadioButton {
id: cameraOrientationPortrait
text: "Portrait"
exclusiveGroup: cameraOrientationGroup
}
}
QGCLabel { text: qsTr("Side Overlap:") }
QGCTextField {
id: sideOverlapField
width: _editFieldWidth
unitsLabel: "%"
showUnits: true
onEditingFinished: recalcFromCameraValues()
validator: IntValidator {bottom:0}
}
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: gridTypeCombo.currentIndex == _gridTypeCustomCamera
Component.onCompleted: recalcFromMissionValues()
}
GridLayout {
columns: 3
columnSpacing: _margin
rowSpacing: _margin
QGCLabel { text: qsTr("Camera:") }
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: qgcPal.text
}
QGCLabel { }
QGCLabel { text: qsTr("Width") }
QGCLabel { text: qsTr("Height") }
Grid {
columns: 2
spacing: ScreenTools.defaultFontPixelWidth
verticalItemAlignment: Grid.AlignVCenter
QGCRadioButton {
id: cameraOrientationLandscape
width: _editFieldWidth
text: "Landscape"
checked: true
exclusiveGroup: cameraOrientationGroup
QGCLabel { text: qsTr("Sensor:") }
FactTextField {
Layout.preferredWidth: parent._fieldWidth
fact: missionItem.cameraSensorWidth
}
FactTextField {
Layout.preferredWidth: parent._fieldWidth
fact: missionItem.cameraSensorHeight
}
QGCLabel { text: qsTr("Image:") }
FactTextField {
Layout.preferredWidth: parent._fieldWidth
fact: missionItem.cameraResolutionWidth
}
FactTextField {
Layout.preferredWidth: parent._fieldWidth
fact: missionItem.cameraResolutionHeight
}
}
FactTextFieldRow {
spacing: _margin
fact: missionItem.cameraFocalLength
}
} // Column - custom camera
QGCLabel { text: qsTr("Image Overlap") }
Row {
spacing: _margin
Item {
width: ScreenTools.defaultFontPixelWidth * 2
height: 1
}
QGCLabel {
anchors.baseline: frontalOverlapField.baseline
text: qsTr("Frontal:")
}
FactTextField {
id: frontalOverlapField
width: ScreenTools.defaultFontPixelWidth * 7
fact: missionItem.frontalOverlap
}
QGCLabel {
anchors.baseline: frontalOverlapField.baseline
text: qsTr("Side:")
}
FactTextField {
width: frontalOverlapField.width
fact: missionItem.sideOverlap
}
}
QGCRadioButton {
id: cameraOrientationPortrait
text: "Portrait"
exclusiveGroup: cameraOrientationGroup
QGCLabel { text: qsTr("Grid:") }
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: qgcPal.text
}
QGCCheckBox {
id: cameraTrigger
width: _editFieldWidth
text: qsTr("Trigger:")
checked: missionItem.cameraTrigger
onClicked: missionItem.cameraTrigger = checked
FactTextFieldGrid {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
factList: [ missionItem.gridAngle, missionItem.turnaroundDist ]
}
FactTextField {
width: _editFieldWidth
showUnits: true
fact: missionItem.cameraTriggerDistance
enabled: missionItem.cameraTrigger
onEditingFinished: recalcFromMissionValues()
validator: DoubleValidator{bottom:0.0; decimals:2}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
font.pointSize: ScreenTools.smallFontPointSize
text: qsTr("Which value would you like to keep constant as you adjust other settings:")
}
}
Component {
id: cameraFields
QGCViewDialog {
Column {
id: dialogColumn
anchors.margins: _margin
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin * 5
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
id: selectCameraModelText
text: qsTr("Select Camera Model:")
}
QGCComboBox {
id: cameraModelCombo
model: cameraModelList
width: dialogColumn.width - selectCameraModelText.width - ScreenTools.defaultFontPixelWidth
onActivated: {
cameraIndex = index
}
Component.onCompleted: {
var index = cameraIndex
if (index === -1) {
console.warn("Active camera model name not in combo", cameraIndex)
} else {
cameraModelCombo.currentIndex = index
}
}
}
}
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
QGCRadioButton {
id: fixedAltitudeRadio
anchors.baseline: gridAltitudeField.baseline
text: qsTr("Altitude:")
checked: missionItem.fixedValueIsAltitude
exclusiveGroup: fixedValueGroup
onClicked: missionItem.fixedValueIsAltitude = true
}
Grid {
columns: 2
spacing: ScreenTools.defaultFontPixelWidth
verticalItemAlignment: Grid.AlignVCenter
QGCLabel { text: qsTr("Sensor Width:") }
QGCTextField {
id: sensorWidthField
unitsLabel: "mm"
showUnits: true
text: cameraModelList.get(cameraIndex).sensorWidth.toFixed(2)
readOnly: cameraIndex != 0
enabled: cameraIndex == 0
validator: DoubleValidator{bottom:0.0; decimals:2}
onEditingFinished: {
if (cameraIndex == 0) {
cameraModelList.setProperty(cameraIndex, "sensorWidth", Number(text))
}
}
}
QGCLabel { text: qsTr("Sensor Height:") }
QGCTextField {
id: sensorHeightField
unitsLabel: "mm"
showUnits: true
text: cameraModelList.get(cameraIndex).sensorHeight.toFixed(2)
readOnly: cameraIndex != 0
enabled: cameraIndex == 0
validator: DoubleValidator{bottom:0.0; decimals:2}
onEditingFinished: {
if (cameraIndex == 0) {
cameraModelList.setProperty(cameraIndex, "sensorHeight", Number(text))
}
}
}
QGCLabel { text: qsTr("Image Width:") }
QGCTextField {
id: imageWidthField
unitsLabel: "px"
showUnits: true
text: cameraModelList.get(cameraIndex).imageWidth.toFixed(0)
readOnly: cameraIndex != 0
enabled: cameraIndex == 0
validator: IntValidator {bottom:0}
onEditingFinished: {
if (cameraIndex == 0) {
cameraModelList.setProperty(cameraIndex, "imageWidth", Number(text))
}
}
}
QGCLabel { text: qsTr("Image Height:") }
QGCTextField {
id: imageHeightField
unitsLabel: "px"
showUnits: true
text: cameraModelList.get(cameraIndex).imageHeight.toFixed(0)
readOnly: cameraIndex != 0
enabled: cameraIndex == 0
validator: IntValidator {bottom:0}
onEditingFinished: {
if (cameraIndex == 0) {
cameraModelList.setProperty(cameraIndex, "imageHeight", Number(text))
}
}
}
QGCLabel { text: qsTr("Focal Length:") }
QGCTextField {
id: focalLengthField
unitsLabel: "mm"
showUnits: true
text: cameraModelList.get(cameraIndex).focalLength.toFixed(2)
readOnly: cameraIndex != 0
enabled: cameraIndex == 0
validator: DoubleValidator{bottom:0.0; decimals:2}
onEditingFinished: {
if (cameraIndex == 0) {
cameraModelList.setProperty(cameraIndex, "focalLength", Number(text))
}
}
}
}
FactTextField {
id: gridAltitudeField
Layout.fillWidth: true
fact: missionItem.gridAltitude
enabled: fixedAltitudeRadio.checked
}
}
function accept() {
hideDialog()
recalcFromCameraValues()
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
QGCRadioButton {
id: fixedGroundResolutionRadio
anchors.baseline: groundResolutionField.baseline
text: qsTr("Ground res:")
checked: !missionItem.fixedValueIsAltitude
exclusiveGroup: fixedValueGroup
onClicked: missionItem.fixedValueIsAltitude = false
}
}//QGCViewDialog
}//Component
FactTextField {
id: groundResolutionField
Layout.fillWidth: true
fact: missionItem.groundResolution
enabled: fixedGroundResolutionRadio.checked
}
}
}
// Manual grid ui
Column {
spacing: ScreenTools.defaultFontPixelHeight*0.01
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: gridTypeCombo.currentIndex == _gridTypeManual
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel { text: qsTr("Grid:") }
QGCLabel { text: qsTr("Model:") }
QGCLabel { text: cameraModelList.get(cameraIndex).text }
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: qgcPal.text
}
Grid {
columns: 2
columnSpacing: ScreenTools.defaultFontPixelWidth
rowSpacing: ScreenTools.defaultFontPixelHeight*0.01
FactTextFieldGrid {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
factList: [ missionItem.gridAngle, missionItem.gridSpacing, missionItem.gridAltitude, missionItem.turnaroundDist ]
}
QGCLabel {
text: qsTr("Sensor Size:")
width: _editFieldWidth
}
QGCLabel {
text: cameraModelList.get(cameraIndex).sensorWidth.toFixed(2) + qsTr(" x ") + cameraModelList.get(cameraIndex).sensorHeight.toFixed(2)
width: _editFieldWidth
}
QGCCheckBox {
anchors.left: parent.left
text: qsTr("Relative altitude")
checked: missionItem.gridAltitudeRelative
onClicked: missionItem.gridAltitudeRelative = checked
}
QGCLabel { text: qsTr("Image Size:") }
QGCLabel { text: cameraModelList.get(cameraIndex).imageWidth.toFixed(0) + qsTr(" x ") + cameraModelList.get(cameraIndex).imageHeight.toFixed(0) }
QGCLabel { text: qsTr("Camera:") }
QGCLabel { text: qsTr("Focal length:") }
QGCLabel { text: cameraModelList.get(cameraIndex).focalLength.toFixed(2) }
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: qgcPal.text
}
}
QGCButton {
id: cameraModelChange
text: qsTr("Change")
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
QGCCheckBox {
id: cameraTrigger
anchors.baseline: cameraTriggerDistanceField.baseline
text: qsTr("Trigger Distance:")
checked: missionItem.cameraTrigger
onClicked: missionItem.cameraTrigger = checked
}
onClicked: {
qgcView.showDialog(cameraFields, qsTr("Set Camera Model"), qgcView.showDialogDefaultWidth, StandardButton.Save)
FactTextField {
id: cameraTriggerDistanceField
Layout.fillWidth: true
fact: missionItem.cameraTriggerDistance
enabled: missionItem.cameraTrigger
}
}
}
QGCLabel { text: qsTr("Polygon:") }
Rectangle {
......
......@@ -18,20 +18,85 @@
"shortDescription": "Amount of spacing in between parallel grid lines.",
"type": "double",
"decimalPlaces": 2,
"min": 0.1,
"units": "m"
},
{
"name": "Turnaround dist.",
"name": "Turnaround dist",
"shortDescription": "Amount of additional distance to add outside the grid area for vehicle turnaround.",
"type": "double",
"decimalPlaces": 2,
"min": 0,
"units": "m"
},
{
"name": "Ground resolution",
"shortDescription": "Resolution of image in relationship to ground distance.",
"type": "double",
"decimalPlaces": 2,
"min": 0,
"units": "cm/px"
},
{
"name": "Frontal overlap",
"shortDescription": "Amount of overlap between images in the forward facing direction.",
"type": "double",
"decimalPlaces": 0,
"max": 75,
"units": "%"
},
{
"name": "Side overlap",
"shortDescription": "Amount of overlap between images in the side facing direction.",
"type": "double",
"decimalPlaces": 0,
"max": 75,
"units": "%"
},
{
"name": "Camera sensor width",
"shortDescription": "Amount of overlap between images in the side facing direction.",
"type": "double",
"decimalPlaces": 2,
"min": 1,
"units": "mm"
},
{
"name": "Camera sensor height",
"shortDescription": "Amount of overlap between images in the side facing direction.",
"type": "double",
"decimalPlaces": 2,
"min": 1,
"units": "mm"
},
{
"name": "Camera resolution width",
"shortDescription": "Amount of overlap between images in the side facing direction.",
"type": "uint32",
"min": 1,
"units": "px"
},
{
"name": "Camera resolution height",
"shortDescription": "Amount of overlap between images in the side facing direction.",
"type": "uint32",
"min": 1,
"units": "px"
},
{
"name": "Focal length",
"shortDescription": "Amount of overlap between images in the side facing direction.",
"type": "double",
"decimalPlaces": 1,
"min": 1,
"units": "mm"
},
{
"name": "Camera trigger distance",
"shortDescription": "Distance between each triggering of the camera.",
"type": "double",
"decimalPlaces": 2,
"min": 0.1,
"units": "m"
}
]
......@@ -17,22 +17,44 @@
QGC_LOGGING_CATEGORY(SurveyMissionItemLog, "SurveyMissionItemLog")
const char* SurveyMissionItem::_jsonTypeKey = "type";
const char* SurveyMissionItem::_jsonPolygonKey = "polygon";
const char* SurveyMissionItem::_jsonIdKey = "id";
const char* SurveyMissionItem::_jsonGridAltitudeKey = "gridAltitude";
const char* SurveyMissionItem::_jsonGridAltitudeRelativeKey = "gridAltitudeRelative";
const char* SurveyMissionItem::_jsonGridAngleKey = "gridAngle";
const char* SurveyMissionItem::_jsonGridSpacingKey = "gridSpacing";
const char* SurveyMissionItem::_jsonTurnaroundDistKey = "turnaroundDist";
const char* SurveyMissionItem::_jsonCameraTriggerKey = "cameraTrigger";
const char* SurveyMissionItem::_jsonCameraTriggerDistanceKey = "cameraTriggerDistance";
const char* SurveyMissionItem::_gridAltitudeFactName = "Altitude";
const char* SurveyMissionItem::_gridAngleFactName = "Grid angle";
const char* SurveyMissionItem::_gridSpacingFactName = "Grid spacing";
const char* SurveyMissionItem::_turnaroundDistFactName = "Turnaround dist.";
const char* SurveyMissionItem::_cameraTriggerDistanceFactName = "Camera trigger distance";
const char* SurveyMissionItem::_jsonTypeKey = "type";
const char* SurveyMissionItem::_jsonPolygonObjectKey = "polygon";
const char* SurveyMissionItem::_jsonIdKey = "id";
const char* SurveyMissionItem::_jsonGridObjectKey = "grid";
const char* SurveyMissionItem::_jsonGridAltitudeKey = "altitude";
const char* SurveyMissionItem::_jsonGridAltitudeRelativeKey = "relativeAltitude";
const char* SurveyMissionItem::_jsonGridAngleKey = "angle";
const char* SurveyMissionItem::_jsonGridSpacingKey = "spacing";
const char* SurveyMissionItem::_jsonTurnaroundDistKey = "turnAroundDistance";
const char* SurveyMissionItem::_jsonCameraTriggerKey = "cameraTrigger";
const char* SurveyMissionItem::_jsonCameraTriggerDistanceKey = "cameraTriggerDistance";
const char* SurveyMissionItem::_jsonGroundResolutionKey = "groundResolution";
const char* SurveyMissionItem::_jsonFrontalOverlapKey = "imageFrontalOverlap";
const char* SurveyMissionItem::_jsonSideOverlapKey = "imageSizeOverlap";
const char* SurveyMissionItem::_jsonCameraSensorWidthKey = "sensorWidth";
const char* SurveyMissionItem::_jsonCameraSensorHeightKey = "sensorHeight";
const char* SurveyMissionItem::_jsonCameraResolutionWidthKey = "resolutionWidth";
const char* SurveyMissionItem::_jsonCameraResolutionHeightKey = "resolutionHeight";
const char* SurveyMissionItem::_jsonCameraFocalLengthKey = "focalLength";
const char* SurveyMissionItem::_jsonCameraObjectKey = "camera";
const char* SurveyMissionItem::_jsonCameraNameKey = "name";
const char* SurveyMissionItem::_jsonManualGridKey = "manualGrid";
const char* SurveyMissionItem::_jsonCameraOrientationLandscapeKey = "orientationLandscape";
const char* SurveyMissionItem::_jsonFixedValueIsAltitudeKey = "fixedValueIsAltitude";
const char* SurveyMissionItem::_gridAltitudeFactName = "Altitude";
const char* SurveyMissionItem::_gridAngleFactName = "Grid angle";
const char* SurveyMissionItem::_gridSpacingFactName = "Grid spacing";
const char* SurveyMissionItem::_turnaroundDistFactName = "Turnaround dist";
const char* SurveyMissionItem::_cameraTriggerDistanceFactName = "Camera trigger distance";
const char* SurveyMissionItem::_groundResolutionFactName = "Ground resolution";
const char* SurveyMissionItem::_frontalOverlapFactName = "Frontal overlap";
const char* SurveyMissionItem::_sideOverlapFactName = "Side overlap";
const char* SurveyMissionItem::_cameraSensorWidthFactName = "Camera sensor width";
const char* SurveyMissionItem::_cameraSensorHeightFactName = "Camera sensor height";
const char* SurveyMissionItem::_cameraResolutionWidthFactName = "Camera resolution width";
const char* SurveyMissionItem::_cameraResolutionHeightFactName = "Camera resolution height";
const char* SurveyMissionItem::_cameraFocalLengthFactName = "Focal length";
const char* SurveyMissionItem::_complexType = "survey";
......@@ -44,29 +66,57 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent)
, _dirty(false)
, _cameraTrigger(true)
, _gridAltitudeRelative(true)
, _manualGrid(true)
, _cameraOrientationLandscape(true)
, _fixedValueIsAltitude(false)
, _surveyDistance(0.0)
, _cameraShots(0)
, _coveredArea(0.0)
, _gridAltitudeFact (0, _gridAltitudeFactName, FactMetaData::valueTypeDouble)
, _gridAngleFact (0, _gridAngleFactName, FactMetaData::valueTypeDouble)
, _gridSpacingFact (0, _gridSpacingFactName, FactMetaData::valueTypeDouble)
, _turnaroundDistFact (0, _turnaroundDistFactName, FactMetaData::valueTypeDouble)
, _cameraTriggerDistanceFact(0, _cameraTriggerDistanceFactName, FactMetaData::valueTypeDouble)
, _gridAltitudeFact (0, _gridAltitudeFactName, FactMetaData::valueTypeDouble)
, _gridAngleFact (0, _gridAngleFactName, FactMetaData::valueTypeDouble)
, _gridSpacingFact (0, _gridSpacingFactName, FactMetaData::valueTypeDouble)
, _turnaroundDistFact (0, _turnaroundDistFactName, FactMetaData::valueTypeDouble)
, _cameraTriggerDistanceFact (0, _cameraTriggerDistanceFactName, FactMetaData::valueTypeDouble)
, _groundResolutionFact (0, _groundResolutionFactName, FactMetaData::valueTypeDouble)
, _frontalOverlapFact (0, _frontalOverlapFactName, FactMetaData::valueTypeDouble)
, _sideOverlapFact (0, _sideOverlapFactName, FactMetaData::valueTypeDouble)
, _cameraSensorWidthFact (0, _cameraSensorWidthFactName, FactMetaData::valueTypeDouble)
, _cameraSensorHeightFact (0, _cameraSensorHeightFactName, FactMetaData::valueTypeDouble)
, _cameraResolutionWidthFact (0, _cameraResolutionWidthFactName, FactMetaData::valueTypeUint32)
, _cameraResolutionHeightFact (0, _cameraResolutionHeightFactName, FactMetaData::valueTypeUint32)
, _cameraFocalLengthFact (0, _cameraFocalLengthFactName, FactMetaData::valueTypeDouble)
{
if (_metaDataMap.isEmpty()) {
_metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/Survey.FactMetaData.json"), NULL /* metaDataParent */);
}
_gridAltitudeFact.setRawValue(50);
_gridSpacingFact.setRawValue(10);
_turnaroundDistFact.setRawValue(60);
_gridSpacingFact.setRawValue(30);
_turnaroundDistFact.setRawValue(_vehicle->multiRotor() ? 0 : 60);
_cameraTriggerDistanceFact.setRawValue(25);
_groundResolutionFact.setRawValue(3);
_frontalOverlapFact.setRawValue(10);
_sideOverlapFact.setRawValue(10);
_cameraSensorWidthFact.setRawValue(6.17);
_cameraSensorHeightFact.setRawValue(4.55);
_cameraResolutionWidthFact.setRawValue(4000);
_cameraResolutionHeightFact.setRawValue(3000);
_cameraFocalLengthFact.setRawValue(4.5);
_gridAltitudeFact.setMetaData(_metaDataMap[_gridAltitudeFactName]);
_gridAngleFact.setMetaData(_metaDataMap[_gridAngleFactName]);
_gridSpacingFact.setMetaData(_metaDataMap[_gridSpacingFactName]);
_turnaroundDistFact.setMetaData(_metaDataMap[_turnaroundDistFactName]);
_cameraTriggerDistanceFact.setMetaData(_metaDataMap[_cameraTriggerDistanceFactName]);
_groundResolutionFact.setMetaData(_metaDataMap[_groundResolutionFactName]);
_frontalOverlapFact.setMetaData(_metaDataMap[_frontalOverlapFactName]);
_sideOverlapFact.setMetaData(_metaDataMap[_sideOverlapFactName]);
_cameraSensorWidthFact.setMetaData(_metaDataMap[_cameraSensorWidthFactName]);
_cameraSensorHeightFact.setMetaData(_metaDataMap[_cameraSensorHeightFactName]);
_cameraResolutionWidthFact.setMetaData(_metaDataMap[_cameraResolutionWidthFactName]);
_cameraResolutionHeightFact.setMetaData(_metaDataMap[_cameraResolutionHeightFactName]);
_cameraFocalLengthFact.setMetaData(_metaDataMap[_cameraFocalLengthFactName]);
connect(&_gridSpacingFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid);
connect(&_gridAngleFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid);
......@@ -74,18 +124,17 @@ SurveyMissionItem::SurveyMissionItem(Vehicle* vehicle, QObject* parent)
connect(&_cameraTriggerDistanceFact, &Fact::valueChanged, this, &SurveyMissionItem::_generateGrid);
connect(&_gridAltitudeFact, &Fact::valueChanged, this, &SurveyMissionItem::_updateCoordinateAltitude);
connect(this, &SurveyMissionItem::cameraTriggerChanged, this, &SurveyMissionItem::_cameraTriggerChanged);
}
const SurveyMissionItem& SurveyMissionItem::operator=(const SurveyMissionItem& other)
{
ComplexMissionItem::operator=(other);
_setSurveyDistance(other._surveyDistance);
_setCameraShots(other._cameraShots);
_setCoveredArea(other._coveredArea);
// Signal to Qml when camera value changes to it can recalc
connect(&_groundResolutionFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged);
connect(&_frontalOverlapFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged);
connect(&_sideOverlapFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged);
connect(&_cameraSensorWidthFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged);
connect(&_cameraSensorHeightFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged);
connect(&_cameraResolutionWidthFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged);
connect(&_cameraResolutionHeightFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged);
connect(&_cameraFocalLengthFact, &Fact::valueChanged, this, &SurveyMissionItem::_cameraValueChanged);
return *this;
connect(this, &SurveyMissionItem::cameraTriggerChanged, this, &SurveyMissionItem::_cameraTriggerChanged);
}
void SurveyMissionItem::_setSurveyDistance(double surveyDistance)
......@@ -190,16 +239,41 @@ void SurveyMissionItem::setDirty(bool dirty)
void SurveyMissionItem::save(QJsonObject& saveObject) const
{
saveObject[JsonHelper::jsonVersionKey] = 1;
saveObject[JsonHelper::jsonVersionKey] = 2;
saveObject[_jsonTypeKey] = _complexType;
saveObject[_jsonIdKey] = sequenceNumber();
saveObject[_jsonGridAltitudeKey] = _gridAltitudeFact.rawValue().toDouble();
saveObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelative;
saveObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble();
saveObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble();
saveObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble();
saveObject[_jsonCameraTriggerKey] = _cameraTrigger;
saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble();
saveObject[_jsonManualGridKey] = _manualGrid;
saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitude;
if (_cameraTrigger) {
saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble();
}
QJsonObject gridObject;
gridObject[_jsonGridAltitudeKey] = _gridAltitudeFact.rawValue().toDouble();
gridObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelative;
gridObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble();
gridObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble();
gridObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble();
saveObject[_jsonGridObjectKey] = gridObject;
if (!_manualGrid) {
QJsonObject cameraObject;
cameraObject[_jsonCameraNameKey] = _camera;
cameraObject[_jsonCameraOrientationLandscapeKey] = _cameraOrientationLandscape;
cameraObject[_jsonCameraSensorWidthKey] = _cameraSensorWidthFact.rawValue().toDouble();
cameraObject[_jsonCameraSensorHeightKey] = _cameraSensorHeightFact.rawValue().toDouble();
cameraObject[_jsonCameraResolutionWidthKey] = _cameraResolutionWidthFact.rawValue().toDouble();
cameraObject[_jsonCameraResolutionHeightKey] = _cameraResolutionHeightFact.rawValue().toDouble();
cameraObject[_jsonCameraFocalLengthKey] = _cameraFocalLengthFact.rawValue().toDouble();
cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble();
cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt();
cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt();
saveObject[_jsonCameraObjectKey] = cameraObject;
}
// Polygon shape
......@@ -213,7 +287,7 @@ void SurveyMissionItem::save(QJsonObject& saveObject) const
polygonArray += jsonValue;
}
saveObject[_jsonPolygonKey] = polygonArray;
saveObject[_jsonPolygonObjectKey] = polygonArray;
}
void SurveyMissionItem::setSequenceNumber(int sequenceNumber)
......@@ -234,55 +308,115 @@ void SurveyMissionItem::_clear(void)
bool SurveyMissionItem::load(const QJsonObject& complexObject, QString& errorString)
{
_clear();
// Validate requires keys
QStringList requiredKeys;
requiredKeys << JsonHelper::jsonVersionKey << _jsonTypeKey << _jsonIdKey << _jsonPolygonKey << _jsonGridAltitudeKey << _jsonGridAngleKey << _jsonGridSpacingKey <<
_jsonCameraTriggerKey << _jsonCameraTriggerDistanceKey << _jsonGridAltitudeRelativeKey;
if (!JsonHelper::validateRequiredKeys(complexObject, requiredKeys, errorString)) {
_clear();
struct jsonKeyInfo_s {
const char* key;
QJsonValue::Type type;
bool required;
};
QList<JsonHelper::KeyValidateInfo> mainKeyInfoList = {
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true },
{ _jsonTypeKey, QJsonValue::String, true },
{ _jsonPolygonObjectKey, QJsonValue::Array, true },
{ _jsonIdKey, QJsonValue::Double, true },
{ _jsonGridObjectKey, QJsonValue::Object, true },
{ _jsonCameraObjectKey, QJsonValue::Object, false },
{ _jsonCameraTriggerKey, QJsonValue::Bool, true },
{ _jsonCameraTriggerDistanceKey, QJsonValue::Double, false },
{ _jsonManualGridKey, QJsonValue::Bool, true },
{ _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true },
};
QList<JsonHelper::KeyValidateInfo> gridKeyInfoList = {
{ _jsonGridAltitudeKey, QJsonValue::Double, true },
{ _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true },
{ _jsonGridAngleKey, QJsonValue::Double, true },
{ _jsonGridSpacingKey, QJsonValue::Double, true },
{ _jsonTurnaroundDistKey, QJsonValue::Double, true },
};
QList<JsonHelper::KeyValidateInfo> cameraKeyInfoList = {
{ _jsonGroundResolutionKey, QJsonValue::Double, true },
{ _jsonFrontalOverlapKey, QJsonValue::Double, true },
{ _jsonSideOverlapKey, QJsonValue::Double, true },
{ _jsonCameraSensorWidthKey, QJsonValue::Double, true },
{ _jsonCameraSensorHeightKey, QJsonValue::Double, true },
{ _jsonCameraResolutionWidthKey, QJsonValue::Double, true },
{ _jsonCameraResolutionHeightKey, QJsonValue::Double, true },
{ _jsonCameraFocalLengthKey, QJsonValue::Double, true },
{ _jsonCameraNameKey, QJsonValue::String, true },
{ _jsonCameraOrientationLandscapeKey, QJsonValue::Bool, true },
};
if (!JsonHelper::validateKeys(complexObject, mainKeyInfoList, errorString)) {
return false;
}
// Validate types
QStringList keyList;
QList<QJsonValue::Type> typeList;
keyList << JsonHelper::jsonVersionKey << _jsonTypeKey << _jsonIdKey << _jsonPolygonKey << _jsonGridAltitudeKey << _jsonGridAngleKey << _jsonGridSpacingKey << _jsonTurnaroundDistKey <<
_jsonCameraTriggerKey << _jsonCameraTriggerDistanceKey << _jsonGridAltitudeRelativeKey;
typeList << QJsonValue::Double << QJsonValue::String << QJsonValue::Double << QJsonValue::Array << QJsonValue::Double << QJsonValue::Double<< QJsonValue::Double << QJsonValue::Double <<
QJsonValue::Bool << QJsonValue::Double << QJsonValue::Bool;
if (!JsonHelper::validateKeyTypes(complexObject, keyList, typeList, errorString)) {
_clear();
if (!JsonHelper::validateKeys(complexObject[_jsonGridObjectKey].toObject(), gridKeyInfoList, errorString)) {
return false;
}
// Version check
if (complexObject[JsonHelper::jsonVersionKey].toInt() != 1) {
if (complexObject[JsonHelper::jsonVersionKey].toInt() != 2) {
errorString = tr("QGroundControl does not support this version of survey items");
_clear();
return false;
}
QString complexType = complexObject[_jsonTypeKey].toString();
if (complexType != _complexType) {
errorString = tr("QGroundControl does not support loading this complex mission item type: %1").arg(complexType);
_clear();
return false;
}
_clear();
setSequenceNumber(complexObject[_jsonIdKey].toInt());
_cameraTrigger = complexObject[_jsonCameraTriggerKey].toBool();
_gridAltitudeRelative = complexObject[_jsonGridAltitudeRelativeKey].toBool();
_manualGrid = complexObject[_jsonManualGridKey].toBool(true);
_cameraTrigger = complexObject[_jsonCameraTriggerKey].toBool(false);
_fixedValueIsAltitude = complexObject[_jsonFixedValueIsAltitudeKey].toBool(true);
_gridAltitudeRelative = complexObject[_jsonGridAltitudeRelativeKey].toBool(true);
_gridAltitudeFact.setRawValue (complexObject[_jsonGridAltitudeKey].toDouble());
_gridAngleFact.setRawValue (complexObject[_jsonGridAngleKey].toDouble());
_gridSpacingFact.setRawValue (complexObject[_jsonGridSpacingKey].toDouble());
_turnaroundDistFact.setRawValue (complexObject[_jsonTurnaroundDistKey].toDouble());
_cameraTriggerDistanceFact.setRawValue (complexObject[_jsonCameraTriggerDistanceKey].toDouble());
QJsonObject gridObject = complexObject[_jsonGridObjectKey].toObject();
_gridAltitudeFact.setRawValue (gridObject[_jsonGridAltitudeKey].toDouble());
_gridAngleFact.setRawValue (gridObject[_jsonGridAngleKey].toDouble());
_gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble());
_turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble());
if (_cameraTrigger) {
if (!complexObject.contains(_jsonCameraTriggerDistanceKey)) {
errorString = tr("%1 but %2 is missing").arg("cameraTrigger = true").arg("cameraTriggerDistance");
return false;
}
_cameraTriggerDistanceFact.setRawValue(complexObject[_jsonCameraTriggerDistanceKey].toDouble());
}
if (!_manualGrid) {
if (!complexObject.contains(_jsonCameraObjectKey)) {
errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera");
return false;
}
QJsonObject cameraObject = complexObject[_jsonCameraObjectKey].toObject();
if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) {
return false;
}
_camera = cameraObject[_jsonCameraNameKey].toString();
_cameraOrientationLandscape = cameraObject[_jsonCameraOrientationLandscapeKey].toBool(true);
_groundResolutionFact.setRawValue (cameraObject[_jsonGroundResolutionKey].toDouble());
_frontalOverlapFact.setRawValue (cameraObject[_jsonFrontalOverlapKey].toInt());
_sideOverlapFact.setRawValue (cameraObject[_jsonSideOverlapKey].toInt());
_cameraSensorWidthFact.setRawValue (cameraObject[_jsonCameraSensorWidthKey].toDouble());
_cameraSensorHeightFact.setRawValue (cameraObject[_jsonCameraSensorHeightKey].toDouble());
_cameraResolutionWidthFact.setRawValue (cameraObject[_jsonCameraResolutionWidthKey].toDouble());
_cameraResolutionHeightFact.setRawValue (cameraObject[_jsonCameraResolutionHeightKey].toDouble());
_cameraFocalLengthFact.setRawValue (cameraObject[_jsonCameraFocalLengthKey].toDouble());
}
// Polygon shape
QJsonArray polygonArray(complexObject[_jsonPolygonKey].toArray());
QJsonArray polygonArray(complexObject[_jsonPolygonObjectKey].toArray());
for (int i=0; i<polygonArray.count(); i++) {
const QJsonValue& pointValue = polygonArray[i];
......@@ -528,6 +662,9 @@ void SurveyMissionItem::_adjustLineDirection(const QList<QLineF>& lineList, QLis
void SurveyMissionItem::_gridGenerator(const QList<QPointF>& polygonPoints, QList<QPointF>& gridPoints)
{
double gridAngle = _gridAngleFact.rawValue().toDouble();
double gridSpacing = _gridSpacingFact.rawValue().toDouble();
qCDebug(SurveyMissionItemLog) << "SurveyMissionItem::_gridGenerator gridSpacing:gridAngle" << gridSpacing << gridAngle;
gridPoints.clear();
......@@ -557,7 +694,6 @@ void SurveyMissionItem::_gridGenerator(const QList<QPointF>& polygonPoints, QLi
// Create set of rotated parallel lines within the expanded bounding rect. Make the lines larger than the
// bounding box to guarantee intersection.
QList<QLineF> lineList;
float gridSpacing = _gridSpacingFact.rawValue().toDouble();
float x = largeBoundRect.topLeft().x() - (gridSpacing / 2);
while (x < largeBoundRect.bottomRight().x()) {
float yTop = largeBoundRect.topLeft().y() - 100.0;
......@@ -671,3 +807,8 @@ int SurveyMissionItem::cameraShots(void) const
{
return _cameraTrigger ? _cameraShots : 0;
}
void SurveyMissionItem::_cameraValueChanged(void)
{
emit cameraValueChanged();
}
......@@ -25,19 +25,29 @@ class SurveyMissionItem : public ComplexMissionItem
public:
SurveyMissionItem(Vehicle* vehicle, QObject* parent = NULL);
const SurveyMissionItem& operator=(const SurveyMissionItem& other);
Q_PROPERTY(Fact* gridAltitude READ gridAltitude CONSTANT)
Q_PROPERTY(bool gridAltitudeRelative MEMBER _gridAltitudeRelative NOTIFY gridAltitudeRelativeChanged)
Q_PROPERTY(Fact* gridAngle READ gridAngle CONSTANT)
Q_PROPERTY(Fact* gridSpacing READ gridSpacing CONSTANT)
Q_PROPERTY(Fact* turnaroundDist READ turnaroundDist CONSTANT)
Q_PROPERTY(bool cameraTrigger MEMBER _cameraTrigger NOTIFY cameraTriggerChanged)
Q_PROPERTY(Fact* cameraTriggerDistance READ cameraTriggerDistance CONSTANT)
Q_PROPERTY(QVariantList polygonPath READ polygonPath NOTIFY polygonPathChanged)
Q_PROPERTY(QVariantList gridPoints READ gridPoints NOTIFY gridPointsChanged)
Q_PROPERTY(int cameraShots READ cameraShots NOTIFY cameraShotsChanged)
Q_PROPERTY(double coveredArea READ coveredArea NOTIFY coveredAreaChanged)
Q_PROPERTY(Fact* gridAltitude READ gridAltitude CONSTANT)
Q_PROPERTY(bool gridAltitudeRelative MEMBER _gridAltitudeRelative NOTIFY gridAltitudeRelativeChanged)
Q_PROPERTY(Fact* gridAngle READ gridAngle CONSTANT)
Q_PROPERTY(Fact* gridSpacing READ gridSpacing CONSTANT)
Q_PROPERTY(Fact* turnaroundDist READ turnaroundDist CONSTANT)
Q_PROPERTY(bool cameraTrigger MEMBER _cameraTrigger NOTIFY cameraTriggerChanged)
Q_PROPERTY(Fact* cameraTriggerDistance READ cameraTriggerDistance CONSTANT)
Q_PROPERTY(Fact* groundResolution READ groundResolution CONSTANT)
Q_PROPERTY(Fact* frontalOverlap READ frontalOverlap CONSTANT)
Q_PROPERTY(Fact* sideOverlap READ sideOverlap CONSTANT)
Q_PROPERTY(Fact* cameraSensorWidth READ cameraSensorWidth CONSTANT)
Q_PROPERTY(Fact* cameraSensorHeight READ cameraSensorHeight CONSTANT)
Q_PROPERTY(Fact* cameraResolutionWidth READ cameraResolutionWidth CONSTANT)
Q_PROPERTY(Fact* cameraResolutionHeight READ cameraResolutionHeight CONSTANT)
Q_PROPERTY(Fact* cameraFocalLength READ cameraFocalLength CONSTANT)
Q_PROPERTY(QVariantList polygonPath READ polygonPath NOTIFY polygonPathChanged)
Q_PROPERTY(QVariantList gridPoints READ gridPoints NOTIFY gridPointsChanged)
Q_PROPERTY(int cameraShots READ cameraShots NOTIFY cameraShotsChanged)
Q_PROPERTY(double coveredArea READ coveredArea NOTIFY coveredAreaChanged)
Q_PROPERTY(bool fixedValueIsAltitude MEMBER _fixedValueIsAltitude NOTIFY fixedValueIsAltitudeChanged)
Q_PROPERTY(bool cameraOrientationLandscape MEMBER _cameraOrientationLandscape NOTIFY cameraOrientationLandscapeChanged)
Q_PROPERTY(bool manualGrid MEMBER _manualGrid NOTIFY manualGridChanged)
Q_PROPERTY(QString camera MEMBER _camera NOTIFY cameraChanged)
Q_INVOKABLE void clearPolygon(void);
Q_INVOKABLE void addPolygonCoordinate(const QGeoCoordinate coordinate);
......@@ -46,11 +56,19 @@ public:
QVariantList polygonPath(void) { return _polygonPath; }
QVariantList gridPoints (void) { return _gridPoints; }
Fact* gridAltitude(void) { return &_gridAltitudeFact; }
Fact* gridAngle(void) { return &_gridAngleFact; }
Fact* gridSpacing(void) { return &_gridSpacingFact; }
Fact* turnaroundDist(void) { return &_turnaroundDistFact; }
Fact* cameraTriggerDistance(void) { return &_cameraTriggerDistanceFact; }
Fact* gridAltitude (void) { return &_gridAltitudeFact; }
Fact* gridAngle (void) { return &_gridAngleFact; }
Fact* gridSpacing (void) { return &_gridSpacingFact; }
Fact* turnaroundDist (void) { return &_turnaroundDistFact; }
Fact* cameraTriggerDistance (void) { return &_cameraTriggerDistanceFact; }
Fact* groundResolution (void) { return &_groundResolutionFact; }
Fact* frontalOverlap (void) { return &_frontalOverlapFact; }
Fact* sideOverlap (void) { return &_sideOverlapFact; }
Fact* cameraSensorWidth (void) { return &_cameraSensorWidthFact; }
Fact* cameraSensorHeight (void) { return &_cameraSensorHeightFact; }
Fact* cameraResolutionWidth (void) { return &_cameraResolutionWidthFact; }
Fact* cameraResolutionHeight (void) { return &_cameraResolutionHeightFact; }
Fact* cameraFocalLength (void) { return &_cameraFocalLengthFact; }
int cameraShots(void) const;
double coveredArea(void) const { return _coveredArea; }
......@@ -87,14 +105,20 @@ public:
void save (QJsonObject& saveObject) const final;
signals:
void polygonPathChanged (void);
void altitudeChanged (double altitude);
void gridAngleChanged (double gridAngle);
void gridPointsChanged (void);
void cameraTriggerChanged (bool cameraTrigger);
void gridAltitudeRelativeChanged (bool gridAltitudeRelative);
void cameraShotsChanged (int cameraShots);
void coveredAreaChanged (double coveredArea);
void polygonPathChanged (void);
void altitudeChanged (double altitude);
void gridAngleChanged (double gridAngle);
void gridPointsChanged (void);
void cameraTriggerChanged (bool cameraTrigger);
void gridAltitudeRelativeChanged (bool gridAltitudeRelative);
void cameraShotsChanged (int cameraShots);
void coveredAreaChanged (double coveredArea);
void cameraValueChanged (void);
void fixedValueIsAltitudeChanged (bool fixedValueIsAltitude);
void gridTypeChanged (QString gridType);
void cameraOrientationLandscapeChanged (bool cameraOrientationLandscape);
void cameraChanged (QString camera);
void manualGridChanged (bool manualGrid);
private slots:
void _cameraTriggerChanged(void);
......@@ -113,33 +137,46 @@ private:
void _setSurveyDistance(double surveyDistance);
void _setCameraShots(int cameraShots);
void _setCoveredArea(double coveredArea);
int _sequenceNumber;
bool _dirty;
QVariantList _polygonPath;
QVariantList _gridPoints;
QGeoCoordinate _coordinate;
QGeoCoordinate _exitCoordinate;
double _altitude;
double _gridAngle;
bool _cameraTrigger;
bool _gridAltitudeRelative;
double _surveyDistance;
int _cameraShots;
double _coveredArea;
void _cameraValueChanged(void);
int _sequenceNumber;
bool _dirty;
QVariantList _polygonPath;
QVariantList _gridPoints;
QGeoCoordinate _coordinate;
QGeoCoordinate _exitCoordinate;
double _altitude;
bool _cameraTrigger;
bool _gridAltitudeRelative;
bool _manualGrid;
QString _camera;
bool _cameraOrientationLandscape;
bool _fixedValueIsAltitude;
double _surveyDistance;
int _cameraShots;
double _coveredArea;
Fact _gridAltitudeFact;
Fact _gridAngleFact;
Fact _gridSpacingFact;
Fact _turnaroundDistFact;
Fact _cameraTriggerDistanceFact;
Fact _groundResolutionFact;
Fact _frontalOverlapFact;
Fact _sideOverlapFact;
Fact _cameraSensorWidthFact;
Fact _cameraSensorHeightFact;
Fact _cameraResolutionWidthFact;
Fact _cameraResolutionHeightFact;
Fact _cameraFocalLengthFact;
static QMap<QString, FactMetaData*> _metaDataMap;
static const char* _jsonTypeKey;
static const char* _jsonPolygonKey;
static const char* _jsonPolygonObjectKey;
static const char* _jsonIdKey;
static const char* _jsonGridObjectKey;
static const char* _jsonGridAltitudeKey;
static const char* _jsonGridAltitudeRelativeKey;
static const char* _jsonGridAngleKey;
......@@ -147,12 +184,34 @@ private:
static const char* _jsonTurnaroundDistKey;
static const char* _jsonCameraTriggerKey;
static const char* _jsonCameraTriggerDistanceKey;
static const char* _jsonGroundResolutionKey;
static const char* _jsonFrontalOverlapKey;
static const char* _jsonSideOverlapKey;
static const char* _jsonCameraSensorWidthKey;
static const char* _jsonCameraSensorHeightKey;
static const char* _jsonCameraResolutionWidthKey;
static const char* _jsonCameraResolutionHeightKey;
static const char* _jsonCameraFocalLengthKey;
static const char* _jsonManualGridKey;
static const char* _jsonCameraObjectKey;
static const char* _jsonCameraNameKey;
static const char* _jsonCameraOrientationLandscapeKey;
static const char* _jsonFixedValueIsAltitudeKey;
static const char* _gridAltitudeFactName;
static const char* _gridAngleFactName;
static const char* _gridSpacingFactName;
static const char* _turnaroundDistFactName;
static const char* _cameraTriggerDistanceFactName;
static const char* _groundResolutionFactName;
static const char* _frontalOverlapFactName;
static const char* _sideOverlapFactName;
static const char* _cameraSensorWidthFactName;
static const char* _cameraSensorHeightFactName;
static const char* _cameraResolutionWidthFactName;
static const char* _cameraResolutionHeightFactName;
static const char* _cameraFocalLengthFactName;
static const char* _complexType;
};
......
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