Commit 29f87555 authored by DonLakeFlyer's avatar DonLakeFlyer

parent 5b272192
......@@ -623,6 +623,7 @@ HEADERS += \
src/MissionManager/StructureScanPlanCreator.h \
src/MissionManager/SurveyComplexItem.h \
src/MissionManager/SurveyPlanCreator.h \
src/MissionManager/TakeoffMissionItem.h \
src/MissionManager/TransectStyleComplexItem.h \
src/MissionManager/VisualMissionItem.h \
src/PositionManager/PositionManager.h \
......@@ -853,6 +854,7 @@ SOURCES += \
src/MissionManager/StructureScanPlanCreator.cc \
src/MissionManager/SurveyComplexItem.cc \
src/MissionManager/SurveyPlanCreator.cc \
src/MissionManager/TakeoffMissionItem.cc \
src/MissionManager/TransectStyleComplexItem.cc \
src/MissionManager/VisualMissionItem.cc \
src/PositionManager/PositionManager.cpp \
......
......@@ -152,6 +152,7 @@
<file alias="QGroundControl/Controls/StructureScanMapVisual.qml">src/PlanView/StructureScanMapVisual.qml</file>
<file alias="QGroundControl/Controls/SubMenuButton.qml">src/QmlControls/SubMenuButton.qml</file>
<file alias="QGroundControl/Controls/SurveyMapVisual.qml">src/PlanView/SurveyMapVisual.qml</file>
<file alias="QGroundControl/Controls/TakeoffItemMapVisual.qml">src/PlanView/TakeoffItemMapVisual.qml</file>
<file alias="QGroundControl/Controls/ToolStrip.qml">src/QmlControls/ToolStrip.qml</file>
<file alias="QGroundControl/Controls/TransectStyleComplexItemStats.qml">src/PlanView/TransectStyleComplexItemStats.qml</file>
<file alias="QGroundControl/Controls/TransectStyleMapVisuals.qml">src/PlanView/TransectStyleMapVisuals.qml</file>
......
......@@ -32,7 +32,6 @@ MapQuickItem {
id: _label
checked: _isCurrentItem
label: missionItem ? missionItem.abbreviation : ""
//index: missionItem ? missionItem.sequenceNumber : 0
gimbalYaw: missionItem.missionGimbalYaw
vehicleYaw: missionItem.missionVehicleYaw
showGimbalYaw: !isNaN(missionItem.missionGimbalYaw)
......
......@@ -30,6 +30,7 @@
#include "PlanMasterController.h"
#include "KML.h"
#include "QGCCorePlugin.h"
#include "TakeoffMissionItem.h"
#define UPDATE_TIMEOUT 5000 ///< How often we check for bounding box changes
......@@ -160,6 +161,7 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque
// - A load from vehicle was manually requested
// - The initial automatic load from a vehicle completed and the current editor is empty
_settingsItem = nullptr;
QmlObjectListModel* newControllerMissionItems = new QmlObjectListModel(this);
const QList<MissionItem*>& newMissionItems = _missionManager->missionItems();
qCDebug(MissionControllerLog) << "loading from vehicle: count"<< newMissionItems.count();
......@@ -171,34 +173,34 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque
if (_controllerVehicle->firmwarePlugin()->sendHomePositionToVehicle() && newMissionItems.count() != 0) {
// First item is fake home position
_addMissionSettings(newControllerMissionItems, false /* addToCenter */);
MissionSettingsItem* settingsItem = newControllerMissionItems->value<MissionSettingsItem*>(0);
if (!settingsItem) {
qWarning() << "First item is not settings item";
return;
}
MissionItem* fakeHomeItem = newMissionItems[0];
if (fakeHomeItem->coordinate().latitude() != 0 || fakeHomeItem->coordinate().longitude() != 0) {
settingsItem->setCoordinate(fakeHomeItem->coordinate());
_settingsItem->setInitialHomePosition(fakeHomeItem->coordinate());
}
i = 1;
}
if (!_controllerVehicle->firmwarePlugin()->sendHomePositionToVehicle() || _visualItems->count() == 0) {
_addMissionSettings(_visualItems, !_flyView && _visualItems->count() > 0 /* addToCenter */);
}
for (; i < newMissionItems.count(); i++) {
const MissionItem* missionItem = newMissionItems[i];
newControllerMissionItems->append(new SimpleMissionItem(_controllerVehicle, _flyView, *missionItem, this));
SimpleMissionItem* simpleItem = new SimpleMissionItem(_controllerVehicle, _flyView, *missionItem, this);
if (TakeoffMissionItem::isTakeoffCommand(static_cast<MAV_CMD>(simpleItem->command()))) {
// This needs to be a TakeoffMissionItem
TakeoffMissionItem* takeoffItem = new TakeoffMissionItem(*missionItem, _controllerVehicle, _flyView, _settingsItem, this);
simpleItem->deleteLater();
simpleItem = takeoffItem;
}
newControllerMissionItems->append(simpleItem);
}
_deinitAllVisualItems();
_visualItems->deleteLater();
_settingsItem = nullptr;
_visualItems = nullptr;
_updateContainsItems(); // This will clear containsItems which will be set again below. This will re-pop Start Mission confirmation.
_visualItems = newControllerMissionItems;
if (!_controllerVehicle->firmwarePlugin()->sendHomePositionToVehicle() || _visualItems->count() == 0) {
_addMissionSettings(_visualItems, !_flyView && _visualItems->count() > 0 /* addToCenter */);
}
MissionController::_scanForAdditionalSettings(_visualItems, _controllerVehicle);
_initAllVisualItems();
......@@ -357,12 +359,44 @@ VisualMissionItem* MissionController::insertSimpleMissionItem(QGeoCoordinate coo
newItem->setCoordinate(coordinate);
newItem->setCommand(MAV_CMD_NAV_WAYPOINT);
_initVisualItem(newItem);
if (_visualItems->count() == 1 && (_controllerVehicle->fixedWing() || _controllerVehicle->vtol() || _controllerVehicle->multiRotor())) {
MAV_CMD takeoffCmd = _controllerVehicle->vtol() ? MAV_CMD_NAV_VTOL_TAKEOFF : MAV_CMD_NAV_TAKEOFF;
if (_controllerVehicle->firmwarePlugin()->supportedMissionCommands().contains(takeoffCmd)) {
newItem->setCommand(takeoffCmd);
if (newItem->specifiesAltitude()) {
double prevAltitude;
int prevAltitudeMode;
if (_findPreviousAltitude(visualItemIndex, &prevAltitude, &prevAltitudeMode)) {
newItem->altitude()->setRawValue(prevAltitude);
newItem->setAltitudeMode(static_cast<QGroundControlQmlGlobal::AltitudeMode>(prevAltitudeMode));
}
}
newItem->setMissionFlightStatus(_missionFlightStatus);
if (visualItemIndex == -1) {
_visualItems->append(newItem);
} else {
_visualItems->insert(visualItemIndex, newItem);
}
// We send the click coordinate through here to be able to set the planned home position from the user click location if needed
_recalcAllWithClickCoordinate(coordinate);
if (makeCurrentItem) {
setCurrentPlanViewIndex(newItem->sequenceNumber(), true);
}
return newItem;
}
VisualMissionItem* MissionController::insertTakeoffItem(QGeoCoordinate coordinate, int visualItemIndex, bool makeCurrentItem)
{
int sequenceNumber = _nextSequenceNumber();
TakeoffMissionItem * newItem = new TakeoffMissionItem(_controllerVehicle->vtol() ? MAV_CMD_NAV_VTOL_TAKEOFF : MAV_CMD_NAV_TAKEOFF, _controllerVehicle, _flyView, _settingsItem, this);
newItem->setSequenceNumber(sequenceNumber);
if (!newItem->coordinate().isValid()) {
newItem->setCoordinate(coordinate);
}
newItem->setWizardMode(true);
_initVisualItem(newItem);
if (newItem->specifiesAltitude()) {
double prevAltitude;
int prevAltitudeMode;
......@@ -552,8 +586,7 @@ void MissionController::removeMissionItem(int index)
bool rollSupported = false;
bool pitchSupported = false;
bool yawSupported = false;
MissionSettingsItem* settingsItem = _visualItems->value<MissionSettingsItem*>(0);
CameraSection* cameraSection = settingsItem->cameraSection();
CameraSection* cameraSection = _settingsItem->cameraSection();
if (_controllerVehicle->firmwarePlugin()->hasGimbal(_controllerVehicle, rollSupported, pitchSupported, yawSupported) && pitchSupported) {
if (cameraSection->specifyGimbal() && cameraSection->gimbalPitch()->rawValue().toDouble() == -90.0 && cameraSection->gimbalYaw()->rawValue().toDouble() == 0.0) {
cameraSection->setSpecifyGimbal(false);
......@@ -625,6 +658,17 @@ bool MissionController::_loadJsonMissionFileV1(const QJsonObject& json, QmlObjec
int nextSequenceNumber = 1; // Start with 1 since home is in 0
QJsonArray itemArray(json[_jsonItemsKey].toArray());
_addMissionSettings(visualItems, true /* addToCenter */);
if (json.contains(_jsonPlannedHomePositionKey)) {
SimpleMissionItem* item = new SimpleMissionItem(_controllerVehicle, _flyView, visualItems);
if (item->load(json[_jsonPlannedHomePositionKey].toObject(), 0, errorString)) {
_settingsItem->setInitialHomePositionFromUser(item->coordinate());
item->deleteLater();
} else {
return false;
}
}
qCDebug(MissionControllerLog) << "Json load: simple item loop start simpleItemCount:ComplexItemCount" << itemArray.count() << surveyItems.count();
do {
qCDebug(MissionControllerLog) << "Json load: simple item loop nextSimpleItemIndex:nextComplexItemIndex:nextSequenceNumber" << nextSimpleItemIndex << nextComplexItemIndex << nextSequenceNumber;
......@@ -654,6 +698,13 @@ bool MissionController::_loadJsonMissionFileV1(const QJsonObject& json, QmlObjec
const QJsonObject itemObject = itemValue.toObject();
SimpleMissionItem* item = new SimpleMissionItem(_controllerVehicle, _flyView, visualItems);
if (item->load(itemObject, itemObject["id"].toInt(), errorString)) {
if (TakeoffMissionItem::isTakeoffCommand(item->mavCommand())) {
// This needs to be a TakeoffMissionItem
TakeoffMissionItem* takeoffItem = new TakeoffMissionItem(_controllerVehicle, _flyView, _settingsItem, visualItems);
takeoffItem->load(itemObject, itemObject["id"].toInt(), errorString);
item->deleteLater();
item = takeoffItem;
}
qCDebug(MissionControllerLog) << "Json load: adding simple item expectedSequence:actualSequence" << nextSequenceNumber << item->sequenceNumber();
nextSequenceNumber = item->lastSequenceNumber() + 1;
visualItems->append(item);
......@@ -663,21 +714,6 @@ bool MissionController::_loadJsonMissionFileV1(const QJsonObject& json, QmlObjec
}
} while (nextSimpleItemIndex < itemArray.count() || nextComplexItemIndex < surveyItems.count());
if (json.contains(_jsonPlannedHomePositionKey)) {
SimpleMissionItem* item = new SimpleMissionItem(_controllerVehicle, _flyView, visualItems);
if (item->load(json[_jsonPlannedHomePositionKey].toObject(), 0, errorString)) {
MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, _flyView, visualItems);
settingsItem->setCoordinate(item->coordinate());
visualItems->insert(0, settingsItem);
item->deleteLater();
} else {
return false;
}
} else {
_addMissionSettings(visualItems, true /* addToCenter */);
}
return true;
}
......@@ -719,9 +755,9 @@ bool MissionController::_loadJsonMissionFileV2(const QJsonObject& json, QmlObjec
if (!JsonHelper::loadGeoCoordinate(json[_jsonPlannedHomePositionKey], true /* altitudeRequired */, homeCoordinate, errorString)) {
return false;
}
MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, _flyView, visualItems);
settingsItem->setCoordinate(homeCoordinate);
visualItems->insert(0, settingsItem);
_settingsItem = new MissionSettingsItem(_controllerVehicle, _flyView, visualItems);
_settingsItem->setCoordinate(homeCoordinate);
visualItems->insert(0, _settingsItem);
qCDebug(MissionControllerLog) << "plannedHomePosition" << homeCoordinate;
// Read mission items
......@@ -750,6 +786,13 @@ bool MissionController::_loadJsonMissionFileV2(const QJsonObject& json, QmlObjec
if (itemType == VisualMissionItem::jsonTypeSimpleItemValue) {
SimpleMissionItem* simpleItem = new SimpleMissionItem(_controllerVehicle, _flyView, visualItems);
if (simpleItem->load(itemObject, nextSequenceNumber, errorString)) {
if (TakeoffMissionItem::isTakeoffCommand(static_cast<MAV_CMD>(simpleItem->command()))) {
// This needs to be a TakeoffMissionItem
TakeoffMissionItem* takeoffItem = new TakeoffMissionItem(_controllerVehicle, _flyView, _settingsItem, this);
takeoffItem->load(itemObject, nextSequenceNumber, errorString);
simpleItem->deleteLater();
simpleItem = takeoffItem;
}
qCDebug(MissionControllerLog) << "Loading simple item: nextSequenceNumber:command" << nextSequenceNumber << simpleItem->command();
nextSequenceNumber = simpleItem->lastSequenceNumber() + 1;
visualItems->append(simpleItem);
......@@ -801,15 +844,6 @@ bool MissionController::_loadJsonMissionFileV2(const QJsonObject& json, QmlObjec
nextSequenceNumber = corridorItem->lastSequenceNumber() + 1;
qCDebug(MissionControllerLog) << "Corridor Scan load complete: nextSequenceNumber" << nextSequenceNumber;
visualItems->append(corridorItem);
} else if (complexItemType == MissionSettingsItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog) << "Loading Mission Settings: nextSequenceNumber" << nextSequenceNumber;
MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, _flyView, visualItems);
if (!settingsItem->load(itemObject, nextSequenceNumber++, errorString)) {
return false;
}
nextSequenceNumber = settingsItem->lastSequenceNumber() + 1;
qCDebug(MissionControllerLog) << "Mission Settings load complete: nextSequenceNumber" << nextSequenceNumber;
visualItems->append(settingsItem);
} else {
errorString = tr("Unsupported complex item type: %1").arg(complexItemType);
}
......@@ -893,15 +927,20 @@ bool MissionController::_loadTextMissionFile(QTextStream& stream, QmlObjectListM
if (versionOk) {
// Start with planned home in center
_addMissionSettings(visualItems, true /* addToCenter */);
MissionSettingsItem* settingsItem = visualItems->value<MissionSettingsItem*>(0);
while (!stream.atEnd()) {
SimpleMissionItem* item = new SimpleMissionItem(_controllerVehicle, _flyView, visualItems);
if (item->load(stream)) {
if (firstItem && plannedHomePositionInFile) {
settingsItem->setCoordinate(item->coordinate());
_settingsItem->setInitialHomePositionFromUser(item->coordinate());
} else {
if (TakeoffMissionItem::isTakeoffCommand(static_cast<MAV_CMD>(item->command()))) {
// This needs to be a TakeoffMissionItem
TakeoffMissionItem* takeoffItem = new TakeoffMissionItem(_controllerVehicle, _flyView, _settingsItem, visualItems);
takeoffItem->load(stream);
item->deleteLater();
item = takeoffItem;
}
visualItems->append(item);
}
firstItem = false;
......@@ -1631,7 +1670,7 @@ void MissionController::_setPlannedHomePositionFromFirstCoordinate(const QGeoCoo
if (firstCoordinate.isValid()) {
QGeoCoordinate plannedHomeCoord = firstCoordinate.atDistanceAndAzimuth(30, 0);
plannedHomeCoord.setAltitude(0);
_settingsItem->setCoordinate(plannedHomeCoord);
_settingsItem->setInitialHomePositionFromUser(plannedHomeCoord);
}
}
......@@ -1658,18 +1697,16 @@ void MissionController::_initAllVisualItems(void)
{
// Setup home position at index 0
_settingsItem = qobject_cast<MissionSettingsItem*>(_visualItems->get(0));
if (!_settingsItem) {
qWarning() << "First item not MissionSettingsItem";
return;
}
if (!_flyView) {
_settingsItem->setIsCurrentItem(true);
qWarning() << "_initAllVisualItems _settingsItem should already be set";
_settingsItem = qobject_cast<MissionSettingsItem*>(_visualItems->get(0));
if (!_settingsItem) {
qWarning() << "First item not MissionSettingsItem";
return;
}
}
if (_managerVehicle->homePosition().isValid()) {
_settingsItem->setCoordinate(_managerVehicle->homePosition());
}
_settingsItem->setHomePositionFromVehicle(_managerVehicle);
connect(_settingsItem, &MissionSettingsItem::coordinateChanged, this, &MissionController::_recalcAll);
connect(_settingsItem, &MissionSettingsItem::missionEndRTLChanged, this, &MissionController::_recalcAll);
......@@ -1689,6 +1726,10 @@ void MissionController::_initAllVisualItems(void)
emit containsItemsChanged(containsItems());
emit plannedHomePositionChanged(plannedHomePosition());
if (!_flyView) {
setCurrentPlanViewIndex(0, true);
}
setDirty(false);
}
......@@ -1781,21 +1822,21 @@ void MissionController::managerVehicleChanged(Vehicle* managerVehicle)
connect(_managerVehicle, &Vehicle::vehicleTypeChanged, this, &MissionController::complexMissionItemNamesChanged);
if (!_masterController->offline()) {
_managerVehicleHomePositionChanged(_managerVehicle->homePosition());
_managerVehicleHomePositionChanged();
}
emit complexMissionItemNamesChanged();
emit resumeMissionIndexChanged();
}
void MissionController::_managerVehicleHomePositionChanged(const QGeoCoordinate& homePosition)
void MissionController::_managerVehicleHomePositionChanged(void)
{
if (_visualItems) {
bool currentDirtyBit = dirty();
MissionSettingsItem* settingsItem = qobject_cast<MissionSettingsItem*>(_visualItems->get(0));
if (settingsItem) {
settingsItem->setHomePositionFromVehicle(homePosition);
settingsItem->setHomePositionFromVehicle(_managerVehicle);
} else {
qWarning() << "First item is not MissionSettingsItem";
}
......@@ -1863,11 +1904,11 @@ double MissionController::_normalizeLon(double lon)
/// Add the Mission Settings complex item to the front of the items
void MissionController::_addMissionSettings(QmlObjectListModel* visualItems, bool addToCenter)
{
MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, _flyView, visualItems);
_settingsItem = new MissionSettingsItem(_controllerVehicle, _flyView, visualItems);
qCDebug(MissionControllerLog) << "_addMissionSettings addToCenter" << addToCenter;
visualItems->insert(0, settingsItem);
visualItems->insert(0, _settingsItem);
if (addToCenter) {
if (visualItems->count() > 1) {
......@@ -1898,11 +1939,11 @@ void MissionController::_addMissionSettings(QmlObjectListModel* visualItems, boo
}
if (firstCoordSet) {
settingsItem->setCoordinate(QGeoCoordinate((south + ((north - south) / 2)) - 90.0, (west + ((east - west) / 2)) - 180.0, 0.0));
_settingsItem->setInitialHomePositionFromUser(QGeoCoordinate((south + ((north - south) / 2)) - 90.0, (west + ((east - west) / 2)) - 180.0, 0.0));
}
}
} else if (_managerVehicle->homePosition().isValid()) {
settingsItem->setCoordinate(_managerVehicle->homePosition());
} else {
_settingsItem->setHomePositionFromVehicle(_managerVehicle);
}
}
......@@ -2133,13 +2174,28 @@ VisualMissionItem* MissionController::currentPlanViewItem(void) const
void MissionController::setCurrentPlanViewIndex(int sequenceNumber, bool force)
{
if(_visualItems && (force || sequenceNumber != _currentPlanViewIndex)) {
if (_visualItems && (force || sequenceNumber != _currentPlanViewIndex)) {
_splitSegment = nullptr;
_currentPlanViewItem = nullptr;
_currentPlanViewIndex = -1;
_isInsertTakeoffValid = true;
for (int i = 0; i < _visualItems->count(); i++) {
VisualMissionItem* pVI = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
if (pVI && pVI->sequenceNumber() == sequenceNumber) {
if (sequenceNumber != 0 && pVI->sequenceNumber() <= sequenceNumber) {
if (pVI->specifiesCoordinate() && !pVI->isStandaloneCoordinate()) {
// Coordinate based flight commands prior to where the takeoff would be inserted
_isInsertTakeoffValid = false;
}
}
if (qobject_cast<TakeoffMissionItem*>(pVI)) {
// Already contains a takeoff command
_isInsertTakeoffValid = false;
}
if (pVI->sequenceNumber() == sequenceNumber) {
pVI->setIsCurrentItem(true);
_currentPlanViewItem = pVI;
_currentPlanViewIndex = sequenceNumber;
......@@ -2160,9 +2216,11 @@ void MissionController::setCurrentPlanViewIndex(int sequenceNumber, bool force)
pVI->setIsCurrentItem(false);
}
}
emit currentPlanViewIndexChanged();
emit currentPlanViewItemChanged();
emit splitSegmentChanged();
emit isInsertTakeoffValidChanged();
}
}
......
......@@ -7,9 +7,7 @@
*
****************************************************************************/
#ifndef MissionController_H
#define MissionController_H
#pragma once
#include "PlanElementController.h"
#include "QmlObjectListModel.h"
......@@ -28,6 +26,7 @@ class AppSettings;
class MissionManager;
class SimpleMissionItem;
class ComplexMissionItem;
class MissionSettingsItem;
class QDomDocument;
Q_DECLARE_LOGGING_CATEGORY(MissionControllerLog)
......@@ -67,38 +66,33 @@ public:
int batteriesRequired; ///< -1 for not supported
} MissionFlightStatus_t;
Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged)
Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines CONSTANT) ///< Used by Plan view only for interactive editing
Q_PROPERTY(QVariantList waypointPath READ waypointPath NOTIFY waypointPathChanged) ///< Used by Fly view only for static display
Q_PROPERTY(QmlObjectListModel* directionArrows READ directionArrows CONSTANT)
Q_PROPERTY(QStringList complexMissionItemNames READ complexMissionItemNames NOTIFY complexMissionItemNamesChanged)
Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged)
Q_PROPERTY(CoordinateVector* splitSegment MEMBER _splitSegment NOTIFY splitSegmentChanged) ///< Segment which show show + split ui element
Q_PROPERTY(double progressPct READ progressPct NOTIFY progressPctChanged)
Q_PROPERTY(int missionItemCount READ missionItemCount NOTIFY missionItemCountChanged) ///< True mission item command count (only valid in Fly View)
Q_PROPERTY(int currentMissionIndex READ currentMissionIndex NOTIFY currentMissionIndexChanged)
Q_PROPERTY(int resumeMissionIndex READ resumeMissionIndex NOTIFY resumeMissionIndexChanged) ///< Returns the item index two which a mission should be resumed. -1 indicates resume mission not available.
Q_PROPERTY(int currentPlanViewIndex READ currentPlanViewIndex NOTIFY currentPlanViewIndexChanged)
Q_PROPERTY(VisualMissionItem* currentPlanViewItem READ currentPlanViewItem NOTIFY currentPlanViewItemChanged)
Q_PROPERTY(double missionDistance READ missionDistance NOTIFY missionDistanceChanged)
Q_PROPERTY(double missionTime READ missionTime NOTIFY missionTimeChanged)
Q_PROPERTY(double missionHoverDistance READ missionHoverDistance NOTIFY missionHoverDistanceChanged)
Q_PROPERTY(double missionCruiseDistance READ missionCruiseDistance NOTIFY missionCruiseDistanceChanged)
Q_PROPERTY(double missionHoverTime READ missionHoverTime NOTIFY missionHoverTimeChanged)
Q_PROPERTY(double missionCruiseTime READ missionCruiseTime NOTIFY missionCruiseTimeChanged)
Q_PROPERTY(double missionMaxTelemetry READ missionMaxTelemetry NOTIFY missionMaxTelemetryChanged)
Q_PROPERTY(int batteryChangePoint READ batteryChangePoint NOTIFY batteryChangePointChanged)
Q_PROPERTY(int batteriesRequired READ batteriesRequired NOTIFY batteriesRequiredChanged)
Q_PROPERTY(QGCGeoBoundingCube* travelBoundingCube READ travelBoundingCube NOTIFY missionBoundingCubeChanged)
Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged)
Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines CONSTANT) ///< Used by Plan view only for interactive editing
Q_PROPERTY(QVariantList waypointPath READ waypointPath NOTIFY waypointPathChanged) ///< Used by Fly view only for static display
Q_PROPERTY(QmlObjectListModel* directionArrows READ directionArrows CONSTANT)
Q_PROPERTY(QStringList complexMissionItemNames READ complexMissionItemNames NOTIFY complexMissionItemNamesChanged)
Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged)
Q_PROPERTY(CoordinateVector* splitSegment MEMBER _splitSegment NOTIFY splitSegmentChanged) ///< Segment which show show + split ui element
Q_PROPERTY(double progressPct READ progressPct NOTIFY progressPctChanged)
Q_PROPERTY(int missionItemCount READ missionItemCount NOTIFY missionItemCountChanged) ///< True mission item command count (only valid in Fly View)
Q_PROPERTY(int currentMissionIndex READ currentMissionIndex NOTIFY currentMissionIndexChanged)
Q_PROPERTY(int resumeMissionIndex READ resumeMissionIndex NOTIFY resumeMissionIndexChanged) ///< Returns the item index two which a mission should be resumed. -1 indicates resume mission not available.
Q_PROPERTY(int currentPlanViewIndex READ currentPlanViewIndex NOTIFY currentPlanViewIndexChanged)
Q_PROPERTY(VisualMissionItem* currentPlanViewItem READ currentPlanViewItem NOTIFY currentPlanViewItemChanged)
Q_PROPERTY(double missionDistance READ missionDistance NOTIFY missionDistanceChanged)
Q_PROPERTY(double missionTime READ missionTime NOTIFY missionTimeChanged)
Q_PROPERTY(double missionHoverDistance READ missionHoverDistance NOTIFY missionHoverDistanceChanged)
Q_PROPERTY(double missionCruiseDistance READ missionCruiseDistance NOTIFY missionCruiseDistanceChanged)
Q_PROPERTY(double missionHoverTime READ missionHoverTime NOTIFY missionHoverTimeChanged)
Q_PROPERTY(double missionCruiseTime READ missionCruiseTime NOTIFY missionCruiseTimeChanged)
Q_PROPERTY(double missionMaxTelemetry READ missionMaxTelemetry NOTIFY missionMaxTelemetryChanged)
Q_PROPERTY(int batteryChangePoint READ batteryChangePoint NOTIFY batteryChangePointChanged)
Q_PROPERTY(int batteriesRequired READ batteriesRequired NOTIFY batteriesRequiredChanged)
Q_PROPERTY(QGCGeoBoundingCube* travelBoundingCube READ travelBoundingCube NOTIFY missionBoundingCubeChanged)
Q_PROPERTY(QString surveyComplexItemName READ surveyComplexItemName CONSTANT)
Q_PROPERTY(QString corridorScanComplexItemName READ corridorScanComplexItemName CONSTANT)
Q_PROPERTY(QString structureScanComplexItemName READ structureScanComplexItemName CONSTANT)
Q_PROPERTY(bool isInsertTakeoffValid MEMBER _isInsertTakeoffValid NOTIFY isInsertTakeoffValidChanged) ///< true: Takeoff tool should be enabled
Q_INVOKABLE void removeMissionItem(int index);
......@@ -109,6 +103,13 @@ public:
/// @return Newly created item
Q_INVOKABLE VisualMissionItem* insertSimpleMissionItem(QGeoCoordinate coordinate, int visualItemIndex, bool makeCurrentItem = false);
/// Add a new takeoff item to the list
/// @param coordinate: Coordinate for item
/// @param visualItemIndex: index to insert at, -1 for end of list
/// @param makeCurrentItem: true: Make this item the current item
/// @return Newly created item
Q_INVOKABLE VisualMissionItem* insertTakeoffItem(QGeoCoordinate coordinate, int visualItemIndex, bool makeCurrentItem = false);
/// Add a new ROI mission item to the list
/// @param coordinate: Coordinate for item
/// @param visualItemIndex: index to insert at, -1 for end of list
......@@ -191,6 +192,7 @@ public:
QString surveyComplexItemName (void) const { return patternSurveyName; }
QString corridorScanComplexItemName (void) const { return patternCorridorScanName; }
QString structureScanComplexItemName(void) const { return patternStructureScanName; }
bool isInsertTakeoffValid (void) const;
int missionItemCount (void) const { return _missionItemCount; }
int currentMissionIndex (void) const;
......@@ -242,11 +244,12 @@ signals:
void currentPlanViewItemChanged (void);
void missionBoundingCubeChanged (void);
void missionItemCountChanged (int missionItemCount);
void isInsertTakeoffValidChanged (void);
private slots:
void _newMissionItemsAvailableFromVehicle(bool removeAllRequested);
void _itemCommandChanged(void);
void _managerVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
void _managerVehicleHomePositionChanged(void);
void _inProgressChanged(bool inProgress);
void _currentMissionIndexChanged(int sequenceNumber);
void _recalcWaypointLines(void);
......@@ -316,6 +319,7 @@ private:
QGCGeoBoundingCube _travelBoundingCube;
QGeoCoordinate _takeoffCoordinate;
CoordinateVector* _splitSegment;
bool _isInsertTakeoffValid = true;
static const char* _settingsGroup;
......@@ -335,5 +339,3 @@ private:
static const int _missionFileVersion;
};
#endif
......@@ -21,8 +21,6 @@
QGC_LOGGING_CATEGORY(MissionSettingsComplexItemLog, "MissionSettingsComplexItemLog")
const char* MissionSettingsItem::jsonComplexItemTypeValue = "MissionSettings";
const char* MissionSettingsItem::_plannedHomePositionAltitudeName = "PlannedHomePositionAltitude";
QMap<QString, FactMetaData*> MissionSettingsItem::_metaDataMap;
......@@ -30,12 +28,8 @@ QMap<QString, FactMetaData*> MissionSettingsItem::_metaDataMap;
MissionSettingsItem::MissionSettingsItem(Vehicle* vehicle, bool flyView, QObject* parent)
: ComplexMissionItem (vehicle, flyView, parent)
, _plannedHomePositionAltitudeFact (0, _plannedHomePositionAltitudeName, FactMetaData::valueTypeDouble)
, _plannedHomePositionFromVehicle (false)
, _missionEndRTL (false)
, _cameraSection (vehicle)
, _speedSection (vehicle)
, _sequenceNumber (0)
, _dirty (false)
{
_editorQml = "qrc:/qml/MissionSettingsEditor.qml";
......@@ -95,7 +89,7 @@ void MissionSettingsItem::save(QJsonArray& missionItems)
appendMissionItems(items, this);
// First item show be planned home position, we are not responsible for save/load
// First item should be planned home position, we are not responsible for save/load
// Remaining items we just output as is
for (int i=1; i<items.count(); i++) {
MissionItem* item = items[i];
......@@ -222,25 +216,54 @@ void MissionSettingsItem::_setDirty(void)
setDirty(true);
}
void MissionSettingsItem::setHomePositionFromVehicle(const QGeoCoordinate& coordinate)
void MissionSettingsItem::_setCoordinateWorker(const QGeoCoordinate& coordinate)
{
_plannedHomePositionFromVehicle = true;
setCoordinate(coordinate);
if (_plannedHomePositionCoordinate != coordinate) {
_plannedHomePositionCoordinate = coordinate;
emit coordinateChanged(coordinate);
emit exitCoordinateChanged(coordinate);
_plannedHomePositionAltitudeFact.setRawValue(coordinate.altitude());
}
}
void MissionSettingsItem::setCoordinate(const QGeoCoordinate& coordinate)
void MissionSettingsItem::setHomePositionFromVehicle(Vehicle* vehicle)
{
if (_plannedHomePositionCoordinate != coordinate) {
// If the user hasn't moved the planned home position manually we use the value from the vehicle
if (!_plannedHomePositionMovedByUser) {
QGeoCoordinate coordinate = vehicle->homePosition();
// ArduPilot tends to send crap home positions at initial vehicle boot, discard them
if (coordinate.isValid() && (coordinate.latitude() != 0 || coordinate.longitude() != 0)) {
_plannedHomePositionCoordinate = coordinate;
emit coordinateChanged(coordinate);
emit exitCoordinateChanged(coordinate);
_plannedHomePositionAltitudeFact.setRawValue(coordinate.altitude());
_plannedHomePositionFromVehicle = true;
_setCoordinateWorker(coordinate);
}
}
}
void MissionSettingsItem::setInitialHomePosition(const QGeoCoordinate& coordinate)
{
_plannedHomePositionMovedByUser = false;
_plannedHomePositionFromVehicle = false;
_setCoordinateWorker(coordinate);
}
void MissionSettingsItem::setInitialHomePositionFromUser(const QGeoCoordinate& coordinate)
{
_plannedHomePositionMovedByUser = true;
_plannedHomePositionFromVehicle = false;
_setCoordinateWorker(coordinate);
}
void MissionSettingsItem::setCoordinate(const QGeoCoordinate& coordinate)
{
if (coordinate != this->coordinate()) {
// The user is moving the planned home position manually. Stop tracking vehicle home position.
_plannedHomePositionMovedByUser = true;
_plannedHomePositionFromVehicle = false;
_setCoordinateWorker(coordinate);
}
}
void MissionSettingsItem::_setDirtyAndUpdateLastSequenceNumber(void)
{
emit lastSequenceNumberChanged(lastSequenceNumber());
......@@ -301,5 +324,5 @@ void MissionSettingsItem::_setHomeAltFromTerrain(double terrainAltitude)
QString MissionSettingsItem::abbreviation(void) const
{
return _flyView ? tr("H") : tr("Planned Home");
return _flyView ? tr("H") : tr("Launch");
}
......@@ -48,8 +48,14 @@ public:
/// @return true: Mission end action was added
bool addMissionEndAction(QList<MissionItem*>& items, int seqNum, QObject* missionItemParent);
/// Called to updaet home position coordinate when it comes from a connected vehicle
void setHomePositionFromVehicle(const QGeoCoordinate& coordinate);
/// Called to update home position coordinate when it comes from a connected vehicle
void setHomePositionFromVehicle(Vehicle* vehicle);
// Called to set the initial home position. Vehicle can still update home position after this.
void setInitialHomePosition(const QGeoCoordinate& coordinate);
// Called to set the initial home position specified by user. Vehicle will no longer affect home position.
void setInitialHomePositionFromUser(const QGeoCoordinate& coordinate);
// Overrides from ComplexMissionItem
......@@ -75,7 +81,7 @@ public:
double specifiedGimbalYaw (void) final;
double specifiedGimbalPitch (void) final;
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
void applyNewAltitude (double newAltitude) final { Q_UNUSED(newAltitude); /* no action */ }
void applyNewAltitude (double /*newAltitude*/) final { /* no action */ }
double specifiedFlightSpeed (void) final;
double additionalTimeDelay (void) const final { return 0; }
......@@ -84,12 +90,10 @@ public:
bool exitCoordinateSameAsEntry (void) const final { return true; }
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final;
void setCoordinate (const QGeoCoordinate& coordinate) final; // Should only be called if the end user is moving
void setSequenceNumber (int sequenceNumber) final;
void save (QJsonArray& missionItems) final;
static const char* jsonComplexItemTypeValue;
signals:
void specifyMissionFlightSpeedChanged (bool specifyMissionFlightSpeed);
void missionEndRTLChanged (bool missionEndRTL);
......@@ -100,16 +104,17 @@ private slots:
void _sectionDirtyChanged (bool dirty);
void _updateAltitudeInCoordinate (QVariant value);
void _setHomeAltFromTerrain (double terrainAltitude);
void _setCoordinateWorker (const QGeoCoordinate& coordinate);
private:
QGeoCoordinate _plannedHomePositionCoordinate; // Does not include altitude
Fact _plannedHomePositionAltitudeFact;
bool _plannedHomePositionFromVehicle;
bool _missionEndRTL;
int _sequenceNumber = 0;
bool _plannedHomePositionFromVehicle = false;
bool _plannedHomePositionMovedByUser = false;
bool _missionEndRTL = false;
CameraSection _cameraSection;
SpeedSection _speedSection;
int _sequenceNumber;
bool _dirty;
static QMap<QString, FactMetaData*> _metaDataMap;
......
......@@ -146,37 +146,6 @@ SimpleMissionItem::SimpleMissionItem(Vehicle* vehicle, bool flyView, const Missi
setDirty(false);
}
SimpleMissionItem::SimpleMissionItem(const SimpleMissionItem& other, bool flyView, QObject* parent)
: VisualMissionItem (other, flyView, parent)
, _missionItem (other._vehicle)
, _rawEdit (false)
, _dirty (false)
, _ignoreDirtyChangeSignals (false)
, _speedSection (nullptr)
, _cameraSection (nullptr)
, _commandTree (qgcApp()->toolbox()->missionCommandTree())
, _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
, _altitudeMode (other._altitudeMode)
, _altitudeFact (0, "Altitude", FactMetaData::valueTypeDouble)
, _amslAltAboveTerrainFact (qQNaN(), "Alt above terrain", FactMetaData::valueTypeDouble)
, _param1MetaData (FactMetaData::valueTypeDouble)
, _param2MetaData (FactMetaData::valueTypeDouble)
, _param3MetaData (FactMetaData::valueTypeDouble)
, _param4MetaData (FactMetaData::valueTypeDouble)
, _syncingHeadingDegreesAndParam4 (false)
{
_editorQml = QStringLiteral("qrc:/qml/SimpleItemEditor.qml");
_altitudeFact.setRawValue(other._altitudeFact.rawValue());
_amslAltAboveTerrainFact.setRawValue(other._amslAltAboveTerrainFact.rawValue());
_setupMetaData();
_connectSignals();
_updateOptionalSections();
_rebuildFacts();
setDirty(false);
}
void SimpleMissionItem::_connectSignals(void)
{
// Connect to change signals to track dirty state
......
......@@ -26,7 +26,7 @@ class SimpleMissionItem : public VisualMissionItem
public:
SimpleMissionItem(Vehicle* vehicle, bool flyView, QObject* parent);
SimpleMissionItem(Vehicle* vehicle, bool flyView, const MissionItem& missionItem, QObject* parent);
SimpleMissionItem(const SimpleMissionItem& other, bool flyView, QObject* parent);
//SimpleMissionItem(const SimpleMissionItem& other, bool flyView, QObject* parent);
~SimpleMissionItem();
......@@ -64,7 +64,8 @@ public:
// Property accesors
QString category (void) const;
int command(void) const { return _missionItem._commandFact.cookedValue().toInt(); }
int command (void) const { return _missionItem._commandFact.cookedValue().toInt(); }
MAV_CMD mavCommand (void) const { return static_cast<MAV_CMD>(command()); }
bool friendlyEditAllowed (void) const;
bool rawEdit (void) const;
bool specifiesAltitude (void) const;
......@@ -92,14 +93,14 @@ public:
void setAzimuth (double azimuth);
void setDistance (double distance);
bool load(QTextStream &loadStream);
bool load(const QJsonObject& json, int sequenceNumber, QString& errorString);
virtual bool load(QTextStream &loadStream);
virtual bool load(const QJsonObject& json, int sequenceNumber, QString& errorString);
MissionItem& missionItem(void) { return _missionItem; }
const MissionItem& missionItem(void) const { return _missionItem; }
// Overrides from VisualMissionItem
bool dirty (void) const final { return _dirty; }
bool dirty (void) const override { return _dirty; }
bool isSimpleItem (void) const final { return true; }
bool isStandaloneCoordinate (void) const final;
bool specifiesCoordinate (void) const final;
......@@ -110,10 +111,10 @@ public:
QGeoCoordinate coordinate (void) const final { return _missionItem.coordinate(); }
QGeoCoordinate exitCoordinate (void) const final { return coordinate(); }
int sequenceNumber (void) const final { return _missionItem.sequenceNumber(); }
double specifiedFlightSpeed (void) final;
double specifiedGimbalYaw (void) final;
double specifiedGimbalPitch (void) final;
QString mapVisualQML (void) const final { return QStringLiteral("SimpleItemMapVisual.qml"); }
double specifiedFlightSpeed (void) override;
double specifiedGimbalYaw (void) override;
double specifiedGimbalPitch (void) override;
QString mapVisualQML (void) const override { return QStringLiteral("SimpleItemMapVisual.qml"); }
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
void applyNewAltitude (double newAltitude) final;
void setMissionFlightStatus (MissionController::MissionFlightStatus_t& missionFlightStatus) final;
......@@ -125,7 +126,7 @@ public:
bool exitCoordinateSameAsEntry (void) const final { return true; }
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final;
void setCoordinate (const QGeoCoordinate& coordinate) override;
void setSequenceNumber (int sequenceNumber) final;
int lastSequenceNumber (void) const final;
void save (QJsonArray& missionItems) final;
......
/****************************************************************************
*
* (c) 2009-2016 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 <QStringList>
#include <QDebug>
#include "TakeoffMissionItem.h"
#include "FirmwarePluginManager.h"
#include "QGCApplication.h"
#include "JsonHelper.h"
#include "MissionCommandTree.h"
#include "MissionCommandUIInfo.h"
#include "QGroundControlQmlGlobal.h"
#include "SettingsManager.h"
TakeoffMissionItem::TakeoffMissionItem(Vehicle* vehicle, bool flyView, MissionSettingsItem* settingsItem, QObject* parent)
: SimpleMissionItem (vehicle, flyView, parent)
, _settingsItem (settingsItem)
{
_init();
}
TakeoffMissionItem::TakeoffMissionItem(MAV_CMD takeoffCmd, Vehicle* vehicle, bool flyView, MissionSettingsItem* settingsItem, QObject* parent)
: SimpleMissionItem (vehicle, flyView, parent)
, _settingsItem (settingsItem)
{
setCommand(takeoffCmd);
_init();
}
TakeoffMissionItem::TakeoffMissionItem(const MissionItem& missionItem, Vehicle* vehicle, bool flyView, MissionSettingsItem* settingsItem, QObject* parent)
: SimpleMissionItem (vehicle, flyView, missionItem, parent)
, _settingsItem (settingsItem)
{
_init();
}
TakeoffMissionItem::~TakeoffMissionItem()
{
}
void TakeoffMissionItem::_init(void)
{
_editorQml = QStringLiteral("qrc:/qml/SimpleItemEditor.qml");
if (_settingsItem->coordinate().isValid()) {
// Either the user has set a Launch location or it came from a connected vehicle.
// Use it as starting point.
setCoordinate(_settingsItem->coordinate());
}
connect(_settingsItem, &MissionSettingsItem::coordinateChanged, this, &TakeoffMissionItem::launchCoordinateChanged);
_initLaunchTakeoffAtSameLocation();
setDirty(false);
}
void TakeoffMissionItem::setLaunchTakeoffAtSameLocation(bool launchTakeoffAtSameLocation)
{
if (launchTakeoffAtSameLocation != _launchTakeoffAtSameLocation) {
_launchTakeoffAtSameLocation = launchTakeoffAtSameLocation;
if (_launchTakeoffAtSameLocation) {
setLaunchCoordinate(coordinate());
}
emit launchTakeoffAtSameLocationChanged(_launchTakeoffAtSameLocation);
setDirty(true);
}
}
void TakeoffMissionItem::setCoordinate(const QGeoCoordinate& coordinate)
{
if (this->coordinate().isValid() || !_vehicle->fixedWing()) {
if (coordinate != this->coordinate()) {
if (_launchTakeoffAtSameLocation) {
setLaunchCoordinate(coordinate);
}
SimpleMissionItem::setCoordinate(coordinate);
}
} else {
// First time setup for fixed wing
if (!launchCoordinate().isValid()) {
setLaunchCoordinate(coordinate);
}
SimpleMissionItem::setCoordinate(launchCoordinate().atDistanceAndAzimuth(60, 0));
}
}
bool TakeoffMissionItem::isTakeoffCommand(MAV_CMD command)
{
return command == MAV_CMD_NAV_TAKEOFF || command == MAV_CMD_NAV_VTOL_TAKEOFF;
}
void TakeoffMissionItem::_initLaunchTakeoffAtSameLocation(void)
{
if (_vehicle->fixedWing()) {
setLaunchTakeoffAtSameLocation(!specifiesCoordinate());
} else {
setLaunchTakeoffAtSameLocation(coordinate().latitude() == _settingsItem->coordinate().latitude() && coordinate().longitude() == _settingsItem->coordinate().longitude());
}
}
bool TakeoffMissionItem::load(QTextStream &loadStream)
{
bool success = SimpleMissionItem::load(loadStream);
if (success) {
_initLaunchTakeoffAtSameLocation();
}
return success;
}
bool TakeoffMissionItem::load(const QJsonObject& json, int sequenceNumber, QString& errorString)
{
bool success = SimpleMissionItem::load(json, sequenceNumber, errorString);
if (success) {
_initLaunchTakeoffAtSameLocation();
}
return success;
}
/****************************************************************************
*
* (c) 2009-2016 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.
*
****************************************************************************/
#pragma once
#include "SimpleMissionItem.h"
#include "MissionSettingsItem.h"
/// Takeoff mission item is a special case of a SimpleMissionItem which supports Launch Location display/editing
/// which is tied to home position.
class TakeoffMissionItem : public SimpleMissionItem
{
Q_OBJECT
public:
TakeoffMissionItem(Vehicle* vehicle, bool flyView, MissionSettingsItem* settingsItem, QObject* parent);
TakeoffMissionItem(MAV_CMD takeoffCmd, Vehicle* vehicle, bool flyView, MissionSettingsItem* settingsItem, QObject* parent);
TakeoffMissionItem(const MissionItem& missionItem, Vehicle* vehicle, bool flyView, MissionSettingsItem* settingsItem, QObject* parent);
Q_PROPERTY(QGeoCoordinate launchCoordinate READ launchCoordinate WRITE setLaunchCoordinate NOTIFY launchCoordinateChanged)
Q_PROPERTY(bool launchTakeoffAtSameLocation READ launchTakeoffAtSameLocation WRITE setLaunchTakeoffAtSameLocation NOTIFY launchTakeoffAtSameLocationChanged)
QGeoCoordinate launchCoordinate (void) const { return _settingsItem->coordinate(); }
bool launchTakeoffAtSameLocation (void) const { return _launchTakeoffAtSameLocation; }
void setLaunchCoordinate (const QGeoCoordinate& launchCoordinate) { _settingsItem->setCoordinate(launchCoordinate); }
void setLaunchTakeoffAtSameLocation (bool launchTakeoffAtSameLocation);
static bool isTakeoffCommand(MAV_CMD command);
~TakeoffMissionItem();
// Overrides from VisualMissionItem
void setCoordinate (const QGeoCoordinate& coordinate) override;
bool isTakeoffItem (void) const final { return true; }
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(); }
QString mapVisualQML (void) const override { return QStringLiteral("TakeoffItemMapVisual.qml"); }
// Overrides from SimpleMissionItem
bool load(QTextStream &loadStream) final;
bool load(const QJsonObject& json, int sequenceNumber, QString& errorString) final;
//void setDirty(bool dirty) final;
signals:
void launchCoordinateChanged (const QGeoCoordinate& launchCoordinate);
void launchTakeoffAtSameLocationChanged (bool launchTakeoffAtSameLocation);
private:
void _init(void);
void _initLaunchTakeoffAtSameLocation(void);
MissionSettingsItem* _settingsItem;
bool _launchTakeoffAtSameLocation = true;
};
......@@ -16,6 +16,7 @@
#include "QGCApplication.h"
#include "JsonHelper.h"
#include "TerrainQuery.h"
#include "TakeoffMissionItem.h"
const char* VisualMissionItem::jsonTypeKey = "type";
const char* VisualMissionItem::jsonTypeSimpleItemValue = "SimpleItem";
......
......@@ -65,6 +65,7 @@ public:
Q_PROPERTY(bool isStandaloneCoordinate READ isStandaloneCoordinate NOTIFY isStandaloneCoordinateChanged) ///< true: Waypoint line does not go through item
Q_PROPERTY(bool specifiesAltitudeOnly READ specifiesAltitudeOnly NOTIFY specifiesAltitudeOnlyChanged) ///< true: Item has altitude only, no full coordinate
Q_PROPERTY(bool isSimpleItem READ isSimpleItem NOTIFY isSimpleItemChanged) ///< Simple or Complex MissionItem
Q_PROPERTY(bool isTakeoffItem READ isTakeoffItem NOTIFY isTakeoffItemChanged) ///< true: Takeoff item special case
Q_PROPERTY(QString editorQml MEMBER _editorQml CONSTANT) ///< Qml code for editing this item
Q_PROPERTY(QString mapVisualQML READ mapVisualQML CONSTANT) ///< QMl code for map visuals
Q_PROPERTY(QmlObjectListModel* childItems READ childItems CONSTANT)
......@@ -120,6 +121,7 @@ public:
virtual bool dirty (void) const = 0;
virtual bool isSimpleItem (void) const = 0;
virtual bool isTakeoffItem (void) const { return false; }
virtual bool isStandaloneCoordinate (void) const = 0;
virtual bool specifiesCoordinate (void) const = 0;
virtual bool specifiesAltitudeOnly (void) const = 0;
......@@ -194,6 +196,7 @@ signals:
void isCurrentItemChanged (bool isCurrentItem);
void sequenceNumberChanged (int sequenceNumber);
void isSimpleItemChanged (bool isSimpleItem);
void isTakeoffItemChanged (bool isTakeoffItem);
void specifiesCoordinateChanged (void);
void isStandaloneCoordinateChanged (void);
void specifiesAltitudeOnlyChanged (void);
......
......@@ -252,7 +252,7 @@ Rectangle {
id: commandLabel
anchors.leftMargin: ScreenTools.comboBoxPadding
anchors.fill: commandPicker
visible: !missionItem.isCurrentItem || !missionItem.isSimpleItem || _waypointsOnlyMode
visible: (!missionItem.isCurrentItem || !missionItem.isSimpleItem || _waypointsOnlyMode) && !missionItem.isTakeoffItem
verticalAlignment: Text.AlignVCenter
text: missionItem.commandName
color: _outerTextColor
......
......@@ -60,18 +60,22 @@ Item {
readonly property int _layerRallyPoints: 3
readonly property string _armedVehicleUploadPrompt: qsTr("Vehicle is currently armed. Do you want to upload the mission to the vehicle?")
function addComplexItem(complexItemName) {
function mapCenter() {
var coordinate = editorMap.center
coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
return coordinate
}
function addComplexItem(complexItemName) {
var next_index = _missionController.visualItemIndexFromSequenceNumber(_missionController.currentPlanViewIndex)+1
if(next_index ==1 && _missionController.visualItems.count >1){
console.log(next_index, _missionController.visualItems.count)
insertComplexMissionItem(complexItemName, coordinate, next_index+1)
insertComplexMissionItem(complexItemName, mapCenter(), next_index+1)
}
else if(next_index <= _missionController.visualItems.count){
insertComplexMissionItem(complexItemName, coordinate, next_index)
insertComplexMissionItem(complexItemName, mapCenter(), next_index)
}
}
......@@ -618,7 +622,13 @@ Item {
z: QGroundControl.zOrderWidgets
maxHeight: mapScale.y - toolStrip.y
property int fileButtonIndex: 1
readonly property int flyButtonIndex: 0
readonly property int fileButtonIndex: 1
readonly property int takeoffButtonIndex: 2
readonly property int waypointButtonIndex: 3
readonly property int roiButtonIndex: 4
readonly property int patternButtonIndex: 5
readonly property int centerButtonIndex: 6
property bool _isRally: _editingLayer == _layerRallyPoints
......@@ -638,6 +648,12 @@ Item {
alternateIconSource:"/qmlimages/MapSyncChanged.svg",
dropPanelComponent: syncDropPanel
},
{
name: qsTr("Takeoff"),
iconSource: "/res/takeoff.svg",
buttonEnabled: _missionController.isInsertTakeoffValid,
buttonVisible: _editingLayer == _layerMission
},
{
name: _editingLayer == _layerRallyPoints ? qsTr("Rally Point") : qsTr("Waypoint"),
iconSource: "/qmlimages/MapAddMission.svg",
......@@ -671,10 +687,13 @@ Item {
onClicked: {
switch (index) {
case 0:
case flyButtonIndex:
mainWindow.showFlyView()
break;
case 2:
break
case takeoffButtonIndex:
_missionController.insertTakeoffItem(mapCenter(), _missionController.currentMissionIndex, true /* makeCurrentItem */)
break
case waypointButtonIndex:
if(_addWaypointOnClick) {
//-- Toggle it off
_addWaypointOnClick = false
......@@ -685,11 +704,11 @@ Item {
_addROIOnClick = false
}
break
case 3:
case roiButtonIndex:
_addROIOnClick = checked
_addWaypointOnClick = false
break
case 4:
case patternButtonIndex:
if (_singleComplexItem) {
addComplexItem(_missionController.complexMissionItemNames[0])
}
......
......@@ -66,13 +66,14 @@ Rectangle {
visible: missionItem.wizardMode
QGCLabel {
text: qsTr("Adjust the initial launch location by selecting 'P' and dragging it to the correct location.")
text: qsTr("Adjust the initial launch location by dragging 'L' indicator to the desired location.")
Layout.fillWidth: true
wrapMode: Text.WordWrap
visible: !missionItem.launchTakeoffAtSameLocation
}
QGCLabel {
text: qsTr("Adjust the takeoff completion location by dragging it to the correct location.")
text: qsTr("Adjust the takeoff %1 location by dragging 'T' indicator to the desired location.").arg(missionItem.launchTakeoffAtSameLocation ? "" : qsTr("completion "))
Layout.fillWidth: true
wrapMode: Text.WordWrap
}
......
/****************************************************************************
*
* (c) 2009-2016 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.
*
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtLocation 5.3
import QtPositioning 5.3
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightMap 1.0
/// Simple Mission Item visuals
Item {
id: _root
property var map ///< Map control to place item in
property var vehicle ///< Vehicle associated with this item
property var _missionItem: object
property var _takeoffIndicatorItem
property var _launchIndicatorItem
signal clicked(int sequenceNumber)
function addCommonVisuals() {
if (_objMgrCommonVisuals.empty) {
_takeoffIndicatorItem = _objMgrCommonVisuals.createObject(takeoffIndicatorComponent, map, true /* addToMap */)
_launchIndicatorItem = _objMgrCommonVisuals.createObject(launchIndicatorComponent, map, true /* addToMap */)
}
}
function addEditingVisuals() {
if (_objMgrEditingVisuals.empty) {
_objMgrEditingVisuals.createObjects([ takeoffDragComponent, launchDragComponent ], map, false /* addToMap */)
}
}
QGCDynamicObjectManager { id: _objMgrCommonVisuals }
QGCDynamicObjectManager { id: _objMgrEditingVisuals }
Component.onCompleted: {
addCommonVisuals()
if (_missionItem.isCurrentItem && map.planView) {
addEditingVisuals()
}
}
Connections {
target: _missionItem
onIsCurrentItemChanged: {
if (_missionItem.isCurrentItem && map.planView) {
addEditingVisuals()
} else {
_objMgrEditingVisuals.destroyObjects()
}
}
}
Component {
id: takeoffDragComponent
MissionItemIndicatorDrag {
mapControl: _root.map
itemIndicator: _takeoffIndicatorItem
itemCoordinate: _missionItem.specifiesCoordinate ? _missionItem.coordinate : _missionItem.launchCoordinate
onItemCoordinateChanged: {
if (_missionItem.specifiesCoordinate) {
_missionItem.coordinate = itemCoordinate
} else {
_missionItem.launchCoordinate = itemCoordinate
}
}
}
}
Component {
id: launchDragComponent
MissionItemIndicatorDrag {
mapControl: _root.map
itemIndicator: _launchIndicatorItem
itemCoordinate: _missionItem.launchCoordinate
visible: !_missionItem.launchTakeoffAtSameLocation
onItemCoordinateChanged: _missionItem.launchCoordinate = itemCoordinate
}
}
Component {
id: takeoffIndicatorComponent
MissionItemIndicator {
coordinate: _missionItem.specifiesCoordinate ? _missionItem.coordinate : _missionItem.launchCoordinate
z: QGroundControl.zOrderMapItems
missionItem: _missionItem
sequenceNumber: _missionItem.sequenceNumber
onClicked: _root.clicked(_missionItem.sequenceNumber)
}
}
Component {
id: launchIndicatorComponent
MapQuickItem {
coordinate: _missionItem.launchCoordinate
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
visible: !_missionItem.launchTakeoffAtSameLocation
sourceItem:
MissionItemIndexLabel {
checked: _missionItem.isCurrentItem
label: qsTr("Launch")
highlightSelected: true
onClicked: _root.clicked(_missionItem.sequenceNumber)
}
}
}
}
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