You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
6.5 KiB
148 lines
6.5 KiB
/**************************************************************************** |
|
* |
|
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> |
|
* |
|
* QGroundControl is licensed according to the terms in the file |
|
* COPYING.md in the root of the source code directory. |
|
* |
|
****************************************************************************/ |
|
|
|
#include "VTOLLandingComplexItem.h" |
|
#include "JsonHelper.h" |
|
#include "MissionController.h" |
|
#include "QGCGeo.h" |
|
#include "SimpleMissionItem.h" |
|
#include "PlanMasterController.h" |
|
#include "FlightPathSegment.h" |
|
#include "QGC.h" |
|
|
|
#include <QPolygonF> |
|
|
|
QGC_LOGGING_CATEGORY(VTOLLandingComplexItemLog, "VTOLLandingComplexItemLog") |
|
|
|
const QString VTOLLandingComplexItem::name(tr("VTOL Landing")); |
|
|
|
const char* VTOLLandingComplexItem::settingsGroup = "VTOLLanding"; |
|
const char* VTOLLandingComplexItem::jsonComplexItemTypeValue = "vtolLandingPattern"; |
|
|
|
VTOLLandingComplexItem::VTOLLandingComplexItem(PlanMasterController* masterController, bool flyView, QObject* parent) |
|
: LandingComplexItem (masterController, flyView, parent) |
|
, _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/VTOLLandingPattern.FactMetaData.json"), this)) |
|
, _landingDistanceFact (settingsGroup, _metaDataMap[finalApproachToLandDistanceName]) |
|
, _finalApproachAltitudeFact(settingsGroup, _metaDataMap[finalApproachAltitudeName]) |
|
, _loiterRadiusFact (settingsGroup, _metaDataMap[loiterRadiusName]) |
|
, _loiterClockwiseFact (settingsGroup, _metaDataMap[loiterClockwiseName]) |
|
, _landingHeadingFact (settingsGroup, _metaDataMap[landingHeadingName]) |
|
, _landingAltitudeFact (settingsGroup, _metaDataMap[landingAltitudeName]) |
|
, _useLoiterToAltFact (settingsGroup, _metaDataMap[useLoiterToAltName]) |
|
, _stopTakingPhotosFact (settingsGroup, _metaDataMap[stopTakingPhotosName]) |
|
, _stopTakingVideoFact (settingsGroup, _metaDataMap[stopTakingVideoName]) |
|
{ |
|
_editorQml = "qrc:/qml/VTOLLandingPatternEditor.qml"; |
|
_isIncomplete = false; |
|
|
|
_init(); |
|
|
|
// We adjust landing distance meta data to Plan View settings unless there was a custom build override |
|
if (QGC::fuzzyCompare(_landingDistanceFact.rawValue().toDouble(), _landingDistanceFact.rawDefaultValue().toDouble())) { |
|
Fact* vtolTransitionDistanceFact = qgcApp()->toolbox()->settingsManager()->planViewSettings()->vtolTransitionDistance(); |
|
double vtolTransitionDistance = vtolTransitionDistanceFact->rawValue().toDouble(); |
|
_landingDistanceFact.metaData()->setRawDefaultValue(vtolTransitionDistance); |
|
_landingDistanceFact.setRawValue(vtolTransitionDistance); |
|
_landingDistanceFact.metaData()->setRawMin(vtolTransitionDistanceFact->metaData()->rawMin()); |
|
} |
|
|
|
_recalcFromHeadingAndDistanceChange(); |
|
|
|
setDirty(false); |
|
} |
|
|
|
void VTOLLandingComplexItem::save(QJsonArray& missionItems) |
|
{ |
|
QJsonObject saveObject = _save(); |
|
|
|
saveObject[JsonHelper::jsonVersionKey] = 1; |
|
saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; |
|
saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; |
|
|
|
missionItems.append(saveObject); |
|
} |
|
|
|
bool VTOLLandingComplexItem::load(const QJsonObject& complexObject, int sequenceNumber, QString& errorString) |
|
{ |
|
QList<JsonHelper::KeyValidateInfo> keyInfoList = { |
|
{ JsonHelper::jsonVersionKey, QJsonValue::Double, true }, |
|
}; |
|
if (!JsonHelper::validateKeys(complexObject, keyInfoList, errorString)) { |
|
return false; |
|
} |
|
|
|
int version = complexObject[JsonHelper::jsonVersionKey].toInt(); |
|
if (version != 1) { |
|
errorString = tr("%1 complex item version %2 not supported").arg(jsonComplexItemTypeValue).arg(version); |
|
_ignoreRecalcSignals = false; |
|
return false; |
|
} |
|
|
|
return _load(complexObject, sequenceNumber, jsonComplexItemTypeValue, false /* useDeprecatedRelAltKeys */, errorString); |
|
} |
|
|
|
MissionItem* VTOLLandingComplexItem::_createLandItem(int seqNum, bool altRel, double lat, double lon, double alt, QObject* parent) |
|
{ |
|
return new MissionItem(seqNum, |
|
MAV_CMD_NAV_VTOL_LAND, |
|
altRel ? MAV_FRAME_GLOBAL_RELATIVE_ALT : MAV_FRAME_GLOBAL, |
|
0.0, 0.0, 0.0, 0.0, |
|
lat, lon, alt, |
|
true, // autoContinue |
|
false, // isCurrentItem |
|
parent); |
|
|
|
} |
|
|
|
void VTOLLandingComplexItem::_calcGlideSlope(void) |
|
{ |
|
// No glide slope calc for VTOL |
|
} |
|
|
|
bool VTOLLandingComplexItem::_isValidLandItem(const MissionItem& missionItem) |
|
{ |
|
if (missionItem.command() != MAV_CMD_NAV_LAND || |
|
!(missionItem.frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT || missionItem.frame() == MAV_FRAME_GLOBAL) || |
|
missionItem.param1() != 0 || missionItem.param2() != 0 || missionItem.param3() != 0 || missionItem.param4() != 0) { |
|
return false; |
|
} else { |
|
return true; |
|
} |
|
} |
|
|
|
bool VTOLLandingComplexItem::scanForItem(QmlObjectListModel* visualItems, bool flyView, PlanMasterController* masterController) |
|
{ |
|
return _scanForItem(visualItems, flyView, masterController, _isValidLandItem, _createItem); |
|
} |
|
|
|
// Never call this method directly. If you want to update the flight segments you emit _updateFlightPathSegmentsSignal() |
|
void VTOLLandingComplexItem::_updateFlightPathSegmentsDontCallDirectly(void) |
|
{ |
|
if (_cTerrainCollisionSegments != 0) { |
|
_cTerrainCollisionSegments = 0; |
|
emit terrainCollisionChanged(false); |
|
} |
|
|
|
_flightPathSegments.beginReset(); |
|
_flightPathSegments.clearAndDeleteContents(); |
|
if (useLoiterToAlt()->rawValue().toBool()) { |
|
_appendFlightPathSegment(finalApproachCoordinate(), amslEntryAlt(), loiterTangentCoordinate(), amslEntryAlt()); // Best we can do to simulate loiter circle terrain profile |
|
_appendFlightPathSegment(loiterTangentCoordinate(), amslEntryAlt(), landingCoordinate(), amslEntryAlt()); |
|
} else { |
|
_appendFlightPathSegment(finalApproachCoordinate(), amslEntryAlt(), landingCoordinate(), amslEntryAlt()); |
|
} |
|
_appendFlightPathSegment(landingCoordinate(), amslEntryAlt(), landingCoordinate(), amslExitAlt()); |
|
_flightPathSegments.endReset(); |
|
|
|
if (_cTerrainCollisionSegments != 0) { |
|
emit terrainCollisionChanged(true); |
|
} |
|
|
|
_masterController->missionController()->recalcTerrainProfile(); |
|
}
|
|
|