Commit 0245f6f7 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #3584 from NaterGator/missionperformance

Rework mission lines + various mission-related bug fixes
parents 65c163f3 d5ab9686
...@@ -67,8 +67,8 @@ FlightMap { ...@@ -67,8 +67,8 @@ FlightMap {
line.color: "red" line.color: "red"
z: QGroundControl.zOrderMapItems - 1 z: QGroundControl.zOrderMapItems - 1
path: [ path: [
{ latitude: object.coordinate1.latitude, longitude: object.coordinate1.longitude }, object.coordinate1,
{ latitude: object.coordinate2.latitude, longitude: object.coordinate2.longitude }, object.coordinate2,
] ]
} }
} }
......
...@@ -27,8 +27,8 @@ MapItemView { ...@@ -27,8 +27,8 @@ MapItemView {
z: QGroundControl.zOrderMapItems - 1 // Under item indicators z: QGroundControl.zOrderMapItems - 1 // Under item indicators
path: [ path: [
{ latitude: object.coordinate1.latitude, longitude: object.coordinate1.longitude }, object.coordinate1,
{ latitude: object.coordinate2.latitude, longitude: object.coordinate2.longitude }, object.coordinate2,
] ]
} }
} }
...@@ -81,6 +81,7 @@ QGCView { ...@@ -81,6 +81,7 @@ QGCView {
} else { } else {
controller.loadMissionFromFilePicker() controller.loadMissionFromFilePicker()
fitViewportToMissionItems() fitViewportToMissionItems()
_currentMissionItem = _visualItems.get(0)
} }
} }
...@@ -185,6 +186,7 @@ QGCView { ...@@ -185,6 +186,7 @@ QGCView {
onFilenameReturned: { onFilenameReturned: {
controller.loadMissionFromFile(filename) controller.loadMissionFromFile(filename)
fitViewportToMissionItems() fitViewportToMissionItems()
_currentMissionItem = _visualItems.get(0)
} }
} }
} }
...@@ -498,6 +500,11 @@ QGCView { ...@@ -498,6 +500,11 @@ QGCView {
controller.removeMissionItem(index) controller.removeMissionItem(index)
} }
onInsert: {
var sequenceNumber = controller.insertSimpleMissionItem(editorMap.center, insertAfterIndex)
setCurrentItem(sequenceNumber)
}
onMoveHomeToMapCenter: controller.visualItems.get(0).coordinate = editorMap.center onMoveHomeToMapCenter: controller.visualItems.get(0).coordinate = editorMap.center
Connections { Connections {
......
...@@ -86,12 +86,7 @@ MAV_AUTOPILOT MissionCommands::_firmwareTypeFromVehicle(Vehicle* vehicle) const ...@@ -86,12 +86,7 @@ MAV_AUTOPILOT MissionCommands::_firmwareTypeFromVehicle(Vehicle* vehicle) const
if (vehicle) { if (vehicle) {
return vehicle->firmwareType(); return vehicle->firmwareType();
} else { } else {
QSettings settings; return (MAV_AUTOPILOT)QGroundControlQmlGlobal::offlineEditingFirmwareType()->rawValue().toInt();
// FIXME: Hack duplicated code from QGroundControlQmlGlobal. Had to do this for now since
// QGroundControlQmlGlobal is not available from C++ side.
return (MAV_AUTOPILOT)settings.value("OfflineEditingFirmwareType", MAV_AUTOPILOT_ARDUPILOTMEGA).toInt();
} }
} }
......
...@@ -186,7 +186,7 @@ int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int i) ...@@ -186,7 +186,7 @@ int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int i)
_recalcAll(); _recalcAll();
return sequenceNumber; return newItem->sequenceNumber();
} }
int MissionController::insertComplexMissionItem(QGeoCoordinate coordinate, int i) int MissionController::insertComplexMissionItem(QGeoCoordinate coordinate, int i)
...@@ -202,7 +202,7 @@ int MissionController::insertComplexMissionItem(QGeoCoordinate coordinate, int i ...@@ -202,7 +202,7 @@ int MissionController::insertComplexMissionItem(QGeoCoordinate coordinate, int i
_recalcAll(); _recalcAll();
return sequenceNumber; return newItem->sequenceNumber();
} }
void MissionController::removeMissionItem(int index) void MissionController::removeMissionItem(int index)
...@@ -608,13 +608,98 @@ void MissionController::_recalcWaypointLines(void) ...@@ -608,13 +608,98 @@ void MissionController::_recalcWaypointLines(void)
if (!homeItem) { if (!homeItem) {
qWarning() << "Home item is not SimpleMissionItem"; qWarning() << "Home item is not SimpleMissionItem";
} else {
connect(homeItem, &VisualMissionItem::coordinateChanged, this, &MissionController::_recalcAltitudeRangeBearing);
} }
bool showHomePosition = homeItem->showHomePosition(); bool showHomePosition = homeItem->showHomePosition();
double homeAlt = homeItem->coordinate().altitude();
qCDebug(MissionControllerLog) << "_recalcWaypointLines"; qCDebug(MissionControllerLog) << "_recalcWaypointLines";
CoordVectHashTable old_table = _linesTable;
_linesTable.clear();
_waypointLines.clear();
bool linkBackToHome = false;
for (int i=1; i<_visualItems->count(); i++) {
VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
// If we still haven't found the first coordinate item and we hit a a takeoff command link back to home
if (firstCoordinateItem &&
item->isSimpleItem() &&
qobject_cast<SimpleMissionItem*>(item)->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) {
linkBackToHome = true;
}
if (item->specifiesCoordinate()) {
if (!item->isStandaloneCoordinate()) {
firstCoordinateItem = false;
VisualItemPair pair(lastCoordinateItem, item);
if (lastCoordinateItem != homeItem || (showHomePosition && linkBackToHome)) {
if (old_table.contains(pair)) {
// Do nothing, this segment already exists and is wired up
_linesTable[pair] = old_table.take(pair);
} else {
// Create a new segment and wire update notifiers
auto linevect = new CoordinateVector(lastCoordinateItem->isSimpleItem() ? lastCoordinateItem->coordinate() : lastCoordinateItem->exitCoordinate(), item->coordinate(), this);
auto originNotifier = lastCoordinateItem->isSimpleItem() ? &VisualMissionItem::coordinateChanged : &VisualMissionItem::exitCoordinateChanged,
endNotifier = &VisualMissionItem::coordinateChanged;
// Use signals/slots to update the coordinate endpoints
connect(lastCoordinateItem, originNotifier, linevect, &CoordinateVector::setCoordinate1);
connect(item, endNotifier, linevect, &CoordinateVector::setCoordinate2);
// FIXME: We should ideally have signals for 2D position change, alt change, and 3D position change
// Not optimal, but still pretty fast, do a full update of range/bearing/altitudes
connect(item, &VisualMissionItem::coordinateChanged, this, &MissionController::_recalcAltitudeRangeBearing);
_linesTable[pair] = linevect;
}
}
lastCoordinateItem = item;
}
}
}
{
// Create a temporary QObjectList and replace the model data
QObjectList objs;
objs.reserve(_linesTable.count());
foreach(CoordinateVector *vect, _linesTable.values()) {
objs.append(vect);
}
// We don't delete here because many links may still be valid
_waypointLines.swapObjectList(objs);
}
// Anything left in the old table is an obsolete line object that can go
qDeleteAll(old_table);
_recalcAltitudeRangeBearing();
emit waypointLinesChanged();
}
void MissionController::_recalcAltitudeRangeBearing()
{
if (!_visualItems->count())
return;
bool firstCoordinateItem = true;
VisualMissionItem* lastCoordinateItem = qobject_cast<VisualMissionItem*>(_visualItems->get(0));
SimpleMissionItem* homeItem = qobject_cast<SimpleMissionItem*>(lastCoordinateItem);
if (!homeItem) {
qWarning() << "Home item is not SimpleMissionItem";
}
bool showHomePosition = homeItem->showHomePosition();
qCDebug(MissionControllerLog) << "_recalcAltitudeRangeBearing";
// If home position is valid we can calculate distances between all waypoints. // If home position is valid we can calculate distances between all waypoints.
// If home position is not valid we can only calculate distances between waypoints which are // If home position is not valid we can only calculate distances between waypoints which are
// both relative altitude. // both relative altitude.
...@@ -626,11 +711,9 @@ void MissionController::_recalcWaypointLines(void) ...@@ -626,11 +711,9 @@ void MissionController::_recalcWaypointLines(void)
double minAltSeen = 0.0; double minAltSeen = 0.0;
double maxAltSeen = 0.0; double maxAltSeen = 0.0;
double homePositionAltitude = homeItem->coordinate().altitude(); const double homePositionAltitude = homeItem->coordinate().altitude();
minAltSeen = maxAltSeen = homeItem->coordinate().altitude(); minAltSeen = maxAltSeen = homeItem->coordinate().altitude();
_waypointLines.clear();
bool linkBackToHome = false; bool linkBackToHome = false;
for (int i=1; i<_visualItems->count(); i++) { for (int i=1; i<_visualItems->count(); i++) {
VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->get(i)); VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
...@@ -672,11 +755,10 @@ void MissionController::_recalcWaypointLines(void) ...@@ -672,11 +755,10 @@ void MissionController::_recalcWaypointLines(void)
// Subsequent coordinate items link to last coordinate item. If the last coordinate item // Subsequent coordinate items link to last coordinate item. If the last coordinate item
// is an invalid home position we skip the line // is an invalid home position we skip the line
_calcPrevWaypointValues(homeAlt, item, lastCoordinateItem, &azimuth, &distance, &altDifference); _calcPrevWaypointValues(homePositionAltitude, item, lastCoordinateItem, &azimuth, &distance, &altDifference);
item->setAltDifference(altDifference); item->setAltDifference(altDifference);
item->setAzimuth(azimuth); item->setAzimuth(azimuth);
item->setDistance(distance); item->setDistance(distance);
_waypointLines.append(new CoordinateVector(lastCoordinateItem->isSimpleItem() ? lastCoordinateItem->coordinate() : lastCoordinateItem->exitCoordinate(), item->coordinate()));
} }
lastCoordinateItem = item; lastCoordinateItem = item;
} }
...@@ -700,8 +782,6 @@ void MissionController::_recalcWaypointLines(void) ...@@ -700,8 +782,6 @@ void MissionController::_recalcWaypointLines(void)
} }
} }
} }
emit waypointLinesChanged();
} }
// This will update the sequence numbers to be sequential starting from 0 // This will update the sequence numbers to be sequential starting from 0
...@@ -822,7 +902,6 @@ void MissionController::_initVisualItem(VisualMissionItem* visualItem) ...@@ -822,7 +902,6 @@ void MissionController::_initVisualItem(VisualMissionItem* visualItem)
{ {
_visualItems->setDirty(false); _visualItems->setDirty(false);
connect(visualItem, &VisualMissionItem::coordinateChanged, this, &MissionController::_itemCoordinateChanged);
connect(visualItem, &VisualMissionItem::specifiesCoordinateChanged, this, &MissionController::_recalcWaypointLines); connect(visualItem, &VisualMissionItem::specifiesCoordinateChanged, this, &MissionController::_recalcWaypointLines);
connect(visualItem, &VisualMissionItem::coordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines); connect(visualItem, &VisualMissionItem::coordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines);
connect(visualItem, &VisualMissionItem::exitCoordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines); connect(visualItem, &VisualMissionItem::exitCoordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines);
...@@ -848,12 +927,6 @@ void MissionController::_deinitVisualItem(VisualMissionItem* visualItem) ...@@ -848,12 +927,6 @@ void MissionController::_deinitVisualItem(VisualMissionItem* visualItem)
disconnect(visualItem, 0, 0, 0); disconnect(visualItem, 0, 0, 0);
} }
void MissionController::_itemCoordinateChanged(const QGeoCoordinate& coordinate)
{
Q_UNUSED(coordinate);
_recalcWaypointLines();
}
void MissionController::_itemCommandChanged(void) void MissionController::_itemCommandChanged(void)
{ {
_recalcChildItems(); _recalcChildItems();
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define MissionController_H #define MissionController_H
#include <QObject> #include <QObject>
#include <QHash>
#include "QmlObjectListModel.h" #include "QmlObjectListModel.h"
#include "Vehicle.h" #include "Vehicle.h"
...@@ -19,8 +20,12 @@ ...@@ -19,8 +20,12 @@
#include "MavlinkQmlSingleton.h" #include "MavlinkQmlSingleton.h"
#include "VisualMissionItem.h" #include "VisualMissionItem.h"
class CoordinateVector;
Q_DECLARE_LOGGING_CATEGORY(MissionControllerLog) Q_DECLARE_LOGGING_CATEGORY(MissionControllerLog)
typedef QPair<VisualMissionItem*,VisualMissionItem*> VisualItemPair;
typedef QHash<VisualItemPair, CoordinateVector*> CoordVectHashTable;
class MissionController : public QObject class MissionController : public QObject
{ {
Q_OBJECT Q_OBJECT
...@@ -77,7 +82,6 @@ signals: ...@@ -77,7 +82,6 @@ signals:
private slots: private slots:
void _newMissionItemsAvailableFromVehicle(); void _newMissionItemsAvailableFromVehicle();
void _itemCoordinateChanged(const QGeoCoordinate& coordinate);
void _itemCommandChanged(void); void _itemCommandChanged(void);
void _activeVehicleChanged(Vehicle* activeVehicle); void _activeVehicleChanged(Vehicle* activeVehicle);
void _activeVehicleHomePositionAvailableChanged(bool homePositionAvailable); void _activeVehicleHomePositionAvailableChanged(bool homePositionAvailable);
...@@ -86,6 +90,7 @@ private slots: ...@@ -86,6 +90,7 @@ private slots:
void _inProgressChanged(bool inProgress); void _inProgressChanged(bool inProgress);
void _currentMissionItemChanged(int sequenceNumber); void _currentMissionItemChanged(int sequenceNumber);
void _recalcWaypointLines(void); void _recalcWaypointLines(void);
void _recalcAltitudeRangeBearing();
private: private:
void _recalcSequence(void); void _recalcSequence(void);
...@@ -97,7 +102,7 @@ private: ...@@ -97,7 +102,7 @@ private:
void _deinitVisualItem(VisualMissionItem* item); void _deinitVisualItem(VisualMissionItem* item);
void _autoSyncSend(void); void _autoSyncSend(void);
void _setupActiveVehicle(Vehicle* activeVehicle, bool forceLoadFromVehicle); void _setupActiveVehicle(Vehicle* activeVehicle, bool forceLoadFromVehicle);
void _calcPrevWaypointValues(double homeAlt, VisualMissionItem* currentItem, VisualMissionItem* prevItem, double* azimuth, double* distance, double* altDifference); static void _calcPrevWaypointValues(double homeAlt, VisualMissionItem* currentItem, VisualMissionItem* prevItem, double* azimuth, double* distance, double* altDifference);
bool _findLastAltitude(double* lastAltitude); bool _findLastAltitude(double* lastAltitude);
bool _findLastAcceptanceRadius(double* lastAcceptanceRadius); bool _findLastAcceptanceRadius(double* lastAcceptanceRadius);
void _addPlannedHomePosition(QmlObjectListModel* visualItems, bool addToCenter); void _addPlannedHomePosition(QmlObjectListModel* visualItems, bool addToCenter);
...@@ -112,6 +117,7 @@ private: ...@@ -112,6 +117,7 @@ private:
QmlObjectListModel* _visualItems; QmlObjectListModel* _visualItems;
QmlObjectListModel* _complexItems; QmlObjectListModel* _complexItems;
QmlObjectListModel _waypointLines; QmlObjectListModel _waypointLines;
CoordVectHashTable _linesTable;
Vehicle* _activeVehicle; Vehicle* _activeVehicle;
bool _autoSync; bool _autoSync;
bool _firstItemsFromVehicle; bool _firstItemsFromVehicle;
......
...@@ -593,5 +593,10 @@ void SimpleMissionItem::setCoordinate(const QGeoCoordinate& coordinate) ...@@ -593,5 +593,10 @@ void SimpleMissionItem::setCoordinate(const QGeoCoordinate& coordinate)
void SimpleMissionItem::setSequenceNumber(int sequenceNumber) void SimpleMissionItem::setSequenceNumber(int sequenceNumber)
{ {
_missionItem.setSequenceNumber(sequenceNumber); if (_missionItem.sequenceNumber() != sequenceNumber) {
_missionItem.setSequenceNumber(sequenceNumber);
emit sequenceNumberChanged(sequenceNumber);
// This is too likely to ignore
emit abbreviationChanged();
}
} }
...@@ -70,24 +70,32 @@ void VisualMissionItem::setIsCurrentItem(bool isCurrentItem) ...@@ -70,24 +70,32 @@ void VisualMissionItem::setIsCurrentItem(bool isCurrentItem)
void VisualMissionItem::setDistance(double distance) void VisualMissionItem::setDistance(double distance)
{ {
_distance = distance; if (!qFuzzyCompare(_distance, distance)) {
emit distanceChanged(_distance); _distance = distance;
emit distanceChanged(_distance);
}
} }
void VisualMissionItem::setAltDifference(double altDifference) void VisualMissionItem::setAltDifference(double altDifference)
{ {
_altDifference = altDifference; if (!qFuzzyCompare(_altDifference, altDifference)) {
emit altDifferenceChanged(_altDifference); _altDifference = altDifference;
emit altDifferenceChanged(_altDifference);
}
} }
void VisualMissionItem::setAltPercent(double altPercent) void VisualMissionItem::setAltPercent(double altPercent)
{ {
_altPercent = altPercent; if (!qFuzzyCompare(_altPercent, altPercent)) {
emit altPercentChanged(_altPercent); _altPercent = altPercent;
emit altPercentChanged(_altPercent);
}
} }
void VisualMissionItem::setAzimuth(double azimuth) void VisualMissionItem::setAzimuth(double azimuth)
{ {
_azimuth = azimuth; if (!qFuzzyCompare(_azimuth, azimuth)) {
emit azimuthChanged(_azimuth); _azimuth = azimuth;
emit azimuthChanged(_azimuth);
}
} }
...@@ -27,15 +27,24 @@ CoordinateVector::CoordinateVector(const QGeoCoordinate& coordinate1, const QGeo ...@@ -27,15 +27,24 @@ CoordinateVector::CoordinateVector(const QGeoCoordinate& coordinate1, const QGeo
} }
CoordinateVector::~CoordinateVector() void CoordinateVector::setCoordinates(const QGeoCoordinate& coordinate1, const QGeoCoordinate& coordinate2)
{ {
setCoordinate1(coordinate1);
setCoordinate2(coordinate2);
} }
void CoordinateVector::setCoordinates(const QGeoCoordinate& coordinate1, const QGeoCoordinate& coordinate2) void CoordinateVector::setCoordinate1(const QGeoCoordinate &coordinate)
{
if (_coordinate1 != coordinate) {
_coordinate1 = coordinate;
emit coordinate1Changed(_coordinate1);
}
}
void CoordinateVector::setCoordinate2(const QGeoCoordinate &coordinate)
{ {
_coordinate1 = coordinate1; if (_coordinate2 != coordinate) {
_coordinate2 = coordinate2; _coordinate2 = coordinate;
emit coordinate1Changed(_coordinate1); emit coordinate2Changed(_coordinate2);
emit coordinate2Changed(_coordinate2); }
} }
...@@ -21,12 +21,15 @@ class CoordinateVector : public QObject ...@@ -21,12 +21,15 @@ class CoordinateVector : public QObject
public: public:
CoordinateVector(QObject* parent = NULL); CoordinateVector(QObject* parent = NULL);
CoordinateVector(const QGeoCoordinate& coordinate1, const QGeoCoordinate& coordinate2, QObject* parent = NULL); CoordinateVector(const QGeoCoordinate& coordinate1, const QGeoCoordinate& coordinate2, QObject* parent = NULL);
~CoordinateVector();
Q_PROPERTY(QGeoCoordinate coordinate1 MEMBER _coordinate1 NOTIFY coordinate1Changed) Q_PROPERTY(QGeoCoordinate coordinate1 MEMBER _coordinate1 NOTIFY coordinate1Changed)
Q_PROPERTY(QGeoCoordinate coordinate2 MEMBER _coordinate2 NOTIFY coordinate2Changed) Q_PROPERTY(QGeoCoordinate coordinate2 MEMBER _coordinate2 NOTIFY coordinate2Changed)
void setCoordinates(const QGeoCoordinate& coordinate1, const QGeoCoordinate& coordinate2); void setCoordinates(const QGeoCoordinate& coordinate1, const QGeoCoordinate& coordinate2);
public slots:
void setCoordinate1(const QGeoCoordinate& coordinate);
void setCoordinate2(const QGeoCoordinate& coordinate);
signals: signals:
void coordinate1Changed(QGeoCoordinate coordinate); void coordinate1Changed(QGeoCoordinate coordinate);
......
...@@ -24,7 +24,7 @@ Rectangle { ...@@ -24,7 +24,7 @@ Rectangle {
signal clicked signal clicked
signal remove signal remove
signal insert(int i) signal insert(int insertAfterIndex)
signal moveHomeToMapCenter signal moveHomeToMapCenter
property bool _currentItem: missionItem.isCurrentItem property bool _currentItem: missionItem.isCurrentItem
......
...@@ -179,6 +179,15 @@ void QmlObjectListModel::append(QObject* object) ...@@ -179,6 +179,15 @@ void QmlObjectListModel::append(QObject* object)
insert(_objectList.count(), object); insert(_objectList.count(), object);
} }
QObjectList QmlObjectListModel::swapObjectList(QObjectList newlist)
{
QObjectList oldlist(_objectList);
beginResetModel();
_objectList = newlist;
endResetModel();
return oldlist;
}
int QmlObjectListModel::count(void) const int QmlObjectListModel::count(void) const
{ {
return rowCount(); return rowCount();
......
...@@ -37,6 +37,7 @@ public: ...@@ -37,6 +37,7 @@ public:
void setDirty(bool dirty); void setDirty(bool dirty);
void append(QObject* object); void append(QObject* object);
QObjectList swapObjectList(QObjectList newlist);
void clear(void); void clear(void);
QObject* removeAt(int i); QObject* removeAt(int i);
QObject* removeOne(QObject* object) { return removeAt(indexOf(object)); } QObject* removeOne(QObject* object) { return removeAt(indexOf(object)); }
......
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