Commit db55f46d authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #5751 from DonLakeFlyer/StructureScan

Structure scan: Support for scan distance from structure polygon
parents 0a56e483 86efb38e
...@@ -911,7 +911,7 @@ void PlanManager::removeAll(void) ...@@ -911,7 +911,7 @@ void PlanManager::removeAll(void)
return; return;
} }
qCDebug(PlanManagerLog) << QStringLiteral("removeAll").arg(_planTypeString()); qCDebug(PlanManagerLog) << QStringLiteral("removeAll %1").arg(_planTypeString());
_clearAndDeleteMissionItems(); _clearAndDeleteMissionItems();
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <QGeoRectangle> #include <QGeoRectangle>
#include <QDebug> #include <QDebug>
#include <QJsonArray> #include <QJsonArray>
#include <QLineF>
const char* QGCMapPolygon::jsonPolygonKey = "polygon"; const char* QGCMapPolygon::jsonPolygonKey = "polygon";
...@@ -290,7 +291,7 @@ void QGCMapPolygon::_updateCenter(void) ...@@ -290,7 +291,7 @@ void QGCMapPolygon::_updateCenter(void)
if (!_ignoreCenterUpdates) { if (!_ignoreCenterUpdates) {
QGeoCoordinate center; QGeoCoordinate center;
if (_polygonPath.count() > 2) { if (_polygonPath.count() > 2) {
QPointF centroid(0, 0); QPointF centroid(0, 0);
QPolygonF polygonF = _toPolygonF(); QPolygonF polygonF = _toPolygonF();
for (int i=0; i<polygonF.count(); i++) { for (int i=0; i<polygonF.count(); i++) {
...@@ -356,3 +357,80 @@ QGeoCoordinate QGCMapPolygon::vertexCoordinate(int vertex) const ...@@ -356,3 +357,80 @@ QGeoCoordinate QGCMapPolygon::vertexCoordinate(int vertex) const
return QGeoCoordinate(); return QGeoCoordinate();
} }
} }
QList<QPointF> QGCMapPolygon::nedPolygon(void)
{
QList<QPointF> nedPolygon;
if (count() > 0) {
QGeoCoordinate tangentOrigin = vertexCoordinate(0);
for (int i=0; i<_polygonModel.count(); i++) {
double y, x, down;
QGeoCoordinate vertex = vertexCoordinate(i);
if (i == 0) {
// This avoids a nan calculation that comes out of convertGeoToNed
x = y = 0;
} else {
convertGeoToNed(vertex, tangentOrigin, &y, &x, &down);
}
nedPolygon += QPointF(x, y);
}
}
return nedPolygon;
}
void QGCMapPolygon::offset(double distance)
{
QList<QGeoCoordinate> rgNewPolygon;
// I'm sure there is some beautiful famous algorithm to do this, but here is a brute force method
if (count() > 2) {
// Convert the polygon to NED
QList<QPointF> rgNedVertices = nedPolygon();
// Walk the edges, offsetting by the specified distance
QList<QLineF> rgOffsetEdges;
for (int i=0; i<rgNedVertices.count(); i++) {
int lastIndex = i == rgNedVertices.count() - 1 ? 0 : i + 1;
QLineF offsetEdge;
QLineF originalEdge(rgNedVertices[i], rgNedVertices[lastIndex]);
QLineF workerLine = originalEdge;
workerLine.setLength(distance);
workerLine.setAngle(workerLine.angle() - 90.0);
offsetEdge.setP1(workerLine.p2());
workerLine.setPoints(originalEdge.p2(), originalEdge.p1());
workerLine.setLength(distance);
workerLine.setAngle(workerLine.angle() + 90.0);
offsetEdge.setP2(workerLine.p2());
rgOffsetEdges.append(offsetEdge);
}
// Intersect the offset edges to generate new vertices
QPointF newVertex;
QGeoCoordinate tangentOrigin = vertexCoordinate(0);
for (int i=0; i<rgOffsetEdges.count(); i++) {
int prevIndex = i == 0 ? rgOffsetEdges.count() - 1 : i - 1;
if (rgOffsetEdges[prevIndex].intersect(rgOffsetEdges[i], &newVertex) == QLineF::NoIntersection) {
// FIXME: Better error handling?
qWarning("Intersection failed");
return;
}
QGeoCoordinate coord;
convertNedToGeo(newVertex.y(), newVertex.x(), 0, tangentOrigin, &coord);
rgNewPolygon.append(coord);
}
}
// Update internals
clear();
for (int i=0; i<rgNewPolygon.count(); i++) {
appendVertex(rgNewPolygon[i]);
}
}
...@@ -52,6 +52,9 @@ public: ...@@ -52,6 +52,9 @@ public:
/// Returns true if the specified coordinate is within the polygon /// Returns true if the specified coordinate is within the polygon
Q_INVOKABLE bool containsCoordinate(const QGeoCoordinate& coordinate) const; Q_INVOKABLE bool containsCoordinate(const QGeoCoordinate& coordinate) const;
/// Offsets the current polygon edges by the specified distance in meters
Q_INVOKABLE void offset(double distance);
/// Returns the path in a list of QGeoCoordinate's format /// Returns the path in a list of QGeoCoordinate's format
QList<QGeoCoordinate> coordinateList(void) const; QList<QGeoCoordinate> coordinateList(void) const;
...@@ -69,6 +72,9 @@ public: ...@@ -69,6 +72,9 @@ public:
/// @return true: success, false: failure (errorString set) /// @return true: success, false: failure (errorString set)
bool loadFromJson(const QJsonObject& json, bool required, QString& errorString); bool loadFromJson(const QJsonObject& json, bool required, QString& errorString);
/// Convert polygon to NED and return (D is ignored)
QList<QPointF> nedPolygon(void);
// Property methods // Property methods
int count (void) const { return _polygonPath.count(); } int count (void) const { return _polygonPath.count(); }
......
...@@ -23,6 +23,15 @@ ...@@ -23,6 +23,15 @@
"units": "m", "units": "m",
"defaultValue": 25 "defaultValue": 25
}, },
{
"name": "Scan distance",
"shortDescription": "Scan distance away from structure.",
"type": "double",
"decimalPlaces": 2,
"min": 0,
"units": "m",
"defaultValue": 25
},
{ {
"name": "Trigger distance", "name": "Trigger distance",
"shortDescription": "Distance between each triggering of the camera. 0 specifies not camera trigger.", "shortDescription": "Distance between each triggering of the camera. 0 specifies not camera trigger.",
......
...@@ -23,36 +23,11 @@ QGC_LOGGING_CATEGORY(StructureScanComplexItemLog, "StructureScanComplexItemLog") ...@@ -23,36 +23,11 @@ QGC_LOGGING_CATEGORY(StructureScanComplexItemLog, "StructureScanComplexItemLog")
const char* StructureScanComplexItem::jsonComplexItemTypeValue = "StructureScan-WIP"; const char* StructureScanComplexItem::jsonComplexItemTypeValue = "StructureScan-WIP";
const char* StructureScanComplexItem::_jsonGridObjectKey = "grid";
const char* StructureScanComplexItem::_jsonGridAltitudeKey = "altitude";
const char* StructureScanComplexItem::_jsonGridAltitudeRelativeKey = "relativeAltitude";
const char* StructureScanComplexItem::_jsonGridAngleKey = "angle";
const char* StructureScanComplexItem::_jsonGridSpacingKey = "spacing";
const char* StructureScanComplexItem::_jsonGridEntryLocationKey = "entryLocation";
const char* StructureScanComplexItem::_jsonTurnaroundDistKey = "turnAroundDistance";
const char* StructureScanComplexItem::_jsonCameraTriggerDistanceKey = "cameraTriggerDistance";
const char* StructureScanComplexItem::_jsonCameraTriggerInTurnaroundKey = "cameraTriggerInTurnaround";
const char* StructureScanComplexItem::_jsonHoverAndCaptureKey = "hoverAndCapture";
const char* StructureScanComplexItem::_jsonGroundResolutionKey = "groundResolution";
const char* StructureScanComplexItem::_jsonFrontalOverlapKey = "imageFrontalOverlap";
const char* StructureScanComplexItem::_jsonSideOverlapKey = "imageSideOverlap";
const char* StructureScanComplexItem::_jsonCameraSensorWidthKey = "sensorWidth";
const char* StructureScanComplexItem::_jsonCameraSensorHeightKey = "sensorHeight";
const char* StructureScanComplexItem::_jsonCameraResolutionWidthKey = "resolutionWidth";
const char* StructureScanComplexItem::_jsonCameraResolutionHeightKey = "resolutionHeight";
const char* StructureScanComplexItem::_jsonCameraFocalLengthKey = "focalLength";
const char* StructureScanComplexItem::_jsonCameraMinTriggerIntervalKey = "minTriggerInterval";
const char* StructureScanComplexItem::_jsonCameraObjectKey = "camera";
const char* StructureScanComplexItem::_jsonCameraNameKey = "name";
const char* StructureScanComplexItem::_jsonManualGridKey = "manualGrid";
const char* StructureScanComplexItem::_jsonCameraOrientationLandscapeKey = "orientationLandscape";
const char* StructureScanComplexItem::_jsonFixedValueIsAltitudeKey = "fixedValueIsAltitude";
const char* StructureScanComplexItem::_jsonRefly90DegreesKey = "refly90Degrees";
const char* StructureScanComplexItem::_altitudeFactName = "Altitude"; const char* StructureScanComplexItem::_altitudeFactName = "Altitude";
const char* StructureScanComplexItem::_layersFactName = "Layers"; const char* StructureScanComplexItem::_layersFactName = "Layers";
const char* StructureScanComplexItem::_layerDistanceFactName = "Layer distance"; const char* StructureScanComplexItem::_layerDistanceFactName = "Layer distance";
const char* StructureScanComplexItem::_cameraTriggerDistanceFactName = "Trigger distance"; const char* StructureScanComplexItem::_cameraTriggerDistanceFactName = "Trigger distance";
const char* StructureScanComplexItem::_scanDistanceFactName = "Scan distance";
QMap<QString, FactMetaData*> StructureScanComplexItem::_metaDataMap; QMap<QString, FactMetaData*> StructureScanComplexItem::_metaDataMap;
...@@ -70,22 +45,26 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, QObject* pa ...@@ -70,22 +45,26 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, QObject* pa
, _layersFact (0, _layersFactName, FactMetaData::valueTypeUint32) , _layersFact (0, _layersFactName, FactMetaData::valueTypeUint32)
, _layerDistanceFact (0, _layerDistanceFactName, FactMetaData::valueTypeDouble) , _layerDistanceFact (0, _layerDistanceFactName, FactMetaData::valueTypeDouble)
, _cameraTriggerDistanceFact(0, _cameraTriggerDistanceFactName, FactMetaData::valueTypeDouble) , _cameraTriggerDistanceFact(0, _cameraTriggerDistanceFactName, FactMetaData::valueTypeDouble)
, _scanDistanceFact (0, _scanDistanceFactName, FactMetaData::valueTypeDouble)
{ {
_editorQml = "qrc:/qml/StructureScanEditor.qml"; _editorQml = "qrc:/qml/StructureScanEditor.qml";
if (_metaDataMap.isEmpty()) { if (_metaDataMap.isEmpty()) {
_metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/StructureScan.SettingsGroup.json"), this); _metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/StructureScan.SettingsGroup.json"), NULL /* QObject parent */);
} }
qDebug() << _metaDataMap[_altitudeFactName];
_altitudeFact.setMetaData (_metaDataMap[_altitudeFactName]); _altitudeFact.setMetaData (_metaDataMap[_altitudeFactName]);
_layersFact.setMetaData (_metaDataMap[_layersFactName]); _layersFact.setMetaData (_metaDataMap[_layersFactName]);
_layerDistanceFact.setMetaData (_metaDataMap[_layerDistanceFactName]); _layerDistanceFact.setMetaData (_metaDataMap[_layerDistanceFactName]);
_cameraTriggerDistanceFact.setMetaData (_metaDataMap[_cameraTriggerDistanceFactName]); _cameraTriggerDistanceFact.setMetaData (_metaDataMap[_cameraTriggerDistanceFactName]);
_scanDistanceFact.setMetaData (_metaDataMap[_scanDistanceFactName]);
_altitudeFact.setRawValue (_altitudeFact.rawDefaultValue()); _altitudeFact.setRawValue (_altitudeFact.rawDefaultValue());
_layersFact.setRawValue (_layersFact.rawDefaultValue()); _layersFact.setRawValue (_layersFact.rawDefaultValue());
_layerDistanceFact.setRawValue (_layerDistanceFact.rawDefaultValue()); _layerDistanceFact.setRawValue (_layerDistanceFact.rawDefaultValue());
_cameraTriggerDistanceFact.setRawValue (_cameraTriggerDistanceFact.rawDefaultValue()); _cameraTriggerDistanceFact.setRawValue (_cameraTriggerDistanceFact.rawDefaultValue());
_scanDistanceFact.setRawValue (_scanDistanceFact.rawDefaultValue());
_altitudeFact.setRawValue(qgcApp()->toolbox()->settingsManager()->appSettings()->defaultMissionItemAltitude()->rawValue()); _altitudeFact.setRawValue(qgcApp()->toolbox()->settingsManager()->appSettings()->defaultMissionItemAltitude()->rawValue());
...@@ -93,6 +72,7 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, QObject* pa ...@@ -93,6 +72,7 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, QObject* pa
connect(&_layersFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty); connect(&_layersFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty);
connect(&_layerDistanceFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty); connect(&_layerDistanceFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty);
connect(&_cameraTriggerDistanceFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty); connect(&_cameraTriggerDistanceFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty);
connect(&_scanDistanceFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty);
connect(this, &StructureScanComplexItem::altitudeRelativeChanged, this, &StructureScanComplexItem::_setDirty); connect(this, &StructureScanComplexItem::altitudeRelativeChanged, this, &StructureScanComplexItem::_setDirty);
connect(this, &StructureScanComplexItem::altitudeRelativeChanged, this, &StructureScanComplexItem::coordinateHasRelativeAltitudeChanged); connect(this, &StructureScanComplexItem::altitudeRelativeChanged, this, &StructureScanComplexItem::coordinateHasRelativeAltitudeChanged);
...@@ -100,9 +80,13 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, QObject* pa ...@@ -100,9 +80,13 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, QObject* pa
connect(&_altitudeFact, &Fact::valueChanged, this, &StructureScanComplexItem::_updateCoordinateAltitudes); connect(&_altitudeFact, &Fact::valueChanged, this, &StructureScanComplexItem::_updateCoordinateAltitudes);
connect(&_mapPolygon, &QGCMapPolygon::dirtyChanged, this, &StructureScanComplexItem::_polygonDirtyChanged); connect(&_structurePolygon, &QGCMapPolygon::dirtyChanged, this, &StructureScanComplexItem::_polygonDirtyChanged);
connect(&_mapPolygon, &QGCMapPolygon::countChanged, this, &StructureScanComplexItem::_polygonCountChanged); connect(&_structurePolygon, &QGCMapPolygon::countChanged, this, &StructureScanComplexItem::_polygonCountChanged);
connect(&_mapPolygon, &QGCMapPolygon::pathChanged, this, &StructureScanComplexItem::_polygonPathChanged); connect(&_structurePolygon, &QGCMapPolygon::pathChanged, this, &StructureScanComplexItem::_rebuildFlightPolygon);
connect(&_flightPolygon, &QGCMapPolygon::pathChanged, this, &StructureScanComplexItem::_flightPathChanged);
connect(&_scanDistanceFact, &Fact::valueChanged, this, &StructureScanComplexItem::_rebuildFlightPolygon);
} }
void StructureScanComplexItem::_setScanDistance(double scanDistance) void StructureScanComplexItem::_setScanDistance(double scanDistance)
...@@ -138,7 +122,7 @@ void StructureScanComplexItem::_polygonCountChanged(int count) ...@@ -138,7 +122,7 @@ void StructureScanComplexItem::_polygonCountChanged(int count)
int StructureScanComplexItem::lastSequenceNumber(void) const int StructureScanComplexItem::lastSequenceNumber(void) const
{ {
return _sequenceNumber + return _sequenceNumber +
((_mapPolygon.count() + 1) * _layersFact.rawValue().toInt()) + // 1 waypoint for each polygon vertex + 1 to go back to first polygon vertex ((_flightPolygon.count() + 1) * _layersFact.rawValue().toInt()) + // 1 waypoint for each polygon vertex + 1 to go back to first polygon vertex
1; // Gimbal yaw command 1; // Gimbal yaw command
} }
...@@ -193,7 +177,7 @@ void StructureScanComplexItem::save(QJsonArray& missionItems) ...@@ -193,7 +177,7 @@ void StructureScanComplexItem::save(QJsonArray& missionItems)
} }
// Polygon shape // Polygon shape
_mapPolygon.saveToJson(saveObject); _structurePolygon.saveToJson(saveObject);
missionItems.append(saveObject); missionItems.append(saveObject);
#endif #endif
...@@ -260,7 +244,7 @@ bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequen ...@@ -260,7 +244,7 @@ bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequen
_ignoreRecalc = true; _ignoreRecalc = true;
_mapPolygon.clear(); _structurePolygon.clear();
setSequenceNumber(sequenceNumber); setSequenceNumber(sequenceNumber);
...@@ -346,8 +330,8 @@ bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequen ...@@ -346,8 +330,8 @@ bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequen
/// @param required true: no polygon in object will generate error /// @param required true: no polygon in object will generate error
/// @param errorString Error string if return is false /// @param errorString Error string if return is false
/// @return true: success, false: failure (errorString set) /// @return true: success, false: failure (errorString set)
if (!_mapPolygon.loadFromJson(v2Object, true /* required */, errorString)) { if (!_structurePolygon.loadFromJson(v2Object, true /* required */, errorString)) {
_mapPolygon.clear(); _structurePolygon.clear();
return false; return false;
} }
...@@ -364,7 +348,7 @@ bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequen ...@@ -364,7 +348,7 @@ bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequen
#endif #endif
} }
void StructureScanComplexItem::_polygonPathChanged(void) void StructureScanComplexItem::_flightPathChanged(void)
{ {
emit coordinateChanged(coordinate()); emit coordinateChanged(coordinate());
emit exitCoordinateChanged(exitCoordinate()); emit exitCoordinateChanged(exitCoordinate());
...@@ -374,7 +358,7 @@ void StructureScanComplexItem::_polygonPathChanged(void) ...@@ -374,7 +358,7 @@ void StructureScanComplexItem::_polygonPathChanged(void)
double StructureScanComplexItem::greatestDistanceTo(const QGeoCoordinate &other) const double StructureScanComplexItem::greatestDistanceTo(const QGeoCoordinate &other) const
{ {
double greatestDistance = 0.0; double greatestDistance = 0.0;
QList<QGeoCoordinate> vertices = _mapPolygon.coordinateList(); QList<QGeoCoordinate> vertices = _flightPolygon.coordinateList();
for (int i=0; i<vertices.count(); i++) { for (int i=0; i<vertices.count(); i++) {
QGeoCoordinate vertex = vertices[i]; QGeoCoordinate vertex = vertices[i];
...@@ -389,7 +373,7 @@ double StructureScanComplexItem::greatestDistanceTo(const QGeoCoordinate &other) ...@@ -389,7 +373,7 @@ double StructureScanComplexItem::greatestDistanceTo(const QGeoCoordinate &other)
bool StructureScanComplexItem::specifiesCoordinate(void) const bool StructureScanComplexItem::specifiesCoordinate(void) const
{ {
return _mapPolygon.count() > 2; return _flightPolygon.count() > 2;
} }
void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent) void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent)
...@@ -413,8 +397,8 @@ void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QO ...@@ -413,8 +397,8 @@ void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QO
for (int layer=0; layer<_layersFact.rawValue().toInt(); layer++) { for (int layer=0; layer<_layersFact.rawValue().toInt(); layer++) {
double layerAltitude = baseAltitude + (layer * _layerDistanceFact.rawValue().toDouble()); double layerAltitude = baseAltitude + (layer * _layerDistanceFact.rawValue().toDouble());
for (int i=0; i<_mapPolygon.count(); i++) { for (int i=0; i<_flightPolygon.count(); i++) {
QGeoCoordinate vertexCoord = _mapPolygon.pathModel().value<QGCQGeoCoordinate*>(i)->coordinate(); QGeoCoordinate vertexCoord = _flightPolygon.vertexCoordinate(i);
MissionItem* item = new MissionItem(seqNum++, MissionItem* item = new MissionItem(seqNum++,
MAV_CMD_NAV_WAYPOINT, MAV_CMD_NAV_WAYPOINT,
...@@ -432,7 +416,7 @@ void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QO ...@@ -432,7 +416,7 @@ void StructureScanComplexItem::appendMissionItems(QList<MissionItem*>& items, QO
items.append(item); items.append(item);
} }
QGeoCoordinate vertexCoord = _mapPolygon.pathModel().value<QGCQGeoCoordinate*>(0)->coordinate(); QGeoCoordinate vertexCoord = _flightPolygon.vertexCoordinate(0);
MissionItem* item = new MissionItem(seqNum++, MissionItem* item = new MissionItem(seqNum++,
MAV_CMD_NAV_WAYPOINT, MAV_CMD_NAV_WAYPOINT,
...@@ -489,9 +473,9 @@ double StructureScanComplexItem::timeBetweenShots(void) const ...@@ -489,9 +473,9 @@ double StructureScanComplexItem::timeBetweenShots(void) const
QGeoCoordinate StructureScanComplexItem::coordinate(void) const QGeoCoordinate StructureScanComplexItem::coordinate(void) const
{ {
if (_mapPolygon.count() > 0) { if (_flightPolygon.count() > 0) {
int entryVertex = qMax(qMin(_entryVertex, _mapPolygon.count() - 1), 0); int entryVertex = qMax(qMin(_entryVertex, _flightPolygon.count() - 1), 0);
return _mapPolygon.vertexCoordinate(entryVertex); return _flightPolygon.vertexCoordinate(entryVertex);
} else { } else {
return QGeoCoordinate(); return QGeoCoordinate();
} }
...@@ -511,9 +495,15 @@ void StructureScanComplexItem::_updateCoordinateAltitudes(void) ...@@ -511,9 +495,15 @@ void StructureScanComplexItem::_updateCoordinateAltitudes(void)
void StructureScanComplexItem::rotateEntryPoint(void) void StructureScanComplexItem::rotateEntryPoint(void)
{ {
_entryVertex++; _entryVertex++;
if (_entryVertex >= _mapPolygon.count()) { if (_entryVertex >= _flightPolygon.count()) {
_entryVertex = 0; _entryVertex = 0;
} }
emit coordinateChanged(coordinate()); emit coordinateChanged(coordinate());
emit exitCoordinateChanged(exitCoordinate()); emit exitCoordinateChanged(exitCoordinate());
} }
void StructureScanComplexItem::_rebuildFlightPolygon(void)
{
_flightPolygon = _structurePolygon;
_flightPolygon.offset(_scanDistanceFact.rawValue().toDouble());
}
...@@ -30,20 +30,24 @@ public: ...@@ -30,20 +30,24 @@ public:
Q_PROPERTY(Fact* layers READ layers CONSTANT) Q_PROPERTY(Fact* layers READ layers CONSTANT)
Q_PROPERTY(Fact* layerDistance READ layerDistance CONSTANT) Q_PROPERTY(Fact* layerDistance READ layerDistance CONSTANT)
Q_PROPERTY(Fact* cameraTriggerDistance READ cameraTriggerDistance CONSTANT) Q_PROPERTY(Fact* cameraTriggerDistance READ cameraTriggerDistance CONSTANT)
Q_PROPERTY(Fact* scanDistance READ scanDistance CONSTANT)
Q_PROPERTY(bool altitudeRelative MEMBER _altitudeRelative NOTIFY altitudeRelativeChanged) Q_PROPERTY(bool altitudeRelative MEMBER _altitudeRelative NOTIFY altitudeRelativeChanged)
Q_PROPERTY(int cameraShots READ cameraShots NOTIFY cameraShotsChanged) Q_PROPERTY(int cameraShots READ cameraShots NOTIFY cameraShotsChanged)
Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged) Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged)
Q_PROPERTY(double cameraMinTriggerInterval MEMBER _cameraMinTriggerInterval NOTIFY cameraMinTriggerIntervalChanged) Q_PROPERTY(double cameraMinTriggerInterval MEMBER _cameraMinTriggerInterval NOTIFY cameraMinTriggerIntervalChanged)
Q_PROPERTY(QGCMapPolygon* mapPolygon READ mapPolygon CONSTANT) Q_PROPERTY(QGCMapPolygon* structurePolygon READ structurePolygon CONSTANT)
Q_PROPERTY(QGCMapPolygon* flightPolygon READ flightPolygon CONSTANT)
Fact* altitude (void) { return &_altitudeFact; } Fact* altitude (void) { return &_altitudeFact; }
Fact* layers (void) { return &_layersFact; } Fact* layers (void) { return &_layersFact; }
Fact* layerDistance (void) { return &_layerDistanceFact; } Fact* layerDistance (void) { return &_layerDistanceFact; }
Fact* cameraTriggerDistance (void) { return &_cameraTriggerDistanceFact; } Fact* cameraTriggerDistance (void) { return &_cameraTriggerDistanceFact; }
Fact* scanDistance (void) { return &_scanDistanceFact; }
int cameraShots (void) const; int cameraShots (void) const;
double timeBetweenShots(void) const; double timeBetweenShots(void) const;
QGCMapPolygon* mapPolygon (void) { return &_mapPolygon; } QGCMapPolygon* structurePolygon(void) { return &_structurePolygon; }
QGCMapPolygon* flightPolygon (void) { return &_flightPolygon; }
Q_INVOKABLE void rotateEntryPoint(void); Q_INVOKABLE void rotateEntryPoint(void);
...@@ -95,9 +99,10 @@ private slots: ...@@ -95,9 +99,10 @@ private slots:
void _setDirty(void); void _setDirty(void);
void _polygonDirtyChanged(bool dirty); void _polygonDirtyChanged(bool dirty);
void _polygonCountChanged(int count); void _polygonCountChanged(int count);
void _polygonPathChanged(void); void _flightPathChanged(void);
void _clearInternal(void); void _clearInternal(void);
void _updateCoordinateAltitudes(void); void _updateCoordinateAltitudes(void);
void _rebuildFlightPolygon(void);
private: private:
void _setExitCoordinate(const QGeoCoordinate& coordinate); void _setExitCoordinate(const QGeoCoordinate& coordinate);
...@@ -107,7 +112,8 @@ private: ...@@ -107,7 +112,8 @@ private:
int _sequenceNumber; int _sequenceNumber;
bool _dirty; bool _dirty;
QGCMapPolygon _mapPolygon; QGCMapPolygon _structurePolygon;
QGCMapPolygon _flightPolygon;
bool _altitudeRelative; bool _altitudeRelative;
int _entryVertex; // Polygon vertext which is used as the mission entry point int _entryVertex; // Polygon vertext which is used as the mission entry point
...@@ -124,39 +130,13 @@ private: ...@@ -124,39 +130,13 @@ private:
Fact _layersFact; Fact _layersFact;
Fact _layerDistanceFact; Fact _layerDistanceFact;
Fact _cameraTriggerDistanceFact; Fact _cameraTriggerDistanceFact;
Fact _scanDistanceFact;
static const char* _altitudeFactName; static const char* _altitudeFactName;
static const char* _layersFactName; static const char* _layersFactName;
static const char* _layerDistanceFactName; static const char* _layerDistanceFactName;
static const char* _cameraTriggerDistanceFactName; static const char* _cameraTriggerDistanceFactName;
static const char* _scanDistanceFactName;
static const char* _jsonGridObjectKey;
static const char* _jsonGridAltitudeKey;
static const char* _jsonGridAltitudeRelativeKey;
static const char* _jsonGridAngleKey;
static const char* _jsonGridSpacingKey;
static const char* _jsonGridEntryLocationKey;
static const char* _jsonTurnaroundDistKey;
static const char* _jsonCameraTriggerDistanceKey;
static const char* _jsonCameraTriggerInTurnaroundKey;
static const char* _jsonHoverAndCaptureKey;
static const char* _jsonGroundResolutionKey;
static const char* _jsonFrontalOverlapKey;
static const char* _jsonSideOverlapKey;
static const char* _jsonCameraSensorWidthKey;
static const char* _jsonCameraSensorHeightKey;
static const char* _jsonCameraResolutionWidthKey;
static const char* _jsonCameraResolutionHeightKey;
static const char* _jsonCameraFocalLengthKey;
static const char* _jsonCameraMinTriggerIntervalKey;
static const char* _jsonManualGridKey;
static const char* _jsonCameraObjectKey;
static const char* _jsonCameraNameKey;
static const char* _jsonCameraOrientationLandscapeKey;
static const char* _jsonFixedValueIsAltitudeKey;
static const char* _jsonRefly90DegreesKey;
static const int _hoverAndCaptureDelaySeconds = 1;
}; };
#endif #endif
...@@ -60,11 +60,19 @@ Rectangle { ...@@ -60,11 +60,19 @@ Rectangle {
QGCLabel { QGCLabel {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
text: qsTr("WARNING: WORK IN PROGRESS. USE AT YOUR OWN RISK.") text: qsTr("WARNING: WORK IN PROGRESS. USE AT YOUR OWN RISK. MEANT FOR DISCUSSION ONLY. DO NOT REPORT BUGS.")
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
color: qgcPal.warningText color: qgcPal.warningText
} }
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("Note: Polygon respresents structure surface not vehicle flight path.")
wrapMode: Text.WordWrap
font.pointSize: ScreenTools.smallFontPointSize
}
QGCLabel { QGCLabel {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
...@@ -99,6 +107,12 @@ Rectangle { ...@@ -99,6 +107,12 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
} }
QGCLabel { text: qsTr("Scan distance") }
FactTextField {
fact: missionItem.scanDistance
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Trigger Distance") } QGCLabel { text: qsTr("Trigger Distance") }
FactTextField { FactTextField {
fact: missionItem.cameraTriggerDistance fact: missionItem.cameraTriggerDistance
......
...@@ -25,31 +25,28 @@ Item { ...@@ -25,31 +25,28 @@ Item {
property var map ///< Map control to place item in property var map ///< Map control to place item in
property var _missionItem: object property var _missionItem: object
property var _mapPolygon: object.mapPolygon property var _structurePolygon: object.structurePolygon
property var _gridComponent property var _flightPolygon: object.flightPolygon
property var _entryCoordinate property var _entryCoordinate
property var _exitCoordinate property var _exitCoordinate
signal clicked(int sequenceNumber) signal clicked(int sequenceNumber)
function _addVisualElements() { function _addVisualElements() {
_gridComponent = gridComponent.createObject(map)
_entryCoordinate = entryPointComponent.createObject(map) _entryCoordinate = entryPointComponent.createObject(map)
_exitCoordinate = exitPointComponent.createObject(map) _exitCoordinate = exitPointComponent.createObject(map)
map.addMapItem(_gridComponent)
map.addMapItem(_entryCoordinate) map.addMapItem(_entryCoordinate)
map.addMapItem(_exitCoordinate) map.addMapItem(_exitCoordinate)
} }
function _destroyVisualElements() { function _destroyVisualElements() {
_gridComponent.destroy()
_entryCoordinate.destroy() _entryCoordinate.destroy()
_exitCoordinate.destroy() _exitCoordinate.destroy()
} }
/// Add an initial 4 sided polygon if there is none /// Add an initial 4 sided polygon if there is none
function _addInitialPolygon() { function _addInitialPolygon() {
if (_mapPolygon.count < 3) { if (_structurePolygon.count < 3) {
// Initial polygon is inset to take 2/3rds space // Initial polygon is inset to take 2/3rds space
var rect = Qt.rect(map.centerViewport.x, map.centerViewport.y, map.centerViewport.width, map.centerViewport.height) var rect = Qt.rect(map.centerViewport.x, map.centerViewport.y, map.centerViewport.width, map.centerViewport.height)
rect.x += (rect.width * 0.25) / 2 rect.x += (rect.width * 0.25) / 2
...@@ -71,10 +68,10 @@ Item { ...@@ -71,10 +68,10 @@ Item {
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180) bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180) bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180)
_mapPolygon.appendVertex(topLeftCoord) _structurePolygon.appendVertex(topLeftCoord)
_mapPolygon.appendVertex(topRightCoord) _structurePolygon.appendVertex(topRightCoord)
_mapPolygon.appendVertex(bottomRightCoord) _structurePolygon.appendVertex(bottomRightCoord)
_mapPolygon.appendVertex(bottomLeftCoord) _structurePolygon.appendVertex(bottomLeftCoord)
} }
} }
...@@ -88,9 +85,8 @@ Item { ...@@ -88,9 +85,8 @@ Item {
} }
QGCMapPolygonVisuals { QGCMapPolygonVisuals {
id: mapPolygonVisuals
mapControl: map mapControl: map
mapPolygon: _mapPolygon mapPolygon: _structurePolygon
interactive: _missionItem.isCurrentItem interactive: _missionItem.isCurrentItem
borderWidth: 1 borderWidth: 1
borderColor: "black" borderColor: "black"
...@@ -98,15 +94,12 @@ Item { ...@@ -98,15 +94,12 @@ Item {
interiorOpacity: 0.5 interiorOpacity: 0.5
} }
// Survey grid lines QGCMapPolygonVisuals {
Component { mapControl: map
id: gridComponent mapPolygon: _flightPolygon
interactive: false
MapPolyline { borderWidth: 2
line.color: "white" borderColor: "white"
line.width: 2
path: _missionItem.gridPoints
}
} }
// Entry point // Entry point
......
...@@ -70,11 +70,7 @@ bool MockLinkMissionItemHandler::handleMessage(const mavlink_message_t& msg) ...@@ -70,11 +70,7 @@ bool MockLinkMissionItemHandler::handleMessage(const mavlink_message_t& msg)
break; break;
case MAVLINK_MSG_ID_MISSION_CLEAR_ALL: case MAVLINK_MSG_ID_MISSION_CLEAR_ALL:
// Delete all plan items _handleMissionClearAll(msg);
_missionItems.clear();
_fenceItems.clear();
_rallyItems.clear();
_sendAck(MAV_MISSION_ACCEPTED);
break; break;
default: default:
...@@ -84,6 +80,40 @@ bool MockLinkMissionItemHandler::handleMessage(const mavlink_message_t& msg) ...@@ -84,6 +80,40 @@ bool MockLinkMissionItemHandler::handleMessage(const mavlink_message_t& msg)
return true; return true;
} }
void MockLinkMissionItemHandler::_handleMissionClearAll(const mavlink_message_t& msg)
{
mavlink_mission_clear_all_t clearAll;
mavlink_msg_mission_clear_all_decode(&msg, &clearAll);
Q_ASSERT(clearAll.target_system == _mockLink->vehicleId());
_requestType = (MAV_MISSION_TYPE)clearAll.mission_type;
qCDebug(MockLinkMissionItemHandlerLog) << QStringLiteral("_handleMissionClearAll %1").arg(_requestType);
switch (_requestType) {
case MAV_MISSION_TYPE_MISSION:
_missionItems.clear();
break;
case MAV_MISSION_TYPE_FENCE:
_fenceItems.clear();
break;
case MAV_MISSION_TYPE_RALLY:
_rallyItems.clear();
break;
case MAV_MISSION_TYPE_ALL:
_missionItems.clear();
_fenceItems.clear();
_rallyItems.clear();
break;
default:
Q_ASSERT(false);
}
_sendAck(MAV_MISSION_ACCEPTED);
}
void MockLinkMissionItemHandler::_handleMissionRequestList(const mavlink_message_t& msg) void MockLinkMissionItemHandler::_handleMissionRequestList(const mavlink_message_t& msg)
{ {
qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequestList read sequence"; qCDebug(MockLinkMissionItemHandlerLog) << "_handleMissionRequestList read sequence";
......
...@@ -88,6 +88,7 @@ private: ...@@ -88,6 +88,7 @@ private:
void _handleMissionRequest(const mavlink_message_t& msg); void _handleMissionRequest(const mavlink_message_t& msg);
void _handleMissionItem(const mavlink_message_t& msg); void _handleMissionItem(const mavlink_message_t& msg);
void _handleMissionCount(const mavlink_message_t& msg); void _handleMissionCount(const mavlink_message_t& msg);
void _handleMissionClearAll(const mavlink_message_t& msg);
void _requestNextMissionItem(int sequenceNumber); void _requestNextMissionItem(int sequenceNumber);
void _sendAck(MAV_MISSION_RESULT ackType); void _sendAck(MAV_MISSION_RESULT ackType);
void _startMissionItemResponseTimer(void); void _startMissionItemResponseTimer(void);
......
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