|
|
|
@ -1,6 +1,7 @@
@@ -1,6 +1,7 @@
|
|
|
|
|
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 {
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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 { |
|
|
|
|