Commit af4b4687 authored by Valentin Platzgummer's avatar Valentin Platzgummer

wima planer issues solve, progress indicator added

parent dfceedc3
......@@ -63,8 +63,8 @@ execute_process(
)
add_definitions(
-DQGC_APPLICATION_NAME="QGroundControl"
-DQGC_ORG_NAME="QGroundControl.org"
-DQGC_APPLICATION_NAME="QGCWima"
-DQGC_ORG_NAME="QGCWima.org"
-DQGC_ORG_DOMAIN="org.qgroundcontrol"
)
......
......@@ -2,4 +2,5 @@
<qresource prefix="/qml">
<file alias="QGroundControl/Controls/HackFileDialog.qml">src/QmlControls/HackFileDialog.qml</file>
</qresource>
<qresource prefix="/"/>
</RCC>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -29,6 +29,7 @@ DebugBuild {
DESTDIR = $${OUT_PWD}/debug
DEFINES += DEBUG
DEFINES += SNAKE_SHOW_TIME
DEFINES += DEBUG_SRTL
#DEFINES += SNAKE_DEBUG
DEFINES += SHOW_CIRCULAR_SURVEY_TIME
DEFINES += DEBUG_CIRCULAR_SURVEY
......@@ -37,7 +38,9 @@ DebugBuild {
else {
DESTDIR = $${OUT_PWD}/release
#DEFINES += ROS_BRIDGE_DEBUG
DEFINES += SNAKE_SHOW_TIME
#DEFINES += SHOW_CIRCULAR_SURVEY_TIME
#DEFINES += SNAKE_SHOW_TIME
DEFINES += DEBUG_SRTL
DEFINES += NDEBUG
}
......@@ -66,9 +69,9 @@ WindowsBuild {
# Branding
#
QGC_APP_NAME = "QGroundControl"
QGC_ORG_NAME = "QGroundControl.org"
QGC_ORG_DOMAIN = "org.qgroundcontrol"
QGC_APP_NAME = "QGCWima"
QGC_ORG_NAME = "QGCWima.org"
QGC_ORG_DOMAIN = "org.qgcwima"
QGC_APP_DESCRIPTION = "Open source ground control app provided by QGroundControl dev team"
QGC_APP_COPYRIGHT = "Copyright (C) 2017 QGroundControl Development Team. All rights reserved."
......@@ -317,9 +320,9 @@ CustomBuild {
RESOURCES += $$PWD/qgcresources.qrc
}
} else {
DEFINES += QGC_APPLICATION_NAME=\"\\\"QGroundControl\\\"\"
DEFINES += QGC_ORG_NAME=\"\\\"QGroundControl.org\\\"\"
DEFINES += QGC_ORG_DOMAIN=\"\\\"org.qgroundcontrol\\\"\"
DEFINES += QGC_APPLICATION_NAME=\"\\\"QGCWima\\\"\"
DEFINES += QGC_ORG_NAME=\"\\\"QGCWima.org\\\"\"
DEFINES += QGC_ORG_DOMAIN=\"\\\"org.qgcwima\\\"\"
RESOURCES += \
$$PWD/qgroundcontrol.qrc \
$$PWD/qgcresources.qrc
......@@ -413,9 +416,9 @@ FORMS += \
#
HEADERS += \
src/Wima/CSWorker.h \
src/Wima/CircularSurvey.h \
src/Wima/Geometry/GenericCircle.h \
src/Wima/RoutingThread.h \
src/Wima/Snake/clipper/clipper.hpp \
src/Wima/Snake/mapbox/feature.hpp \
src/Wima/Snake/mapbox/geometry.hpp \
......@@ -503,8 +506,8 @@ HEADERS += \
src/comm/ros_bridge/include/topic_subscriber.h \
src/comm/utilities.h
SOURCES += \
src/Wima/CSWorker.cpp \
src/Wima/CircularSurvey.cc \
src/Wima/RoutingThread.cpp \
src/Wima/Snake/clipper/clipper.cpp \
src/Wima/Snake/snake.cpp \
src/Wima/Geometry/GeoPoint3D.cpp \
......
......@@ -231,6 +231,7 @@
<file alias="QGroundControl/FlightDisplay/FlightDisplayWimaMenu.qml">src/FlightDisplay/FlightDisplayWimaMenu.qml</file>
<file alias="QGroundControl/Controls/CircularSurveyMapVisual.qml">src/WimaView/CircularSurveyMapVisual.qml</file>
<file alias="QGroundControl/FlightDisplay/SmallValue.qml">src/FlightDisplay/SmallValue.qml</file>
<file alias="QGroundControl/Controls/ProgressIndicator.qml">src/WimaView/ProgressIndicator.qml</file>
</qresource>
<qresource prefix="/json">
<file alias="APMMavlinkStreamRate.SettingsGroup.json">src/Settings/APMMavlinkStreamRate.SettingsGroup.json</file>
......
......@@ -247,22 +247,20 @@ FlightMap {
&& wimaController.enableSnake.value
model: _enable ? wimaController.snakeTileCenterPoints : 0
delegate: MapCircle{
center: modelData
border.color: "transparent"
border.width: 1
color: getColor(wimaController.nemoProgress[index])
radius: 0.6
opacity: 1
delegate: ProgressIndicator{
coordinate: modelData
currentValue: getProgress()
width: 10
height: 10
z: 1
function getColor(progress) {
if (progress < 50)
return "red"
if (progress < 100)
return "orange"
return "green"
function getProgress() {
var progress = wimaController.nemoProgress[index]
if (progress < 0)
progress = 0
if (progress > 100)
progress = 100
return progress
}
}
}
......
......@@ -100,5 +100,6 @@ CircularSurveyMapVisual 1.0 CircularSurveyMapVisual.qml
DragCoordinate 1.0 DragCoordinate.qml
CoordinateIndicator 1.0 CoordinateIndicator.qml
CoordinateIndicatorDrag 1.0 CoordinateIndicatorDrag.qml
ProgressIndicator 1.0 ProgressIndicator.qml
......@@ -7,79 +7,84 @@
*
****************************************************************************/
#ifndef QmlObjectListModel_H
#define QmlObjectListModel_H
#include <QAbstractListModel>
class QmlObjectListModel : public QAbstractListModel
{
class QmlObjectListModel : public QAbstractListModel {
Q_OBJECT
public:
QmlObjectListModel(QObject* parent = NULL);
QmlObjectListModel(QObject *parent = NULL);
~QmlObjectListModel();
Q_PROPERTY(int count READ count NOTIFY countChanged)
/// Returns true if any of the items in the list are dirty. Requires each object to have
/// a dirty property and dirtyChanged signal.
/// Returns true if any of the items in the list are dirty. Requires each
/// object to have a dirty property and dirtyChanged signal.
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
Q_INVOKABLE QObject* get(int index) { return _objectList[index]; }
Q_INVOKABLE QObject *get(int index) { return _objectList[index]; }
Q_INVOKABLE const QObject *get(int index) const { return _objectList[index]; }
// Property accessors
int count () const;
bool dirty () const { return _dirty; }
void setDirty (bool dirty);
void append (QObject* object);
void append (QList<QObject*> objects);
QObjectList swapObjectList (const QObjectList& newlist);
void clear ();
QObject* removeAt (int i);
QObject* removeOne (QObject* object) { return removeAt(indexOf(object)); }
void insert (int i, QObject* object);
void insert (int i, QList<QObject*> objects);
bool contains (QObject* object) { return _objectList.indexOf(object) != -1; }
int indexOf (QObject* object) { return _objectList.indexOf(object); }
QObject* operator[] (int i);
const QObject* operator[] (int i) const;
template<class T> T value (int index) const { return qobject_cast<T>(_objectList[index]); }
QList<QObject*>* objectList () { return &_objectList; }
int count() const;
bool dirty() const { return _dirty; }
void setDirty(bool dirty);
void append(QObject *object);
void append(QList<QObject *> objects);
QObjectList swapObjectList(const QObjectList &newlist);
void clear();
QObject *removeAt(int i);
QObject *removeOne(QObject *object) { return removeAt(indexOf(object)); }
void insert(int i, QObject *object);
void insert(int i, QList<QObject *> objects);
bool contains(QObject *object) { return _objectList.indexOf(object) != -1; }
int indexOf(QObject *object) { return _objectList.indexOf(object); }
QObject *operator[](int i);
const QObject *operator[](int i) const;
template <class T> T value(int index) const {
return qobject_cast<T>(_objectList[index]);
}
QList<QObject *> *objectList() { return &_objectList; }
/// Calls deleteLater on all items and this itself.
void deleteListAndContents ();
void deleteListAndContents();
/// Clears the list and calls deleteLater on each entry
void clearAndDeleteContents ();
void clearAndDeleteContents();
void beginReset () { beginResetModel(); }
void endReset () { endResetModel(); }
void beginReset() { beginResetModel(); }
void endReset() { endResetModel(); }
// Friends
friend void swap(QmlObjectListModel& list1, QmlObjectListModel& list2);
friend void swap(QmlObjectListModel &list1, QmlObjectListModel &list2);
signals:
void countChanged (int count);
void dirtyChanged (bool dirtyChanged);
void countChanged(int count);
void dirtyChanged(bool dirtyChanged);
private slots:
void _childDirtyChanged (bool dirty);
void _childDirtyChanged(bool dirty);
private:
// Overrides from QAbstractListModel
int rowCount (const QModelIndex & parent = QModelIndex()) const override;
QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override;
bool insertRows (int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool removeRows (int position, int rows, const QModelIndex &index = QModelIndex()) override;
bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index,
int role = Qt::DisplayRole) const override;
bool insertRows(int position, int rows,
const QModelIndex &index = QModelIndex()) override;
bool removeRows(int position, int rows,
const QModelIndex &index = QModelIndex()) override;
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
QHash<int, QByteArray> roleNames(void) const override;
private:
QList<QObject*> _objectList;
QList<QObject *> _objectList;
bool _dirty;
bool _skipDirtyFirstItem;
......
#include "CircularSurvey.h"
#include "CSWorker.h"
#include "RoutingThread.h"
// QGC
#include "JsonHelper.h"
#include "QGCApplication.h"
......@@ -60,7 +60,7 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
_alpha(settingsGroup, _metaDataMap[alphaName]),
_minLength(settingsGroup, _metaDataMap[minLengthName]),
_type(settingsGroup, _metaDataMap[typeName]),
_pWorker(std::make_unique<RoutingWorker>()), _needsStoring(false),
_pWorker(std::make_unique<RoutingThread>()), _needsStoring(false),
_needsReversal(false), _hidePolygon(false) {
Q_UNUSED(kmlOrShpFile)
_editorQml = "qrc:/qml/CircularSurveyItemEditor.qml";
......@@ -81,9 +81,9 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
connect(&this->_type, &Fact::rawValueChanged, this,
&CircularSurvey::_rebuildTransects);
// Connect worker.
connect(this->_pWorker.get(), &RoutingWorker::result, this,
connect(this->_pWorker.get(), &RoutingThread::result, this,
&CircularSurvey::_setTransects);
connect(this->_pWorker.get(), &RoutingWorker::calculatingChanged, this,
connect(this->_pWorker.get(), &RoutingThread::calculatingChanged, this,
&CircularSurvey::calculatingChanged);
this->_transectsDirty = false;
}
......@@ -287,7 +287,7 @@ void CircularSurvey::_appendLoadedMissionItems(QList<MissionItem *> &items,
void CircularSurvey::_buildAndAppendMissionItems(QList<MissionItem *> &items,
QObject *missionItemParent) {
if (_transectsDirty)
if (_transectsDirty || _transects.count() == 0)
return;
MissionItem *item;
......
......@@ -6,7 +6,7 @@
#include "SettingsFact.h"
#include "TransectStyleComplexItem.h"
class RoutingWorker;
class RoutingThread;
class RoutingData;
class CircularSurvey : public TransectStyleComplexItem {
......@@ -119,7 +119,7 @@ private:
SettingsFact _type;
// Worker
using PtrWorker = std::shared_ptr<RoutingWorker>;
using PtrWorker = std::shared_ptr<RoutingThread>;
PtrWorker _pWorker;
PtrRoutingData _workerOutput;
QList<QList<QGeoCoordinate>> _rawTransects;
......
#include "CSWorker.h"
#include "RoutingThread.h"
// std
#include <chrono>
// Qt
#include <QDebug>
RoutingWorker::RoutingWorker(QObject *parent)
RoutingThread::RoutingThread(QObject *parent)
: QThread(parent), _calculating(false), _stop(false), _restart(false) {
static std::once_flag flag;
......@@ -12,7 +12,7 @@ RoutingWorker::RoutingWorker(QObject *parent)
[] { qRegisterMetaType<PtrRoutingData>("PtrRoutingData"); });
}
RoutingWorker::~RoutingWorker() {
RoutingThread::~RoutingThread() {
this->_stop = true;
Lock lk(this->_mutex);
this->_restart = true;
......@@ -21,10 +21,10 @@ RoutingWorker::~RoutingWorker() {
this->wait();
}
bool RoutingWorker::calculating() { return this->_calculating; }
bool RoutingThread::calculating() { return this->_calculating; }
void RoutingWorker::route(const snake::BoostPolygon &safeArea,
const RoutingWorker::Generator &generator) {
void RoutingThread::route(const snake::BoostPolygon &safeArea,
const RoutingThread::Generator &generator) {
// Sample input.
Lock lk(this->_mutex);
this->_safeArea = safeArea;
......@@ -40,7 +40,7 @@ void RoutingWorker::route(const snake::BoostPolygon &safeArea,
}
}
void RoutingWorker::run() {
void RoutingThread::run() {
qWarning() << "RoutingWorker::run(): thread start.";
while (!this->_stop) {
#ifdef DEBUG_CIRCULAR_SURVEY
......
......@@ -20,7 +20,7 @@ struct RoutingData {
//! \brief The CSWorker class
//! \note Don't call QThread::start, QThread::quit, etc. onyl use Worker
//! members!
class RoutingWorker : public QThread {
class RoutingThread : public QThread {
Q_OBJECT
using Lock = std::unique_lock<std::mutex>;
......@@ -28,8 +28,8 @@ public:
using PtrRoutingData = QSharedPointer<RoutingData>;
using Generator = std::function<bool(snake::Transects &)>;
RoutingWorker(QObject *parent = nullptr);
~RoutingWorker() override;
RoutingThread(QObject *parent = nullptr);
~RoutingThread() override;
bool calculating();
......
......@@ -326,7 +326,7 @@ bool dijkstraAlgorithm(
return true;
}
void toDistanceMatrix(Matrix<double> &graph) {
bool toDistanceMatrix(Matrix<double> &graph) {
size_t n = graph.getN();
auto distance = [graph](size_t i, size_t j) { return graph.get(i, j); };
......@@ -338,9 +338,9 @@ void toDistanceMatrix(Matrix<double> &graph) {
if (!std::isinf(d))
continue;
path.clear();
bool ret = dijkstraAlgorithm(n, i, j, path, distance);
assert(ret);
(void)ret;
if (!dijkstraAlgorithm(n, i, j, path, distance)) {
return false;
}
// cout << "(" << i << "," << j << ") d: " << d << endl;
// cout << "Path size: " << path.size() << endl;
// for (auto idx : path)
......@@ -360,6 +360,7 @@ void toDistanceMatrix(Matrix<double> &graph) {
graph.set(j, i, d);
}
}
return true;
}
void shortestPathFromGraph(const Matrix<double> &graph, size_t startIndex,
......@@ -740,7 +741,7 @@ struct RoutingDataModel {
RoutingIndexManager::NodeIndex depot;
};
void generateRoutingModel(const BoostLineString &vertices,
bool generateRoutingModel(const BoostLineString &vertices,
const BoostPolygon &polygonOffset, size_t n0,
RoutingDataModel &dataModel, Matrix<double> &graph) {
......@@ -758,7 +759,9 @@ void generateRoutingModel(const BoostLineString &vertices,
#ifdef SNAKE_SHOW_TIME
start = std::chrono::high_resolution_clock::now();
#endif
toDistanceMatrix(distanceMatrix);
if (!toDistanceMatrix(distanceMatrix)) {
return false;
}
#ifdef SNAKE_SHOW_TIME
delta = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start);
......@@ -778,6 +781,7 @@ void generateRoutingModel(const BoostLineString &vertices,
}
dataModel.numVehicles = 1;
dataModel.depot = 0;
return true;
}
bool route(const BoostPolygon &area, const Transects &transects,
......@@ -836,7 +840,11 @@ bool route(const BoostPolygon &area, const Transects &transects,
#ifdef SNAKE_SHOW_TIME
auto start = std::chrono::high_resolution_clock::now();
#endif
generateRoutingModel(vertices, areaOffset, n0, dataModel, connectionGraph);
if (!generateRoutingModel(vertices, areaOffset, n0, dataModel,
connectionGraph)) {
errorString = "Routing model generation failed.";
return false;
}
#ifdef SNAKE_SHOW_TIME
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start);
......
......@@ -149,7 +149,7 @@ void offsetPolygon(const BoostPolygon &polygon, BoostPolygon &polygonOffset,
double offset);
void graphFromPolygon(const BoostPolygon &polygon,
const BoostLineString &vertices, Matrix<double> &graph);
void toDistanceMatrix(Matrix<double> &graph);
bool toDistanceMatrix(Matrix<double> &graph);
bool dijkstraAlgorithm(
const size_t numElements, size_t startIndex, size_t endIndex,
std::vector<size_t> &elementPath,
......
This diff is collapsed.
......@@ -270,8 +270,11 @@ void WimaController::resetPhase() {
}
void WimaController::requestSmartRTL() {
QString errorString("Smart RTL requested. ");
if (!_checkSmartRTLPreCondition(errorString)) {
#ifdef DEBUG_SRTL
qWarning() << "WimaController::requestSmartRTL() called";
#endif
QString errorString("Smart RTL requested.");
if (!_SRTLPrecondition(errorString)) {
qgcApp()->showMessage(errorString);
return;
}
......@@ -279,59 +282,85 @@ void WimaController::requestSmartRTL() {
}
bool WimaController::upload() {
auto &currentMissionItems = _defaultWM.currentMissionItems();
if (!_serviceArea.containsCoordinate(
_masterController->managerVehicle()->coordinate()) &&
currentMissionItems.count() > 0) {
auto &items = _currentWM->currentMissionItems();
if (_masterController && _masterController->managerVehicle() &&
items.count() > 0) {
if (!_joinedArea.containsCoordinate(
_masterController->managerVehicle()->coordinate())) {
emit forceUploadConfirm();
return false;
}
} else {
return forceUpload();
}
} else {
return false;
}
}
bool WimaController::forceUpload() {
auto &currentMissionItems = _defaultWM.currentMissionItems();
if (currentMissionItems.count() < 1)
auto &currentMissionItems = _currentWM->currentMissionItems();
if (currentMissionItems.count() < 1 || !_missionController ||
!_masterController) {
qWarning() << "WimaController::forceUpload(): error:";
qWarning() << "currentMissionItems.count(): "
<< currentMissionItems.count();
qWarning() << "_missionController: " << _missionController;
qWarning() << "_masterController: " << _masterController;
return false;
} else {
_missionController->removeAll();
// Set homeposition of settingsItem.
QmlObjectListModel *visuals = _missionController->visualItems();
MissionSettingsItem *settingsItem = visuals->value<MissionSettingsItem *>(0);
MissionSettingsItem *settingsItem =
visuals->value<MissionSettingsItem *>(0);
if (settingsItem == nullptr) {
Q_ASSERT(false);
qWarning("WimaController::updateCurrentMissionItems(): nullptr");
return false;
}
} else {
settingsItem->setCoordinate(_WMSettings.homePosition());
// Copy mission items to _missionController.
// Copy mission items to _missionController and send them.
for (int i = 1; i < currentMissionItems.count(); i++) {
auto *item = currentMissionItems.value<const SimpleMissionItem *>(i);
_missionController->insertSimpleMissionItem(*item, visuals->count());
}
_masterController->sendToVehicle();
return true;
}
}
}
void WimaController::removeFromVehicle() {
if (_masterController && _missionController) {
_masterController->removeAllFromVehicle();
_missionController->removeAll();
}
}
void WimaController::executeSmartRTL() {
#ifdef DEBUG_SRTL
qWarning() << "WimaController::executeSmartRTL() called";
#endif
if (_masterController && _masterController->managerVehicle()) {
forceUpload();
masterController()->managerVehicle()->startMission();
_masterController->managerVehicle()->startMission();
}
}
void WimaController::initSmartRTL() { _initSmartRTL(); }
void WimaController::initSmartRTL() {
#ifdef DEBUG_SRTL
qWarning() << "WimaController::initSmartRTL() called";
#endif
_initSmartRTL();
}
void WimaController::removeVehicleTrajectoryHistory() {
Vehicle *managerVehicle = masterController()->managerVehicle();
managerVehicle->trajectoryPoints()->clear();
if (_masterController && _masterController->managerVehicle()) {
_masterController->managerVehicle()
->trajectoryPoints()
->clearAndDeleteContents();
}
}
bool WimaController::_calcShortestPath(const QGeoCoordinate &start,
......@@ -371,8 +400,8 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
QList<const WimaAreaData *> areaList = planData->areaList();
int areaCounter = 0;
const int numAreas = 4; // extract only numAreas Areas, if there are more they
// are invalid and ignored
const int numAreas = 4; // extract only numAreas Areas, if there are more
// they are invalid and ignored
for (int i = 0; i < areaList.size(); i++) {
const WimaAreaData *areaData = areaList[i];
......@@ -586,16 +615,17 @@ void WimaController::_updateAltitude() {
}
void WimaController::_checkBatteryLevel() {
if (_missionController && _masterController &&
_masterController->managerVehicle()) {
Vehicle *managerVehicle = masterController()->managerVehicle();
WimaSettings *wimaSettings =
qgcApp()->toolbox()->settingsManager()->wimaSettings();
int batteryThreshold =
wimaSettings->lowBatteryThreshold()->rawValue().toInt();
int threshold = wimaSettings->lowBatteryThreshold()->rawValue().toInt();
bool enabled = _enableWimaController.rawValue().toBool();
unsigned int minTime =
wimaSettings->minimalRemainingMissionTime()->rawValue().toUInt();
if (managerVehicle != nullptr && enabled == true) {
if (enabled) {
Fact *battery1percentRemaining =
managerVehicle->battery1FactGroup()->getFact(
VehicleBatteryFactGroup::_percentRemainingFactName);
......@@ -603,8 +633,8 @@ void WimaController::_checkBatteryLevel() {
managerVehicle->battery2FactGroup()->getFact(
VehicleBatteryFactGroup::_percentRemainingFactName);
if (battery1percentRemaining->rawValue().toDouble() < batteryThreshold &&
battery2percentRemaining->rawValue().toDouble() < batteryThreshold) {
if (battery1percentRemaining->rawValue().toDouble() < threshold &&
battery2percentRemaining->rawValue().toDouble() < threshold) {
if (!_lowBatteryHandlingTriggered) {
_lowBatteryHandlingTriggered = true;
if (!(_missionController->remainingTime() <= minTime)) {
......@@ -615,6 +645,7 @@ void WimaController::_checkBatteryLevel() {
_lowBatteryHandlingTriggered = false;
}
}
}
}
void WimaController::_eventTimerHandler() {
......@@ -630,9 +661,8 @@ void WimaController::_eventTimerHandler() {
}
void WimaController::_smartRTLCleanUp(bool flying) {
if (!flying) { // vehicle has landed
if (!flying && _missionController) { // vehicle has landed
_switchWaypointManager(_defaultWM);
_missionController->removeAllFromVehicle();
_missionController->removeAll();
disconnect(masterController()->managerVehicle(), &Vehicle::flyingChanged,
this, &WimaController::_smartRTLCleanUp);
......@@ -657,7 +687,7 @@ void WimaController::_setPhaseDuration(double duration) {
// }
}
bool WimaController::_checkSmartRTLPreCondition(QString &errorString) {
bool WimaController::_SRTLPrecondition(QString &errorString) {
if (!_localPlanDataValid) {
errorString.append(tr("No WiMA data available. Please define at least a "
"measurement and a service area."));
......@@ -695,25 +725,28 @@ void WimaController::_switchWaypointManager(
emit waypointPathChanged();
emit currentWaypointPathChanged();
qWarning()
<< "WimaController::_switchWaypointManager: statistics update missing.";
qWarning() << "WimaController::_switchWaypointManager: statistics update "
"missing.";
}
}
void WimaController::_initSmartRTL() {
QString errorString;
static int attemptCounter = 0;
attemptCounter++;
QString errorString;
if (_checkSmartRTLPreCondition(errorString)) {
if (_SRTLPrecondition(errorString)) {
if (_missionController && _masterController &&
_masterController->managerVehicle()) {
_masterController->managerVehicle()->pauseVehicle();
connect(masterController()->managerVehicle(), &Vehicle::flyingChanged, this,
&WimaController::_smartRTLCleanUp);
connect(_masterController->managerVehicle(), &Vehicle::flyingChanged,
this, &WimaController::_smartRTLCleanUp);
if (_rtlWM.update()) { // Calculate return path.
_switchWaypointManager(_rtlWM);
removeFromVehicle();
attemptCounter = 0;
emit smartRTLPathConfirm();
return;
}
}
} else if (attemptCounter > SMART_RTL_MAX_ATTEMPTS) {
errorString.append(
......
......@@ -138,7 +138,6 @@ public:
QString nemoStatusString(void) const;
bool snakeCalcInProgress(void) const;
// Smart RTL.
bool uploadOverrideRequired(void) const;
bool vehicleHasLowBattery(void) const;
// Waypoint statistics.
......@@ -234,7 +233,7 @@ private slots:
void _setPhaseDuration(double duration);
// SMART RTL
void _checkBatteryLevel(void);
bool _checkSmartRTLPreCondition(QString &errorString);
bool _SRTLPrecondition(QString &errorString);
void _initSmartRTL();
void _smartRTLCleanUp(bool flying);
// Snake.
......
......@@ -742,12 +742,14 @@ QSharedPointer<WimaPlanData> WimaPlaner::toPlanData() {
// convert mission items to mavlink commands
QList<MissionItem *> missionItems;
if (_missionController && _missionController->visualItems()) {
int surveyIndex =
_missionController->visualItems()->indexOf(_TSComplexItem);
if (surveyIndex > 0) {
_TSComplexItem->appendMissionItems(missionItems, nullptr);
// store mavlink commands
qWarning() << "WimaPlaner";
for (auto *item : missionItems) {
qWarning() << item->coordinate();
}
}
// store mavlink commands
planData->append(missionItems);
return planData;
}
......
import QtQml 2.2
import QtQuick 2.0
import QtLocation 5.3
MapQuickItem {
id: root
width: 20
height: 20
anchorPoint.x: width/2
anchorPoint.y: height/2
property color primaryColor: "orange"
property color secondaryColor: "lightblue"
property real centerWidth: width / 2
property real centerHeight: height / 2
property real radius: Math.min(canvas.width, canvas.height) / 2
property real minimumValue: 0
property real maximumValue: 100
property real currentValue: 33
// this is the angle that splits the circle in two arcs
// first arc is drawn from 0 radians to angle radians
// second arc is angle radians to 2*PI radians
property real angle: (currentValue - minimumValue) / (maximumValue - minimumValue) * 2 * Math.PI
// we want both circle to start / end at 12 o'clock
// without this offset we would start / end at 9 o'clock
property real angleOffset: -Math.PI / 2
property string text: ""
signal clicked()
onPrimaryColorChanged: canvas.requestPaint()
onSecondaryColorChanged: canvas.requestPaint()
onMinimumValueChanged: canvas.requestPaint()
onMaximumValueChanged: canvas.requestPaint()
onCurrentValueChanged: canvas.requestPaint()
// draws two arcs (portion of a circle)
// fills the circle with a lighter secondary color
// when pressed
sourceItem: Canvas {
id: canvas
width: root.width
height: root.height
antialiasing: true
onPaint: {
var ctx = getContext("2d");
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
// fills the mouse area when pressed
// the fill color is a lighter version of the
// secondary color
if (mouseArea.pressed) {
ctx.beginPath();
ctx.lineWidth = 1;
ctx.fillStyle = Qt.lighter(root.secondaryColor, 1.25);
ctx.arc(root.centerWidth,
root.centerHeight,
root.radius,
0,
2*Math.PI);
ctx.fill();
}
// First, thinner arc
// From angle to 2*PI
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = primaryColor;
ctx.arc(root.centerWidth,
root.centerHeight,
root.radius,
angleOffset + root.angle,
angleOffset + 2*Math.PI);
ctx.stroke();
// Second, thicker arc
// From 0 to angle
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = root.secondaryColor;
ctx.arc(root.centerWidth,
root.centerHeight,
root.radius,
root.angleOffset,
root.angleOffset + root.angle);
ctx.stroke();
ctx.restore();
}
Text {
anchors.centerIn: parent
text: root.text
color: root.primaryColor
}
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: root.clicked()
onPressedChanged: canvas.requestPaint()
}
}
}
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