TransectStyleComplexItem.h 13.9 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#pragma once

#include "ComplexMissionItem.h"
#include "MissionItem.h"
#include "SettingsFact.h"
#include "QGCLoggingCategory.h"
#include "QGCMapPolyline.h"
#include "QGCMapPolygon.h"
#include "CameraCalc.h"
19
#include "TerrainQuery.h"
20 21 22

Q_DECLARE_LOGGING_CATEGORY(TransectStyleComplexItemLog)

23 24
class PlanMasterController;

25 26 27 28 29
class TransectStyleComplexItem : public ComplexMissionItem
{
    Q_OBJECT

public:
30
    TransectStyleComplexItem(PlanMasterController* masterController, bool flyView, QString settignsGroup, QObject* parent);
31

32 33 34 35 36 37 38 39 40 41 42
    Q_PROPERTY(QGCMapPolygon*   surveyAreaPolygon           READ surveyAreaPolygon                                  CONSTANT)
    Q_PROPERTY(CameraCalc*      cameraCalc                  READ cameraCalc                                         CONSTANT)
    Q_PROPERTY(Fact*            turnAroundDistance          READ turnAroundDistance                                 CONSTANT)
    Q_PROPERTY(Fact*            cameraTriggerInTurnAround   READ cameraTriggerInTurnAround                          CONSTANT)
    Q_PROPERTY(Fact*            hoverAndCapture             READ hoverAndCapture                                    CONSTANT)
    Q_PROPERTY(Fact*            refly90Degrees              READ refly90Degrees                                     CONSTANT)

    Q_PROPERTY(int              cameraShots                 READ cameraShots                                        NOTIFY cameraShotsChanged)
    Q_PROPERTY(double           timeBetweenShots            READ timeBetweenShots                                   NOTIFY timeBetweenShotsChanged)
    Q_PROPERTY(double           coveredArea                 READ coveredArea                                        NOTIFY coveredAreaChanged)
    Q_PROPERTY(bool             hoverAndCaptureAllowed      READ hoverAndCaptureAllowed                             CONSTANT)
43
    Q_PROPERTY(QVariantList     visualTransectPoints        READ visualTransectPoints                               NOTIFY visualTransectPointsChanged)
44 45 46 47 48

    Q_PROPERTY(bool             followTerrain               READ followTerrain              WRITE setFollowTerrain  NOTIFY followTerrainChanged)
    Q_PROPERTY(Fact*            terrainAdjustTolerance      READ terrainAdjustTolerance                             CONSTANT)
    Q_PROPERTY(Fact*            terrainAdjustMaxDescentRate READ terrainAdjustMaxDescentRate                        CONSTANT)
    Q_PROPERTY(Fact*            terrainAdjustMaxClimbRate   READ terrainAdjustMaxClimbRate                          CONSTANT)
49 50 51

    QGCMapPolygon*  surveyAreaPolygon   (void) { return &_surveyAreaPolygon; }
    CameraCalc*     cameraCalc          (void) { return &_cameraCalc; }
52
    QVariantList    visualTransectPoints(void) { return _visualTransectPoints; }
53

54 55 56 57 58
    Fact* turnAroundDistance            (void) { return &_turnAroundDistanceFact; }
    Fact* cameraTriggerInTurnAround     (void) { return &_cameraTriggerInTurnAroundFact; }
    Fact* hoverAndCapture               (void) { return &_hoverAndCaptureFact; }
    Fact* refly90Degrees                (void) { return &_refly90DegreesFact; }
    Fact* terrainAdjustTolerance        (void) { return &_terrainAdjustToleranceFact; }
Don Gagne's avatar
Don Gagne committed
59 60
    Fact* terrainAdjustMaxDescentRate   (void) { return &_terrainAdjustMaxDescentRateFact; }
    Fact* terrainAdjustMaxClimbRate     (void) { return &_terrainAdjustMaxClimbRateFact; }
61

DonLakeFlyer's avatar
DonLakeFlyer committed
62 63
    const Fact* hoverAndCapture         (void) const { return &_hoverAndCaptureFact; }

64 65 66
    int             cameraShots             (void) const { return _cameraShots; }
    double          coveredArea             (void) const;
    bool            hoverAndCaptureAllowed  (void) const;
67 68
    bool            followTerrain           (void) const { return _followTerrain; }

69 70
    virtual double  timeBetweenShots        (void) { return 0; } // Most be overridden. Implementation here is needed for unit testing.

71
    void setFollowTerrain(bool followTerrain);
72

DonLakeFlyer's avatar
DonLakeFlyer committed
73 74 75 76
    double  triggerDistance         (void) const { return _cameraCalc.adjustedFootprintFrontal()->rawValue().toDouble(); }
    bool    hoverAndCaptureEnabled  (void) const { return hoverAndCapture()->rawValue().toBool(); }
    bool    triggerCamera           (void) const { return triggerDistance() != 0; }

77
    // Used internally only by unit tests
78
    int _transectCount(void) const { return _transects.count(); }
79

80
    // Overrides from ComplexMissionItem
81 82 83 84 85 86
    int     lastSequenceNumber  (void) const final;
    QString mapVisualQML        (void) const override = 0;
    bool    load                (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) override = 0;
    void    addKMLVisuals       (KMLPlanDomDocument& domDocument) final;
    double  complexDistance     (void) const final { return _complexDistance; }
    double  greatestDistanceTo  (const QGeoCoordinate &other) const final;
87 88

    // Overrides from VisualMissionItem
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    void                save                        (QJsonArray&  planItems) override = 0;
    bool                specifiesCoordinate         (void) const override = 0;
    void                appendMissionItems          (QList<MissionItem*>& items, QObject* missionItemParent) final;
    void                applyNewAltitude            (double newAltitude) final;
    bool                dirty                       (void) const final { return _dirty; }
    bool                isSimpleItem                (void) const final { return false; }
    bool                isStandaloneCoordinate      (void) const final { return false; }
    bool                specifiesAltitudeOnly       (void) const final { return false; }
    QGeoCoordinate      coordinate                  (void) const final { return _coordinate; }
    QGeoCoordinate      exitCoordinate              (void) const final { return _exitCoordinate; }
    int                 sequenceNumber              (void) const final { return _sequenceNumber; }
    double              specifiedFlightSpeed        (void) final { return std::numeric_limits<double>::quiet_NaN(); }
    double              specifiedGimbalYaw          (void) final { return std::numeric_limits<double>::quiet_NaN(); }
    double              specifiedGimbalPitch        (void) final { return std::numeric_limits<double>::quiet_NaN(); }
    void                setMissionFlightStatus      (MissionController::MissionFlightStatus_t& missionFlightStatus) final;
    ReadyForSaveState   readyForSaveState         (void) const override;
    QString             commandDescription          (void) const override { return tr("Transect"); }
    QString             commandName                 (void) const override { return tr("Transect"); }
    QString             abbreviation                (void) const override { return tr("T"); }
    bool                exitCoordinateSameAsEntry   (void) const final { return false; }
    void                setDirty                    (bool dirty) final;
    void                setCoordinate               (const QGeoCoordinate& coordinate) final { Q_UNUSED(coordinate); }
    void                setSequenceNumber           (int sequenceNumber) final;
    double              amslEntryAlt                (void) const final;
    double              amslExitAlt                 (void) const final;
    double              minAMSLAltitude             (void) const final { return _minAMSLAltitude; }
    double              maxAMSLAltitude             (void) const final { return _maxAMSLAltitude; }
116 117 118 119 120 121

    static const char* turnAroundDistanceName;
    static const char* turnAroundDistanceMultiRotorName;
    static const char* cameraTriggerInTurnAroundName;
    static const char* hoverAndCaptureName;
    static const char* refly90DegreesName;
122 123 124
    static const char* terrainAdjustToleranceName;
    static const char* terrainAdjustMaxClimbRateName;
    static const char* terrainAdjustMaxDescentRateName;
125 126 127 128

signals:
    void cameraShotsChanged             (void);
    void timeBetweenShotsChanged        (void);
129
    void visualTransectPointsChanged    (void);
130
    void coveredAreaChanged             (void);
131
    void followTerrainChanged           (bool followTerrain);
132
    void _updateFlightPathSegmentsSignal(void);
133 134 135

protected slots:
    void _setDirty                          (void);
136
    void _setIfDirty                        (bool dirty);
137
    void _updateCoordinateAltitudes         (void);
138
    void _polyPathTerrainData               (bool success, const QList<TerrainPathQuery::PathHeightInfo_t>& rgPathHeightInfo);
139
    void _rebuildTransects                  (void);
140 141

protected:
142 143 144
    virtual void _rebuildTransectsPhase1    (void) = 0; ///< Rebuilds the _transects array
    virtual void _recalcCameraShots         (void) = 0;

145
    void    _save                           (QJsonObject& saveObject);
Don Gagne's avatar
Don Gagne committed
146
    bool    _load                           (const QJsonObject& complexObject, bool forPresets, QString& errorString);
147 148 149 150
    void    _setExitCoordinate              (const QGeoCoordinate& coordinate);
    void    _setCameraShots                 (int cameraShots);
    double  _triggerDistance                (void) const;
    bool    _hasTurnaround                  (void) const;
151 152 153 154 155 156 157 158
    double  _turnAroundDistance             (void) const;
    void    _appendWaypoint                 (QList<MissionItem*>& items, QObject* missionItemParent, int& seqNum, MAV_FRAME mavFrame, float holdTime, const QGeoCoordinate& coordinate);
    void    _appendSinglePhotoCapture       (QList<MissionItem*>& items, QObject* missionItemParent, int& seqNum);
    void    _appendConditionGate            (QList<MissionItem*>& items, QObject* missionItemParent, int& seqNum, MAV_FRAME mavFrame, const QGeoCoordinate& coordinate);
    void    _appendCameraTriggerDistance    (QList<MissionItem*>& items, QObject* missionItemParent, int& seqNum, float triggerDistance);
    void    _appendCameraTriggerDistanceUpdatePoint(QList<MissionItem*>& items, QObject* missionItemParent, int& seqNum, MAV_FRAME mavFrame, const QGeoCoordinate& coordinate, bool useConditionGate, float triggerDistance);
    void    _buildAndAppendMissionItems     (QList<MissionItem*>& items, QObject* missionItemParent);
    void    _appendLoadedMissionItems       (QList<MissionItem*>& items, QObject* missionItemParent);
159
    void    _recalcComplexDistance          (void);
160

161
    int                 _sequenceNumber = 0;
162 163 164
    QGeoCoordinate      _coordinate;
    QGeoCoordinate      _exitCoordinate;
    QGCMapPolygon       _surveyAreaPolygon;
165

166
    enum CoordType {
DonLakeFlyer's avatar
DonLakeFlyer committed
167 168 169
        CoordTypeInterior,              ///< Interior waypoint for flight path only
        CoordTypeInteriorHoverTrigger,  ///< Interior waypoint for hover and capture trigger
        CoordTypeInteriorTerrainAdded,  ///< Interior waypoint added for terrain
170 171 172
        CoordTypeSurveyEntry,           ///< Waypoint at entry edge of survey polygon
        CoordTypeSurveyExit,            ///< Waypoint at exit edge of survey polygon
        CoordTypeTurnaround,            ///< First turnaround waypoint
173 174 175 176 177 178 179 180 181 182
    };

    typedef struct {
        QGeoCoordinate  coord;
        CoordType       coordType;
    } CoordInfo_t;

    QVariantList                                        _visualTransectPoints;
    QList<QList<CoordInfo_t>>                           _transects;
    QList<QList<TerrainPathQuery::PathHeightInfo_t>>    _transectsPathHeightInfo;
183 184 185 186 187 188

    bool            _ignoreRecalc =     false;
    double          _complexDistance =  qQNaN();
    int             _cameraShots =      0;
    double          _timeBetweenShots = 0;
    double          _cruiseSpeed =      0;
189
    CameraCalc      _cameraCalc;
190 191 192
    bool            _followTerrain =    false;
    double          _minAMSLAltitude =  qQNaN();
    double          _maxAMSLAltitude =  qQNaN();
193

194 195
    QObject*            _loadedMissionItemsParent = nullptr;	///< Parent for all items in _loadedMissionItems for simpler delete
    QList<MissionItem*> _loadedMissionItems;                    ///< Mission items loaded from plan file
196

197 198 199 200 201 202
    QMap<QString, FactMetaData*> _metaDataMap;

    SettingsFact _turnAroundDistanceFact;
    SettingsFact _cameraTriggerInTurnAroundFact;
    SettingsFact _hoverAndCaptureFact;
    SettingsFact _refly90DegreesFact;
203 204 205
    SettingsFact _terrainAdjustToleranceFact;
    SettingsFact _terrainAdjustMaxClimbRateFact;
    SettingsFact _terrainAdjustMaxDescentRateFact;
206 207

    static const char* _jsonCameraCalcKey;
208
    static const char* _jsonTransectStyleComplexItemKey;
DonLakeFlyer's avatar
DonLakeFlyer committed
209
    static const char* _jsonVisualTransectPointsKey;
210
    static const char* _jsonItemsKey;
211
    static const char* _jsonFollowTerrainKey;
212
    static const char* _jsonCameraShotsKey;
213

214 215
    static const int _terrainQueryTimeoutMsecs=     1000;
    static const int _hoverAndCaptureDelaySeconds = 4;
216

217
private slots:
218 219 220 221 222
    void _reallyQueryTransectsPathHeightInfo        (void);
    void _followTerrainChanged                      (bool followTerrain);
    void _handleHoverAndCaptureEnabled              (QVariant enabled);
    void _updateFlightPathSegmentsDontCallDirectly  (void);
    void _segmentTerrainCollisionChanged            (bool terrainCollision) final;
223

224
private:
225 226 227 228 229 230 231
    void    _queryTransectsPathHeightInfo   (void);
    void    _adjustTransectsForTerrain      (void);
    void    _addInterstitialTerrainPoints   (QList<CoordInfo_t>& transect, const QList<TerrainPathQuery::PathHeightInfo_t>& transectPathHeightInfo);
    void    _adjustForMaxRates              (QList<CoordInfo_t>& transect);
    void    _adjustForTolerance             (QList<CoordInfo_t>& transect);
    double  _altitudeBetweenCoords          (const QGeoCoordinate& fromCoord, const QGeoCoordinate& toCoord, double percentTowardsTo);
    int     _maxPathHeight                  (const TerrainPathQuery::PathHeightInfo_t& pathHeightInfo, int fromIndex, int toIndex, double& maxHeight);
232 233 234

    TerrainPolyPathQuery*       _currentTerrainFollowQuery =            nullptr;
    QTimer                      _terrainQueryTimer;
235
};