Unverified Commit d2f97086 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #8965 from DonLakeFlyer/CameraBrandModel

Plan: Camera brand/model support. Use canonical camera names in Plan files.
parents a8270a44 f0df0818
......@@ -9,7 +9,9 @@
#include "CameraMetaData.h"
CameraMetaData::CameraMetaData(const QString& name,
CameraMetaData::CameraMetaData(const QString& canonicalName,
const QString& brand,
const QString& model,
double sensorWidth,
double sensorHeight,
double imageWidth,
......@@ -18,17 +20,21 @@ CameraMetaData::CameraMetaData(const QString& name,
bool landscape,
bool fixedOrientation,
double minTriggerInterval,
const QString& deprecatedTranslatedName,
QObject* parent)
: QObject (parent)
, _name (name)
, _sensorWidth (sensorWidth)
, _sensorHeight (sensorHeight)
, _imageWidth (imageWidth)
, _imageHeight (imageHeight)
, _focalLength (focalLength)
, _landscape (landscape)
, _fixedOrientation (fixedOrientation)
, _minTriggerInterval (minTriggerInterval)
: QObject (parent)
, canonicalName (canonicalName)
, brand (brand)
, model (model)
, sensorWidth (sensorWidth)
, sensorHeight (sensorHeight)
, imageWidth (imageWidth)
, imageHeight (imageHeight)
, focalLength (focalLength)
, landscape (landscape)
, fixedOrientation (fixedOrientation)
, minTriggerInterval (minTriggerInterval)
, deprecatedTranslatedName (deprecatedTranslatedName)
{
}
......@@ -17,7 +17,9 @@ class CameraMetaData : public QObject
Q_OBJECT
public:
CameraMetaData(const QString& name,
CameraMetaData(const QString& canonicalName,
const QString& brand,
const QString& model,
double sensorWidth,
double sensorHeight,
double imageWidth,
......@@ -26,36 +28,37 @@ public:
bool landscape,
bool fixedOrientation,
double minTriggerInterval,
const QString& deprecatedTranslatedName,
QObject* parent = nullptr);
Q_PROPERTY(QString name READ name CONSTANT) ///< Camera name
Q_PROPERTY(double sensorWidth READ sensorWidth CONSTANT) ///< Sensor size in millimeters
Q_PROPERTY(double sensorHeight READ sensorHeight CONSTANT) ///< Sensor size in millimeters
Q_PROPERTY(double imageWidth READ imageWidth CONSTANT) ///< Image size in pixels
Q_PROPERTY(double imageHeight READ imageHeight CONSTANT) ///< Image size in pixels
Q_PROPERTY(double focalLength READ focalLength CONSTANT) ///< Focal length in millimeters
Q_PROPERTY(bool landscape READ landscape CONSTANT) ///< true: camera is in landscape orientation
Q_PROPERTY(bool fixedOrientation READ fixedOrientation CONSTANT) ///< true: camera is in fixed orientation
Q_PROPERTY(double minTriggerInterval READ minTriggerInterval CONSTANT) ///< Minimum time in seconds between each photo taken, 0 for not specified
Q_PROPERTY(QString canonicalName MEMBER canonicalName CONSTANT)
Q_PROPERTY(QString deprecatedTranslatedName MEMBER deprecatedTranslatedName CONSTANT)
Q_PROPERTY(QString brand MEMBER brand CONSTANT)
Q_PROPERTY(QString model MEMBER model CONSTANT)
Q_PROPERTY(double sensorWidth MEMBER sensorWidth CONSTANT)
Q_PROPERTY(double sensorHeight MEMBER sensorHeight CONSTANT)
Q_PROPERTY(double imageWidth MEMBER imageWidth CONSTANT)
Q_PROPERTY(double imageHeight MEMBER imageHeight CONSTANT)
Q_PROPERTY(double focalLength MEMBER focalLength CONSTANT)
Q_PROPERTY(bool landscape MEMBER landscape CONSTANT)
Q_PROPERTY(bool fixedOrientation MEMBER fixedOrientation CONSTANT)
Q_PROPERTY(double minTriggerInterval MEMBER minTriggerInterval CONSTANT)
QString name (void) const { return _name; }
double sensorWidth (void) const { return _sensorWidth; }
double sensorHeight (void) const { return _sensorHeight; }
double imageWidth (void) const { return _imageWidth; }
double imageHeight (void) const { return _imageHeight; }
double focalLength (void) const { return _focalLength; }
bool landscape (void) const { return _landscape; }
bool fixedOrientation (void) const { return _fixedOrientation; }
double minTriggerInterval (void) const { return _minTriggerInterval; }
QString canonicalName; ///< Canonical name saved in plan files. Not translated.
QString brand; ///< Camera brand. Used for grouping.
QString model; ///< Camerar model
double sensorWidth; ///< Sensor size in millimeters
double sensorHeight; ///< Sensor size in millimeters
double imageWidth; ///< Image size in pixels
double imageHeight; ///< Image size in pixels
double focalLength; ///< Focal length in millimeters
bool landscape; ///< true: camera is in landscape orientation
bool fixedOrientation; ///< true: camera is in fixed orientation
double minTriggerInterval; ///< Minimum time in seconds between each photo taken, 0 for not specified
private:
QString _name;
double _sensorWidth;
double _sensorHeight;
double _imageWidth;
double _imageHeight;
double _focalLength;
bool _landscape;
bool _fixedOrientation;
double _minTriggerInterval;
/// In older builds camera names were incorrect marked for translation. This leads to plan files which have are language
/// dependant which is not a good thing. Newer plan files use the canonical name which is not translated. In order to support
/// loading older plan files we continue to include the incorrect translation so we can match against them as needed.
/// Newly added CameraMetaData entries should leave this value empty.
QString deprecatedTranslatedName;
};
This diff is collapsed.
{
"version": 1,
"fileType": "FactMetaData",
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "CameraName",
"shortDesc": "Camera name.",
"type": "string",
"default": "Manual (no camera specs)"
"name": "CameraName",
"shortDesc": "Camera name.",
"type": "string",
"default": "Manual (no camera specs)"
},
{
"name": "ValueSetIsDistance",
"shortDesc": "Value specified is distance to surface.",
"type": "bool",
"default": 1
"name": "ValueSetIsDistance",
"shortDesc": "Value specified is distance to surface.",
"type": "bool",
"default": 1
},
{
"name": "DistanceToSurface",
"shortDesc": "Distance vehicle is away from surface.",
"shortDesc": "Distance vehicle is away from surface.",
"type": "double",
"min": 0.1,
"units": "m",
"decimalPlaces": 2,
"default": 50.0
"default": 50.0
},
{
"name": "ImageDensity",
"shortDesc": "Image desity at surface.",
"shortDesc": "Image desity at surface.",
"type": "double",
"min": 0,
"units": "cm/px",
"decimalPlaces": 1,
"default": 1.2
"default": 1.2
},
{
"name": "FrontalOverlap",
"shortDesc": "Amount of overlap between images in the forward facing direction.",
"shortDesc": "Amount of overlap between images in the forward facing direction.",
"type": "double",
"decimalPlaces": 0,
"min": 0,
"max": 85,
"units": "%",
"default": 70
"default": 70
},
{
"name": "SideOverlap",
"shortDesc": "Amount of overlap between images in the side facing direction.",
"shortDesc": "Amount of overlap between images in the side facing direction.",
"type": "double",
"decimalPlaces": 0,
"min": 0,
"max": 85,
"units": "%",
"default": 70
"default": 70
},
{
"name": "AdjustedFootprintFrontal",
......@@ -59,7 +59,7 @@
"decimalPlaces": 2,
"min": 0,
"units": "m",
"default": 25
"default": 25
},
{
"name": "AdjustedFootprintSide",
......@@ -67,7 +67,7 @@
"decimalPlaces": 2,
"min": 0,
"units": "m",
"default": 25
"default": 25
}
]
}
This diff is collapsed.
......@@ -21,11 +21,14 @@ class CameraCalc : public CameraSpec
public:
CameraCalc(PlanMasterController* masterController, const QString& settingsGroup, QObject* parent = nullptr);
Q_PROPERTY(QString customCameraName READ customCameraName CONSTANT) ///< Camera name for custom camera setting
Q_PROPERTY(QString manualCameraName READ manualCameraName CONSTANT) ///< Camera name for manual camera setting
Q_PROPERTY(QString xlatCustomCameraName READ xlatCustomCameraName CONSTANT) ///< User visible camera name for custom camera setting
Q_PROPERTY(QString xlatManualCameraName READ xlatManualCameraName CONSTANT) ///< User visible camera name for manual camera setting
Q_PROPERTY(bool isManualCamera READ isManualCamera NOTIFY isManualCameraChanged)
Q_PROPERTY(bool isCustomCamera READ isCustomCamera NOTIFY isCustomCameraChanged)
Q_PROPERTY(Fact* cameraName READ cameraName CONSTANT)
Q_PROPERTY(QString cameraBrand MEMBER _cameraBrand WRITE setCameraBrand NOTIFY cameraBrandChanged)
Q_PROPERTY(QString cameraModel MEMBER _cameraModel WRITE setCameraModel NOTIFY cameraModelChanged)
Q_PROPERTY(QStringList cameraBrandList MEMBER _cameraBrandList CONSTANT)
Q_PROPERTY(QStringList cameraModelList MEMBER _cameraModelList NOTIFY cameraModelListChanged)
Q_PROPERTY(Fact* valueSetIsDistance READ valueSetIsDistance CONSTANT) ///< true: distance specified, resolution calculated
Q_PROPERTY(Fact* distanceToSurface READ distanceToSurface CONSTANT) ///< Distance to surface for image foot print calculation
Q_PROPERTY(Fact* imageDensity READ imageDensity CONSTANT) ///< Image density on surface (cm/px)
......@@ -46,10 +49,11 @@ public:
Q_PROPERTY(double imageFootprintSide READ imageFootprintSide NOTIFY imageFootprintSideChanged) ///< Size of image size side in meters
Q_PROPERTY(double imageFootprintFrontal READ imageFootprintFrontal NOTIFY imageFootprintFrontalChanged) ///< Size of image size frontal in meters
static QString customCameraName(void);
static QString manualCameraName(void);
static QString xlatCustomCameraName (void);
static QString xlatManualCameraName (void);
static QString canonicalCustomCameraName(void);
static QString canonicalManualCameraName(void);
Fact* cameraName (void) { return &_cameraNameFact; }
Fact* valueSetIsDistance (void) { return &_valueSetIsDistanceFact; }
Fact* distanceToSurface (void) { return &_distanceToSurfaceFact; }
Fact* imageDensity (void) { return &_imageDensityFact; }
......@@ -67,18 +71,22 @@ public:
const Fact* adjustedFootprintFrontal (void) const { return &_adjustedFootprintFrontalFact; }
bool dirty (void) const { return _dirty; }
bool isManualCamera (void) const { return _cameraNameFact.rawValue().toString() == manualCameraName(); }
bool isCustomCamera (void) const { return _cameraNameFact.rawValue().toString() == customCameraName(); }
bool isManualCamera (void) const { return _cameraNameFact.rawValue().toString() == canonicalManualCameraName(); }
bool isCustomCamera (void) const { return _cameraNameFact.rawValue().toString() == canonicalCustomCameraName(); }
double imageFootprintSide (void) const { return _imageFootprintSide; }
double imageFootprintFrontal (void) const { return _imageFootprintFrontal; }
bool distanceToSurfaceRelative (void) const { return _distanceToSurfaceRelative; }
void setDirty (bool dirty);
void setDistanceToSurfaceRelative (bool distanceToSurfaceRelative);
void setCameraBrand (const QString& cameraBrand);
void setCameraModel (const QString& cameraModel);
void save(QJsonObject& json) const;
bool load(const QJsonObject& json, QString& errorString);
void _setCameraNameFromV3TransectLoad (const QString& cameraName);
static const char* cameraNameName;
static const char* valueSetIsDistanceName;
static const char* distanceToSurfaceName;
......@@ -96,6 +104,10 @@ signals:
void distanceToSurfaceRelativeChanged (bool distanceToSurfaceRelative);
void isManualCameraChanged (void);
void isCustomCameraChanged (void);
void cameraBrandChanged (void);
void cameraModelChanged (void);
void cameraModelListChanged (void);
void updateCameraStats (void);
private slots:
void _recalcTriggerDistance (void);
......@@ -104,9 +116,20 @@ private slots:
void _cameraNameChanged (void);
private:
bool _dirty;
bool _disableRecalc;
bool _distanceToSurfaceRelative;
void _setBrandModelFromCanonicalName (const QString& cameraName);
void _rebuildCameraModelList (void);
QString _validCanonicalCameraName (const QString& cameraName);
bool _dirty = false;
bool _disableRecalc = false;
QString _cameraBrand;
QString _cameraModel;
QStringList _cameraBrandList;
QStringList _cameraModelList;
bool _distanceToSurfaceRelative = true;
double _imageFootprintSide = 0;
double _imageFootprintFrontal = 0;
QVariantList _knownCameraList;
QMap<QString, FactMetaData*> _metaDataMap;
......@@ -119,11 +142,6 @@ private:
SettingsFact _adjustedFootprintSideFact;
SettingsFact _adjustedFootprintFrontalFact;
double _imageFootprintSide;
double _imageFootprintFrontal;
QVariantList _knownCameraList;
// The following are deprecated usage and only included in order to convert older formats
enum CameraSpecType {
......
......@@ -23,7 +23,7 @@ void CameraCalcTest::init(void)
_masterController = new PlanMasterController(this);
_controllerVehicle = _masterController->controllerVehicle();
_cameraCalc = new CameraCalc(_masterController, "CameraCalcUnitTest" /* settingsGroup */, this);
_cameraCalc->cameraName()->setRawValue(_cameraCalc->customCameraName());
_cameraCalc->setCameraBrand(CameraCalc::canonicalCustomCameraName());
_cameraCalc->setDirty(false);
_rgSignals[dirtyChangedIndex] = SIGNAL(dirtyChanged(bool));
......@@ -87,7 +87,7 @@ void CameraCalcTest::_testDirty(void)
QVERIFY(_cameraCalc->dirty());
_multiSpy->clearAllSignals();
_cameraCalc->cameraName()->setRawValue(_cameraCalc->manualCameraName());
_cameraCalc->setCameraBrand(CameraCalc::canonicalManualCameraName());
QVERIFY(_cameraCalc->dirty());
_multiSpy->clearAllSignals();
}
......
......@@ -85,7 +85,7 @@ void StructureScanComplexItemTest::_initItem(void)
mapPolygon->appendVertex(vertex);
}
_structureScanItem->cameraCalc()->cameraName()->setRawValue(CameraCalc::manualCameraName());
_structureScanItem->cameraCalc()->setCameraBrand(CameraCalc::canonicalManualCameraName());
_structureScanItem->layers()->setCookedValue(2);
_structureScanItem->setDirty(false);
......
......@@ -324,7 +324,7 @@ bool SurveyComplexItem::_loadV3(const QJsonObject& complexObject, int sequenceNu
_cameraCalc.adjustedFootprintFrontal()->setRawValue (complexObject[_jsonV3CameraTriggerDistanceKey].toDouble());
if (manualGrid) {
_cameraCalc.cameraName()->setRawValue(_cameraCalc.manualCameraName());
_cameraCalc.setCameraBrand(CameraCalc::canonicalManualCameraName());
} else {
if (!complexObject.contains(_jsonV3CameraObjectKey)) {
errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera");
......@@ -359,7 +359,6 @@ bool SurveyComplexItem::_loadV3(const QJsonObject& complexObject, int sequenceNu
return false;
}
_cameraCalc.cameraName()->setRawValue (cameraObject[_jsonV3CameraNameKey].toString());
_cameraCalc.landscape()->setRawValue (cameraObject[_jsonV3CameraOrientationLandscapeKey].toBool(true));
_cameraCalc.frontalOverlap()->setRawValue (cameraObject[_jsonV3FrontalOverlapKey].toInt());
_cameraCalc.sideOverlap()->setRawValue (cameraObject[_jsonV3SideOverlapKey].toInt());
......@@ -371,6 +370,7 @@ bool SurveyComplexItem::_loadV3(const QJsonObject& complexObject, int sequenceNu
_cameraCalc.minTriggerInterval()->setRawValue (cameraObject[_jsonV3CameraMinTriggerIntervalKey].toDouble(0));
_cameraCalc.imageDensity()->setRawValue (cameraObject[_jsonV3GroundResolutionKey].toDouble());
_cameraCalc.fixedOrientation()->setRawValue (false);
_cameraCalc._setCameraNameFromV3TransectLoad (cameraObject[_jsonV3CameraNameKey].toString());
}
// Polygon shape
......
......@@ -20,7 +20,7 @@ void TransectStyleComplexItemTest::init(void)
_transectStyleItem = new TestTransectStyleItem(_masterController, this);
_transectStyleItem->cameraTriggerInTurnAround()->setRawValue(false);
_transectStyleItem->cameraCalc()->cameraName()->setRawValue(_transectStyleItem->cameraCalc()->customCameraName());
_transectStyleItem->cameraCalc()->setCameraBrand(CameraCalc::canonicalCustomCameraName());
_transectStyleItem->cameraCalc()->valueSetIsDistance()->setRawValue(true);
_transectStyleItem->cameraCalc()->distanceToSurface()->setRawValue(100);
_transectStyleItem->setDirty(false);
......@@ -192,9 +192,9 @@ void TransectStyleComplexItemTest::_testAltMode(void)
// Manual camera allows non-relative altitudes, validate that changing back to known
// camera switches back to relative
_transectStyleItem->cameraCalc()->cameraName()->setRawValue(_transectStyleItem->cameraCalc()->manualCameraName());
_transectStyleItem->cameraCalc()->setCameraBrand(CameraCalc::canonicalManualCameraName());
_transectStyleItem->cameraCalc()->setDistanceToSurfaceRelative(false);
_transectStyleItem->cameraCalc()->cameraName()->setRawValue(_transectStyleItem->cameraCalc()->customCameraName());
_transectStyleItem->cameraCalc()->setCameraBrand(CameraCalc::canonicalCustomCameraName());
QVERIFY(_transectStyleItem->cameraCalc()->distanceToSurfaceRelative());
// When you turn off terrain following mode make sure that the altitude mode changed back to relative altitudes
......
......@@ -17,42 +17,13 @@ Column {
property var cameraCalc
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property string _cameraName: cameraCalc.cameraName.value
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10.5
property var _cameraList: [ ]
property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
property var _vehicleCameraList: _vehicle ? _vehicle.staticCameraList : []
property bool _cameraComboFilled: false
readonly property int _gridTypeManual: 0
readonly property int _gridTypeCustomCamera: 1
readonly property int _gridTypeCamera: 2
Component.onCompleted: _fillCameraCombo()
on_CameraNameChanged: _updateSelectedCamera()
function _fillCameraCombo() {
_cameraComboFilled = true
_cameraList.push(cameraCalc.manualCameraName)
_cameraList.push(cameraCalc.customCameraName)
for (var i=0; i<_vehicle.staticCameraList.length; i++) {
_cameraList.push(_vehicle.staticCameraList[i].name)
}
gridTypeCombo.model = _cameraList
_updateSelectedCamera()
}
function _updateSelectedCamera() {
if (_cameraComboFilled) {
var knownCameraIndex = gridTypeCombo.find(_cameraName)
if (knownCameraIndex !== -1) {
gridTypeCombo.currentIndex = knownCameraIndex
} else {
console.log("Internal error: Known camera not found", _cameraName)
gridTypeCombo.currentIndex = _gridTypeCustomCamera
}
}
Component.onCompleted:{
cameraBrandCombo.selectCurrentBrand()
cameraModelCombo.selectCurrentModel()
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
......@@ -67,13 +38,41 @@ Column {
spacing: _margin
QGCComboBox {
id: gridTypeCombo
id: cameraBrandCombo
anchors.left: parent.left
anchors.right: parent.right
model: _cameraList
currentIndex: -1
onActivated: cameraCalc.cameraName.value = gridTypeCombo.textAt(index)
} // QGCComboxBox
model: cameraCalc.cameraBrandList
onModelChanged: selectCurrentBrand()
onActivated: cameraCalc.cameraBrand = currentText
Connections {
target: cameraCalc
onCameraBrandChanged: cameraBrandCombo.selectCurrentBrand()
}
function selectCurrentBrand() {
currentIndex = cameraBrandCombo.find(cameraCalc.cameraBrand)
}
}
QGCComboBox {
id: cameraModelCombo
anchors.left: parent.left
anchors.right: parent.right
model: cameraCalc.cameraModelList
visible: !cameraCalc.isManualCamera && !cameraCalc.isCustomCamera
onModelChanged: selectCurrentModel()
onActivated: cameraCalc.cameraModel = currentText
Connections {
target: cameraCalc
onCameraModelChanged: cameraModelCombo.selectCurrentModel()
}
function selectCurrentModel() {
currentIndex = cameraModelCombo.find(cameraCalc.cameraModel)
}
}
// Camera based grid ui
Column {
......@@ -108,7 +107,7 @@ Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: cameraCalc.isCustomCamera
enabled: cameraCalc.isCustomCamera
RowLayout {
anchors.left: parent.left
......
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