Commit 196165c5 authored by Don Gagne's avatar Don Gagne

Structure Scan persistence and mission creation

parent 1ea97d2f
......@@ -21,6 +21,8 @@ const char* CameraCalc::_frontalOverlapName = "FrontalOverlap";
const char* CameraCalc::_sideOverlapName = "SideOverlap";
const char* CameraCalc::_adjustedFootprintFrontalName = "AdjustedFootprintFrontal";
const char* CameraCalc::_adjustedFootprintSideName = "AdjustedFootprintSide";
const char* CameraCalc::_jsonCameraSpecTypeKey = "CameraSpecType";
const char* CameraCalc::_jsonKnownCameraNameKey = "CameraName";
CameraCalc::CameraCalc(Vehicle* vehicle, QObject* parent)
: CameraSpec (parent)
......@@ -47,8 +49,8 @@ CameraCalc::CameraCalc(Vehicle* vehicle, QObject* parent)
_imageDensityFact.setMetaData (_metaDataMap[_imageDensityName], true);
_frontalOverlapFact.setMetaData (_metaDataMap[_frontalOverlapName], true);
_sideOverlapFact.setMetaData (_metaDataMap[_sideOverlapName], true);
_adjustedFootprintSideFact.setMetaData (_metaDataMap[_adjustedFootprintSideName], false);
_adjustedFootprintFrontalFact.setMetaData (_metaDataMap[_adjustedFootprintFrontalName], false);
_adjustedFootprintSideFact.setMetaData (_metaDataMap[_adjustedFootprintSideName], true);
_adjustedFootprintFrontalFact.setMetaData (_metaDataMap[_adjustedFootprintFrontalName], true);
connect(this, &CameraCalc::knownCameraNameChanged, this, &CameraCalc::_knownCameraNameChanged);
......@@ -71,6 +73,22 @@ void CameraCalc::setDirty(bool dirty)
}
}
void CameraCalc::setCameraSpecType(CameraSpecType cameraSpecType)
{
if (cameraSpecType != _cameraSpecType) {
_cameraSpecType = cameraSpecType;
emit cameraSpecTypeChanged(_cameraSpecType);
}
}
void CameraCalc::setKnownCameraName(QString knownCameraName)
{
if (knownCameraName != _knownCameraName) {
_knownCameraName = knownCameraName;
emit knownCameraNameChanged(_knownCameraName);
}
}
void CameraCalc::_knownCameraNameChanged(QString knownCameraName)
{
if (_cameraSpecType == CameraSpecKnown) {
......@@ -150,206 +168,76 @@ void CameraCalc::_recalcTriggerDistance(void)
void CameraCalc::save(QJsonObject& json) const
{
Q_UNUSED(json);
#if 0
QJsonObject saveObject;
saveObject[JsonHelper::jsonVersionKey] = 3;
saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue;
saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue;
saveObject[_jsonManualGridKey] = _manualGridFact.rawValue().toBool();
saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitudeFact.rawValue().toBool();
saveObject[_jsonHoverAndCaptureKey] = _hoverAndCaptureFact.rawValue().toBool();
saveObject[_jsonRefly90DegreesKey] = _refly90Degrees;
saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble();
saveObject[_jsonCameraTriggerInTurnaroundKey] = _cameraTriggerInTurnaroundFact.rawValue().toBool();
QJsonObject gridObject;
gridObject[_jsonGridAltitudeKey] = _gridAltitudeFact.rawValue().toDouble();
gridObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelativeFact.rawValue().toBool();
gridObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble();
gridObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble();
gridObject[_jsonGridEntryLocationKey] = _gridEntryLocationFact.rawValue().toDouble();
gridObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble();
saveObject[_jsonGridObjectKey] = gridObject;
if (!_manualGridFact.rawValue().toBool()) {
QJsonObject cameraObject;
cameraObject[_jsonCameraNameKey] = _cameraFact.rawValue().toString();
cameraObject[_jsonCameraOrientationLandscapeKey] = _cameraOrientationLandscapeFact.rawValue().toBool();
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[_jsonCameraMinTriggerIntervalKey] = _cameraMinTriggerInterval;
cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble();
cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt();
cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt();
saveObject[_jsonCameraObjectKey] = cameraObject;
json[_jsonCameraSpecTypeKey] = (int)_cameraSpecType;
json[_adjustedFootprintSideName] = _adjustedFootprintSideFact.rawValue().toDouble();
json[_adjustedFootprintFrontalName] = _adjustedFootprintFrontalFact.rawValue().toDouble();
json[_distanceToSurfaceName] = _distanceToSurfaceFact.rawValue().toDouble();
if (_cameraSpecType != CameraSpecNone) {
CameraSpec::save(json);
json[_jsonKnownCameraNameKey] = _knownCameraName;
json[_valueSetIsDistanceName] = _valueSetIsDistanceFact.rawValue().toBool();
json[_imageDensityName] = _imageDensityFact.rawValue().toDouble();
json[_frontalOverlapName] = _frontalOverlapFact.rawValue().toDouble();
json[_sideOverlapName] = _sideOverlapFact.rawValue().toDouble();
}
// Polygon shape
_mapPolygon.saveToJson(saveObject);
missionItems.append(saveObject);
#endif
}
bool CameraCalc::load(const QJsonObject& complexObject, QString& errorString)
bool CameraCalc::load(const QJsonObject& json, QString& errorString)
{
Q_UNUSED(complexObject);
Q_UNUSED(errorString);
#if 0
QJsonObject v2Object = complexObject;
// We need to pull version first to determine what validation/conversion needs to be performed.
QList<JsonHelper::KeyValidateInfo> versionKeyInfoList = {
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true },
QList<JsonHelper::KeyValidateInfo> keyInfoList1 = {
{ _jsonCameraSpecTypeKey, QJsonValue::Double, true },
{ _adjustedFootprintSideName, QJsonValue::Double, true },
{ _adjustedFootprintFrontalName, QJsonValue::Double, true },
{ _distanceToSurfaceName, QJsonValue::Double, true },
};
if (!JsonHelper::validateKeys(v2Object, versionKeyInfoList, errorString)) {
if (!JsonHelper::validateKeys(json, keyInfoList1, errorString)) {
return false;
}
int version = v2Object[JsonHelper::jsonVersionKey].toInt();
if (version != 2 && version != 3) {
errorString = tr("%1 does not support this version of survey items").arg(qgcApp()->applicationName());
return false;
}
if (version == 2) {
// Convert to v3
if (v2Object.contains(VisualMissionItem::jsonTypeKey) && v2Object[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("survey")) {
v2Object[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue;
v2Object[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue;
}
}
QList<JsonHelper::KeyValidateInfo> mainKeyInfoList = {
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true },
{ VisualMissionItem::jsonTypeKey, QJsonValue::String, true },
{ ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true },
{ QGCMapPolygon::jsonPolygonKey, QJsonValue::Array, true },
{ _jsonGridObjectKey, QJsonValue::Object, true },
{ _jsonCameraObjectKey, QJsonValue::Object, false },
{ _jsonCameraTriggerDistanceKey, QJsonValue::Double, true },
{ _jsonManualGridKey, QJsonValue::Bool, true },
{ _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true },
{ _jsonHoverAndCaptureKey, QJsonValue::Bool, false },
{ _jsonRefly90DegreesKey, QJsonValue::Bool, false },
{ _jsonCameraTriggerInTurnaroundKey, QJsonValue::Bool, false }, // Should really be required, but it was missing from initial code due to bug
};
if (!JsonHelper::validateKeys(v2Object, mainKeyInfoList, errorString)) {
return false;
}
QString itemType = v2Object[VisualMissionItem::jsonTypeKey].toString();
QString complexType = v2Object[ComplexMissionItem::jsonComplexItemTypeKey].toString();
if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) {
errorString = tr("%1 does not support loading this complex mission item type: %2:%3").arg(qgcApp()->applicationName()).arg(itemType).arg(complexType);
int cameraSpecType = json[_jsonCameraSpecTypeKey].toInt();
switch (cameraSpecType) {
case CameraSpecNone:
case CameraSpecCustom:
case CameraSpecKnown:
break;
default:
errorString = tr("Unsupported CameraSpecType %d").arg(cameraSpecType);
return false;
}
_ignoreRecalc = true;
_mapPolygon.clear();
setSequenceNumber(sequenceNumber);
_manualGridFact.setRawValue (v2Object[_jsonManualGridKey].toBool(true));
_fixedValueIsAltitudeFact.setRawValue (v2Object[_jsonFixedValueIsAltitudeKey].toBool(true));
_gridAltitudeRelativeFact.setRawValue (v2Object[_jsonGridAltitudeRelativeKey].toBool(true));
_hoverAndCaptureFact.setRawValue (v2Object[_jsonHoverAndCaptureKey].toBool(false));
_cameraTriggerInTurnaroundFact.setRawValue (v2Object[_jsonCameraTriggerInTurnaroundKey].toBool(true));
_refly90Degrees = v2Object[_jsonRefly90DegreesKey].toBool(false);
_disableRecalc = true;
QList<JsonHelper::KeyValidateInfo> gridKeyInfoList = {
{ _jsonGridAltitudeKey, QJsonValue::Double, true },
{ _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true },
{ _jsonGridAngleKey, QJsonValue::Double, true },
{ _jsonGridSpacingKey, QJsonValue::Double, true },
{ _jsonGridEntryLocationKey, QJsonValue::Double, false },
{ _jsonTurnaroundDistKey, QJsonValue::Double, true },
setCameraSpecType((CameraSpecType)cameraSpecType);
_adjustedFootprintSideFact.setRawValue (json[_adjustedFootprintSideName].toDouble());
_adjustedFootprintFrontalFact.setRawValue (json[_adjustedFootprintFrontalName].toDouble());
_distanceToSurfaceFact.setRawValue (json[_distanceToSurfaceName].toDouble());
if (_cameraSpecType != CameraSpecNone) {
QList<JsonHelper::KeyValidateInfo> keyInfoList2 = {
{ _jsonKnownCameraNameKey, QJsonValue::String, true },
{ _valueSetIsDistanceName, QJsonValue::Bool, true },
{ _imageDensityName, QJsonValue::Double, true },
{ _frontalOverlapName, QJsonValue::Double, true },
{ _sideOverlapName, QJsonValue::Double, true },
};
QJsonObject gridObject = v2Object[_jsonGridObjectKey].toObject();
if (!JsonHelper::validateKeys(gridObject, gridKeyInfoList, errorString)) {
return false;
}
_gridAltitudeFact.setRawValue (gridObject[_jsonGridAltitudeKey].toDouble());
_gridAngleFact.setRawValue (gridObject[_jsonGridAngleKey].toDouble());
_gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble());
_turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble());
_cameraTriggerDistanceFact.setRawValue (v2Object[_jsonCameraTriggerDistanceKey].toDouble());
if (gridObject.contains(_jsonGridEntryLocationKey)) {
_gridEntryLocationFact.setRawValue(gridObject[_jsonGridEntryLocationKey].toDouble());
} else {
_gridEntryLocationFact.setRawValue(_gridEntryLocationFact.rawDefaultValue());
}
if (!_manualGridFact.rawValue().toBool()) {
if (!v2Object.contains(_jsonCameraObjectKey)) {
errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera");
if (!JsonHelper::validateKeys(json, keyInfoList2, errorString)) {
return false;
_disableRecalc = false;
}
QJsonObject cameraObject = v2Object[_jsonCameraObjectKey].toObject();
// Older code had typo on "imageSideOverlap" incorrectly being "imageSizeOverlap"
QString incorrectImageSideOverlap = "imageSizeOverlap";
if (cameraObject.contains(incorrectImageSideOverlap)) {
cameraObject[_jsonSideOverlapKey] = cameraObject[incorrectImageSideOverlap];
cameraObject.remove(incorrectImageSideOverlap);
}
setKnownCameraName(json[_jsonKnownCameraNameKey].toString());
_valueSetIsDistanceFact.setRawValue (json[_valueSetIsDistanceName].toBool());
_imageDensityFact.setRawValue (json[_imageDensityName].toDouble());
_frontalOverlapFact.setRawValue (json[_frontalOverlapName].toDouble());
_sideOverlapFact.setRawValue (json[_sideOverlapName].toDouble());
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 },
{ _jsonCameraMinTriggerIntervalKey, QJsonValue::Double, false },
};
if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) {
if (!CameraSpec::load(json, errorString)) {
return false;
}
_cameraFact.setRawValue(cameraObject[_jsonCameraNameKey].toString());
_cameraOrientationLandscapeFact.setRawValue(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());
_cameraMinTriggerInterval = cameraObject[_jsonCameraMinTriggerIntervalKey].toDouble(0);
}
// Polygon shape
/// Load a polygon from json
/// @param json Json object to load from
/// @param required true: no polygon in object will generate error
/// @param errorString Error string if return is false
/// @return true: success, false: failure (errorString set)
if (!_mapPolygon.loadFromJson(v2Object, true /* required */, errorString)) {
_mapPolygon.clear();
return false;
}
_ignoreRecalc = false;
_generateGrid();
_disableRecalc = false;
return true;
#endif
return false;
}
......@@ -22,8 +22,8 @@ public:
Q_ENUMS(CameraSpecType)
Q_PROPERTY(CameraSpecType cameraSpecType MEMBER _cameraSpecType NOTIFY cameraSpecTypeChanged)
Q_PROPERTY(QString knownCameraName MEMBER _knownCameraName NOTIFY knownCameraNameChanged)
Q_PROPERTY(CameraSpecType cameraSpecType READ cameraSpecType WRITE setCameraSpecType NOTIFY cameraSpecTypeChanged)
Q_PROPERTY(QString knownCameraName READ knownCameraName WRITE setKnownCameraName NOTIFY knownCameraNameChanged)
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)
......@@ -42,6 +42,11 @@ public:
CameraSpecKnown
};
CameraSpecType cameraSpecType(void) const { return _cameraSpecType; }
QString knownCameraName(void) const { return _knownCameraName; }
void setCameraSpecType(CameraSpecType cameraSpecType);
void setKnownCameraName(QString knownCameraName);
Fact* valueSetIsDistance (void) { return &_valueSetIsDistanceFact; }
Fact* distanceToSurface (void) { return &_distanceToSurfaceFact; }
Fact* imageDensity (void) { return &_imageDensityFact; }
......@@ -99,4 +104,6 @@ private:
static const char* _sideOverlapName;
static const char* _adjustedFootprintSideName;
static const char* _adjustedFootprintFrontalName;
static const char* _jsonCameraSpecTypeKey;
static const char* _jsonKnownCameraNameKey;
};
......@@ -12,16 +12,6 @@
#include <QQmlEngine>
const char* CameraSpec::_jsonSensorWidthKey = "sensorWidth";
const char* CameraSpec::_jsonSensorHeightKey = "sensorHeight";
const char* CameraSpec::_jsonImageWidthKey = "imageWidth";
const char* CameraSpec::_jsonImageHeightKey = "imageHeight";
const char* CameraSpec::_jsonFocalLengthKey = "focalLength";
const char* CameraSpec::_jsonMinTriggerIntervalKey = "minTriggerInterval";
const char* CameraSpec::_jsonNameKey = "name";
const char* CameraSpec::_jsonLandscapeKey = "orientationLandscape";
const char* CameraSpec::_nameName = "Camera";
const char* CameraSpec::_sensorWidthName = "SensorWidth";
const char* CameraSpec::_sensorHeightName = "SensorHeight";
const char* CameraSpec::_imageWidthName = "ImageWidth";
......@@ -35,7 +25,6 @@ CameraSpec::CameraSpec(QObject* parent)
: QObject (parent)
, _dirty (false)
, _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSpec.FactMetaData.json"), this))
, _nameFact (0, _nameName, FactMetaData::valueTypeString)
, _sensorWidthFact (0, _sensorWidthName, FactMetaData::valueTypeDouble)
, _sensorHeightFact (0, _sensorHeightName, FactMetaData::valueTypeDouble)
, _imageWidthFact (0, _imageWidthName, FactMetaData::valueTypeUint32)
......@@ -48,47 +37,10 @@ CameraSpec::CameraSpec(QObject* parent)
_init(true);
}
CameraSpec::CameraSpec(const QString& name,
double sensorWidth,
double sensorHeight,
double imageWidth,
double imageHeight,
double focalLength,
bool landscape,
bool fixedOrientation,
double minTriggerInterval,
QObject* parent)
: QObject (parent)
, _dirty (false)
, _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSpec.FactMetaData.json"), this))
, _nameFact (0, _nameName, FactMetaData::valueTypeString)
, _sensorWidthFact (0, _sensorWidthName, FactMetaData::valueTypeDouble)
, _sensorHeightFact (0, _sensorHeightName, FactMetaData::valueTypeDouble)
, _imageWidthFact (0, _imageWidthName, FactMetaData::valueTypeUint32)
, _imageHeightFact (0, _imageHeightName, FactMetaData::valueTypeUint32)
, _focalLengthFact (0, _focalLengthName, FactMetaData::valueTypeDouble)
, _landscapeFact (0, _landscapeName, FactMetaData::valueTypeBool)
, _fixedOrientationFact (0, _fixedOrientationName, FactMetaData::valueTypeBool)
, _minTriggerIntervalFact (0, _minTriggerIntervalName, FactMetaData::valueTypeDouble)
{
_init(false);
_nameFact.setRawValue (name);
_sensorWidthFact.setRawValue (sensorWidth);
_sensorHeightFact.setRawValue (sensorHeight);
_imageWidthFact.setRawValue (imageWidth);
_imageHeightFact.setRawValue (imageHeight);
_focalLengthFact.setRawValue (focalLength);
_landscapeFact.setRawValue (landscape);
_fixedOrientationFact.setRawValue (fixedOrientation);
_minTriggerIntervalFact.setRawValue (minTriggerInterval);
}
CameraSpec::CameraSpec(const CameraSpec& other, QObject* parent)
: QObject (parent)
, _dirty (false)
, _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSpec.FactMetaData.json"), this))
, _nameFact (0, _nameName, FactMetaData::valueTypeString)
, _sensorWidthFact (0, _sensorWidthName, FactMetaData::valueTypeDouble)
, _sensorHeightFact (0, _sensorHeightName, FactMetaData::valueTypeDouble)
, _imageWidthFact (0, _imageWidthName, FactMetaData::valueTypeUint32)
......@@ -105,7 +57,6 @@ CameraSpec::CameraSpec(const CameraSpec& other, QObject* parent)
const CameraSpec& CameraSpec::operator=(const CameraSpec& other)
{
_nameFact.setRawValue (other._nameFact.rawValue());
_sensorWidthFact.setRawValue (other._sensorWidthFact.rawValue());
_sensorHeightFact.setRawValue (other._sensorHeightFact.rawValue());
_imageWidthFact.setRawValue (other._imageWidthFact.rawValue());
......@@ -122,7 +73,6 @@ void CameraSpec::_init(bool setDefaults)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
_nameFact.setMetaData (_metaDataMap[_nameName], setDefaults /* setDefaultFromMetaData */);
_sensorWidthFact.setMetaData (_metaDataMap[_sensorWidthName], setDefaults);
_sensorHeightFact.setMetaData (_metaDataMap[_sensorHeightName], setDefaults);
_imageWidthFact.setMetaData (_metaDataMap[_imageWidthName], setDefaults);
......@@ -143,255 +93,40 @@ void CameraSpec::setDirty(bool dirty)
void CameraSpec::save(QJsonObject& json) const
{
Q_UNUSED(json);
#if 0
QJsonObject saveObject;
saveObject[JsonHelper::jsonVersionKey] = 3;
saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue;
saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue;
saveObject[_jsonManualGridKey] = _manualGridFact.rawValue().toBool();
saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitudeFact.rawValue().toBool();
saveObject[_jsonHoverAndCaptureKey] = _hoverAndCaptureFact.rawValue().toBool();
saveObject[_jsonRefly90DegreesKey] = _refly90Degrees;
saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble();
saveObject[_jsonCameraTriggerInTurnaroundKey] = _cameraTriggerInTurnaroundFact.rawValue().toBool();
QJsonObject gridObject;
gridObject[_jsonGridAltitudeKey] = _gridAltitudeFact.rawValue().toDouble();
gridObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelativeFact.rawValue().toBool();
gridObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble();
gridObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble();
gridObject[_jsonGridEntryLocationKey] = _gridEntryLocationFact.rawValue().toDouble();
gridObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble();
saveObject[_jsonGridObjectKey] = gridObject;
if (!_manualGridFact.rawValue().toBool()) {
QJsonObject cameraObject;
cameraObject[_jsonCameraNameKey] = _cameraFact.rawValue().toString();
cameraObject[_jsonCameraOrientationLandscapeKey] = _cameraOrientationLandscapeFact.rawValue().toBool();
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[_jsonCameraMinTriggerIntervalKey] = _cameraMinTriggerInterval;
cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble();
cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt();
cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt();
saveObject[_jsonCameraObjectKey] = cameraObject;
}
// Polygon shape
_mapPolygon.saveToJson(saveObject);
missionItems.append(saveObject);
#endif
json[_sensorWidthName] = _sensorWidthFact.rawValue().toDouble();
json[_sensorHeightName] = _sensorHeightFact.rawValue().toDouble();
json[_imageWidthName] = _imageWidthFact.rawValue().toDouble();
json[_imageHeightName] = _imageHeightFact.rawValue().toDouble();
json[_focalLengthName] = _focalLengthFact.rawValue().toDouble();
json[_landscapeName] = _landscapeFact.rawValue().toBool();
json[_fixedOrientationName] = _fixedOrientationFact.rawValue().toBool();
json[_minTriggerIntervalName] = _minTriggerIntervalFact.rawValue().toDouble();
}
bool CameraSpec::load(const QJsonObject& complexObject, QString& errorString)
bool CameraSpec::load(const QJsonObject& json, QString& errorString)
{
Q_UNUSED(complexObject);
Q_UNUSED(errorString);
#if 0
QJsonObject v2Object = complexObject;
// We need to pull version first to determine what validation/conversion needs to be performed.
QList<JsonHelper::KeyValidateInfo> versionKeyInfoList = {
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true },
};
if (!JsonHelper::validateKeys(v2Object, versionKeyInfoList, errorString)) {
return false;
}
int version = v2Object[JsonHelper::jsonVersionKey].toInt();
if (version != 2 && version != 3) {
errorString = tr("%1 does not support this version of survey items").arg(qgcApp()->applicationName());
return false;
}
if (version == 2) {
// Convert to v3
if (v2Object.contains(VisualMissionItem::jsonTypeKey) && v2Object[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("survey")) {
v2Object[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue;
v2Object[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue;
}
}
QList<JsonHelper::KeyValidateInfo> mainKeyInfoList = {
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true },
{ VisualMissionItem::jsonTypeKey, QJsonValue::String, true },
{ ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true },
{ QGCMapPolygon::jsonPolygonKey, QJsonValue::Array, true },
{ _jsonGridObjectKey, QJsonValue::Object, true },
{ _jsonCameraObjectKey, QJsonValue::Object, false },
{ _jsonCameraTriggerDistanceKey, QJsonValue::Double, true },
{ _jsonManualGridKey, QJsonValue::Bool, true },
{ _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true },
{ _jsonHoverAndCaptureKey, QJsonValue::Bool, false },
{ _jsonRefly90DegreesKey, QJsonValue::Bool, false },
{ _jsonCameraTriggerInTurnaroundKey, QJsonValue::Bool, false }, // Should really be required, but it was missing from initial code due to bug
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ _sensorWidthName, QJsonValue::Double, true },
{ _sensorHeightName, QJsonValue::Double, true },
{ _imageWidthName, QJsonValue::Double, true },
{ _imageHeightName, QJsonValue::Double, true },
{ _focalLengthName, QJsonValue::Double, true },
{ _landscapeName, QJsonValue::Bool, true },
{ _fixedOrientationName, QJsonValue::Bool, true },
{ _minTriggerIntervalName, QJsonValue::Double, true },
};
if (!JsonHelper::validateKeys(v2Object, mainKeyInfoList, errorString)) {
if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) {
return false;
}
QString itemType = v2Object[VisualMissionItem::jsonTypeKey].toString();
QString complexType = v2Object[ComplexMissionItem::jsonComplexItemTypeKey].toString();
if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) {
errorString = tr("%1 does not support loading this complex mission item type: %2:%3").arg(qgcApp()->applicationName()).arg(itemType).arg(complexType);
return false;
}
_ignoreRecalc = true;
_mapPolygon.clear();
setSequenceNumber(sequenceNumber);
_manualGridFact.setRawValue (v2Object[_jsonManualGridKey].toBool(true));
_fixedValueIsAltitudeFact.setRawValue (v2Object[_jsonFixedValueIsAltitudeKey].toBool(true));
_gridAltitudeRelativeFact.setRawValue (v2Object[_jsonGridAltitudeRelativeKey].toBool(true));
_hoverAndCaptureFact.setRawValue (v2Object[_jsonHoverAndCaptureKey].toBool(false));
_cameraTriggerInTurnaroundFact.setRawValue (v2Object[_jsonCameraTriggerInTurnaroundKey].toBool(true));
_refly90Degrees = v2Object[_jsonRefly90DegreesKey].toBool(false);
QList<JsonHelper::KeyValidateInfo> gridKeyInfoList = {
{ _jsonGridAltitudeKey, QJsonValue::Double, true },
{ _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true },
{ _jsonGridAngleKey, QJsonValue::Double, true },
{ _jsonGridSpacingKey, QJsonValue::Double, true },
{ _jsonGridEntryLocationKey, QJsonValue::Double, false },
{ _jsonTurnaroundDistKey, QJsonValue::Double, true },
};
QJsonObject gridObject = v2Object[_jsonGridObjectKey].toObject();
if (!JsonHelper::validateKeys(gridObject, gridKeyInfoList, errorString)) {
return false;
}
_gridAltitudeFact.setRawValue (gridObject[_jsonGridAltitudeKey].toDouble());
_gridAngleFact.setRawValue (gridObject[_jsonGridAngleKey].toDouble());
_gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble());
_turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble());
_cameraTriggerDistanceFact.setRawValue (v2Object[_jsonCameraTriggerDistanceKey].toDouble());
if (gridObject.contains(_jsonGridEntryLocationKey)) {
_gridEntryLocationFact.setRawValue(gridObject[_jsonGridEntryLocationKey].toDouble());
} else {
_gridEntryLocationFact.setRawValue(_gridEntryLocationFact.rawDefaultValue());
}
if (!_manualGridFact.rawValue().toBool()) {
if (!v2Object.contains(_jsonCameraObjectKey)) {
errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera");
return false;
}
QJsonObject cameraObject = v2Object[_jsonCameraObjectKey].toObject();
// Older code had typo on "imageSideOverlap" incorrectly being "imageSizeOverlap"
QString incorrectImageSideOverlap = "imageSizeOverlap";
if (cameraObject.contains(incorrectImageSideOverlap)) {
cameraObject[_jsonSideOverlapKey] = cameraObject[incorrectImageSideOverlap];
cameraObject.remove(incorrectImageSideOverlap);
}
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 },
{ _jsonCameraMinTriggerIntervalKey, QJsonValue::Double, false },
};
if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) {
return false;
}
_cameraFact.setRawValue(cameraObject[_jsonCameraNameKey].toString());
_cameraOrientationLandscapeFact.setRawValue(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());
_cameraMinTriggerInterval = cameraObject[_jsonCameraMinTriggerIntervalKey].toDouble(0);
}
// Polygon shape
/// Load a polygon from json
/// @param json Json object to load from
/// @param required true: no polygon in object will generate error
/// @param errorString Error string if return is false
/// @return true: success, false: failure (errorString set)
if (!_mapPolygon.loadFromJson(v2Object, true /* required */, errorString)) {
_mapPolygon.clear();
return false;
}
_ignoreRecalc = false;
_generateGrid();
_sensorWidthFact.setRawValue (json[_sensorWidthName].toDouble());
_sensorHeightFact.setRawValue (json[_sensorHeightName].toDouble());
_imageWidthFact.setRawValue (json[_imageWidthName].toDouble());
_imageHeightFact.setRawValue (json[_imageHeightName].toDouble());
_focalLengthFact.setRawValue (json[_focalLengthName].toDouble());
_landscapeFact.setRawValue (json[_landscapeName].toBool());
_fixedOrientationFact.setRawValue (json[_fixedOrientationName].toBool());
_minTriggerIntervalFact.setRawValue (json[_minTriggerIntervalName].toDouble());
return true;
#endif
return false;
}
#if 0
void CameraSpec::recalcImageOnGround(bool valueIsAltitude, double value)
{
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 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
if (missionItem.fixedValueIsAltitude.value) {
groundResolution = (altitude * sensorWidth * 100) / (imageWidth * focalLength)
} else {
altitude = (imageWidth * groundResolution * focalLength) / (sensorWidth * 100)
}
if (missionItem.cameraOrientationLandscape.value) {
imageSizeSideGround = (imageWidth * groundResolution) / 100
imageSizeFrontGround = (imageHeight * groundResolution) / 100
} else {
imageSizeSideGround = (imageHeight * groundResolution) / 100
imageSizeFrontGround = (imageWidth * groundResolution) / 100
}
gridSpacing = imageSizeSideGround * ( (100-sideOverlap) / 100 )
cameraTriggerDistance = imageSizeFrontGround * ( (100-frontalOverlap) / 100 )
if (missionItem.fixedValueIsAltitude.value) {
missionItem.groundResolution.rawValue = groundResolution
} else {
missionItem.gridAltitude.rawValue = altitude
}
missionItem.gridSpacing.rawValue = gridSpacing
missionItem.cameraTriggerDistance.rawValue = cameraTriggerDistance
}
#endif
......@@ -17,22 +17,11 @@ class CameraSpec : public QObject
public:
CameraSpec(QObject* parent = NULL);
CameraSpec(const QString& name,
double sensorWidth,
double sensorHeight,
double imageWidth,
double imageHeight,
double focalLength,
bool landscape,
bool fixedOrientation,
double minTriggerInterval,
QObject* parent = NULL);
CameraSpec(const CameraSpec& other, QObject* parent);
const CameraSpec& operator=(const CameraSpec& other);
// These properties are persisted to Json
Q_PROPERTY(Fact* name READ name CONSTANT) ///< Camera name
Q_PROPERTY(Fact* sensorWidth READ sensorWidth CONSTANT) ///< Sensor size in millimeters
Q_PROPERTY(Fact* sensorHeight READ sensorHeight CONSTANT) ///< Sensor size in millimeters
Q_PROPERTY(Fact* imageWidth READ imageWidth CONSTANT) ///< Image size in pixels
......@@ -42,7 +31,6 @@ public:
Q_PROPERTY(Fact* fixedOrientation READ fixedOrientation CONSTANT) ///< true: camera is in fixed orientation
Q_PROPERTY(Fact* minTriggerInterval READ minTriggerInterval CONSTANT) ///< Minimum time in seconds between each photo taken, 0 for not specified
Fact* name (void) { return &_nameFact; }
Fact* sensorWidth (void) { return &_sensorWidthFact; }
Fact* sensorHeight (void) { return &_sensorHeightFact; }
Fact* imageWidth (void) { return &_imageWidthFact; }
......@@ -68,7 +56,6 @@ private:
QMap<QString, FactMetaData*> _metaDataMap;
Fact _nameFact;
Fact _sensorWidthFact;
Fact _sensorHeightFact;
Fact _imageWidthFact;
......@@ -78,7 +65,6 @@ private:
Fact _fixedOrientationFact;
Fact _minTriggerIntervalFact;
static const char* _nameName;
static const char* _sensorWidthName;
static const char* _sensorHeightName;
static const char* _imageWidthName;
......@@ -87,14 +73,4 @@ private:
static const char* _landscapeName;
static const char* _fixedOrientationName;
static const char* _minTriggerIntervalName;
static const char* _jsonNameKey;
static const char* _jsonSensorWidthKey;
static const char* _jsonSensorHeightKey;
static const char* _jsonImageWidthKey;
static const char* _jsonImageHeightKey;
static const char* _jsonFocalLengthKey;
static const char* _jsonLandscapeKey;
static const char* _jsonFixedOrientationKey;
static const char* _jsonMinTriggerIntervalKey;
};
......@@ -19,6 +19,7 @@
#include "SurveyMissionItem.h"
#include "FixedWingLandingComplexItem.h"
#include "StructureScanComplexItem.h"
#include "StructureScanComplexItem.h"
#include "JsonHelper.h"
#include "ParameterManager.h"
#include "QGroundControlQmlGlobal.h"
......@@ -264,11 +265,15 @@ void MissionController::convertToKMLDocument(QDomDocument& document)
{
QJsonObject missionJson;
QmlObjectListModel* visualItems = new QmlObjectListModel();
QList<MissionItem*> missionItens;
QList<MissionItem*> missionItems;
QString error;
save(missionJson);
_loadItemsFromJson(missionJson, visualItems, error);
_convertToMissionItems(visualItems, missionItens, this);
_convertToMissionItems(visualItems, missionItems, this);
if (missionItems.count() == 0) {
return;
}
float altitude = missionJson[_jsonPlannedHomePositionKey].toArray()[2].toDouble();
......@@ -276,7 +281,7 @@ void MissionController::convertToKMLDocument(QDomDocument& document)
QStringList coords;
// Drop home position
bool dropPoint = true;
for(const auto& item : missionItens) {
for(const auto& item : missionItems) {
if(dropPoint) {
dropPoint = false;
continue;
......@@ -655,6 +660,15 @@ bool MissionController::_loadJsonMissionFileV2(const QJsonObject& json, QmlObjec
nextSequenceNumber = landingItem->lastSequenceNumber() + 1;
qCDebug(MissionControllerLog) << "FW Landing Pattern load complete: nextSequenceNumber" << nextSequenceNumber;
visualItems->append(landingItem);
} else if (complexItemType == StructureScanComplexItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog) << "Loading Structure Scan: nextSequenceNumber" << nextSequenceNumber;
StructureScanComplexItem* structureItem = new StructureScanComplexItem(_controllerVehicle, visualItems);
if (!structureItem->load(itemObject, nextSequenceNumber++, errorString)) {
return false;
}
nextSequenceNumber = structureItem->lastSequenceNumber() + 1;
qCDebug(MissionControllerLog) << "Structure Scan load complete: nextSequenceNumber" << nextSequenceNumber;
visualItems->append(structureItem);
} else if (complexItemType == MissionSettingsItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog) << "Loading Mission Settings: nextSequenceNumber" << nextSequenceNumber;
MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, visualItems);
......
......@@ -21,10 +21,11 @@
QGC_LOGGING_CATEGORY(StructureScanComplexItemLog, "StructureScanComplexItemLog")
const char* StructureScanComplexItem::jsonComplexItemTypeValue = "StructureScan-WIP";
const char* StructureScanComplexItem::jsonComplexItemTypeValue = "StructureScan";
const char* StructureScanComplexItem::_altitudeFactName = "Altitude";
const char* StructureScanComplexItem::_layersFactName = "Layers";
const char* StructureScanComplexItem::_jsonCameraCalcKey = "CameraCalc";
const char* StructureScanComplexItem::_jsonAltitudeRelativeKey = "altitudeRelative";
QMap<QString, FactMetaData*> StructureScanComplexItem::_metaDataMap;
......@@ -121,51 +122,24 @@ void StructureScanComplexItem::setDirty(bool dirty)
void StructureScanComplexItem::save(QJsonArray& missionItems)
{
Q_UNUSED(missionItems);
#if 0
QJsonObject saveObject;
saveObject[JsonHelper::jsonVersionKey] = 3;
// Header
saveObject[JsonHelper::jsonVersionKey] = 1;
saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue;
saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue;
saveObject[_jsonManualGridKey] = _manualGridFact.rawValue().toBool();
saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitudeFact.rawValue().toBool();
saveObject[_jsonHoverAndCaptureKey] = _hoverAndCaptureFact.rawValue().toBool();
saveObject[_jsonRefly90DegreesKey] = _refly90Degrees;
saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble();
QJsonObject gridObject;
gridObject[_jsonGridAltitudeKey] = _gridAltitudeFact.rawValue().toDouble();
gridObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelativeFact.rawValue().toBool();
gridObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble();
gridObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble();
gridObject[_jsonGridEntryLocationKey] = _gridEntryLocationFact.rawValue().toDouble();
gridObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble();
saveObject[_jsonGridObjectKey] = gridObject;
if (!_manualGridFact.rawValue().toBool()) {
QJsonObject cameraObject;
cameraObject[_jsonCameraNameKey] = _cameraFact.rawValue().toString();
cameraObject[_jsonCameraOrientationLandscapeKey] = _cameraOrientationLandscapeFact.rawValue().toBool();
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[_jsonCameraMinTriggerIntervalKey] = _cameraMinTriggerInterval;
cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble();
cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt();
cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt();
saveObject[_jsonCameraObjectKey] = cameraObject;
}
// Polygon shape
saveObject[_altitudeFactName] = _altitudeFact.rawValue().toDouble();
saveObject[_jsonAltitudeRelativeKey] = _altitudeRelative;
saveObject[_layersFactName] = _layersFact.rawValue().toDouble();
QJsonObject cameraCalcObject;
_cameraCalc.save(cameraCalcObject);
saveObject[_jsonCameraCalcKey] = cameraCalcObject;
_structurePolygon.saveToJson(saveObject);
missionItems.append(saveObject);
#endif
}
void StructureScanComplexItem::setSequenceNumber(int sequenceNumber)
......@@ -179,158 +153,50 @@ void StructureScanComplexItem::setSequenceNumber(int sequenceNumber)
bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequenceNumber, QString& errorString)
{
#if 0
QJsonObject v2Object = complexObject;
// We need to pull version first to determine what validation/conversion needs to be performed.
QList<JsonHelper::KeyValidateInfo> versionKeyInfoList = {
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true },
};
if (!JsonHelper::validateKeys(v2Object, versionKeyInfoList, errorString)) {
return false;
}
int version = v2Object[JsonHelper::jsonVersionKey].toInt();
if (version != 2 && version != 3) {
errorString = tr("%1 does not support this version of survey items").arg(qgcApp()->applicationName());
return false;
}
if (version == 2) {
// Convert to v3
if (v2Object.contains(VisualMissionItem::jsonTypeKey) && v2Object[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("survey")) {
v2Object[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue;
v2Object[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue;
}
}
QList<JsonHelper::KeyValidateInfo> mainKeyInfoList = {
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true },
{ VisualMissionItem::jsonTypeKey, QJsonValue::String, true },
{ ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true },
{ QGCMapPolygon::jsonPolygonKey, QJsonValue::Array, true },
{ _jsonGridObjectKey, QJsonValue::Object, true },
{ _jsonCameraObjectKey, QJsonValue::Object, false },
{ _jsonCameraTriggerDistanceKey, QJsonValue::Double, true },
{ _jsonManualGridKey, QJsonValue::Bool, true },
{ _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true },
{ _jsonHoverAndCaptureKey, QJsonValue::Bool, false },
{ _jsonRefly90DegreesKey, QJsonValue::Bool, false },
{ _altitudeFactName, QJsonValue::Double, true },
{ _jsonAltitudeRelativeKey, QJsonValue::Bool, false },
{ _layersFactName, QJsonValue::Double, true },
{ _jsonCameraCalcKey, QJsonValue::Object, true },
};
if (!JsonHelper::validateKeys(v2Object, mainKeyInfoList, errorString)) {
return false;
}
QString itemType = v2Object[VisualMissionItem::jsonTypeKey].toString();
QString complexType = v2Object[ComplexMissionItem::jsonComplexItemTypeKey].toString();
if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) {
errorString = tr("%1 does not support loading this complex mission item type: %2:%3").arg(qgcApp()->applicationName()).arg(itemType).arg(complexType);
if (!JsonHelper::validateKeys(complexObject, keyInfoList, errorString)) {
return false;
}
_ignoreRecalc = true;
_structurePolygon.clear();
setSequenceNumber(sequenceNumber);
_manualGridFact.setRawValue (v2Object[_jsonManualGridKey].toBool(true));
_fixedValueIsAltitudeFact.setRawValue (v2Object[_jsonFixedValueIsAltitudeKey].toBool(true));
_gridAltitudeRelativeFact.setRawValue (v2Object[_jsonGridAltitudeRelativeKey].toBool(true));
_hoverAndCaptureFact.setRawValue (v2Object[_jsonHoverAndCaptureKey].toBool(false));
_refly90Degrees = v2Object[_jsonRefly90DegreesKey].toBool(false);
QList<JsonHelper::KeyValidateInfo> gridKeyInfoList = {
{ _jsonGridAltitudeKey, QJsonValue::Double, true },
{ _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true },
{ _jsonGridAngleKey, QJsonValue::Double, true },
{ _jsonGridSpacingKey, QJsonValue::Double, true },
{ _jsonGridEntryLocationKey, QJsonValue::Double, false },
{ _jsonTurnaroundDistKey, QJsonValue::Double, true },
};
QJsonObject gridObject = v2Object[_jsonGridObjectKey].toObject();
if (!JsonHelper::validateKeys(gridObject, gridKeyInfoList, errorString)) {
QString itemType = complexObject[VisualMissionItem::jsonTypeKey].toString();
QString complexType = complexObject[ComplexMissionItem::jsonComplexItemTypeKey].toString();
if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) {
errorString = tr("%1 does not support loading this complex mission item type: %2:%3").arg(qgcApp()->applicationName()).arg(itemType).arg(complexType);
return false;
}
_gridAltitudeFact.setRawValue (gridObject[_jsonGridAltitudeKey].toDouble());
_gridAngleFact.setRawValue (gridObject[_jsonGridAngleKey].toDouble());
_gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble());
_turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble());
_cameraTriggerDistanceFact.setRawValue (v2Object[_jsonCameraTriggerDistanceKey].toDouble());
if (gridObject.contains(_jsonGridEntryLocationKey)) {
_gridEntryLocationFact.setRawValue(gridObject[_jsonGridEntryLocationKey].toDouble());
} else {
_gridEntryLocationFact.setRawValue(_gridEntryLocationFact.rawDefaultValue());
}
if (!_manualGridFact.rawValue().toBool()) {
if (!v2Object.contains(_jsonCameraObjectKey)) {
errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera");
int version = complexObject[JsonHelper::jsonVersionKey].toInt();
if (version != 1) {
errorString = tr("Version %1 not supported").arg(version);
return false;
}
QJsonObject cameraObject = v2Object[_jsonCameraObjectKey].toObject();
setSequenceNumber(sequenceNumber);
// Older code had typo on "imageSideOverlap" incorrectly being "imageSizeOverlap"
QString incorrectImageSideOverlap = "imageSizeOverlap";
if (cameraObject.contains(incorrectImageSideOverlap)) {
cameraObject[_jsonSideOverlapKey] = cameraObject[incorrectImageSideOverlap];
cameraObject.remove(incorrectImageSideOverlap);
}
_altitudeFact.setRawValue (complexObject[_altitudeFactName].toDouble());
_layersFact.setRawValue (complexObject[_layersFactName].toDouble());
_altitudeRelative = complexObject[_jsonAltitudeRelativeKey].toBool(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 },
{ _jsonCameraMinTriggerIntervalKey, QJsonValue::Double, false },
};
if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) {
if (!_cameraCalc.load(complexObject[_jsonCameraCalcKey].toObject(), errorString)) {
return false;
}
_cameraFact.setRawValue(cameraObject[_jsonCameraNameKey].toString());
_cameraOrientationLandscapeFact.setRawValue(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());
_cameraMinTriggerInterval = cameraObject[_jsonCameraMinTriggerIntervalKey].toDouble(0);
}
// Polygon shape
/// Load a polygon from json
/// @param json Json object to load from
/// @param required true: no polygon in object will generate error
/// @param errorString Error string if return is false
/// @return true: success, false: failure (errorString set)
if (!_structurePolygon.loadFromJson(v2Object, true /* required */, errorString)) {
if (!_structurePolygon.loadFromJson(complexObject, true /* required */, errorString)) {
_structurePolygon.clear();
return false;
}
_ignoreRecalc = false;
_generateGrid();
return true;
#else
Q_UNUSED(complexObject);
Q_UNUSED(sequenceNumber);
Q_UNUSED(errorString);
return false;
#endif
}
void StructureScanComplexItem::_flightPathChanged(void)
......@@ -380,6 +246,7 @@ void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QO
items.append(item);
for (int layer=0; layer<_layersFact.rawValue().toInt(); layer++) {
bool addTriggerStart = true;
double layerAltitude = baseAltitude + (layer * _cameraCalc.adjustedFootprintFrontal()->rawValue().toDouble());
for (int i=0; i<_flightPolygon.count(); i++) {
......@@ -399,6 +266,21 @@ void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QO
false, // isCurrentItem
missionItemParent);
items.append(item);
if (addTriggerStart) {
addTriggerStart = false;
item = new MissionItem(seqNum++,
MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION,
_cameraCalc.adjustedFootprintSide()->rawValue().toDouble(), // trigger distance
0, // shutter integration (ignore)
1, // trigger immediately when starting
0, 0, 0, 0, // param 4-7 unused
true, // autoContinue
false, // isCurrentItem
missionItemParent);
items.append(item);
}
}
QGeoCoordinate vertexCoord = _flightPolygon.vertexCoordinate(0);
......@@ -417,6 +299,18 @@ void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QO
false, // isCurrentItem
missionItemParent);
items.append(item);
item = new MissionItem(seqNum++,
MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION,
0, // stop triggering
0, // shutter integration (ignore)
0, // trigger immediately when starting
0, 0, 0, 0, // param 4-7 unused
true, // autoContinue
false, // isCurrentItem
missionItemParent);
items.append(item);
}
}
......
......@@ -129,6 +129,9 @@ private:
static const char* _altitudeFactName;
static const char* _layersFactName;
static const char* _jsonCameraCalcKey;
static const char* _jsonAltitudeRelativeKey;
};
#endif
......@@ -60,7 +60,7 @@ Rectangle {
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("WARNING: WORK IN PROGRESS. DO NOT FLY. NO BUG REPORTS.")
text: qsTr("WORK IN PROGRESS. CAREFUL!")
wrapMode: Text.WordWrap
color: qgcPal.warningText
}
......
......@@ -91,7 +91,7 @@ Item {
borderWidth: 1
borderColor: "black"
interiorColor: "green"
interiorOpacity: 0.5
interiorOpacity: 0.25
}
QGCMapPolygonVisuals {
......
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