191 lines
6.2 KiB
C++
191 lines
6.2 KiB
C++
/****************************************************************************
|
|
*
|
|
* (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 <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, bool forLoad, QObject* parent)
|
|
: SimpleMissionItem (vehicle, flyView, forLoad, parent)
|
|
, _settingsItem (settingsItem)
|
|
{
|
|
_init(forLoad);
|
|
}
|
|
|
|
TakeoffMissionItem::TakeoffMissionItem(MAV_CMD takeoffCmd, Vehicle* vehicle, bool flyView, MissionSettingsItem* settingsItem, QObject* parent)
|
|
: SimpleMissionItem (vehicle, flyView, false /* forLoad */, parent)
|
|
, _settingsItem (settingsItem)
|
|
{
|
|
setCommand(takeoffCmd);
|
|
_init(false /* forLoad */);
|
|
}
|
|
|
|
TakeoffMissionItem::TakeoffMissionItem(const MissionItem& missionItem, Vehicle* vehicle, bool flyView, MissionSettingsItem* settingsItem, QObject* parent)
|
|
: SimpleMissionItem (vehicle, flyView, missionItem, parent)
|
|
, _settingsItem (settingsItem)
|
|
{
|
|
_init(false /* forLoad */);
|
|
_wizardMode = false;
|
|
}
|
|
|
|
TakeoffMissionItem::~TakeoffMissionItem()
|
|
{
|
|
|
|
}
|
|
|
|
void TakeoffMissionItem::_init(bool forLoad)
|
|
{
|
|
_editorQml = QStringLiteral("qrc:/qml/SimpleItemEditor.qml");
|
|
|
|
connect(_settingsItem, &MissionSettingsItem::coordinateChanged, this, &TakeoffMissionItem::launchCoordinateChanged);
|
|
|
|
if (_flyView) {
|
|
_initLaunchTakeoffAtSameLocation();
|
|
return;
|
|
}
|
|
|
|
QGeoCoordinate homePosition = _settingsItem->coordinate();
|
|
if (!homePosition.isValid()) {
|
|
Vehicle* activeVehicle = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle();
|
|
if (activeVehicle) {
|
|
homePosition = activeVehicle->homePosition();
|
|
if (homePosition.isValid()) {
|
|
_settingsItem->setCoordinate(homePosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (forLoad) {
|
|
// Load routines will set the rest up after load
|
|
return;
|
|
}
|
|
|
|
_initLaunchTakeoffAtSameLocation();
|
|
|
|
if (homePosition.isValid() && coordinate().isValid()) {
|
|
// Item already fully specified, most likely from mission load from storage
|
|
_wizardMode = false;
|
|
} else {
|
|
if (_launchTakeoffAtSameLocation && homePosition.isValid()) {
|
|
_wizardMode = false;
|
|
SimpleMissionItem::setCoordinate(homePosition);
|
|
} else {
|
|
_wizardMode = true;
|
|
}
|
|
}
|
|
|
|
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 (coordinate != this->coordinate()) {
|
|
SimpleMissionItem::setCoordinate(coordinate);
|
|
if (_launchTakeoffAtSameLocation) {
|
|
_settingsItem->setCoordinate(coordinate);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TakeoffMissionItem::isTakeoffCommand(MAV_CMD command)
|
|
{
|
|
return command == MAV_CMD_NAV_TAKEOFF || command == MAV_CMD_NAV_VTOL_TAKEOFF;
|
|
}
|
|
|
|
void TakeoffMissionItem::_initLaunchTakeoffAtSameLocation(void)
|
|
{
|
|
if (specifiesCoordinate()) {
|
|
if (_vehicle->fixedWing() || _vehicle->vtol()) {
|
|
setLaunchTakeoffAtSameLocation(false);
|
|
} else {
|
|
// PX4 specifies a coordinate for takeoff even for non fixed wing. But it makes more sense to not have a coordinate
|
|
// from and end user standpoint. So even for PX4 we try to keep launch and takeoff at the same position. Unless the
|
|
// user has moved/loaded launch at a different location than takeoff.
|
|
if (coordinate().isValid() && _settingsItem->coordinate().isValid()) {
|
|
setLaunchTakeoffAtSameLocation(coordinate().latitude() == _settingsItem->coordinate().latitude() && coordinate().longitude() == _settingsItem->coordinate().longitude());
|
|
} else {
|
|
setLaunchTakeoffAtSameLocation(true);
|
|
}
|
|
|
|
}
|
|
} else {
|
|
setLaunchTakeoffAtSameLocation(true);
|
|
}
|
|
}
|
|
|
|
bool TakeoffMissionItem::load(QTextStream &loadStream)
|
|
{
|
|
bool success = SimpleMissionItem::load(loadStream);
|
|
if (success) {
|
|
_initLaunchTakeoffAtSameLocation();
|
|
}
|
|
_wizardMode = false; // Always be off for loaded items
|
|
return success;
|
|
}
|
|
|
|
bool TakeoffMissionItem::load(const QJsonObject& json, int sequenceNumber, QString& errorString)
|
|
{
|
|
bool success = SimpleMissionItem::load(json, sequenceNumber, errorString);
|
|
if (success) {
|
|
_initLaunchTakeoffAtSameLocation();
|
|
}
|
|
_wizardMode = false; // Always be off for loaded items
|
|
return success;
|
|
}
|
|
|
|
void TakeoffMissionItem::setLaunchCoordinate(const QGeoCoordinate& launchCoordinate)
|
|
{
|
|
if (!launchCoordinate.isValid()) {
|
|
return;
|
|
}
|
|
|
|
_settingsItem->setCoordinate(launchCoordinate);
|
|
|
|
if (!coordinate().isValid()) {
|
|
QGeoCoordinate takeoffCoordinate;
|
|
if (_launchTakeoffAtSameLocation) {
|
|
takeoffCoordinate = launchCoordinate;
|
|
} else {
|
|
double altitude = this->altitude()->rawValue().toDouble();
|
|
double distance = 0.0;
|
|
|
|
if (coordinateHasRelativeAltitude()) {
|
|
// Offset for fixed wing climb out of 30 degrees
|
|
if (altitude != 0.0) {
|
|
distance = altitude / tan(qDegreesToRadians(30.0));
|
|
}
|
|
} else {
|
|
distance = altitude * 1.5;
|
|
}
|
|
takeoffCoordinate = launchCoordinate.atDistanceAndAzimuth(distance, 0);
|
|
}
|
|
SimpleMissionItem::setCoordinate(takeoffCoordinate);
|
|
}
|
|
}
|