Commit 85009f44 authored by Don Gagne's avatar Don Gagne

Mission AutoLoad support

parent d90dd924
......@@ -214,7 +214,7 @@ void GeoFenceController::loadFromFile(const QString& filename)
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorString = file.errorString();
errorString = file.errorString() + QStringLiteral(" ") + filename;
} else {
QJsonDocument jsonDoc;
QByteArray bytes = file.readAll();
......
This diff is collapsed.
......@@ -59,6 +59,17 @@ public:
/// @return Sequence number for new item
Q_INVOKABLE int insertComplexMissionItem(QGeoCoordinate coordinate, int i);
/// Loads the mission items from the specified file
/// @param[in] vehicle Vehicle we are loading items for
/// @param[in] filename File to load from
/// @param[out] visualItems Visual items loaded, returns NULL if error
/// @param[out] complexItems Complex items loaded, returns NULL if error
/// @return success/fail
static bool loadItemsFromFile(Vehicle* vehicle, const QString& filename, QmlObjectListModel** visualItems, QmlObjectListModel** complexItems);
/// Sends the mission items to the specified vehicle
static void sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel* visualMissionItems);
// Overrides from PlanElementController
void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final;
......@@ -135,13 +146,13 @@ private:
static double _calcDistanceToHome(VisualMissionItem* currentItem, VisualMissionItem* homeItem);
bool _findLastAltitude(double* lastAltitude, MAV_FRAME* frame);
bool _findLastAcceptanceRadius(double* lastAcceptanceRadius);
void _addPlannedHomePosition(QmlObjectListModel* visualItems, bool addToCenter);
double _normalizeLat(double lat);
double _normalizeLon(double lon);
bool _loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
bool _loadJsonMissionFileV1(const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
bool _loadJsonMissionFileV2(const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
bool _loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString);
static double _normalizeLat(double lat);
static double _normalizeLon(double lon);
static void _addPlannedHomePosition(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter);
static bool _loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
static bool _loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
static bool _loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
static bool _loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString);
int _nextSequenceNumber(void);
void _setMissionDistance(double missionDistance);
void _setMissionTime(double missionTime);
......
/****************************************************************************
*
* (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.
*
****************************************************************************/
#ifndef MissionController_H
#define MissionController_H
#include "PlanElementController.h"
#include "QmlObjectListModel.h"
#include "Vehicle.h"
#include "QGCLoggingCategory.h"
#include "MavlinkQmlSingleton.h"
#include "VisualMissionItem.h"
#include <QHash>
class CoordinateVector;
Q_DECLARE_LOGGING_CATEGORY(MissionControllerLog)
typedef QPair<VisualMissionItem*,VisualMissionItem*> VisualItemPair;
typedef QHash<VisualItemPair, CoordinateVector*> CoordVectHashTable;
class MissionController : public PlanElementController
{
Q_OBJECT
public:
MissionController(QObject* parent = NULL);
~MissionController();
Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged)
Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged)
Q_PROPERTY(QmlObjectListModel* complexVisualItems READ complexVisualItems NOTIFY complexVisualItemsChanged)
Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged)
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_INVOKABLE void removeMissionItem(int index);
/// Add a new simple mission item to the list
/// @param i: index to insert at
/// @return Sequence number for new item
Q_INVOKABLE int insertSimpleMissionItem(QGeoCoordinate coordinate, int i);
/// Add a new complex mission item to the list
/// @param i: index to insert at
/// @return Sequence number for new item
Q_INVOKABLE int insertComplexMissionItem(QGeoCoordinate coordinate, int i);
// Overrides from PlanElementController
void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final;
void loadFromVehicle (void) final;
void sendToVehicle (void) final;
void loadFromFilePicker (void) final;
void loadFromFile (const QString& filename) final;
void saveToFilePicker (void) final;
void saveToFile (const QString& filename) final;
void removeAll (void) final;
bool syncInProgress (void) const final;
bool dirty (void) const final;
void setDirty (bool dirty) final;
QString fileExtension(void) const final;
// Property accessors
QGeoCoordinate plannedHomePosition (void);
QmlObjectListModel* visualItems (void) { return _visualItems; }
QmlObjectListModel* complexVisualItems (void) { return _complexItems; }
QmlObjectListModel* waypointLines (void) { return &_waypointLines; }
double missionDistance (void) const { return _missionDistance; }
double missionTime (void) const { return _missionTime; }
double missionHoverDistance (void) const { return _missionHoverDistance; }
double missionHoverTime (void) const { return _missionHoverTime; }
double missionCruiseDistance (void) const { return _missionCruiseDistance; }
double missionCruiseTime (void) const { return _missionCruiseTime; }
double missionMaxTelemetry (void) const { return _missionMaxTelemetry; }
double cruiseSpeed (void) const;
double hoverSpeed (void) const;
static void createVisualItemsFromFile(const QString& filename);
signals:
void plannedHomePositionChanged(QGeoCoordinate plannedHomePosition);
void visualItemsChanged(void);
void complexVisualItemsChanged(void);
void waypointLinesChanged(void);
void newItemsFromVehicle(void);
void missionDistanceChanged(double missionDistance);
void missionTimeChanged(void);
void missionHoverDistanceChanged(double missionHoverDistance);
void missionHoverTimeChanged(void);
void missionCruiseDistanceChanged(double missionCruiseDistance);
void missionCruiseTimeChanged(void);
void missionMaxTelemetryChanged(double missionMaxTelemetry);
void cruiseDistanceChanged(double cruiseDistance);
void hoverDistanceChanged(double hoverDistance);
void cruiseSpeedChanged(double cruiseSpeed);
void hoverSpeedChanged(double hoverSpeed);
private slots:
void _newMissionItemsAvailableFromVehicle();
void _itemCommandChanged(void);
void _activeVehicleHomePositionAvailableChanged(bool homePositionAvailable);
void _activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
void _inProgressChanged(bool inProgress);
void _currentMissionItemChanged(int sequenceNumber);
void _recalcWaypointLines(void);
void _recalcAltitudeRangeBearing(void);
void _homeCoordinateChanged(void);
private:
void _init(void);
void _recalcSequence(void);
void _recalcChildItems(void);
void _recalcAll(void);
void _initAllVisualItems(void);
void _deinitAllVisualItems(void);
void _initVisualItem(VisualMissionItem* item);
void _deinitVisualItem(VisualMissionItem* item);
void _setupActiveVehicle(Vehicle* activeVehicle, bool forceLoadFromVehicle);
static void _calcPrevWaypointValues(double homeAlt, VisualMissionItem* currentItem, VisualMissionItem* prevItem, double* azimuth, double* distance, double* altDifference);
static double _calcDistanceToHome(VisualMissionItem* currentItem, VisualMissionItem* homeItem);
bool _findLastAltitude(double* lastAltitude, MAV_FRAME* frame);
bool _findLastAcceptanceRadius(double* lastAcceptanceRadius);
void _addPlannedHomePosition(QmlObjectListModel* visualItems, bool addToCenter);
double _normalizeLat(double lat);
double _normalizeLon(double lon);
bool _loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
bool _loadJsonMissionFileV1(const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
bool _loadJsonMissionFileV2(const QJsonObject& json, QmlObjectListModel* visualItems, QmlObjectListModel* complexItems, QString& errorString);
bool _loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString);
int _nextSequenceNumber(void);
void _setMissionDistance(double missionDistance);
void _setMissionTime(double missionTime);
void _setMissionHoverDistance(double missionHoverDistance);
void _setMissionHoverTime(double missionHoverTime);
void _setMissionCruiseDistance(double missionCruiseDistance);
void _setMissionCruiseTime(double missionCruiseTime);
void _setMissionMaxTelemetry(double missionMaxTelemetry);
// Overrides from PlanElementController
void _activeVehicleBeingRemoved(void) final;
void _activeVehicleSet(void) final;
private:
QmlObjectListModel* _visualItems;
QmlObjectListModel* _complexItems;
QmlObjectListModel _waypointLines;
CoordVectHashTable _linesTable;
bool _firstItemsFromVehicle;
bool _missionItemsRequested;
bool _queuedSend;
double _missionDistance;
double _missionTime;
double _missionHoverDistance;
double _missionHoverTime;
double _missionCruiseDistance;
double _missionCruiseTime;
double _missionMaxTelemetry;
static const char* _settingsGroup;
static const char* _jsonFileTypeValue;
static const char* _jsonFirmwareTypeKey;
static const char* _jsonVehicleTypeKey;
static const char* _jsonCruiseSpeedKey;
static const char* _jsonHoverSpeedKey;
static const char* _jsonItemsKey;
static const char* _jsonPlannedHomePositionKey;
static const char* _jsonParamsKey;
// Deprecated V1 format keys
static const char* _jsonMavAutopilotKey;
static const char* _jsonComplexItemsKey;
static const int _missionFileVersion;
};
#endif
......@@ -111,7 +111,7 @@ void RallyPointController::loadFromFile(const QString& filename)
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorString = file.errorString();
errorString = file.errorString() + QStringLiteral(" ") + filename;
} else {
QJsonDocument jsonDoc;
QByteArray bytes = file.readAll();
......
......@@ -33,6 +33,7 @@ SettingsFact* QGroundControlQmlGlobal::_batteryPercentRemainingAnnounceFact =
const char* QGroundControlQmlGlobal::_virtualTabletJoystickKey = "VirtualTabletJoystick";
const char* QGroundControlQmlGlobal::_baseFontPointSizeKey = "BaseDeviceFontPointSize";
const char* QGroundControlQmlGlobal::_missionAutoLoadDirKey = "MissionAutoLoadDir";
QGroundControlQmlGlobal::QGroundControlQmlGlobal(QGCApplication* app)
: QGCTool(app)
......@@ -353,3 +354,15 @@ QMap<QString, FactMetaData*>& QGroundControlQmlGlobal::nameToMetaDataMap(void) {
return map;
}
QString QGroundControlQmlGlobal::missionAutoLoadDir(void)
{
QSettings settings;
return settings.value(_missionAutoLoadDirKey).toString();
}
void QGroundControlQmlGlobal::setMissionAutoLoadDir(const QString& missionAutoLoadDir)
{
QSettings settings;
settings.setValue(_missionAutoLoadDirKey, missionAutoLoadDir);
}
......@@ -84,6 +84,7 @@ public:
Q_PROPERTY(bool isSaveLogPromptNotArmed READ isSaveLogPromptNotArmed WRITE setIsSaveLogPromptNotArmed NOTIFY isSaveLogPromptNotArmedChanged)
Q_PROPERTY(bool virtualTabletJoystick READ virtualTabletJoystick WRITE setVirtualTabletJoystick NOTIFY virtualTabletJoystickChanged)
Q_PROPERTY(qreal baseFontPointSize READ baseFontPointSize WRITE setBaseFontPointSize NOTIFY baseFontPointSizeChanged)
Q_PROPERTY(QString missionAutoLoadDir READ missionAutoLoadDir WRITE setMissionAutoLoadDir NOTIFY missionAutoLoadDirChanged STORED false)
//-------------------------------------------------------------------------
// MavLink Protocol
......@@ -148,10 +149,10 @@ public:
Q_INVOKABLE QStringList loggingCategories(void) const { return QGCLoggingCategoryRegister::instance()->registeredCategories(); }
/// Turns on/off logging for the specified category. State is saved in app settings.
Q_INVOKABLE void setCategoryLoggingOn(const QString& category, bool enable) { QGCLoggingCategoryRegister::instance()->setCategoryLoggingOn(category, enable); };
Q_INVOKABLE void setCategoryLoggingOn(const QString& category, bool enable) { QGCLoggingCategoryRegister::instance()->setCategoryLoggingOn(category, enable); }
/// Returns true if logging is turned on for the specified category.
Q_INVOKABLE bool categoryLoggingOn(const QString& category) { return QGCLoggingCategoryRegister::instance()->categoryLoggingOn(category); };
Q_INVOKABLE bool categoryLoggingOn(const QString& category) { return QGCLoggingCategoryRegister::instance()->categoryLoggingOn(category); }
/// Updates the logging filter rules after settings have changed
Q_INVOKABLE void updateLoggingFilterRules(void) { QGCLoggingCategoryRegister::instance()->setFilterRulesFromSettings(QString()); }
......@@ -211,6 +212,9 @@ public:
QString qgcVersion(void) const { return qgcApp()->applicationVersion(); }
static QString missionAutoLoadDir(void);
static void setMissionAutoLoadDir(const QString& missionAutoLoadDir);
// Overrides from QGCTool
virtual void setToolbox(QGCToolbox* toolbox);
......@@ -226,6 +230,7 @@ signals:
void mavlinkSystemIDChanged (int id);
void flightMapPositionChanged (QGeoCoordinate flightMapPosition);
void flightMapZoomChanged (double flightMapZoom);
void missionAutoLoadDirChanged (QString missionAutoLoadDir);
private:
static SettingsFact* _createSettingsFact(const QString& name);
......@@ -261,6 +266,7 @@ private:
static const char* _virtualTabletJoystickKey;
static const char* _baseFontPointSizeKey;
static const char* _missionAutoLoadDirKey;
};
#endif
......@@ -16,6 +16,7 @@
#include "UAS.h"
#include "JoystickManager.h"
#include "MissionManager.h"
#include "MissionController.h"
#include "GeoFenceManager.h"
#include "RallyPointManager.h"
#include "CoordinateVector.h"
......@@ -153,7 +154,7 @@ Vehicle::Vehicle(LinkInterface* link,
connect(this, &Vehicle::remoteControlRSSIChanged, this, &Vehicle::_remoteControlRSSIChanged);
_commonInit();
_autopilotPlugin = _firmwarePlugin->autopilotPlugin(this);
_autopilotPlugin = _firmwarePlugin->autopilotPlugin(this);
// connect this vehicle to the follow me handle manager
connect(this, &Vehicle::flightModeChanged,qgcApp()->toolbox()->followMe(), &FollowMe::followMeHandleManager);
......@@ -294,6 +295,7 @@ void Vehicle::_commonInit(void)
connect(_missionManager, &MissionManager::error, this, &Vehicle::_missionManagerError);
_parameterManager = new ParameterManager(this);
connect(_parameterManager, &ParameterManager::parametersReadyChanged, this, &Vehicle::_parametersReady);
// GeoFenceManager needs to access ParameterManager so make sure to create after
_geoFenceManager = _firmwarePlugin->newGeoFenceManager(this);
......@@ -1518,7 +1520,18 @@ void Vehicle::_parametersReady(bool parametersReady)
{
if (parametersReady && !_missionManagerInitialRequestSent) {
_missionManagerInitialRequestSent = true;
_missionManager->requestMissionItems();
QString missionAutoLoadDirPath = QGroundControlQmlGlobal::missionAutoLoadDir();
if (missionAutoLoadDirPath.isEmpty()) {
_missionManager->requestMissionItems();
} else {
QmlObjectListModel* visualItems = NULL;
QmlObjectListModel* complexItems = NULL;
QDir missionAutoLoadDir(missionAutoLoadDirPath);
QString autoloadFilename = missionAutoLoadDir.absoluteFilePath(tr("AutoLoad%1.mission").arg(_id));
if (MissionController::loadItemsFromFile(this, autoloadFilename, &visualItems, &complexItems)) {
MissionController::sendItemsToVehicle(this, visualItems);
}
}
}
if (parametersReady) {
......@@ -2032,7 +2045,7 @@ void Vehicle::motorTest(int motor, int percent, int timeoutSecs)
void Vehicle::_newMissionItemsAvailable(void)
{
// After the initial mission request complets we ask for the geofence
// After the initial mission request completes we ask for the geofence
if (!_geoFenceManagerInitialRequestSent) {
_geoFenceManagerInitialRequestSent = true;
_geoFenceManager->loadFromVehicle();
......@@ -2041,7 +2054,7 @@ void Vehicle::_newMissionItemsAvailable(void)
void Vehicle::_newGeoFenceAvailable(void)
{
// After the initial mission request complets we ask for the geofence
// After geofence request completes we ask for the rally points
if (!_rallyPointManagerInitialRequestSent) {
_rallyPointManagerInitialRequestSent = true;
_rallyPointManager->loadFromVehicle();
......
......@@ -286,6 +286,33 @@ QGCView {
visible: QGroundControl.corePlugin.options.enableVirtualJoystick
}
//-----------------------------------------------------------------
//-- AutoLoad
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCCheckBox {
id: autoLoadCheckbox
anchors.verticalCenter: parent.verticalCenter
text: qsTr("AutoLoad mission directory:")
checked: QGroundControl.missionAutoLoadDir != ""
onClicked: {
autoLoadDir.enabled = checked
if (!checked) {
QGroundControl.missionAutoLoadDir = ""
autoLoadDir.text = ""
}
}
}
QGCTextField {
id: autoLoadDir
width: _editFieldWidth
enabled: autoLoadCheckbox.checked
anchors.verticalCenter: parent.verticalCenter
text: QGroundControl.missionAutoLoadDir
onEditingFinished: QGroundControl.missionAutoLoadDir = text
}
}
//-----------------------------------------------------------------
//-- Map Providers
Row {
/*
......
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