地面站终端 App
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.

316 lines
9.2 KiB

/****************************************************************************
*
* (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.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "RallyPointController.h"
#include "RallyPoint.h"
#include "Vehicle.h"
#include "FirmwarePlugin.h"
#include "MAVLinkProtocol.h"
#include "QGCApplication.h"
#include "ParameterManager.h"
#include "JsonHelper.h"
#include "SimpleMissionItem.h"
#include "QGroundControlQmlGlobal.h"
#include "SettingsManager.h"
#ifndef __mobile__
#include "QGCFileDialog.h"
#endif
#include <QJsonDocument>
#include <QJsonArray>
QGC_LOGGING_CATEGORY(RallyPointControllerLog, "RallyPointControllerLog")
const char* RallyPointController::_jsonFileTypeValue = "RallyPoints";
const char* RallyPointController::_jsonPointsKey = "points";
RallyPointController::RallyPointController(QObject* parent)
: PlanElementController(parent)
, _dirty(false)
, _currentRallyPoint(NULL)
{
}
RallyPointController::~RallyPointController()
{
}
void RallyPointController::_activeVehicleBeingRemoved(void)
{
_activeVehicle->rallyPointManager()->disconnect(this);
_points.clearAndDeleteContents();
}
void RallyPointController::_activeVehicleSet(void)
{
RallyPointManager* rallyPointManager = _activeVehicle->rallyPointManager();
connect(rallyPointManager, &RallyPointManager::loadComplete, this, &RallyPointController::_loadComplete);
connect(rallyPointManager, &RallyPointManager::inProgressChanged, this, &RallyPointController::syncInProgressChanged);
if (!rallyPointManager->inProgress()) {
_loadComplete(rallyPointManager->points());
}
emit rallyPointsSupportedChanged(rallyPointsSupported());
}
bool RallyPointController::_loadJsonFile(QJsonDocument& jsonDoc, QString& errorString)
{
QJsonObject json = jsonDoc.object();
int fileVersion;
if (!JsonHelper::validateQGCJsonFile(json,
_jsonFileTypeValue, // expected file type
1, // minimum supported version
1, // maximum supported version
fileVersion,
errorString)) {
return false;
}
// Check for required keys
QStringList requiredKeys = { _jsonPointsKey };
if (!JsonHelper::validateRequiredKeys(json, requiredKeys, errorString)) {
return false;
}
// Load points
QList<QGeoCoordinate> rgPoints;
if (!JsonHelper::loadGeoCoordinateArray(json[_jsonPointsKey], true /* altitudeRequired */, rgPoints, errorString)) {
return false;
}
_points.clearAndDeleteContents();
QObjectList pointList;
for (int i=0; i<rgPoints.count(); i++) {
pointList.append(new RallyPoint(rgPoints[i], this));
}
_points.swapObjectList(pointList);
return true;
}
void RallyPointController::loadFromFile(const QString& filename)
{
QString errorString;
if (filename.isEmpty()) {
return;
}
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorString = file.errorString() + QStringLiteral(" ") + filename;
} else {
QJsonDocument jsonDoc;
QByteArray bytes = file.readAll();
if (JsonHelper::isJsonFile(bytes, jsonDoc)) {
_loadJsonFile(jsonDoc, errorString);
} else {
// FIXME: No MP file format support
qgcApp()->showMessage("Rall Point file is in incorrect format.");
return;
}
}
if (!errorString.isEmpty()) {
qgcApp()->showMessage(errorString);
}
setDirty(true);
_setFirstPointCurrent();
}
void RallyPointController::loadFromFilePicker(void)
{
#ifndef __mobile__
QString filename = QGCFileDialog::getOpenFileName(NULL, "Select Rally Point File to load", QString(), "Rally point file (*.rally);;All Files (*.*)");
if (filename.isEmpty()) {
return;
}
loadFromFile(filename);
#endif
}
void RallyPointController::saveToFile(const QString& filename)
{
if (filename.isEmpty()) {
return;
}
QString rallyFilename = filename;
if (!QFileInfo(filename).fileName().contains(".")) {
rallyFilename += QString(".%1").arg(QGCApplication::rallyPointFileExtension);
}
QFile file(rallyFilename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qgcApp()->showMessage(file.errorString());
} else {
QJsonObject jsonObject;
jsonObject[JsonHelper::jsonFileTypeKey] = _jsonFileTypeValue;
jsonObject[JsonHelper::jsonVersionKey] = 1;
jsonObject[JsonHelper::jsonGroundStationKey] = JsonHelper::jsonGroundStationValue;
QJsonArray rgPoints;
QJsonValue jsonPoint;
for (int i=0; i<_points.count(); i++) {
JsonHelper::saveGeoCoordinate(qobject_cast<RallyPoint*>(_points[i])->coordinate(), true /* writeAltitude */, jsonPoint);
rgPoints.append(jsonPoint);
}
jsonObject[_jsonPointsKey] = QJsonValue(rgPoints);
QJsonDocument saveDoc(jsonObject);
file.write(saveDoc.toJson());
}
setDirty(false);
}
void RallyPointController::saveToFilePicker(void)
{
#ifndef __mobile__
QString filename = QGCFileDialog::getSaveFileName(NULL, "Select file to save Rally Points to", QString(), "Rally point file (*.rally);;All Files (*.*)");
if (filename.isEmpty()) {
return;
}
saveToFile(filename);
#endif
}
void RallyPointController::removeAll(void)
{
_points.clearAndDeleteContents();
setDirty(true);
setCurrentRallyPoint(NULL);
}
void RallyPointController::loadFromVehicle(void)
{
if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) {
_activeVehicle->rallyPointManager()->loadFromVehicle();
} else {
qCWarning(RallyPointControllerLog) << "RallyPointController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress();
}
}
void RallyPointController::sendToVehicle(void)
{
if (!syncInProgress()) {
setDirty(false);
QList<QGeoCoordinate> rgPoints;
for (int i=0; i<_points.count(); i++) {
rgPoints.append(qobject_cast<RallyPoint*>(_points[i])->coordinate());
}
_activeVehicle->rallyPointManager()->sendToVehicle(rgPoints);
} else {
qCWarning(RallyPointControllerLog) << "RallyPointController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress();
}
}
bool RallyPointController::syncInProgress(void) const
{
return _activeVehicle->rallyPointManager()->inProgress();
}
void RallyPointController::setDirty(bool dirty)
{
if (dirty != _dirty) {
_dirty = dirty;
emit dirtyChanged(dirty);
}
}
QString RallyPointController::editorQml(void) const
{
return _activeVehicle->rallyPointManager()->editorQml();
}
void RallyPointController::_loadComplete(const QList<QGeoCoordinate> rgPoints)
{
_points.clearAndDeleteContents();
QObjectList pointList;
for (int i=0; i<rgPoints.count(); i++) {
pointList.append(new RallyPoint(rgPoints[i], this));
}
_points.swapObjectList(pointList);
setDirty(false);
_setFirstPointCurrent();
9 years ago
emit loadComplete();
}
QString RallyPointController::fileExtension(void) const
{
return QGCApplication::rallyPointFileExtension;
}
void RallyPointController::addPoint(QGeoCoordinate point)
{
double defaultAlt;
if (_points.count()) {
defaultAlt = qobject_cast<RallyPoint*>(_points[_points.count() - 1])->coordinate().altitude();
} else {
defaultAlt = qgcApp()->toolbox()->settingsManager()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble();
}
point.setAltitude(defaultAlt);
RallyPoint* newPoint = new RallyPoint(point, this);
_points.append(newPoint);
setCurrentRallyPoint(newPoint);
setDirty(true);
}
bool RallyPointController::rallyPointsSupported(void) const
{
return _activeVehicle->rallyPointManager()->rallyPointsSupported();
}
void RallyPointController::removePoint(QObject* rallyPoint)
{
int foundIndex = 0;
for (foundIndex=0; foundIndex<_points.count(); foundIndex++) {
if (_points[foundIndex] == rallyPoint) {
_points.removeOne(rallyPoint);
rallyPoint->deleteLater();
}
}
if (_points.count()) {
int newIndex = qMin(foundIndex, _points.count() - 1);
newIndex = qMax(newIndex, 0);
setCurrentRallyPoint(_points[newIndex]);
} else {
setCurrentRallyPoint(NULL);
}
}
void RallyPointController::setCurrentRallyPoint(QObject* rallyPoint)
{
if (_currentRallyPoint != rallyPoint) {
_currentRallyPoint = rallyPoint;
emit currentRallyPointChanged(rallyPoint);
}
}
void RallyPointController::_setFirstPointCurrent(void)
{
setCurrentRallyPoint(_points.count() ? _points[0] : NULL);
}