Commit 99b27028 authored by Valentin Platzgummer's avatar Valentin Platzgummer

SnakeWorker issues solved, about to add tile visualization.

parent b4c66b1b
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
#include "clipper/clipper.hpp" #include "clipper/clipper.hpp"
#define CLIPPER_SCALE 10000 #define CLIPPER_SCALE 10000
#ifndef NDEBUG
//#define SHOW_TIME
#endif
using namespace snake_geometry; using namespace snake_geometry;
using namespace std; using namespace std;
...@@ -71,6 +75,7 @@ bool Scenario::_areas2enu() ...@@ -71,6 +75,7 @@ bool Scenario::_areas2enu()
} }
bg::correct(_serviceAreaENU); bg::correct(_serviceAreaENU);
polygonCenter(_serviceAreaENU, _homePositionENU); polygonCenter(_serviceAreaENU, _homePositionENU);
fromENU(_geoOrigin, Point3D{_homePositionENU.get<0>(), _homePositionENU.get<1>(), 0}, _homePosition);
_corridorENU.clear(); _corridorENU.clear();
if (_corridor.geoPolygon.size() > 0){ if (_corridor.geoPolygon.size() > 0){
...@@ -146,6 +151,8 @@ bool Scenario::_calculateTiles(double tileWidth, double tileHeight, double minTi ...@@ -146,6 +151,8 @@ bool Scenario::_calculateTiles(double tileWidth, double tileHeight, double minTi
{ {
_tilesENU.clear(); _tilesENU.clear();
_tileCenterPointsENU.clear(); _tileCenterPointsENU.clear();
_tiles.clear();
_tileCenterPoints.clear();
if (tileWidth <= 0 || tileHeight <= 0 || minTileArea <= 0) { if (tileWidth <= 0 || tileHeight <= 0 || minTileArea <= 0) {
errorString = "Parameters tileWidth, tileHeight, minTileArea must be positive."; errorString = "Parameters tileWidth, tileHeight, minTileArea must be positive.";
...@@ -223,6 +230,23 @@ bool Scenario::_calculateTiles(double tileWidth, double tileHeight, double minTi ...@@ -223,6 +230,23 @@ bool Scenario::_calculateTiles(double tileWidth, double tileHeight, double minTi
return false; return false;
} }
for ( auto tile : _tilesENU){
GeoPoint3DList geoTile;
for ( int i=0; i < int(tile.outer().size())-1; ++i) {
BoostPoint vertex(tile.outer()[i]);
GeoPoint3D geoVertex;
fromENU(_geoOrigin, Point3D{vertex.get<0>(), vertex.get<1>(), 0}, geoVertex);
geoTile.push_back(geoVertex);
}
_tiles.push_back(geoTile);
}
for ( auto vertex : _tileCenterPointsENU){
GeoPoint3D geoVertex;
fromENU(_geoOrigin, Point3D{vertex.get<0>(), vertex.get<1>(), 0}, geoVertex);
_tileCenterPoints.push_back(geoVertex);
}
return true; return true;
} }
...@@ -240,8 +264,9 @@ bool Scenario::_calculateJoinedArea() ...@@ -240,8 +264,9 @@ bool Scenario::_calculateJoinedArea()
// Corridor overlaping with measurement area? // Corridor overlaping with measurement area?
if ( bg::intersects(_corridorENU, _measurementAreaENU) ) { if ( bg::intersects(_corridorENU, _measurementAreaENU) ) {
// Corridor overlaping with service area? // Corridor overlaping with service area?
if ( bg::intersects(_corridorENU, _serviceAreaENU) ) if ( bg::intersects(_corridorENU, _serviceAreaENU) ) {
corridor_is_connection = true; corridor_is_connection = true;
}
} }
} }
...@@ -291,12 +316,16 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength) ...@@ -291,12 +316,16 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength)
#ifndef NDEBUG #ifndef NDEBUG
_PathVertices.clear(); _PathVertices.clear();
#endif #endif
#ifdef SHOW_TIME
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
#endif
if (!_generateTransects(lineDistance, minTransectLength)) if (!_generateTransects(lineDistance, minTransectLength))
return false; return false;
#ifdef SHOW_TIME
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start); auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
cout << endl; cout << endl;
cout << "Execution time _generateTransects(): " << delta.count() << " ms" << endl; cout << "Execution time _generateTransects(): " << delta.count() << " ms" << endl;
#endif
//======================================= //=======================================
// Route Transects using Google or-tools. // Route Transects using Google or-tools.
...@@ -330,10 +359,14 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength) ...@@ -330,10 +359,14 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength)
RoutingDataModel_t dataModel; RoutingDataModel_t dataModel;
Matrix<double> connectionGraph(n1, n1); Matrix<double> connectionGraph(n1, n1);
#ifdef SHOW_TIME
start = std::chrono::high_resolution_clock::now(); start = std::chrono::high_resolution_clock::now();
#endif
_generateRoutingModel(vertices, jAreaOffset, n0, dataModel, connectionGraph); _generateRoutingModel(vertices, jAreaOffset, n0, dataModel, connectionGraph);
#ifdef SHOW_TIME
delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start); delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
cout << "Execution time _generateRoutingModel(): " << delta.count() << " ms" << endl; cout << "Execution time _generateRoutingModel(): " << delta.count() << " ms" << endl;
#endif
// Create Routing Index Manager. // Create Routing Index Manager.
RoutingIndexManager manager(dataModel.distanceMatrix.getN(), dataModel.numVehicles, RoutingIndexManager manager(dataModel.distanceMatrix.getN(), dataModel.numVehicles,
...@@ -350,6 +383,9 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength) ...@@ -350,6 +383,9 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength)
return dataModel.distanceMatrix.get(from_node, to_node); return dataModel.distanceMatrix.get(from_node, to_node);
}); });
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index);
// Define Constraints. // Define Constraints.
size_t n = _transects.size()*2; size_t n = _transects.size()*2;
...@@ -373,9 +409,6 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength) ...@@ -373,9 +409,6 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength)
solver->AddConstraint(c); solver->AddConstraint(c);
} }
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index);
// Setting first solution heuristic. // Setting first solution heuristic.
RoutingSearchParameters searchParameters = DefaultRoutingSearchParameters(); RoutingSearchParameters searchParameters = DefaultRoutingSearchParameters();
...@@ -386,10 +419,14 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength) ...@@ -386,10 +419,14 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength)
searchParameters.set_allocated_time_limit(tMax); searchParameters.set_allocated_time_limit(tMax);
// Solve the problem. // Solve the problem.
#ifdef SHOW_TIME
start = std::chrono::high_resolution_clock::now(); start = std::chrono::high_resolution_clock::now();
#endif
const Assignment* solution = routing.SolveWithParameters(searchParameters); const Assignment* solution = routing.SolveWithParameters(searchParameters);
#ifdef SHOW_TIME
delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start); delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
cout << "Execution time routing.SolveWithParameters(): " << delta.count() << " ms" << endl; cout << "Execution time routing.SolveWithParameters(): " << delta.count() << " ms" << endl;
#endif
if (!solution || solution->Size() <= 1){ if (!solution || solution->Size() <= 1){
errorString = "Not able to solve the routing problem."; errorString = "Not able to solve the routing problem.";
...@@ -413,14 +450,25 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength) ...@@ -413,14 +450,25 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength)
{ {
_waypointsENU.push_back(vertices[route[0]]); _waypointsENU.push_back(vertices[route[0]]);
vector<size_t> pathIdx; vector<size_t> pathIdx;
long arrivalPathLength = 0;
for (long i=0; i<long(route.size())-1; ++i){ for (long i=0; i<long(route.size())-1; ++i){
size_t idx0 = route[i]; size_t idx0 = route[i];
size_t idx1 = route[i+1]; size_t idx1 = route[i+1];
pathIdx.clear(); pathIdx.clear();
shortestPathFromGraph(connectionGraph, idx0, idx1, pathIdx); shortestPathFromGraph(connectionGraph, idx0, idx1, pathIdx);
if ( i==0 )
arrivalPathLength = pathIdx.size();
for (size_t j=1; j<pathIdx.size(); ++j) for (size_t j=1; j<pathIdx.size(); ++j)
_waypointsENU.push_back(vertices[pathIdx[j]]); _waypointsENU.push_back(vertices[pathIdx[j]]);
} }
long returnPathLength = pathIdx.size();
for (long i=returnPathLength; i > 0; --i)
_returnPathIdx.push_back(_waypointsENU.size()-i);
for (long i=0; i < arrivalPathLength; ++i)
_arrivalPathIdx.push_back(i);
} }
// Back transform waypoints. // Back transform waypoints.
...@@ -431,18 +479,6 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength) ...@@ -431,18 +479,6 @@ bool FlightPlan::generate(double lineDistance, double minTransectLength)
_waypoints.push_back(GeoPoint2D{geoVertex[0], geoVertex[1]}); _waypoints.push_back(GeoPoint2D{geoVertex[0], geoVertex[1]});
} }
// Reconstruct arrival path;
int i = 0;
for (; route[i] >= n_t; ++i)
_arrivalPathIdx.push_back(i);
_arrivalPathIdx.push_back(i); // vertex of first transect
// Reconstruct return path;
i = route.size()-1;
for (; route[i] >= n_t; --i)
_returnPathIdx.push_back(i);
_returnPathIdx.push_back(i); // vertex of last transect
return true; return true;
} }
...@@ -450,7 +486,13 @@ bool FlightPlan::_generateTransects(double lineDistance, double minTransectLengt ...@@ -450,7 +486,13 @@ bool FlightPlan::_generateTransects(double lineDistance, double minTransectLengt
{ {
_transects.clear(); _transects.clear();
if (_scenario.getTilesENU().size() != _progress.size()){ if (_scenario.getTilesENU().size() != _progress.size()){
errorString = "Number of tiles is not equal to progress array length"; ostringstream strstream;
strstream << "Number of tiles ("
<< _scenario.getTilesENU().size()
<< ") is not equal to progress array length ("
<< _progress.size()
<< ")";
errorString = strstream.str();
return false; return false;
} }
...@@ -573,10 +615,14 @@ void FlightPlan::_generateRoutingModel(const BoostLineString &vertices, ...@@ -573,10 +615,14 @@ void FlightPlan::_generateRoutingModel(const BoostLineString &vertices,
FlightPlan::RoutingDataModel_t &dataModel, FlightPlan::RoutingDataModel_t &dataModel,
Matrix<double> &graph) Matrix<double> &graph)
{ {
#ifdef SHOW_TIME
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
#endif
graphFromPolygon(polygonOffset, vertices, graph); graphFromPolygon(polygonOffset, vertices, graph);
#ifdef SHOW_TIME
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()-start); auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()-start);
cout << "Execution time graphFromPolygon(): " << delta.count() << " ms" << endl; cout << "Execution time graphFromPolygon(): " << delta.count() << " ms" << endl;
#endif
// cout << endl; // cout << endl;
// for (size_t i=0; i<graph.size(); ++i){ // for (size_t i=0; i<graph.size(); ++i){
// vector<double> &row = graph[i]; // vector<double> &row = graph[i];
...@@ -587,10 +633,14 @@ void FlightPlan::_generateRoutingModel(const BoostLineString &vertices, ...@@ -587,10 +633,14 @@ void FlightPlan::_generateRoutingModel(const BoostLineString &vertices,
// } // }
// cout << endl; // cout << endl;
Matrix<double> distanceMatrix(graph); Matrix<double> distanceMatrix(graph);
#ifdef SHOW_TIME
start = std::chrono::high_resolution_clock::now(); start = std::chrono::high_resolution_clock::now();
#endif
toDistanceMatrix(distanceMatrix); toDistanceMatrix(distanceMatrix);
#ifdef SHOW_TIME
delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()-start); delta = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()-start);
cout << "Execution time toDistanceMatrix(): " << delta.count() << " ms" << endl; cout << "Execution time toDistanceMatrix(): " << delta.count() << " ms" << endl;
#endif
dataModel.distanceMatrix.setDimension(n0, n0); dataModel.distanceMatrix.setDimension(n0, n0);
for (size_t i=0; i<n0; ++i){ for (size_t i=0; i<n0; ++i){
...@@ -605,4 +655,23 @@ void FlightPlan::_generateRoutingModel(const BoostLineString &vertices, ...@@ -605,4 +655,23 @@ void FlightPlan::_generateRoutingModel(const BoostLineString &vertices,
dataModel.depot = n0-1; dataModel.depot = n0-1;
} }
Area::Area() : Area(GeoPoint2DList(), 0, 1, AreaType::MeasurementArea)
{
}
Area::Area(const GeoPoint2DList &gP, AreaType tp) : Area(gP, 0, 1, tp)
{
}
Area::Area(const GeoPoint2DList &gP, double alt, size_t l, AreaType tp) :
geoPolygon(gP)
, altitude(alt)
, layers(l)
, type(tp)
{
}
} }
...@@ -20,7 +20,12 @@ namespace snake { ...@@ -20,7 +20,12 @@ namespace snake {
enum AreaType {MeasurementArea, ServiceArea, Corridor}; enum AreaType {MeasurementArea, ServiceArea, Corridor};
struct Area { class Area {
public:
Area();
Area(const GeoPoint2DList &gP, AreaType tp);
Area(const GeoPoint2DList &gP, double alt, size_t l, AreaType tp);
GeoPoint2DList geoPolygon; GeoPoint2DList geoPolygon;
double altitude; double altitude;
size_t layers; size_t layers;
...@@ -51,6 +56,10 @@ namespace snake { ...@@ -51,6 +56,10 @@ namespace snake {
const min_bbox_rt &getMeasurementAreaBBoxENU() {return _mAreaBoundingBox;} const min_bbox_rt &getMeasurementAreaBBoxENU() {return _mAreaBoundingBox;}
const BoostPoint &getHomePositonENU() {return _homePositionENU;} const BoostPoint &getHomePositonENU() {return _homePositionENU;}
const vector<GeoPoint3DList> &getTiles() {return _tiles;}
const vector<GeoPoint3D> &getTileCenterPoints() {return _tileCenterPoints;}
const GeoPoint3D &getHomePositon() {return _homePosition;}
bool defined(double tileWidth, double tileHeight, double minTileArea); bool defined(double tileWidth, double tileHeight, double minTileArea);
string errorString; string errorString;
...@@ -78,8 +87,13 @@ namespace snake { ...@@ -78,8 +87,13 @@ namespace snake {
vector<BoostPolygon> _tilesENU; vector<BoostPolygon> _tilesENU;
BoostLineString _tileCenterPointsENU; BoostLineString _tileCenterPointsENU;
vector<GeoPoint3DList> _tiles;
vector<GeoPoint3D> _tileCenterPoints;
GeoPoint3D _geoOrigin; GeoPoint3D _geoOrigin;
BoostPoint _homePositionENU; BoostPoint _homePositionENU;
GeoPoint3D _homePosition;
}; };
//======================================================================================== //========================================================================================
......
...@@ -15,8 +15,6 @@ public: ...@@ -15,8 +15,6 @@ public:
Q_PROPERTY(QString type READ type CONSTANT) Q_PROPERTY(QString type READ type CONSTANT)
WimaAreaData(QObject *parent = nullptr); WimaAreaData(QObject *parent = nullptr);
//WimaAreaData(const WimaAreaData &other, QObject *parent = nullptr);
//WimaAreaData(const WimaArea &other, QObject *parent = nullptr);
WimaAreaData& operator=(const WimaAreaData& otherData) = delete; // avoid slicing WimaAreaData& operator=(const WimaAreaData& otherData) = delete; // avoid slicing
double maxAltitude() const; double maxAltitude() const;
...@@ -25,8 +23,10 @@ public: ...@@ -25,8 +23,10 @@ public:
QList<QGeoCoordinate> coordinateList() const; QList<QGeoCoordinate> coordinateList() const;
bool containsCoordinate(const QGeoCoordinate &coordinate) const; bool containsCoordinate(const QGeoCoordinate &coordinate) const;
void append(const QGeoCoordinate &c) {_path.push_back(QVariant::fromValue(c));}
void clear() {_path.clear();}
virtual QString type() const = 0; virtual QString type() const { return "Default";}
signals: signals:
void maxAltitudeChanged (double maxAltitude); void maxAltitudeChanged (double maxAltitude);
......
...@@ -91,11 +91,6 @@ WimaController::WimaController(QObject *parent) ...@@ -91,11 +91,6 @@ WimaController::WimaController(QObject *parent)
connect(&_snakeWorker, &SnakeWorker::resultReady, this, &WimaController::_snakeStoreWorkerResults); connect(&_snakeWorker, &SnakeWorker::resultReady, this, &WimaController::_snakeStoreWorkerResults);
} }
QmlObjectListModel* WimaController::visualItems()
{
return &_visualItems;
}
QStringList WimaController::loadNameFilters() const QStringList WimaController::loadNameFilters() const
{ {
QStringList filters; QStringList filters;
...@@ -113,81 +108,6 @@ QStringList WimaController::saveNameFilters() const ...@@ -113,81 +108,6 @@ QStringList WimaController::saveNameFilters() const
return filters; return filters;
} }
WimaDataContainer *WimaController::dataContainer()
{
return _container;
}
QmlObjectListModel *WimaController::missionItems()
{
return &_missionItems;
}
QmlObjectListModel *WimaController::currentMissionItems()
{
return &_currentMissionItems;
}
QVariantList WimaController::waypointPath()
{
return _waypointPath;
}
QVariantList WimaController::currentWaypointPath()
{
return _currentWaypointPath;
}
Fact *WimaController::enableWimaController()
{
return &_enableWimaController;
}
Fact *WimaController::overlapWaypoints()
{
return &_overlapWaypoints;
}
Fact *WimaController::maxWaypointsPerPhase()
{
return &_maxWaypointsPerPhase;
}
Fact *WimaController::showAllMissionItems()
{
return &_showAllMissionItems;
}
Fact *WimaController::showCurrentMissionItems()
{
return &_showCurrentMissionItems;
}
Fact *WimaController::flightSpeed()
{
return &_flightSpeed;
}
Fact *WimaController::arrivalReturnSpeed()
{
return &_arrivalReturnSpeed;
}
Fact *WimaController::altitude()
{
return &_altitude;
}
Fact *WimaController::reverse()
{
return &_reverse;
}
Fact *WimaController::enableSnake()
{
return &_enableSnake;
}
bool WimaController::uploadOverrideRequired() const bool WimaController::uploadOverrideRequired() const
{ {
return _uploadOverrideRequired; return _uploadOverrideRequired;
...@@ -218,11 +138,6 @@ bool WimaController::snakeCalcInProgress() const ...@@ -218,11 +138,6 @@ bool WimaController::snakeCalcInProgress() const
return _snakeCalcInProgress; return _snakeCalcInProgress;
} }
Fact *WimaController::startWaypointIndex()
{
return &_nextPhaseStartWaypointIndex;
}
void WimaController::setMasterController(PlanMasterController *masterC) void WimaController::setMasterController(PlanMasterController *masterC)
{ {
_masterController = masterC; _masterController = masterC;
...@@ -515,7 +430,7 @@ bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVa ...@@ -515,7 +430,7 @@ bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVa
*/ */
bool WimaController::_fetchContainerData() bool WimaController::_fetchContainerData()
{ {
// fetch only if valid, return true on sucess // fetch only if valid, return true on success
// reset visual items // reset visual items
_visualItems.clear(); _visualItems.clear();
...@@ -523,11 +438,13 @@ bool WimaController::_fetchContainerData() ...@@ -523,11 +438,13 @@ bool WimaController::_fetchContainerData()
_currentMissionItems.clearAndDeleteContents(); _currentMissionItems.clearAndDeleteContents();
_waypointPath.clear(); _waypointPath.clear();
_currentWaypointPath.clear(); _currentWaypointPath.clear();
_snakeTiles.clearAndDeleteContents();
emit visualItemsChanged(); emit visualItemsChanged();
emit missionItemsChanged(); emit missionItemsChanged();
emit currentMissionItemsChanged(); emit currentMissionItemsChanged();
emit currentWaypointPathChanged(); emit currentWaypointPathChanged();
emit snakeTilesChanged();
_localPlanDataValid = false; _localPlanDataValid = false;
...@@ -643,11 +560,31 @@ bool WimaController::_fetchContainerData() ...@@ -643,11 +560,31 @@ bool WimaController::_fetchContainerData()
corridor.geoPolygon.push_back(GeoPoint2D{c.latitude(), c.longitude()}); corridor.geoPolygon.push_back(GeoPoint2D{c.latitude(), c.longitude()});
} }
corridor.type = AreaType::Corridor; corridor.type = AreaType::Corridor;
_scenario.addArea(mArea); _scenario.addArea(mArea);
_scenario.addArea(sArea); _scenario.addArea(sArea);
_scenario.addArea(corridor); _scenario.addArea(corridor);
_verifyScenarioDefinedWithErrorMessage(); // Check if scenario is defined.
if ( !_verifyScenarioDefinedWithErrorMessage() )
return false;
// Get tiles.
const auto &tiles = _scenario.getTiles();
const auto &cps = _scenario.getTileCenterPoints();
for ( int i=0; i < int(tiles.size()); ++i ) {
const auto &tile = tiles[i];
WimaAreaData *QTile = new WimaAreaData(this);
for ( const auto &vertex : tile) {
QGeoCoordinate QVertex(vertex[0], vertex[1], vertex[2]);
QTile->append(QVertex);
}
const auto &centerPoint = cps[i];
QGeoCoordinate QCenterPoint(centerPoint[0], centerPoint[1], centerPoint[2]);
QTile->setCenter(QCenterPoint);
_snakeTiles.append(QTile);
}
emit visualItemsChanged(); emit visualItemsChanged();
emit missionItemsChanged(); emit missionItemsChanged();
...@@ -759,7 +696,7 @@ bool WimaController::_calcNextPhase() ...@@ -759,7 +696,7 @@ bool WimaController::_calcNextPhase()
// calculate path from last waypoint to home // calculate path from last waypoint to home
QVector<QGeoCoordinate> returnPath; QVector<QGeoCoordinate> returnPath;
if ( !calcShortestPath(CSWpList.last(), _takeoffLandPostion, returnPath) ) { if ( !calcShortestPath(CSWpList.last(), _takeoffLandPostion, returnPath) ) {
qWarning("WimaController::calcNextPhase(): Not able to calc path from home to first waypoint."); qWarning("WimaController::calcNextPhase(): Not able to calc path from home to last waypoint.");
return false; return false;
} }
...@@ -1039,8 +976,8 @@ void WimaController::_eventTimerHandler() ...@@ -1039,8 +976,8 @@ void WimaController::_eventTimerHandler()
_snakeWorker.setProgress(progress); _snakeWorker.setProgress(progress);
_snakeWorker.setLineDistance(_snakeLineDistance.rawValue().toDouble()); _snakeWorker.setLineDistance(_snakeLineDistance.rawValue().toDouble());
_snakeWorker.setMinTransectLength(_snakeMinTransectLength.rawValue().toDouble()); _snakeWorker.setMinTransectLength(_snakeMinTransectLength.rawValue().toDouble());
_snakeWorker.start();
_setSnakeCalcInProgress(true); _setSnakeCalcInProgress(true);
_snakeWorker.start();
} }
} }
} }
...@@ -1316,8 +1253,10 @@ bool WimaController::_verifyScenarioDefinedWithErrorMessage() ...@@ -1316,8 +1253,10 @@ bool WimaController::_verifyScenarioDefinedWithErrorMessage()
return value; return value;
} }
void WimaController::_snakeStoreWorkerResults(const WorkerResult_t &r) void WimaController::_snakeStoreWorkerResults()
{ {
_missionItems.clearAndDeleteContents();
const WorkerResult_t &r = _snakeWorker.getResult();
_setSnakeCalcInProgress(false); _setSnakeCalcInProgress(false);
if (!r.success) { if (!r.success) {
qgcApp()->showMessage(r.errorMessage); qgcApp()->showMessage(r.errorMessage);
...@@ -1330,40 +1269,37 @@ void WimaController::_snakeStoreWorkerResults(const WorkerResult_t &r) ...@@ -1330,40 +1269,37 @@ void WimaController::_snakeStoreWorkerResults(const WorkerResult_t &r)
QVector<MissionItem> missionItems; QVector<MissionItem> missionItems;
missionItems.reserve(int(n)); missionItems.reserve(int(n));
unsigned long startIdx = r.returnPathIdx.last(); // Remove all items from mission controller.
_missionController->removeAll();
QmlObjectListModel* missionControllerVisualItems = _missionController->visualItems();
// Create QVector<QGeoCoordinate> containing all waypoints;
unsigned long startIdx = r.arrivalPathIdx.last();
unsigned long endIdx = r.returnPathIdx.first(); unsigned long endIdx = r.returnPathIdx.first();
QObject parent; QVector<QGeoCoordinate> waypoints;
int seqNum = 0;
for (unsigned long i = startIdx; i <= endIdx; ++i) { for (unsigned long i = startIdx; i <= endIdx; ++i) {
QGeoCoordinate wp{r.waypoints[int(i)].value<QGeoCoordinate>()}; QGeoCoordinate wp{r.waypoints[int(i)].value<QGeoCoordinate>()};
MissionItem item = new MissionItem(seqNum++, waypoints.append(wp);
MAV_CMD_NAV_WAYPOINT,
MAV_FRAME_GLOBAL_RELATIVE_ALT,
0, // Hold time (delay for hover and capture to settle vehicle before image is taken)
0.0, // No acceptance radius specified
0.0, // Pass through waypoint
std::numeric_limits<double>::quiet_NaN(), // Yaw unchanged
wp.latitude(),
wp.longitude(),
wp.altitude(),
true, // autoContinue
false, // isCurrentItem
&parent);
} }
// create mission items
_missionController->removeAll();
QmlObjectListModel* missionControllerVisualItems = _missionController->visualItems();
// create SimpleMissionItem by using _missionController // create SimpleMissionItem by using _missionController
for ( int i = 0; i < missionItems.size(); i++) { long insertIdx = missionControllerVisualItems->count();
_missionController->insertSimpleMissionItem(missionItems[i], missionControllerVisualItems->count()); for (auto wp : waypoints)
_missionController->insertSimpleMissionItem(wp, insertIdx++);
SimpleMissionItem *takeOffItem = missionControllerVisualItems->value<SimpleMissionItem*>(1);
if (takeOffItem == nullptr) {
qWarning("WimaController::_snakeStoreWorkerResults(): Nullptr at SimpleMissionItem!");
return;
} }
takeOffItem->setCommand(MAV_CMD_NAV_WAYPOINT);
takeOffItem->setCoordinate(waypoints[0]);
// copy mission items from _missionController to _missionItems // copy mission items from _missionController to _missionItems
cout.precision(10);
for ( int i = 1; i < missionControllerVisualItems->count(); i++) { for ( int i = 1; i < missionControllerVisualItems->count(); i++) {
SimpleMissionItem *visualItem = qobject_cast<SimpleMissionItem *>((*missionControllerVisualItems)[i]); SimpleMissionItem *visualItem = qobject_cast<SimpleMissionItem *>((*missionControllerVisualItems)[i]);
if (visualItem == nullptr) { if (visualItem == nullptr) {
qWarning("WimaController::fetchContainerData(): Nullptr at SimpleMissionItem!"); qWarning("WimaController::_snakeStoreWorkerResults(): Nullptr at SimpleMissionItem!");
return; return;
} }
SimpleMissionItem *visualItemCopy = new SimpleMissionItem(*visualItem, true, this); SimpleMissionItem *visualItemCopy = new SimpleMissionItem(*visualItem, true, this);
...@@ -1378,8 +1314,8 @@ void WimaController::_snakeStoreWorkerResults(const WorkerResult_t &r) ...@@ -1378,8 +1314,8 @@ void WimaController::_snakeStoreWorkerResults(const WorkerResult_t &r)
_nextPhaseStartWaypointIndex.setRawValue(reverse? _missionItems.count() : int(1)); _nextPhaseStartWaypointIndex.setRawValue(reverse? _missionItems.count() : int(1));
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase); connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
if(!_calcNextPhase()) _calcNextPhase();
return; emit missionItemsChanged();
} }
void WimaController::_loadCurrentMissionItemsFromBuffer() void WimaController::_loadCurrentMissionItemsFromBuffer()
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define SMART_RTL_MAX_ATTEMPTS 3 // times #define SMART_RTL_MAX_ATTEMPTS 3 // times
#define SMART_RTL_ATTEMPT_INTERVAL 200 // ms #define SMART_RTL_ATTEMPT_INTERVAL 200 // ms
#define EVENT_TIMER_INTERVAL 50 // ms #define EVENT_TIMER_INTERVAL 50 // ms
#define SNAKE_EVENT_LOOP_INTERVAL 50 // ms #define SNAKE_EVENT_LOOP_INTERVAL 5000 // ms
using namespace snake; using namespace snake;
...@@ -86,39 +86,43 @@ public: ...@@ -86,39 +86,43 @@ public:
Q_PROPERTY(Fact* snakeMinTileArea READ snakeMinTileArea CONSTANT) Q_PROPERTY(Fact* snakeMinTileArea READ snakeMinTileArea CONSTANT)
Q_PROPERTY(Fact* snakeLineDistance READ snakeLineDistance CONSTANT) Q_PROPERTY(Fact* snakeLineDistance READ snakeLineDistance CONSTANT)
Q_PROPERTY(Fact* snakeMinTransectLength READ snakeMinTransectLength CONSTANT) Q_PROPERTY(Fact* snakeMinTransectLength READ snakeMinTransectLength CONSTANT)
Q_PROPERTY(QmlObjectListModel* snakeTiles READ snakeTiles NOTIFY snakeTilesChanged)
// Property accessors // Property accessors
PlanMasterController* masterController (void) { return _masterController; } PlanMasterController* masterController (void) { return _masterController; }
MissionController* missionController (void) { return _missionController; } MissionController* missionController (void) { return _missionController; }
QmlObjectListModel* visualItems (void); QmlObjectListModel* visualItems (void) { return &_visualItems; }
QString currentFile (void) const { return _currentFile; } QString currentFile (void) const { return _currentFile; }
QStringList loadNameFilters (void) const; QStringList loadNameFilters (void) const;
QStringList saveNameFilters (void) const; QStringList saveNameFilters (void) const;
QString fileExtension (void) const { return wimaFileExtension; } QString fileExtension (void) const { return wimaFileExtension; }
QGCMapPolygon joinedArea (void) const; QGCMapPolygon joinedArea (void) const;
WimaDataContainer* dataContainer (void); WimaDataContainer* dataContainer (void) { return _container; }
QmlObjectListModel* missionItems (void); QmlObjectListModel* missionItems (void) { return &_missionItems; }
QmlObjectListModel* currentMissionItems (void); QmlObjectListModel* currentMissionItems (void) { return &_currentMissionItems; }
QVariantList waypointPath (void); QVariantList waypointPath (void) { return _waypointPath; }
QVariantList currentWaypointPath (void); QVariantList currentWaypointPath (void) { return _currentWaypointPath; }
Fact* enableWimaController (void); Fact* enableWimaController (void) { return &_enableWimaController; }
Fact* overlapWaypoints (void); Fact* overlapWaypoints (void) { return &_overlapWaypoints; }
Fact* maxWaypointsPerPhase (void); Fact* maxWaypointsPerPhase (void) { return &_maxWaypointsPerPhase; }
Fact* startWaypointIndex (void); Fact* startWaypointIndex (void) { return &_nextPhaseStartWaypointIndex; }
Fact* showAllMissionItems (void); Fact* showAllMissionItems (void) { return &_showAllMissionItems; }
Fact* showCurrentMissionItems(void); Fact* showCurrentMissionItems(void) { return &_showCurrentMissionItems; }
Fact* flightSpeed (void); Fact* flightSpeed (void) { return &_flightSpeed; }
Fact* arrivalReturnSpeed (void); Fact* arrivalReturnSpeed (void) { return &_arrivalReturnSpeed; };
Fact* altitude (void); Fact* altitude (void) { return &_altitude; }
Fact* reverse (void); Fact* reverse (void) { return &_reverse; }
Fact* enableSnake (void);
Fact* snakeTileWidth (void) {return &_snakeTileWidth;} Fact* enableSnake (void) { return &_enableSnake; }
Fact* snakeTileHeight (void) {return &_snakeTileHeight;} Fact* snakeTileWidth (void) { return &_snakeTileWidth;}
Fact* snakeMinTileArea (void) {return &_snakeMinTileArea;} Fact* snakeTileHeight (void) { return &_snakeTileHeight;}
Fact* snakeLineDistance (void) {return &_snakeLineDistance;} Fact* snakeMinTileArea (void) { return &_snakeMinTileArea;}
Fact* snakeMinTransectLength (void) {return &_snakeMinTransectLength;} Fact* snakeLineDistance (void) { return &_snakeLineDistance;}
Fact* snakeMinTransectLength (void) { return &_snakeMinTransectLength;}
QmlObjectListModel* snakeTiles (void) { return &_snakeTiles;}
bool uploadOverrideRequired (void) const; bool uploadOverrideRequired (void) const;
double phaseDistance (void) const; double phaseDistance (void) const;
double phaseDuration (void) const; double phaseDuration (void) const;
...@@ -208,6 +212,7 @@ signals: ...@@ -208,6 +212,7 @@ signals:
void returnUserRequestConfirmRequired (void); void returnUserRequestConfirmRequired (void);
void snakeConnectionStatusChanged (void); void snakeConnectionStatusChanged (void);
void snakeCalcInProgressChanged (void); void snakeCalcInProgressChanged (void);
void snakeTilesChanged (void);
private: private:
enum SRTL_Reason {BatteryLow, UserRequest}; enum SRTL_Reason {BatteryLow, UserRequest};
private slots: private slots:
...@@ -232,7 +237,7 @@ private slots: ...@@ -232,7 +237,7 @@ private slots:
void _setSnakeCalcInProgress (bool inProgress); void _setSnakeCalcInProgress (bool inProgress);
bool _verifyScenarioDefined (void); bool _verifyScenarioDefined (void);
bool _verifyScenarioDefinedWithErrorMessage (void); bool _verifyScenarioDefinedWithErrorMessage (void);
void _snakeStoreWorkerResults (const WorkerResult_t &r); void _snakeStoreWorkerResults ();
private: private:
......
...@@ -16,9 +16,9 @@ void SnakeWorker::setScenario(const Scenario &scenario) ...@@ -16,9 +16,9 @@ void SnakeWorker::setScenario(const Scenario &scenario)
void SnakeWorker::setProgress(const QList<qint8> &progress) void SnakeWorker::setProgress(const QList<qint8> &progress)
{ {
_progress.clear();
for (auto p : progress) { for (auto p : progress) {
assert(p >= -1); assert(p >= -1 && p <= 100);
assert(p <= 100);
_progress.push_back(p); _progress.push_back(p);
} }
} }
...@@ -35,15 +35,20 @@ void SnakeWorker::setMinTransectLength(double minTransectLength) ...@@ -35,15 +35,20 @@ void SnakeWorker::setMinTransectLength(double minTransectLength)
_minTransectLength = minTransectLength; _minTransectLength = minTransectLength;
} }
const WorkerResult_t &SnakeWorker::getResult() const
{
return _result;
}
void SnakeWorker::run() void SnakeWorker::run()
{ {
WorkerResult_t result{QVariantList{}, // Reset _result struct.
QVector<unsigned long>{}, _result.success = false;
QVector<unsigned long>{}, _result.errorMessage = "";
false, _result.waypoints.clear();
QString{}}; _result.returnPathIdx.clear();
_result.arrivalPathIdx.clear();
// partial success
FlightPlan flightplan; FlightPlan flightplan;
flightplan.setScenario(_scenario); flightplan.setScenario(_scenario);
flightplan.setProgress(_progress); flightplan.setProgress(_progress);
...@@ -52,28 +57,29 @@ void SnakeWorker::run() ...@@ -52,28 +57,29 @@ void SnakeWorker::run()
if ( !flightplan.generate(_lineDistance, _minTransectLength) ){ if ( !flightplan.generate(_lineDistance, _minTransectLength) ){
// error // error
for (auto c : flightplan.errorString){ for (auto c : flightplan.errorString){
result.errorMessage.push_back(QChar(c)); _result.errorMessage.push_back(QChar(c));
} }
} else { } else {
//success!!! //success!!!
_result.success = true;
// Fill result struct. // Fill result struct.
auto waypoints = flightplan.getWaypoints(); auto waypoints = flightplan.getWaypoints();
for (auto vertex : waypoints){ for (auto vertex : waypoints){
result.waypoints.append(QVariant::fromValue(QGeoCoordinate(vertex[0], vertex[1], 0))); _result.waypoints.append(QVariant::fromValue(QGeoCoordinate(vertex[0], vertex[1], 0)));
} }
auto arrivalPathIdx = flightplan.getArrivalPathIdx(); auto arrivalPathIdx = flightplan.getArrivalPathIdx();
for (auto idx : arrivalPathIdx){ for (auto idx : arrivalPathIdx){
result.arrivalPathIdx.append(idx); _result.arrivalPathIdx.append(idx);
} }
auto returnPathIdx = flightplan.getReturnPathIdx(); auto returnPathIdx = flightplan.getReturnPathIdx();
for (auto idx : returnPathIdx){ for (auto idx : returnPathIdx){
result.returnPathIdx.append(idx); _result.returnPathIdx.append(idx);
} }
} }
emit resultReady(result); emit resultReady();
} }
...@@ -34,8 +34,10 @@ public: ...@@ -34,8 +34,10 @@ public:
void setLineDistance (double lineDistance); void setLineDistance (double lineDistance);
void setMinTransectLength (double minTransectLength); void setMinTransectLength (double minTransectLength);
const WorkerResult_t &getResult() const;
signals: signals:
void resultReady(const WorkerResult_t &result); void resultReady();
protected: protected:
void run() override; void run() override;
...@@ -45,5 +47,6 @@ private: ...@@ -45,5 +47,6 @@ private:
vector<int8_t> _progress; vector<int8_t> _progress;
double _lineDistance; double _lineDistance;
double _minTransectLength; double _minTransectLength;
WorkerResult_t _result;
}; };
...@@ -33,7 +33,7 @@ WimaPlaner::WimaPlaner(QObject *parent) ...@@ -33,7 +33,7 @@ WimaPlaner::WimaPlaner(QObject *parent)
connect(&_updateTimer, &QTimer::timeout, this, &WimaPlaner::updateTimerSlot); connect(&_updateTimer, &QTimer::timeout, this, &WimaPlaner::updateTimerSlot);
connect(this, &WimaPlaner::joinedAreaValidChanged, this, &WimaPlaner::updateMission); connect(this, &WimaPlaner::joinedAreaValidChanged, this, &WimaPlaner::updateMission);
_updateTimer.setInterval(500); // 250 ms means: max update time 2*250 ms _updateTimer.setInterval(300); // 300 ms means: max update time 2*300 ms
_updateTimer.start(); _updateTimer.start();
// for debugging and testing purpose, remove if not needed anymore // for debugging and testing purpose, remove if not needed anymore
...@@ -445,8 +445,10 @@ bool WimaPlaner::loadFromFile(const QString &filename) ...@@ -445,8 +445,10 @@ bool WimaPlaner::loadFromFile(const QString &filename)
} }
//if (_circularSurvey == nullptr) //if (_circularSurvey == nullptr)
recalcJoinedArea(); if ( !recalcJoinedArea() )
updateMission(); return false;
if ( !updateMission() )
return false;
// remove temporary file // remove temporary file
if ( !temporaryFile.remove() ){ if ( !temporaryFile.remove() ){
...@@ -770,8 +772,9 @@ void WimaPlaner::updateTimerSlot() ...@@ -770,8 +772,9 @@ void WimaPlaner::updateTimerSlot()
// measurementArea // measurementArea
if (_measurementAreaChanging) { if (_measurementAreaChanging) {
if (_measurementArea.path() == _lastMeasurementAreaPath) { // is it still changing? if (_measurementArea.path() == _lastMeasurementAreaPath) { // is it still changing?
recalcJoinedArea(); setReadyForSync(false);
calcArrivalAndReturnPath(); if ( recalcJoinedArea() && calcArrivalAndReturnPath() )
setReadyForSync(true);
_measurementAreaChanging = false; _measurementAreaChanging = false;
} }
} else { } else {
...@@ -782,8 +785,9 @@ void WimaPlaner::updateTimerSlot() ...@@ -782,8 +785,9 @@ void WimaPlaner::updateTimerSlot()
// corridor // corridor
if (_corridorChanging) { if (_corridorChanging) {
if (_corridor.path() == _lastCorridorPath) { // is it still changing? if (_corridor.path() == _lastCorridorPath) { // is it still changing?
recalcJoinedArea(); setReadyForSync(false);
calcArrivalAndReturnPath(); if ( recalcJoinedArea() && calcArrivalAndReturnPath() )
setReadyForSync(true);
_corridorChanging = false; _corridorChanging = false;
} }
} else { } else {
...@@ -794,8 +798,9 @@ void WimaPlaner::updateTimerSlot() ...@@ -794,8 +798,9 @@ void WimaPlaner::updateTimerSlot()
// service area // service area
if (_serviceAreaChanging) { if (_serviceAreaChanging) {
if (_serviceArea.path() == _lastServiceAreaPath) { // is it still changing? if (_serviceArea.path() == _lastServiceAreaPath) { // is it still changing?
recalcJoinedArea(); setReadyForSync(false);
calcArrivalAndReturnPath(); if ( recalcJoinedArea() && calcArrivalAndReturnPath() )
setReadyForSync(true);
_serviceAreaChanging = false; _serviceAreaChanging = false;
} }
} else { } else {
......
...@@ -48,13 +48,13 @@ public: ...@@ -48,13 +48,13 @@ public:
//! \return True if the event is ready to be executed, false either. //! \return True if the event is ready to be executed, false either.
//! //!
//! This function must be called by a user provided timer interrupt handler. A internal counter increases with every call. //! This function must be called by a user provided timer interrupt handler. A internal counter increases with every call.
//! If timerInterval <= tickInerval*counter the counter gets reset and the function returns true. If the condition is not //! If _tickInerval <= _timerInterval*_tickCount the counter gets reset and the function returns true. If the condition is not
//! met the function returns false. //! met the function returns false.
//! //!
bool ready(void) { bool ready(void) {
assert(_isInitialized == true); assert(_isInitialized == true);
_tickCount++; _tickCount++;
bool ready = _timerInterval <= _tickInerval*_tickCount; bool ready = _tickInerval <= _timerInterval*_tickCount;
if (ready) if (ready)
_tickCount = 0; _tickCount = 0;
return ready; return ready;
......
...@@ -148,7 +148,7 @@ int main(int argc, char *argv[]) ...@@ -148,7 +148,7 @@ int main(int argc, char *argv[])
// install the message handler // install the message handler
AppMessages::installHandler(); AppMessages::installHandler();
QList<QPair<QByteArray,QByteArray>
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
#ifndef __ios__ #ifndef __ios__
// Prevent Apple's app nap from screwing us over // Prevent Apple's app nap from screwing us over
...@@ -253,8 +253,8 @@ QList<QPair<QByteArray,QByteArray> ...@@ -253,8 +253,8 @@ QList<QPair<QByteArray,QByteArray>
// on in the code. // on in the code.
qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >(); qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();
// Snake // Snake (Is this the right place for the following statement?)
qRegisterMetaType<WorkerResult>("WorkerResult"); //qRegisterMetaType<WorkerResult_t>("WorkerResult");
app->_initCommon(); app->_initCommon();
//-- Initialize Cache System //-- Initialize Cache System
......
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