Commit 912e993b authored by Valentin Platzgummer's avatar Valentin Platzgummer

wima planer edited

parent 6fd60bb5
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -15,7 +15,8 @@ template <> ClipperLib::cInt get<1>(ClipperLib::IntPoint &p) { return p.Y; } ...@@ -15,7 +15,8 @@ template <> ClipperLib::cInt get<1>(ClipperLib::IntPoint &p) { return p.Y; }
CSWorker::CSWorker(QObject *parent) CSWorker::CSWorker(QObject *parent)
: QThread(parent), _deltaR(2 * bu::si::meter), : QThread(parent), _deltaR(2 * bu::si::meter),
_deltaAlpha(3 * bu::degree::degree), _minLength(10 * bu::si::meter), _deltaAlpha(3 * bu::degree::degree), _minLength(10 * bu::si::meter),
_calculating(false), _stop(false), _restart(false) {} _useDepotSafeArea(false), _calculating(false), _stop(false),
_restart(false) {}
CSWorker::~CSWorker() { CSWorker::~CSWorker() {
this->_stop = true; this->_stop = true;
...@@ -34,11 +35,46 @@ void CSWorker::update(const QList<QGeoCoordinate> &polygon, ...@@ -34,11 +35,46 @@ void CSWorker::update(const QList<QGeoCoordinate> &polygon,
// Sample input. // Sample input.
Lock lk(this->_mutex); Lock lk(this->_mutex);
this->_polygon = polygon; this->_polygon = polygon;
for (auto &v : this->_polygon) {
v.setAltitude(0);
}
this->_origin = origin; this->_origin = origin;
this->_origin.setAltitude(0);
this->_deltaR = deltaR; this->_deltaR = deltaR;
this->_deltaAlpha = deltaAlpha; this->_deltaAlpha = deltaAlpha;
this->_minLength = minLength; this->_minLength = minLength;
lk.unlock(); lk.unlock();
this->_useDepotSafeArea = false;
if (!this->isRunning()) {
this->start();
} else {
Lock lk(this->_mutex);
this->_restart = true;
this->_cv.notify_one();
}
}
void CSWorker::update(const QGeoCoordinate &depot,
const QList<QGeoCoordinate> &safeArea,
const QList<QGeoCoordinate> &polygon,
const QGeoCoordinate &origin, snake::Length deltaR,
snake::Length minLength, snake::Angle deltaAlpha) {
// Sample input.
Lock lk(this->_mutex);
this->_depot = depot;
this->_safeArea = safeArea;
this->_polygon = polygon;
for (auto &v : this->_polygon) {
v.setAltitude(0);
}
this->_origin = origin;
this->_origin.setAltitude(0);
this->_deltaR = deltaR;
this->_deltaAlpha = deltaAlpha;
this->_minLength = minLength;
lk.unlock();
this->_useDepotSafeArea = true;
if (!this->isRunning()) { if (!this->isRunning()) {
this->start(); this->start();
...@@ -53,7 +89,15 @@ void CSWorker::run() { ...@@ -53,7 +89,15 @@ void CSWorker::run() {
qWarning() << "CSWorker::run(): thread start."; qWarning() << "CSWorker::run(): thread start.";
while (!this->_stop) { while (!this->_stop) {
// Copy input. // Copy input.
QGeoCoordinate depot;
QList<QGeoCoordinate> safeArea;
Lock lk(this->_mutex); Lock lk(this->_mutex);
if (this->_useDepotSafeArea) {
depot = this->_depot;
safeArea = this->_safeArea;
} else {
safeArea = this->_polygon;
}
const auto polygon = this->_polygon; const auto polygon = this->_polygon;
const auto origin = this->_origin; const auto origin = this->_origin;
const auto deltaR = this->_deltaR; const auto deltaR = this->_deltaR;
...@@ -74,11 +118,16 @@ void CSWorker::run() { ...@@ -74,11 +118,16 @@ void CSWorker::run() {
emit calculatingChanged(); emit calculatingChanged();
// Convert geo polygon to ENU polygon. // Convert geo polygon to ENU polygon.
snake::BoostPolygon polygonENU; snake::BoostPolygon polygonENU;
snake::BoostPolygon safeAreaENU;
snake::BoostPoint originENU{0, 0}; snake::BoostPoint originENU{0, 0};
snake::BoostPoint depotENU;
snake::areaToEnu(origin, polygon, polygonENU); snake::areaToEnu(origin, polygon, polygonENU);
snake::areaToEnu(origin, safeArea, safeAreaENU);
snake::toENU(origin, depot, depotENU);
std::string error; std::string error;
// Check validity. // Check validity.
if (!bg::is_valid(polygonENU, error)) { if (!bg::is_valid(polygonENU, error) ||
!bg::is_valid(safeAreaENU, error)) {
#ifdef DEBUG_CIRCULAR_SURVEY #ifdef DEBUG_CIRCULAR_SURVEY
qWarning() << "CSWorker::run(): " qWarning() << "CSWorker::run(): "
"invalid polygon."; "invalid polygon.";
...@@ -159,7 +208,9 @@ void CSWorker::run() { ...@@ -159,7 +208,9 @@ void CSWorker::run() {
} }
// Clip sectors to polygonENU. // Clip sectors to polygonENU.
ClipperLib::Path polygonClipper; ClipperLib::Path polygonClipper;
auto &outer = polygonENU.outer(); snake::BoostPolygon shrinked;
snake::offsetPolygon(polygonENU, shrinked, -0.1);
auto &outer = shrinked.outer();
polygonClipper.reserve(outer.size() - 1); polygonClipper.reserve(outer.size() - 1);
for (auto it = outer.begin(); it < outer.end() - 1; ++it) { for (auto it = outer.begin(); it < outer.end() - 1; ++it) {
auto x = ClipperLib::cInt(std::round(it->get<0>() * CLIPPER_SCALE)); auto x = ClipperLib::cInt(std::round(it->get<0>() * CLIPPER_SCALE));
...@@ -176,6 +227,9 @@ void CSWorker::run() { ...@@ -176,6 +227,9 @@ void CSWorker::run() {
// Extract transects from PolyTree and convert them to // Extract transects from PolyTree and convert them to
// BoostLineString // BoostLineString
snake::Transects transectsENU; snake::Transects transectsENU;
if (this->_useDepotSafeArea) {
transectsENU.push_back(snake::BoostLineString{depotENU});
}
for (const auto &child : transectsClipper.Childs) { for (const auto &child : transectsClipper.Childs) {
snake::BoostLineString transect; snake::BoostLineString transect;
transect.reserve(child->Contour.size()); transect.reserve(child->Contour.size());
...@@ -233,44 +287,49 @@ void CSWorker::run() { ...@@ -233,44 +287,49 @@ void CSWorker::run() {
} }
} }
// Remove short transects // Remove short transects
for (auto it = transectsENU.begin(); it < transectsENU.end();) { auto begin = this->_useDepotSafeArea ? transectsENU.begin() + 1
: transectsENU.begin();
for (auto it = begin; it < transectsENU.end();) {
if (bg::length(*it) < minLength.value()) { if (bg::length(*it) < minLength.value()) {
it = transectsENU.erase(it); it = transectsENU.erase(it);
} else { } else {
++it; ++it;
} }
} }
// Move transect with min. distance to the front.
auto minDist = std::numeric_limits<double>::max(); if (!this->_useDepotSafeArea) {
auto minIt = transectsENU.begin(); // Move transect with min. distance to the front.
bool reverse = false; auto minDist = std::numeric_limits<double>::max();
for (auto it = transectsENU.begin(); it < transectsENU.end(); ++it) { auto minIt = transectsENU.begin();
auto distFront = bg::distance(originENU, it->front()); bool reverse = false;
auto distBack = bg::distance(originENU, it->back()); for (auto it = transectsENU.begin(); it < transectsENU.end(); ++it) {
if (distFront < minDist) { auto distFront = bg::distance(originENU, it->front());
minDist = distFront; auto distBack = bg::distance(originENU, it->back());
minIt = it; if (distFront < minDist) {
reverse = false; minDist = distFront;
} minIt = it;
if (distBack < minDist) { reverse = false;
minDist = distBack; }
minIt = it; if (distBack < minDist) {
reverse = true; minDist = distBack;
minIt = it;
reverse = true;
}
} }
} // Swap and reverse (if necessary).
// Swap and reverse (if necessary). if (minIt != transectsENU.begin()) {
if (minIt != transectsENU.begin()) { auto minTransect = *minIt;
auto minTransect = *minIt; if (reverse) {
if (reverse) { snake::BoostLineString rev;
snake::BoostLineString rev; for (auto it = minTransect.end() - 1; it >= minTransect.begin();
for (auto it = minTransect.end() - 1; it >= minTransect.begin(); --it) {
--it) { rev.push_back(*it);
rev.push_back(*it); }
minTransect = rev;
} }
minTransect = rev; *minIt = *transectsENU.begin();
*transectsENU.begin() = minTransect;
} }
*minIt = *transectsENU.begin();
*transectsENU.begin() = minTransect;
} }
#ifdef SHOW_CIRCULAR_SURVEY_TIME #ifdef SHOW_CIRCULAR_SURVEY_TIME
qWarning() << "CSWorker::run(): transect gen. time: " qWarning() << "CSWorker::run(): transect gen. time: "
...@@ -305,9 +364,9 @@ void CSWorker::run() { ...@@ -305,9 +364,9 @@ void CSWorker::run() {
}; };
std::string errorString; std::string errorString;
// Route transects; // Route transects;
bool success = snake::route(polygonENU, transectsENU, transectsInfo, bool success = snake::route(safeAreaENU, transectsENU, transectsInfo,
route, stopLambda, errorString); route, stopLambda, errorString);
if (!success && !this->_restart) { if ((!success || route.size() < 3) && !this->_restart) {
#ifdef DEBUG_CIRCULAR_SURVEY #ifdef DEBUG_CIRCULAR_SURVEY
qWarning() << "CSWorker::run(): " qWarning() << "CSWorker::run(): "
"routing failed."; "routing failed.";
...@@ -318,19 +377,38 @@ void CSWorker::run() { ...@@ -318,19 +377,38 @@ void CSWorker::run() {
"restart requested."; "restart requested.";
#endif #endif
} else { } else {
// Remove return path. // Find index of first waypoint.
std::size_t idxFirst = 0;
const auto &info1 =
this->_useDepotSafeArea ? transectsInfo[1] : transectsInfo[0];
const auto &firstTransect = transectsENU[info1.index];
const auto &firstWaypoint =
info1.reversed ? firstTransect.back() : firstTransect.front();
double th = 0.001;
for (std::size_t i = 0; i < route.size(); ++i) {
auto dist = bg::distance(route[i], firstWaypoint);
if (dist < th) {
idxFirst = i;
break;
}
}
// Find index of last waypoint.
std::size_t idxLast = 0;
const auto &info = transectsInfo.back(); const auto &info = transectsInfo.back();
const auto &lastTransect = transectsENU[info.index]; const auto &lastTransect = transectsENU[info.index];
const auto &lastWaypoint = const auto &lastWaypoint =
info.reversed ? lastTransect.front() : lastTransect.back(); info.reversed ? lastTransect.front() : lastTransect.back();
auto &wp = route.back(); for (long i = route.size() - 1; i >= 0; --i) {
while (wp != lastWaypoint) { auto dist = bg::distance(route[i], lastWaypoint);
route.pop_back(); if (dist < th) {
wp = route.back(); idxLast = i;
break;
}
} }
// Convert to geo coordinates and notify main thread. // Convert to geo coordinates and notify main thread.
auto pRoute = PtrRoute(new Route()); auto pRoute = PtrRoute(new Route());
for (const auto &vertex : route) { for (std::size_t i = idxFirst; i <= idxLast; ++i) {
auto vertex = route[i];
QGeoCoordinate c; QGeoCoordinate c;
snake::fromENU(origin, vertex, c); snake::fromENU(origin, vertex, c);
pRoute->append(c); pRoute->append(c);
......
...@@ -31,6 +31,11 @@ public slots: ...@@ -31,6 +31,11 @@ public slots:
void update(const QList<QGeoCoordinate> &polygon, void update(const QList<QGeoCoordinate> &polygon,
const QGeoCoordinate &origin, snake::Length deltaR, const QGeoCoordinate &origin, snake::Length deltaR,
snake::Length minLength, snake::Angle deltaAlpha); snake::Length minLength, snake::Angle deltaAlpha);
void update(const QGeoCoordinate &depot,
const QList<QGeoCoordinate> &safeArea,
const QList<QGeoCoordinate> &polygon,
const QGeoCoordinate &origin, snake::Length deltaR,
snake::Length minLength, snake::Angle deltaAlpha);
signals: signals:
void ready(PtrRoute pTransects); void ready(PtrRoute pTransects);
...@@ -43,6 +48,8 @@ private: ...@@ -43,6 +48,8 @@ private:
mutable std::mutex _mutex; mutable std::mutex _mutex;
mutable std::condition_variable _cv; mutable std::condition_variable _cv;
// Internal data // Internal data
QGeoCoordinate _depot;
QList<QGeoCoordinate> _safeArea;
QList<QGeoCoordinate> _polygon; QList<QGeoCoordinate> _polygon;
QGeoCoordinate _origin; QGeoCoordinate _origin;
snake::Length _deltaR; snake::Length _deltaR;
...@@ -51,6 +58,7 @@ private: ...@@ -51,6 +58,7 @@ private:
std::size_t _maxWaypoints; std::size_t _maxWaypoints;
// State // State
std::atomic_bool _useDepotSafeArea;
std::atomic_bool _calculating; std::atomic_bool _calculating;
std::atomic_bool _stop; std::atomic_bool _stop;
std::atomic_bool _restart; std::atomic_bool _restart;
......
...@@ -36,8 +36,8 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView, ...@@ -36,8 +36,8 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
_deltaR(settingsGroup, _metaDataMap[deltaRName]), _deltaR(settingsGroup, _metaDataMap[deltaRName]),
_deltaAlpha(settingsGroup, _metaDataMap[deltaAlphaName]), _deltaAlpha(settingsGroup, _metaDataMap[deltaAlphaName]),
_minLength(settingsGroup, _metaDataMap[transectMinLengthName]), _minLength(settingsGroup, _metaDataMap[transectMinLengthName]),
_isInitialized(false), _pWorker(std::make_unique<CSWorker>()), _pWorker(std::make_unique<CSWorker>()), _needsStoring(false),
_needsStoring(false), _needsReversal(false) { _needsReversal(false) {
Q_UNUSED(kmlOrShpFile) Q_UNUSED(kmlOrShpFile)
_editorQml = "qrc:/qml/CircularSurveyItemEditor.qml"; _editorQml = "qrc:/qml/CircularSurveyItemEditor.qml";
...@@ -50,6 +50,10 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView, ...@@ -50,6 +50,10 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
&CircularSurvey::_rebuildTransects); &CircularSurvey::_rebuildTransects);
connect(this, &CircularSurvey::refPointChanged, this, connect(this, &CircularSurvey::refPointChanged, this,
&CircularSurvey::_rebuildTransects); &CircularSurvey::_rebuildTransects);
connect(this, &CircularSurvey::depotChanged, this,
&CircularSurvey::_rebuildTransects);
connect(this, &CircularSurvey::safeAreaChanged, this,
&CircularSurvey::_rebuildTransects);
// Connect worker. // Connect worker.
qRegisterMetaType<PtrRoute>("PtrRoute"); qRegisterMetaType<PtrRoute>("PtrRoute");
connect(this->_pWorker.get(), &CSWorker::ready, this, connect(this->_pWorker.get(), &CSWorker::ready, this,
...@@ -78,21 +82,40 @@ void CircularSurvey::setRefPoint(const QGeoCoordinate &refPt) { ...@@ -78,21 +82,40 @@ void CircularSurvey::setRefPoint(const QGeoCoordinate &refPt) {
} }
} }
void CircularSurvey::setIsInitialized(bool isInitialized) {
if (isInitialized != _isInitialized) {
_isInitialized = isInitialized;
emit isInitializedChanged();
}
}
QGeoCoordinate CircularSurvey::refPoint() const { return _referencePoint; } QGeoCoordinate CircularSurvey::refPoint() const { return _referencePoint; }
Fact *CircularSurvey::deltaR() { return &_deltaR; } Fact *CircularSurvey::deltaR() { return &_deltaR; }
Fact *CircularSurvey::deltaAlpha() { return &_deltaAlpha; } Fact *CircularSurvey::deltaAlpha() { return &_deltaAlpha; }
bool CircularSurvey::isInitialized() { return _isInitialized; } bool CircularSurvey::hidePolygon() const { return _hidePolygon; }
QGeoCoordinate CircularSurvey::depot() const { return this->_depot; }
QList<QGeoCoordinate> CircularSurvey::safeArea() const {
return this->_safeArea;
}
void CircularSurvey::setHidePolygon(bool hide) {
if (this->_hidePolygon != hide) {
this->_hidePolygon = hide;
emit hidePolygonChanged();
}
}
void CircularSurvey::setDepot(const QGeoCoordinate &depot) {
if (this->_depot != depot) {
this->_depot = depot;
emit depotChanged();
}
}
void CircularSurvey::setSafeArea(const QList<QGeoCoordinate> &safeArea) {
if (this->_safeArea != safeArea) {
this->_safeArea = safeArea;
emit safeAreaChanged();
}
}
bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber, bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber,
QString &errorString) { QString &errorString) {
...@@ -161,7 +184,6 @@ bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber, ...@@ -161,7 +184,6 @@ bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber,
_referencePoint.setLongitude(complexObject[refPointLongitudeName].toDouble()); _referencePoint.setLongitude(complexObject[refPointLongitudeName].toDouble());
_referencePoint.setLatitude(complexObject[refPointLatitudeName].toDouble()); _referencePoint.setLatitude(complexObject[refPointLatitudeName].toDouble());
_referencePoint.setAltitude(complexObject[refPointAltitudeName].toDouble()); _referencePoint.setAltitude(complexObject[refPointAltitudeName].toDouble());
setIsInitialized(true);
_ignoreRecalc = false; _ignoreRecalc = false;
...@@ -319,12 +341,21 @@ void CircularSurvey::_rebuildTransectsPhase1(void) { ...@@ -319,12 +341,21 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
} else { } else {
this->_transects.clear(); this->_transects.clear();
auto polygon = this->_surveyAreaPolygon.coordinateList(); auto polygon = this->_surveyAreaPolygon.coordinateList();
this->_pWorker->update( if (this->_depot.isValid() && this->_safeArea.size() >= 3) {
polygon, this->_referencePoint, this->_pWorker->update(
this->_deltaR.rawValue().toDouble() * bu::si::meter, this->_depot, this->_safeArea, polygon, this->_referencePoint,
this->_minLength.rawValue().toDouble() * bu::si::meter, this->_deltaR.rawValue().toDouble() * bu::si::meter,
snake::Angle(this->_deltaAlpha.rawValue().toDouble() * this->_minLength.rawValue().toDouble() * bu::si::meter,
bu::degree::degree)); snake::Angle(this->_deltaAlpha.rawValue().toDouble() *
bu::degree::degree));
} else {
this->_pWorker->update(
polygon, this->_referencePoint,
this->_deltaR.rawValue().toDouble() * bu::si::meter,
this->_minLength.rawValue().toDouble() * bu::si::meter,
snake::Angle(this->_deltaAlpha.rawValue().toDouble() *
bu::degree::degree));
}
} }
} }
...@@ -351,7 +382,9 @@ void CircularSurvey::_setTransects(CircularSurvey::PtrRoute pRoute) { ...@@ -351,7 +382,9 @@ void CircularSurvey::_setTransects(CircularSurvey::PtrRoute pRoute) {
Fact *CircularSurvey::transectMinLength() { return &_minLength; } Fact *CircularSurvey::transectMinLength() { return &_minLength; }
bool CircularSurvey::calculating() { return this->_pWorker->calculating(); } bool CircularSurvey::calculating() const {
return this->_pWorker->calculating();
}
/*! /*!
\class CircularSurveyComplexItem \class CircularSurveyComplexItem
......
...@@ -28,48 +28,43 @@ public: ...@@ -28,48 +28,43 @@ public:
Q_PROPERTY(Fact *deltaR READ deltaR CONSTANT) Q_PROPERTY(Fact *deltaR READ deltaR CONSTANT)
Q_PROPERTY(Fact *deltaAlpha READ deltaAlpha CONSTANT) Q_PROPERTY(Fact *deltaAlpha READ deltaAlpha CONSTANT)
Q_PROPERTY(Fact *transectMinLength READ transectMinLength CONSTANT) Q_PROPERTY(Fact *transectMinLength READ transectMinLength CONSTANT)
Q_PROPERTY(bool isInitialized READ isInitialized WRITE setIsInitialized NOTIFY
isInitializedChanged)
Q_PROPERTY(bool calculating READ calculating NOTIFY calculatingChanged) Q_PROPERTY(bool calculating READ calculating NOTIFY calculatingChanged)
Q_PROPERTY(bool hidePolygon READ hidePolygon NOTIFY hidePolygon)
Q_INVOKABLE void resetReference(void); Q_INVOKABLE void resetReference(void);
Q_INVOKABLE void reverse(void); Q_INVOKABLE void reverse(void);
// Property setters // Property setters
void setRefPoint(const QGeoCoordinate &refPt); void setRefPoint(const QGeoCoordinate &refPt);
// Set this to true if survey was automatically generated, prevents void setHidePolygon(bool hide);
// initialisation from gui. void setDepot(const QGeoCoordinate &depot);
void setIsInitialized(bool isInitialized); void setSafeArea(const QList<QGeoCoordinate> &safeArea);
// Property getters // Property getters
QGeoCoordinate refPoint() const; QGeoCoordinate refPoint() const;
Fact *deltaR(); Fact *deltaR();
Fact *deltaAlpha(); Fact *deltaAlpha();
Fact *transectMinLength(); Fact *transectMinLength();
bool calculating(); bool calculating() const;
// Is true if survey was automatically generated, prevents initialisation from bool hidePolygon() const;
// gui. QGeoCoordinate depot() const;
bool isInitialized(); QList<QGeoCoordinate> safeArea() const;
// Overrides from ComplexMissionItem // Overrides
bool load(const QJsonObject &complexObject, int sequenceNumber, bool load(const QJsonObject &complexObject, int sequenceNumber,
QString &errorString) final; QString &errorString) override final;
QString mapVisualQML(void) const final; QString mapVisualQML(void) const override final;
void save(QJsonArray &planItems) override final;
// Overrides from TransectStyleComplexItem bool specifiesCoordinate(void) const override final;
void save(QJsonArray &planItems) final;
bool specifiesCoordinate(void) const final;
void appendMissionItems(QList<MissionItem *> &items, void appendMissionItems(QList<MissionItem *> &items,
QObject *missionItemParent) final; QObject *missionItemParent) override final;
void applyNewAltitude(double newAltitude) final; void applyNewAltitude(double newAltitude) override final;
double timeBetweenShots(void) final; double timeBetweenShots(void) override final;
QString commandDescription(void) const override final;
// Overrides from VisualMissionionItem QString commandName(void) const override final;
QString commandDescription(void) const final; QString abbreviation(void) const override final;
QString commandName(void) const final; bool readyForSave(void) const override final;
QString abbreviation(void) const final; double additionalTimeDelay(void) const override final;
bool readyForSave(void) const final;
double additionalTimeDelay(void) const final;
static const char *settingsGroup; static const char *settingsGroup;
static const char *deltaRName; static const char *deltaRName;
...@@ -82,8 +77,10 @@ public: ...@@ -82,8 +77,10 @@ public:
signals: signals:
void refPointChanged(); void refPointChanged();
void isInitializedChanged();
void calculatingChanged(); void calculatingChanged();
void hidePolygonChanged();
void depotChanged();
void safeAreaChanged();
private slots: private slots:
// Overrides from TransectStyleComplexItem // Overrides from TransectStyleComplexItem
...@@ -109,14 +106,14 @@ private: ...@@ -109,14 +106,14 @@ private:
// minimal transect lenght, transects are rejected if they are shorter than // minimal transect lenght, transects are rejected if they are shorter than
// this value // this value
SettingsFact _minLength; SettingsFact _minLength;
// indicates if the polygon and refpoint etc. are initialized, prevents
// reinitialisation from gui and execution of _rebuildTransectsPhase1 during
// init from gui
bool _isInitialized;
using PtrWorker = std::shared_ptr<CSWorker>; using PtrWorker = std::shared_ptr<CSWorker>;
PtrWorker _pWorker; PtrWorker _pWorker;
PtrRoute _pRoute; PtrRoute _pRoute;
bool _needsStoring; bool _needsStoring;
bool _needsReversal; bool _needsReversal;
bool _hidePolygon;
QGeoCoordinate _depot;
QList<QGeoCoordinate> _safeArea;
}; };
...@@ -135,14 +135,14 @@ bool WimaMeasurementArea::loadFromJson(const QJsonObject &json, ...@@ -135,14 +135,14 @@ bool WimaMeasurementArea::loadFromJson(const QJsonObject &json,
} }
if (json.contains(tileWidthName) && json[tileWidthName].isDouble()) { if (json.contains(tileWidthName) && json[tileWidthName].isDouble()) {
_tileHeight.setRawValue(json[tileWidthName].toDouble()); _tileWidth.setRawValue(json[tileWidthName].toDouble());
} else { } else {
errorString.append(tr("Could not load tile width!\n")); errorString.append(tr("Could not load tile width!\n"));
retVal = false; retVal = false;
} }
if (json.contains(minTileAreaName) && json[minTileAreaName].isDouble()) { if (json.contains(minTileAreaName) && json[minTileAreaName].isDouble()) {
_tileHeight.setRawValue(json[minTileAreaName].toDouble()); _minTileArea.setRawValue(json[minTileAreaName].toDouble());
} else { } else {
errorString.append(tr("Could not load minimal tile area!\n")); errorString.append(tr("Could not load minimal tile area!\n"));
retVal = false; retVal = false;
...@@ -150,7 +150,7 @@ bool WimaMeasurementArea::loadFromJson(const QJsonObject &json, ...@@ -150,7 +150,7 @@ bool WimaMeasurementArea::loadFromJson(const QJsonObject &json,
if (json.contains(transectDistanceName) && if (json.contains(transectDistanceName) &&
json[transectDistanceName].isDouble()) { json[transectDistanceName].isDouble()) {
_tileHeight.setRawValue(json[transectDistanceName].toDouble()); _transectDistance.setRawValue(json[transectDistanceName].toDouble());
} else { } else {
errorString.append(tr("Could not load transect distance!\n")); errorString.append(tr("Could not load transect distance!\n"));
retVal = false; retVal = false;
...@@ -158,14 +158,14 @@ bool WimaMeasurementArea::loadFromJson(const QJsonObject &json, ...@@ -158,14 +158,14 @@ bool WimaMeasurementArea::loadFromJson(const QJsonObject &json,
if (json.contains(minTransectLengthName) && if (json.contains(minTransectLengthName) &&
json[minTransectLengthName].isDouble()) { json[minTransectLengthName].isDouble()) {
_tileHeight.setRawValue(json[minTransectLengthName].toDouble()); _minTransectLength.setRawValue(json[minTransectLengthName].toDouble());
} else { } else {
errorString.append(tr("Could not load minimal transect length!\n")); errorString.append(tr("Could not load minimal transect length!\n"));
retVal = false; retVal = false;
} }
if (json.contains(showTilesName) && json[showTilesName].isBool()) { if (json.contains(showTilesName) && json[showTilesName].isBool()) {
_tileHeight.setRawValue(json[showTilesName].toDouble()); _showTiles.setRawValue(json[showTilesName].toBool());
} else { } else {
errorString.append(tr("Could not load show tiles !\n")); errorString.append(tr("Could not load show tiles !\n"));
retVal = false; retVal = false;
......
#include "WimaServiceArea.h" #include "WimaServiceArea.h"
const char* WimaServiceArea::wimaServiceAreaName = "Service Area"; const char *WimaServiceArea::wimaServiceAreaName = "Service Area";
WimaServiceArea::WimaServiceArea(QObject *parent) : WimaArea(parent) { init(); }
WimaServiceArea::WimaServiceArea(QObject *parent)
: WimaArea (parent)
{
init();
}
WimaServiceArea::WimaServiceArea(const WimaServiceArea &other, QObject *parent) WimaServiceArea::WimaServiceArea(const WimaServiceArea &other, QObject *parent)
: WimaArea (other, parent) : WimaArea(other, parent) {
{ init();
init();
} }
/*! /*!
...@@ -21,63 +14,53 @@ WimaServiceArea::WimaServiceArea(const WimaServiceArea &other, QObject *parent) ...@@ -21,63 +14,53 @@ WimaServiceArea::WimaServiceArea(const WimaServiceArea &other, QObject *parent)
* *
* Calls the inherited operator WimaArea::operator=(). * Calls the inherited operator WimaArea::operator=().
*/ */
WimaServiceArea &WimaServiceArea::operator=(const WimaServiceArea &other) WimaServiceArea &WimaServiceArea::operator=(const WimaServiceArea &other) {
{ WimaArea::operator=(other);
WimaArea::operator=(other);
return *this;
}
void WimaServiceArea::setTakeOffPosition(const QGeoCoordinate &coordinate) return *this;
{
if(_takeOffPosition != coordinate){
_takeOffPosition = coordinate;
emit takeOffPositionChanged();
}
} }
void WimaServiceArea::setLandPosition(const QGeoCoordinate &coordinate) void WimaServiceArea::setDepot(const QGeoCoordinate &coordinate) {
{ if (_depot != coordinate) {
if(_landPosition != coordinate){ _depot = coordinate;
_landPosition = coordinate; emit depotChanged();
emit landPositionChanged(); }
}
} }
void WimaServiceArea::saveToJson(QJsonObject &json) void WimaServiceArea::saveToJson(QJsonObject &json) {
{ this->WimaArea::saveToJson(json);
this->WimaArea::saveToJson(json); json[areaTypeName] = wimaServiceAreaName;
json[areaTypeName] = wimaServiceAreaName;
} }
bool WimaServiceArea::loadFromJson(const QJsonObject &json, QString &errorString) bool WimaServiceArea::loadFromJson(const QJsonObject &json,
{ QString &errorString) {
if ( this->WimaArea::loadFromJson(json, errorString)) { if (this->WimaArea::loadFromJson(json, errorString)) {
bool retVal = true; bool retVal = true;
// code for loading here // code for loading here
return retVal; return retVal;
} else { } else {
qWarning() << errorString; qWarning() << errorString;
return false; return false;
} }
} }
void print(const WimaServiceArea &area) void print(const WimaServiceArea &area) {
{ QString message;
QString message; print(area, message);
print(area, message); qWarning() << message;
qWarning() << message;
} }
void print(const WimaServiceArea &area, QString &outputStr) void print(const WimaServiceArea &area, QString &outputStr) {
{ print(static_cast<const WimaArea &>(area), outputStr);
print(static_cast<const WimaArea&>(area), outputStr); outputStr.append(QString("Depot Position: %s\n")
outputStr.append(QString("Takeoff Position: %s\n").arg(area._takeOffPosition.toString(QGeoCoordinate::Degrees))); .arg(area._depot.toString(QGeoCoordinate::Degrees)));
outputStr.append(QString("Land Position: %s\n").arg(area._landPosition.toString(QGeoCoordinate::Degrees)));
} }
void WimaServiceArea::init() void WimaServiceArea::init() {
{ this->setObjectName(wimaServiceAreaName);
this->setObjectName(wimaServiceAreaName); connect(this, &WimaServiceArea::centerChanged, [this] {
if (!this->_depot.isValid()) {
this->setDepot(this->center());
}
});
} }
#pragma once #pragma once
#include <QObject>
#include "WimaArea.h" #include "WimaArea.h"
#include "WimaTrackerPolyline.h" #include "WimaTrackerPolyline.h"
#include <QObject>
class WimaServiceArea : public WimaArea class WimaServiceArea : public WimaArea {
{ Q_OBJECT
Q_OBJECT
public: public:
WimaServiceArea(QObject* parent = nullptr); WimaServiceArea(QObject *parent = nullptr);
WimaServiceArea(const WimaServiceArea& other, QObject* parent); WimaServiceArea(const WimaServiceArea &other, QObject *parent);
WimaServiceArea& operator=(const WimaServiceArea &other); WimaServiceArea &operator=(const WimaServiceArea &other);
Q_PROPERTY(const QGeoCoordinate& takeOffPosition READ takeOffPosition WRITE setTakeOffPosition NOTIFY takeOffPositionChanged)
Q_PROPERTY(const QGeoCoordinate& landPosition READ landPosition WRITE setLandPosition NOTIFY landPositionChanged)
// Overrides from WimaPolygon Q_PROPERTY(QGeoCoordinate depot READ depot WRITE setDepot NOTIFY depotChanged)
QString mapVisualQML (void) const { return "WimaServiceAreaMapVisual.qml";}
QString editorQML (void) const { return "WimaServiceAreaEditor.qml";}
// Property acessors // Overrides from WimaPolygon
const QGeoCoordinate& takeOffPosition (void) const { return _takeOffPosition;} QString mapVisualQML(void) const { return "WimaServiceAreaMapVisual.qml"; }
const QGeoCoordinate& landPosition (void) const { return _landPosition;} QString editorQML(void) const { return "WimaServiceAreaEditor.qml"; }
// Member Methodes // Property acessors
void saveToJson(QJsonObject& json); const QGeoCoordinate &depot(void) const { return _depot; }
bool loadFromJson(const QJsonObject& json, QString& errorString);
// Member Methodes
void saveToJson(QJsonObject &json);
bool loadFromJson(const QJsonObject &json, QString &errorString);
// Friends
friend void print(const WimaServiceArea &area, QString &outputStr);
friend void print(const WimaServiceArea &area);
// Friends // static Members
friend void print(const WimaServiceArea& area, QString& outputStr); static const char *wimaServiceAreaName;
friend void print(const WimaServiceArea& area);
// static Members
static const char* wimaServiceAreaName;
signals: signals:
void takeOffPositionChanged (void); void depotChanged(void);
void landPositionChanged (void);
public slots: public slots:
void setTakeOffPosition (const QGeoCoordinate& coordinate); void setDepot(const QGeoCoordinate &coordinate);
void setLandPosition (const QGeoCoordinate& coordinate);
private: private:
// Member Methodes // Member Methodes
void init(); void init();
// Members // Members
QGeoCoordinate _takeOffPosition; QGeoCoordinate _depot;
QGeoCoordinate _landPosition;
}; };
...@@ -100,7 +100,7 @@ void WimaServiceAreaData::assign(const WimaServiceArea &other) ...@@ -100,7 +100,7 @@ void WimaServiceAreaData::assign(const WimaServiceArea &other)
{ {
WimaAreaData::assign(other); WimaAreaData::assign(other);
setLandPosition(other.landPosition()); setLandPosition(other.landPosition());
setTakeOffPosition(other.takeOffPosition()); setTakeOffPosition(other.depot());
} }
......
This diff is collapsed.
...@@ -44,9 +44,8 @@ public: ...@@ -44,9 +44,8 @@ public:
Q_PROPERTY(QGeoCoordinate joinedAreaCenter READ joinedAreaCenter CONSTANT) Q_PROPERTY(QGeoCoordinate joinedAreaCenter READ joinedAreaCenter CONSTANT)
Q_PROPERTY(WimaBridge *wimaBridge READ wimaBridge WRITE setWimaBridge NOTIFY Q_PROPERTY(WimaBridge *wimaBridge READ wimaBridge WRITE setWimaBridge NOTIFY
wimaBridgeChanged) wimaBridgeChanged)
Q_PROPERTY(bool syncronized READ syncronizedWithController NOTIFY Q_PROPERTY(bool synchronized READ synchronized NOTIFY synchronizedChanged)
syncronizedWithControllerChanged) Q_PROPERTY(bool needsUpdate READ needsUpdate NOTIFY needsUpdateChanged)
Q_PROPERTY(bool readyForSync READ readyForSync NOTIFY readyForSyncChanged)
// Property accessors // Property accessors
PlanMasterController *masterController(void); PlanMasterController *masterController(void);
...@@ -59,6 +58,8 @@ public: ...@@ -59,6 +58,8 @@ public:
QString fileExtension(void) const; QString fileExtension(void) const;
QGeoCoordinate joinedAreaCenter(void) const; QGeoCoordinate joinedAreaCenter(void) const;
WimaBridge *wimaBridge(void); WimaBridge *wimaBridge(void);
bool synchronized();
bool needsUpdate();
// Property setters // Property setters
void setMasterController(PlanMasterController *masterController); void setMasterController(PlanMasterController *masterController);
...@@ -68,11 +69,6 @@ public: ...@@ -68,11 +69,6 @@ public:
void setCurrentPolygonIndex(int index); void setCurrentPolygonIndex(int index);
void setWimaBridge(WimaBridge *bridge); void setWimaBridge(WimaBridge *bridge);
// Property acessors
bool syncronizedWithController();
bool readyForSync();
// Member Methodes
Q_INVOKABLE WimaPlaner *thisPointer(); Q_INVOKABLE WimaPlaner *thisPointer();
Q_INVOKABLE bool addMeasurementArea(); Q_INVOKABLE bool addMeasurementArea();
/// Removes an area from _visualItems /// Removes an area from _visualItems
...@@ -84,24 +80,17 @@ public: ...@@ -84,24 +80,17 @@ public:
/// MissionController /// MissionController
Q_INVOKABLE void removeAll(); Q_INVOKABLE void removeAll();
/// Recalculates vehicle corridor, flight path, etc. /// Recalculates vehicle corridor, flight path, etc.
Q_INVOKABLE bool updateMission(); Q_INVOKABLE bool update();
/// Pushes the generated mission data to the wimaController. /// Pushes the generated mission data to the wimaController.
Q_INVOKABLE void pushToWimaController(); Q_INVOKABLE void pushToWimaController();
Q_INVOKABLE void saveToCurrent(); Q_INVOKABLE void saveToCurrent();
Q_INVOKABLE void saveToFile(const QString &filename); Q_INVOKABLE void saveToFile(const QString &filename);
Q_INVOKABLE bool loadFromCurrent(); Q_INVOKABLE bool loadFromCurrent();
Q_INVOKABLE bool loadFromFile(const QString &filename); Q_INVOKABLE bool loadFromFile(const QString &filename);
Q_INVOKABLE void resetAllInteractive(void); Q_INVOKABLE void resetAllInteractive(void);
Q_INVOKABLE void setInteractive(void); Q_INVOKABLE void setInteractive(void);
QJsonDocument saveToJson(FileType fileType); QJsonDocument saveToJson(FileType fileType);
bool calcShortestPath(const QGeoCoordinate &start,
const QGeoCoordinate &destination,
QVector<QGeoCoordinate> &path);
// static Members // static Members
static const char *wimaFileExtension; static const char *wimaFileExtension;
static const char *areaItemsName; static const char *areaItemsName;
...@@ -114,21 +103,14 @@ signals: ...@@ -114,21 +103,14 @@ signals:
void currentPolygonIndexChanged(int index); void currentPolygonIndexChanged(int index);
void currentFileChanged(); void currentFileChanged();
void wimaBridgeChanged(); void wimaBridgeChanged();
void syncronizedWithControllerChanged(void); void synchronizedChanged(void);
void readyForSyncChanged(void); void needsUpdateChanged(void);
private slots: private slots:
void recalcPolygonInteractivity(int index); void updatePolygonInteractivity(int index);
bool calcArrivalAndReturnPath(void);
bool recalcJoinedArea();
// called by _updateTimer::timeout signal, updates different mission parts, if
// parameters (e.g. survey or areas) have changed
void updateTimerSlot();
void setSyncronizedWithControllerFalse(void);
#ifndef NDEBUG #ifndef NDEBUG
void autoLoadMission(void); void autoLoadMission(void);
#endif #endif
void startCalcArrivalAndReturnTimer(void);
private: private:
signals: signals:
...@@ -137,9 +119,10 @@ signals: ...@@ -137,9 +119,10 @@ signals:
private: private:
// Member Functions // Member Functions
WimaPlanData toPlanData(); WimaPlanData toPlanData();
void setSyncronizedWithController(bool sync); bool shortestPath(const QGeoCoordinate &start,
void setReadyForSync(bool ready); const QGeoCoordinate &destination,
void setJoinedAreaValid(bool valid); QVector<QGeoCoordinate> &path);
void setNeedsUpdate(bool needsUpdate);
// Member Variables // Member Variables
PlanMasterController *_masterController; PlanMasterController *_masterController;
...@@ -151,8 +134,11 @@ private: ...@@ -151,8 +134,11 @@ private:
bool _joinedAreaValid; bool _joinedAreaValid;
WimaMeasurementArea _measurementArea; WimaMeasurementArea _measurementArea;
bool _mAreaChanged;
WimaServiceArea _serviceArea; WimaServiceArea _serviceArea;
bool _sAreaChanged;
WimaCorridor _corridor; WimaCorridor _corridor;
bool _corridorChanged;
// contains all visible areas // contains all visible areas
QmlObjectListModel _visualItems; QmlObjectListModel _visualItems;
// joined area fromed by _measurementArea, _serviceArea, _corridor // joined area fromed by _measurementArea, _serviceArea, _corridor
...@@ -162,36 +148,15 @@ private: ...@@ -162,36 +148,15 @@ private:
// path from last measurement point to land // path from last measurement point to land
unsigned long _returnPathLength; unsigned long _returnPathLength;
CircularSurvey *_TSComplexItem; // pointer to the CircularSurvey item in CircularSurvey *_TSComplexItem;
// _missionController.visualItems() bool _surveyChanged;
// auto update
QTimer _updateTimer; // on this timers timeout different mission parts will be
// updated, if parameters (e.g. survey or areas) have
// changed
QGeoCoordinate _lastSurveyRefPoint; // stores the SurveyRefPoint of the
// previous timer call
bool _surveyRefChanging; // true if SurveyRefPoint is changing
QVariantList
_lastMeasurementAreaPath; // stores the path of _measurementArea, at the
// time instance of the previous timer call
bool _measurementAreaChanging; // true if the path of the _measurementArea is
// changing
QVariantList _lastCorridorPath; // stores the path of _corridor, at the time
// instance of the previous timer call
bool _corridorChanging; // true if the path of the _corridor is changing
QVariantList _lastServiceAreaPath; // stores the path of _serviceArea, at the
// time instance of the previous timer call
bool _serviceAreaChanging; // true if the path of the _serviceArea is changing
// sync stuff // sync stuff
bool _syncronizedWithController; // true if planData is syncronized with bool _synchronized; // true if planData is synchronized with
// wimaController // wimaController
bool _readyForSync; // gets set by updateMission and calcArrivalAndReturnPath bool _needsUpdate; // gets set by updateMission and calcArrivalAndReturnPath
#ifndef NDEBUG #ifndef NDEBUG
QTimer _autoLoadTimer; // timer to auto load mission after some time, prevents QTimer _autoLoadTimer; // timer to auto load mission after some time, prevents
// seg. faults // seg. faults
#endif #endif
QTimer _calcArrivalAndReturnPathTimer;
}; };
...@@ -88,13 +88,11 @@ Item { ...@@ -88,13 +88,11 @@ Item {
} }
Component.onCompleted: { Component.onCompleted: {
if ( !_missionItem.isInitialized ) { if ( _missionItem.visualTransectPoints.length === 0 ) {
_addInitialPolygon() _addInitialPolygon()
_missionItem.isInitialized = true // set isInitialized to true, to trigger _rebuildTransectsPhase1 in the last line
_setRefPoint() _setRefPoint()
} }
_addVisualElements() _addVisualElements()
} }
Component.onDestruction: { Component.onDestruction: {
...@@ -111,6 +109,7 @@ Item { ...@@ -111,6 +109,7 @@ Item {
borderColor: "black" borderColor: "black"
interiorColor: "green" interiorColor: "green"
interiorOpacity: 0.5 interiorOpacity: 0.5
visible: !_missionItem.hidePolygon
} }
// Transect lines // Transect lines
......
...@@ -27,11 +27,9 @@ Item { ...@@ -27,11 +27,9 @@ Item {
property var areaItem: object property var areaItem: object
property var _polygon: areaItem property var _polygon: areaItem
//property var _polyline: areaItem.polyline
signal clicked(int sequenceNumber) signal clicked(int sequenceNumber)
/// Add an initial 4 sided polygon if there is none
/// Add an initial 4 sided polygon if there is none /// Add an initial 4 sided polygon if there is none
function _addInitialPolygon() { function _addInitialPolygon() {
...@@ -109,4 +107,30 @@ Item { ...@@ -109,4 +107,30 @@ Item {
interiorOpacity: 1 interiorOpacity: 1
} }
// Depot Point.
Component {
id: depotPointComponent
DragCoordinate {
map: _root.map
qgcView: _root.qgcView
z: QGroundControl.zOrderMapItems
checked: areaItem.interactive
coordinate: areaItem.depot
property var point: areaItem.depot
onRefPointChanged: {
if (point !== coordinate) {
coordinate = point
}
}
onDragReleased: {
areaItem.depot = coordinate
}
}
}
} }
...@@ -285,12 +285,15 @@ Rectangle { ...@@ -285,12 +285,15 @@ Rectangle {
anchors.rightMargin: _margins anchors.rightMargin: _margins
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: qsTr("Sync WiMA") text: wimaPlaner && wimaPlaner.needsUpdate ? qsTr("Update") : qsTr("Sync.")
enabled: true enabled: true
visible: wimaPlaner ? wimaPlaner.readyForSync : false
onClicked: { onClicked: {
if (wimaPlaner && wimaPlaner.readyForSync) { if (wimaPlaner){
wimaPlaner.pushToWimaController() if (!wimaPlaner.needsUpdate) {
wimaPlaner.pushToWimaController()
} else {
wimaPlaner.update()
}
} }
} }
...@@ -299,7 +302,7 @@ Rectangle { ...@@ -299,7 +302,7 @@ Rectangle {
from: 0.5 from: 0.5
to: 1 to: 1
loops: Animation.Infinite loops: Animation.Infinite
running: wimaPlaner ? !wimaPlaner.syncronized && wimaPlaner.readyForSync : false running: wimaPlaner ? wimaPlaner.needsUpdate : false
alwaysRunToEnd: true alwaysRunToEnd: true
duration: 2000 duration: 2000
} }
......
...@@ -699,7 +699,7 @@ QGCView { ...@@ -699,7 +699,7 @@ QGCView {
iconSource: "/res/street.png" iconSource: "/res/street.png"
}, },
{ {
name: qsTr("Calculate"), name: qsTr("Update"),
iconSource: "/res/calculator.png" iconSource: "/res/calculator.png"
}, },
{ {
...@@ -729,7 +729,7 @@ QGCView { ...@@ -729,7 +729,7 @@ QGCView {
wimaPlaner.addCorridor(); wimaPlaner.addCorridor();
break break
case 4: case 4:
wimaPlaner.updateMission(); wimaPlaner.update();
break break
case 6: case 6:
editorMap.zoomLevel += 0.5 editorMap.zoomLevel += 0.5
......
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