/*===================================================================== QGroundControl Open Source Ground Control Station (c) 2009, 2015 QGROUNDCONTROL PROJECT 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 . ======================================================================*/ #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(_missionItems->get(firstIndex)); for (int i=firstIndex; i<_missionItems->count(); i++) { MissionItem* item = qobject_cast(_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(_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(_missionItems->get(firstIndex)); currentParentItem->childItems()->clear(); for (int i=firstIndex+1; i<_missionItems->count(); i++) { MissionItem* item = qobject_cast(_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(_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(_missionItems->get(0))->setHomePositionValid(homePositionValid); emit homePositionValidChanged(_homePositionValid); }