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

189 lines
6.4 KiB

/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "MissionController.h"
#include "ScreenToolsController.h"
#include "MultiVehicleManager.h"
#include "MissionManager.h"
#include "CoordinateVector.h"
MissionController::MissionController(QObject *parent)
: QObject(parent)
, _missionItems(NULL)
, _activeVehicle(NULL)
{
MultiVehicleManager* multiVehicleMgr = MultiVehicleManager::instance();
connect(multiVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this, &MissionController::_activeVehicleChanged);
Vehicle* activeVehicle = multiVehicleMgr->activeVehicle();
if (activeVehicle) {
_activeVehicleChanged(activeVehicle);
} else {
_newMissionItemsAvailable();
}
}
MissionController::~MissionController()
{
}
void MissionController::_newMissionItemsAvailable(void)
{
if (_missionItems) {
_missionItems->deleteLater();
}
MissionManager* missionManager = NULL;
Vehicle* activeVehicle = MultiVehicleManager::instance()->activeVehicle();
if (activeVehicle) {
missionManager = activeVehicle->missionManager();
}
if (!missionManager || missionManager->inProgress()) {
_missionItems = new QmlObjectListModel(this);
} else {
_missionItems = missionManager->copyMissionItems();
}
_initAllMissionItems();
}
void MissionController::_recalcWaypointLines(void)
{
int firstIndex = _homePositionValid ? 0 : 1;
_waypointLines.clear();
if (firstIndex < _missionItems->count()) {
bool firstCoordinateItem = true;
MissionItem* lastCoordinateItem = qobject_cast<MissionItem*>(_missionItems->get(firstIndex));
for (int i=firstIndex; i<_missionItems->count(); i++) {
MissionItem* item = qobject_cast<MissionItem*>(_missionItems->get(i));
if (item->specifiesCoordinate()) {
if (firstCoordinateItem) {
if (item->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF && _homePositionValid) {
// The first coordinate we hit is a takeoff command so link back to home position if we have one
_waypointLines.append(new CoordinateVector(qobject_cast<MissionItem*>(_missionItems->get(0))->coordinate(), item->coordinate()));
} else {
// First coordiante is not a takeoff command, it does not link backwards to anything
}
firstCoordinateItem = false;
} else {
// Subsequent coordinate items link to last coordinate item
_waypointLines.append(new CoordinateVector(lastCoordinateItem->coordinate(), item->coordinate()));
}
lastCoordinateItem = item;
}
}
}
emit waypointLinesChanged();
}
// This will update the child item hierarchy
void MissionController::_recalcChildItems(void)
{
int firstIndex = _homePositionValid ? 0 : 1;
if (_missionItems->count() > firstIndex) {
MissionItem* currentParentItem = qobject_cast<MissionItem*>(_missionItems->get(firstIndex));
currentParentItem->childItems()->clear();
for (int i=firstIndex+1; i<_missionItems->count(); i++) {
MissionItem* item = qobject_cast<MissionItem*>(_missionItems->get(i));
// Set up non-coordinate item child hierarchy
if (item->specifiesCoordinate()) {
item->childItems()->clear();
currentParentItem = item;
} else {
currentParentItem->childItems()->append(item);
}
}
}
}
// This will update the sequence numbers to be sequential starting from 0
void MissionController::_recalcSequence(void)
{
for (int i=0; i<_missionItems->count(); i++) {
MissionItem* item = qobject_cast<MissionItem*>(_missionItems->get(i));
// Setup ascending sequence numbers
item->setSequenceNumber(i);
}
}
void MissionController::_recalcAll(void)
{
_recalcSequence();
_recalcChildItems();
_recalcWaypointLines();
}
/// Initializes a new set of mission items which may have come from the vehicle or have been loaded from a file
void MissionController::_initAllMissionItems(void)
{
// Add the home position item to the front
MissionItem* homeItem = new MissionItem(this);
homeItem->setHomePositionSpecialCase(true);
homeItem->setHomePositionValid(false);
homeItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_WAYPOINT);
homeItem->setLatitude(47.3769);
homeItem->setLongitude(8.549444);
_missionItems->insert(0, homeItem);
_recalcAll();
emit missionItemsChanged();
}
void MissionController::_activeVehicleChanged(Vehicle* activeVehicle)
{
if (_activeVehicle) {
MissionManager* missionManager = _activeVehicle->missionManager();
disconnect(missionManager, &MissionManager::newMissionItemsAvailable, this, &MissionController::_newMissionItemsAvailable);
_activeVehicle = NULL;
}
_activeVehicle = activeVehicle;
if (_activeVehicle) {
MissionManager* missionManager = activeVehicle->missionManager();
connect(missionManager, &MissionManager::newMissionItemsAvailable, this, &MissionController::_newMissionItemsAvailable);
_newMissionItemsAvailable();
}
}
void MissionController::setHomePositionValid(bool homePositionValid)
{
_homePositionValid = homePositionValid;
qobject_cast<MissionItem*>(_missionItems->get(0))->setHomePositionValid(homePositionValid);
emit homePositionValidChanged(_homePositionValid);
}