Commit c65f8eca authored by Valentin Platzgummer's avatar Valentin Platzgummer

wima controller mod, appimage updated

parent 4acc1d5d
...@@ -448,7 +448,6 @@ HEADERS += \ ...@@ -448,7 +448,6 @@ HEADERS += \
src/Wima/Snake/QNemoHeartbeat.h \ src/Wima/Snake/QNemoHeartbeat.h \
src/Wima/Snake/QNemoProgress.h \ src/Wima/Snake/QNemoProgress.h \
src/Wima/Snake/QNemoProgress.h \ src/Wima/Snake/QNemoProgress.h \
src/Wima/Snake/SnakeThread.h \
src/Wima/Snake/SnakeTile.h \ src/Wima/Snake/SnakeTile.h \
src/Wima/Snake/SnakeTileLocal.h \ src/Wima/Snake/SnakeTileLocal.h \
src/Wima/Snake/SnakeTiles.h \ src/Wima/Snake/SnakeTiles.h \
...@@ -513,7 +512,6 @@ SOURCES += \ ...@@ -513,7 +512,6 @@ SOURCES += \
src/Wima/Geometry/GeoPoint3D.cpp \ src/Wima/Geometry/GeoPoint3D.cpp \
src/Wima/Snake/NemoInterface.cpp \ src/Wima/Snake/NemoInterface.cpp \
src/Wima/Snake/QNemoProgress.cc \ src/Wima/Snake/QNemoProgress.cc \
src/Wima/Snake/SnakeThread.cc \
src/Wima/Snake/SnakeTile.cpp \ src/Wima/Snake/SnakeTile.cpp \
src/Wima/WaypointManager/AreaInterface.cpp \ src/Wima/WaypointManager/AreaInterface.cpp \
src/Wima/WaypointManager/DefaultManager.cpp \ src/Wima/WaypointManager/DefaultManager.cpp \
......
...@@ -241,43 +241,66 @@ FlightMap { ...@@ -241,43 +241,66 @@ FlightMap {
color: "green" color: "green"
} }
// Add Snake tile center points to the map // // Add Snake tile center points to the map
MapItemView { // MapItemView {
property bool _enable: wimaController.enableWimaController.value // id:progressView
&& wimaController.enableSnake.value // property bool _enable: wimaController.enableWimaController.value
model: _enable ? wimaController.snakeTileCenterPoints : 0 // && wimaController.enableSnake.value
// property bool valid: wimaController.snakeTileCenterPoints.length
delegate: ProgressIndicator{ // === wimaController.nemoProgress.length
coordinate: modelData // model: _enable ? wimaController.snakeTileCenterPoints : 0
currentValue: getProgress()
width: 10 // delegate: ProgressIndicator{
height: 10 // coordinate: modelData
z: 1 // currentValue: getProgress()
// z: 1
function getProgress() {
var progress = wimaController.nemoProgress[index] // function getProgress() {
if (progress < 0) // var progress = 0
progress = 0 // if (progressView.valid){
if (progress > 100) // progress = wimaController.nemoProgress[index]
progress = 100 // }
return progress // if (progress < 0)
} // progress = 0
} // if (progress > 100)
} // progress = 100
// return progress
// }
// }
// }
// Add Snake tiles to the map // Add Snake tiles to the map
MapItemView { MapItemView {
id: tileView
property bool _enable: wimaController.enableWimaController.value property bool _enable: wimaController.enableWimaController.value
&& wimaController.enableSnake.value && wimaController.enableSnake.value
property bool valid: wimaController.snakeTileCenterPoints.length
=== wimaController.nemoProgress.length
model: _enable ? wimaController.snakeTiles : 0 model: _enable ? wimaController.snakeTiles : 0
delegate: MapPolygon{ delegate: MapPolygon{
path: object.path; path: object.path;
border.color: "black" border.color: "black"
border.width: 1 border.width: 1
color: "transparent" color: getColor()
opacity: 1 opacity: 0.6
z: 2 z: 2
function getColor() {
var progress = 0
if (tileView.valid){
progress = wimaController.nemoProgress[index]
}
if (progress < 25)
return "transparent"
if (progress < 50)
return "orange"
if (progress < 75)
return "yellow"
if (progress < 100)
return "greenyellow"
return "limegreen"
}
} }
} }
......
...@@ -7,476 +7,460 @@ ...@@ -7,476 +7,460 @@
* *
****************************************************************************/ ****************************************************************************/
#include <QStringList>
#include <QDebug> #include <QDebug>
#include <QStringList>
#include "MissionItem.h"
#include "FirmwarePluginManager.h" #include "FirmwarePluginManager.h"
#include "QGCApplication.h"
#include "JsonHelper.h" #include "JsonHelper.h"
#include "MissionItem.h"
#include "QGCApplication.h"
#include "VisualMissionItem.h" #include "VisualMissionItem.h"
const char* MissionItem::_jsonFrameKey = "frame"; const char *MissionItem::_jsonFrameKey = "frame";
const char* MissionItem::_jsonCommandKey = "command"; const char *MissionItem::_jsonCommandKey = "command";
const char* MissionItem::_jsonAutoContinueKey = "autoContinue"; const char *MissionItem::_jsonAutoContinueKey = "autoContinue";
const char* MissionItem::_jsonCoordinateKey = "coordinate"; const char *MissionItem::_jsonCoordinateKey = "coordinate";
const char* MissionItem::_jsonParamsKey = "params"; const char *MissionItem::_jsonParamsKey = "params";
const char* MissionItem::_jsonDoJumpIdKey = "doJumpId"; const char *MissionItem::_jsonDoJumpIdKey = "doJumpId";
// Deprecated V1 format keys // Deprecated V1 format keys
const char* MissionItem::_jsonParam1Key = "param1"; const char *MissionItem::_jsonParam1Key = "param1";
const char* MissionItem::_jsonParam2Key = "param2"; const char *MissionItem::_jsonParam2Key = "param2";
const char* MissionItem::_jsonParam3Key = "param3"; const char *MissionItem::_jsonParam3Key = "param3";
const char* MissionItem::_jsonParam4Key = "param4"; const char *MissionItem::_jsonParam4Key = "param4";
MissionItem::MissionItem(QObject* parent) MissionItem::MissionItem(QObject *parent)
: QObject(parent) : QObject(parent),
, _sequenceNumber(0) _autoContinueFact(0, "AutoContinue", FactMetaData::valueTypeUint32),
, _doJumpId(-1) _commandFact(0, "", FactMetaData::valueTypeUint32),
, _isCurrentItem(false) _frameFact(0, "", FactMetaData::valueTypeUint32),
, _autoContinueFact (0, "AutoContinue", FactMetaData::valueTypeUint32) _param1Fact(0, "Param1:", FactMetaData::valueTypeDouble),
, _commandFact (0, "", FactMetaData::valueTypeUint32) _param2Fact(0, "Param2:", FactMetaData::valueTypeDouble),
, _frameFact (0, "", FactMetaData::valueTypeUint32) _param3Fact(0, "Param3:", FactMetaData::valueTypeDouble),
, _param1Fact (0, "Param1:", FactMetaData::valueTypeDouble) _param4Fact(0, "Param4:", FactMetaData::valueTypeDouble),
, _param2Fact (0, "Param2:", FactMetaData::valueTypeDouble) _param5Fact(0, "Latitude:", FactMetaData::valueTypeDouble),
, _param3Fact (0, "Param3:", FactMetaData::valueTypeDouble) _param6Fact(0, "Longitude:", FactMetaData::valueTypeDouble),
, _param4Fact (0, "Param4:", FactMetaData::valueTypeDouble) _param7Fact(0, "Altitude:", FactMetaData::valueTypeDouble),
, _param5Fact (0, "Latitude:", FactMetaData::valueTypeDouble) _sequenceNumber(0), _doJumpId(-1), _isCurrentItem(false) {
, _param6Fact (0, "Longitude:", FactMetaData::valueTypeDouble) // Need a good command and frame before we start passing signals around
, _param7Fact (0, "Altitude:", FactMetaData::valueTypeDouble) _commandFact.setRawValue(MAV_CMD_NAV_WAYPOINT);
{ _frameFact.setRawValue(MAV_FRAME_GLOBAL_RELATIVE_ALT);
// Need a good command and frame before we start passing signals around
_commandFact.setRawValue(MAV_CMD_NAV_WAYPOINT); setAutoContinue(true);
_frameFact.setRawValue(MAV_FRAME_GLOBAL_RELATIVE_ALT);
connect(&_param1Fact, &Fact::rawValueChanged, this,
setAutoContinue(true); &MissionItem::_param1Changed);
connect(&_param2Fact, &Fact::rawValueChanged, this,
connect(&_param1Fact, &Fact::rawValueChanged, this, &MissionItem::_param1Changed); &MissionItem::_param2Changed);
connect(&_param2Fact, &Fact::rawValueChanged, this, &MissionItem::_param2Changed); connect(&_param3Fact, &Fact::rawValueChanged, this,
connect(&_param3Fact, &Fact::rawValueChanged, this, &MissionItem::_param3Changed); &MissionItem::_param3Changed);
}
MissionItem::MissionItem(int sequenceNumber,
MAV_CMD command,
MAV_FRAME frame,
double param1,
double param2,
double param3,
double param4,
double param5,
double param6,
double param7,
bool autoContinue,
bool isCurrentItem,
QObject* parent)
: QObject(parent)
, _sequenceNumber(sequenceNumber)
, _doJumpId(-1)
, _isCurrentItem(isCurrentItem)
, _commandFact (0, "", FactMetaData::valueTypeUint32)
, _frameFact (0, "", FactMetaData::valueTypeUint32)
, _param1Fact (0, "Param1:", FactMetaData::valueTypeDouble)
, _param2Fact (0, "Param2:", FactMetaData::valueTypeDouble)
, _param3Fact (0, "Param3:", FactMetaData::valueTypeDouble)
, _param4Fact (0, "Param4:", FactMetaData::valueTypeDouble)
, _param5Fact (0, "Lat/X:", FactMetaData::valueTypeDouble)
, _param6Fact (0, "Lon/Y:", FactMetaData::valueTypeDouble)
, _param7Fact (0, "Alt/Z:", FactMetaData::valueTypeDouble)
{
// Need a good command and frame before we start passing signals around
_commandFact.setRawValue(MAV_CMD_NAV_WAYPOINT);
_frameFact.setRawValue(MAV_FRAME_GLOBAL_RELATIVE_ALT);
setCommand(command);
setFrame(frame);
setAutoContinue(autoContinue);
_param1Fact.setRawValue(param1);
_param2Fact.setRawValue(param2);
_param3Fact.setRawValue(param3);
_param4Fact.setRawValue(param4);
_param5Fact.setRawValue(param5);
_param6Fact.setRawValue(param6);
_param7Fact.setRawValue(param7);
connect(&_param2Fact, &Fact::rawValueChanged, this, &MissionItem::_param2Changed);
connect(&_param3Fact, &Fact::rawValueChanged, this, &MissionItem::_param3Changed);
} }
MissionItem::MissionItem(const MissionItem& other, QObject* parent) MissionItem::MissionItem(int sequenceNumber, MAV_CMD command, MAV_FRAME frame,
: QObject(parent) double param1, double param2, double param3,
, _sequenceNumber(0) double param4, double param5, double param6,
, _doJumpId(-1) double param7, bool autoContinue, bool isCurrentItem,
, _isCurrentItem(false) QObject *parent)
, _commandFact (0, "", FactMetaData::valueTypeUint32) : QObject(parent), _commandFact(0, "", FactMetaData::valueTypeUint32),
, _frameFact (0, "", FactMetaData::valueTypeUint32) _frameFact(0, "", FactMetaData::valueTypeUint32),
, _param1Fact (0, "Param1:", FactMetaData::valueTypeDouble) _param1Fact(0, "Param1:", FactMetaData::valueTypeDouble),
, _param2Fact (0, "Param2:", FactMetaData::valueTypeDouble) _param2Fact(0, "Param2:", FactMetaData::valueTypeDouble),
, _param3Fact (0, "Param3:", FactMetaData::valueTypeDouble) _param3Fact(0, "Param3:", FactMetaData::valueTypeDouble),
, _param4Fact (0, "Param4:", FactMetaData::valueTypeDouble) _param4Fact(0, "Param4:", FactMetaData::valueTypeDouble),
, _param5Fact (0, "Lat/X:", FactMetaData::valueTypeDouble) _param5Fact(0, "Lat/X:", FactMetaData::valueTypeDouble),
, _param6Fact (0, "Lon/Y:", FactMetaData::valueTypeDouble) _param6Fact(0, "Lon/Y:", FactMetaData::valueTypeDouble),
, _param7Fact (0, "Alt/Z:", FactMetaData::valueTypeDouble) _param7Fact(0, "Alt/Z:", FactMetaData::valueTypeDouble),
{ _sequenceNumber(sequenceNumber), _doJumpId(-1),
// Need a good command and frame before we start passing signals around _isCurrentItem(isCurrentItem) {
_commandFact.setRawValue(MAV_CMD_NAV_WAYPOINT); // Need a good command and frame before we start passing signals around
_frameFact.setRawValue(MAV_FRAME_GLOBAL_RELATIVE_ALT); _commandFact.setRawValue(MAV_CMD_NAV_WAYPOINT);
_frameFact.setRawValue(MAV_FRAME_GLOBAL_RELATIVE_ALT);
*this = other;
setCommand(command);
connect(&_param2Fact, &Fact::rawValueChanged, this, &MissionItem::_param2Changed); setFrame(frame);
connect(&_param3Fact, &Fact::rawValueChanged, this, &MissionItem::_param3Changed); setAutoContinue(autoContinue);
_param1Fact.setRawValue(param1);
_param2Fact.setRawValue(param2);
_param3Fact.setRawValue(param3);
_param4Fact.setRawValue(param4);
_param5Fact.setRawValue(param5);
_param6Fact.setRawValue(param6);
_param7Fact.setRawValue(param7);
connect(&_param2Fact, &Fact::rawValueChanged, this,
&MissionItem::_param2Changed);
connect(&_param3Fact, &Fact::rawValueChanged, this,
&MissionItem::_param3Changed);
} }
const MissionItem& MissionItem::operator=(const MissionItem& other) MissionItem::MissionItem(const MissionItem &other, QObject *parent)
{ : QObject(parent), _commandFact(0, "", FactMetaData::valueTypeUint32),
_doJumpId = other._doJumpId; _frameFact(0, "", FactMetaData::valueTypeUint32),
_param1Fact(0, "Param1:", FactMetaData::valueTypeDouble),
setCommand(other.command()); _param2Fact(0, "Param2:", FactMetaData::valueTypeDouble),
setFrame(other.frame()); _param3Fact(0, "Param3:", FactMetaData::valueTypeDouble),
setSequenceNumber(other._sequenceNumber); _param4Fact(0, "Param4:", FactMetaData::valueTypeDouble),
setAutoContinue(other.autoContinue()); _param5Fact(0, "Lat/X:", FactMetaData::valueTypeDouble),
setIsCurrentItem(other._isCurrentItem); _param6Fact(0, "Lon/Y:", FactMetaData::valueTypeDouble),
_param7Fact(0, "Alt/Z:", FactMetaData::valueTypeDouble),
_param1Fact.setRawValue(other._param1Fact.rawValue()); _sequenceNumber(0), _doJumpId(-1), _isCurrentItem(false) {
_param2Fact.setRawValue(other._param2Fact.rawValue()); // Need a good command and frame before we start passing signals around
_param3Fact.setRawValue(other._param3Fact.rawValue()); _commandFact.setRawValue(MAV_CMD_NAV_WAYPOINT);
_param4Fact.setRawValue(other._param4Fact.rawValue()); _frameFact.setRawValue(MAV_FRAME_GLOBAL_RELATIVE_ALT);
_param5Fact.setRawValue(other._param5Fact.rawValue());
_param6Fact.setRawValue(other._param6Fact.rawValue()); *this = other;
_param7Fact.setRawValue(other._param7Fact.rawValue());
connect(&_param2Fact, &Fact::rawValueChanged, this,
return *this; &MissionItem::_param2Changed);
connect(&_param3Fact, &Fact::rawValueChanged, this,
&MissionItem::_param3Changed);
} }
MissionItem::~MissionItem() const MissionItem &MissionItem::operator=(const MissionItem &other) {
{ _doJumpId = other._doJumpId;
} setCommand(other.command());
setFrame(other.frame());
setSequenceNumber(other._sequenceNumber);
setAutoContinue(other.autoContinue());
setIsCurrentItem(other._isCurrentItem);
void MissionItem::save(QJsonObject& json) const _param1Fact.setRawValue(other._param1Fact.rawValue());
{ _param2Fact.setRawValue(other._param2Fact.rawValue());
json[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeSimpleItemValue; _param3Fact.setRawValue(other._param3Fact.rawValue());
json[_jsonFrameKey] = frame(); _param4Fact.setRawValue(other._param4Fact.rawValue());
json[_jsonCommandKey] = command(); _param5Fact.setRawValue(other._param5Fact.rawValue());
json[_jsonAutoContinueKey] = autoContinue(); _param6Fact.setRawValue(other._param6Fact.rawValue());
json[_jsonDoJumpIdKey] = _sequenceNumber; _param7Fact.setRawValue(other._param7Fact.rawValue());
QJsonArray rgParams = { param1(), param2(), param3(), param4(), param5(), param6(), param7() }; return *this;
json[_jsonParamsKey] = rgParams;
} }
bool MissionItem::load(QTextStream &loadStream) MissionItem::~MissionItem() {}
{
const QStringList &wpParams = loadStream.readLine().split("\t");
if (wpParams.size() == 12) {
setCommand((MAV_CMD)wpParams[3].toInt()); // Has to be first since it triggers defaults to be set, which are then override by below set calls
setSequenceNumber(wpParams[0].toInt());
setIsCurrentItem(wpParams[1].toInt() == 1 ? true : false);
setFrame((MAV_FRAME)wpParams[2].toInt());
setParam1(wpParams[4].toDouble());
setParam2(wpParams[5].toDouble());
setParam3(wpParams[6].toDouble());
setParam4(wpParams[7].toDouble());
setParam5(wpParams[8].toDouble());
setParam6(wpParams[9].toDouble());
setParam7(wpParams[10].toDouble());
setAutoContinue(wpParams[11].toInt() == 1 ? true : false);
return true;
}
return false; void MissionItem::save(QJsonObject &json) const {
json[VisualMissionItem::jsonTypeKey] =
VisualMissionItem::jsonTypeSimpleItemValue;
json[_jsonFrameKey] = frame();
json[_jsonCommandKey] = command();
json[_jsonAutoContinueKey] = autoContinue();
json[_jsonDoJumpIdKey] = _sequenceNumber;
QJsonArray rgParams = {param1(), param2(), param3(), param4(),
param5(), param6(), param7()};
json[_jsonParamsKey] = rgParams;
} }
bool MissionItem::_convertJsonV1ToV2(const QJsonObject& json, QJsonObject& v2Json, QString& errorString) bool MissionItem::load(QTextStream &loadStream) {
{ const QStringList &wpParams = loadStream.readLine().split("\t");
// V1 format type = "missionItem", V2 format type = "MissionItem" if (wpParams.size() == 12) {
// V1 format has params in separate param[1-n] keys setCommand(
// V2 format has params in params array (MAV_CMD)wpParams[3]
v2Json = json; .toInt()); // Has to be first since it triggers defaults to be set,
// which are then override by below set calls
if (json.contains(_jsonParamsKey)) { setSequenceNumber(wpParams[0].toInt());
// Already V2 format setIsCurrentItem(wpParams[1].toInt() == 1 ? true : false);
return true; setFrame((MAV_FRAME)wpParams[2].toInt());
} setParam1(wpParams[4].toDouble());
setParam2(wpParams[5].toDouble());
QList<JsonHelper::KeyValidateInfo> keyInfoList = { setParam3(wpParams[6].toDouble());
{ VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, setParam4(wpParams[7].toDouble());
{ _jsonParam1Key, QJsonValue::Double, true }, setParam5(wpParams[8].toDouble());
{ _jsonParam2Key, QJsonValue::Double, true }, setParam6(wpParams[9].toDouble());
{ _jsonParam3Key, QJsonValue::Double, true }, setParam7(wpParams[10].toDouble());
{ _jsonParam4Key, QJsonValue::Double, true }, setAutoContinue(wpParams[11].toInt() == 1 ? true : false);
}; return true;
if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) { }
return false;
}
if (v2Json[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("missionItem")) { return false;
v2Json[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeSimpleItemValue; }
}
QJsonArray rgParams = { json[_jsonParam1Key].toDouble(), json[_jsonParam2Key].toDouble(), json[_jsonParam3Key].toDouble(), json[_jsonParam4Key].toDouble() }; bool MissionItem::_convertJsonV1ToV2(const QJsonObject &json,
v2Json[_jsonParamsKey] = rgParams; QJsonObject &v2Json,
v2Json.remove(_jsonParam1Key); QString &errorString) {
v2Json.remove(_jsonParam2Key); // V1 format type = "missionItem", V2 format type = "MissionItem"
v2Json.remove(_jsonParam3Key); // V1 format has params in separate param[1-n] keys
v2Json.remove(_jsonParam4Key); // V2 format has params in params array
v2Json = json;
if (json.contains(_jsonParamsKey)) {
// Already V2 format
return true; return true;
}
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{VisualMissionItem::jsonTypeKey, QJsonValue::String, true},
{_jsonParam1Key, QJsonValue::Double, true},
{_jsonParam2Key, QJsonValue::Double, true},
{_jsonParam3Key, QJsonValue::Double, true},
{_jsonParam4Key, QJsonValue::Double, true},
};
if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) {
return false;
}
if (v2Json[VisualMissionItem::jsonTypeKey].toString() ==
QStringLiteral("missionItem")) {
v2Json[VisualMissionItem::jsonTypeKey] =
VisualMissionItem::jsonTypeSimpleItemValue;
}
QJsonArray rgParams = {
json[_jsonParam1Key].toDouble(), json[_jsonParam2Key].toDouble(),
json[_jsonParam3Key].toDouble(), json[_jsonParam4Key].toDouble()};
v2Json[_jsonParamsKey] = rgParams;
v2Json.remove(_jsonParam1Key);
v2Json.remove(_jsonParam2Key);
v2Json.remove(_jsonParam3Key);
v2Json.remove(_jsonParam4Key);
return true;
} }
bool MissionItem::_convertJsonV2ToV3(QJsonObject& json, QString& errorString) bool MissionItem::_convertJsonV2ToV3(QJsonObject &json, QString &errorString) {
{ // V2 format: param 5/6/7 stored in GeoCoordinate
// V2 format: param 5/6/7 stored in GeoCoordinate // V3 format: param 5/6/7 stored in params array
// V3 format: param 5/6/7 stored in params array
if (!json.contains(_jsonCoordinateKey)) {
// Already V3 format
return true;
}
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ _jsonCoordinateKey, QJsonValue::Array, true },
};
if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) {
return false;
}
QGeoCoordinate coordinate;
if (!JsonHelper::loadGeoCoordinate(json[_jsonCoordinateKey], true /* altitudeRequired */, coordinate, errorString)) {
return false;
}
QJsonArray rgParam = json[_jsonParamsKey].toArray();
rgParam.append(coordinate.latitude());
rgParam.append(coordinate.longitude());
rgParam.append(coordinate.altitude());
json[_jsonParamsKey] = rgParam;
json.remove(_jsonCoordinateKey);
if (!json.contains(_jsonCoordinateKey)) {
// Already V3 format
return true; return true;
} }
bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& errorString)
{
QJsonObject convertedJson;
if (!_convertJsonV1ToV2(json, convertedJson, errorString)) {
return false;
}
if (!_convertJsonV2ToV3(convertedJson, errorString)) {
return false;
}
QList<JsonHelper::KeyValidateInfo> keyInfoList = { QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, {_jsonCoordinateKey, QJsonValue::Array, true},
{ _jsonFrameKey, QJsonValue::Double, true }, };
{ _jsonCommandKey, QJsonValue::Double, true }, if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) {
{ _jsonParamsKey, QJsonValue::Array, true }, return false;
{ _jsonAutoContinueKey, QJsonValue::Bool, true }, }
{ _jsonDoJumpIdKey, QJsonValue::Double, false },
};
if (!JsonHelper::validateKeys(convertedJson, keyInfoList, errorString)) {
return false;
}
if (convertedJson[VisualMissionItem::jsonTypeKey] != VisualMissionItem::jsonTypeSimpleItemValue) { QGeoCoordinate coordinate;
errorString = tr("Type found: %1 must be: %2").arg(convertedJson[VisualMissionItem::jsonTypeKey].toString()).arg(VisualMissionItem::jsonTypeSimpleItemValue); if (!JsonHelper::loadGeoCoordinate(json[_jsonCoordinateKey],
return false; true /* altitudeRequired */, coordinate,
} errorString)) {
return false;
}
QJsonArray rgParams = convertedJson[_jsonParamsKey].toArray(); QJsonArray rgParam = json[_jsonParamsKey].toArray();
if (rgParams.count() != 7) { rgParam.append(coordinate.latitude());
errorString = tr("%1 key must contains 7 values").arg(_jsonParamsKey); rgParam.append(coordinate.longitude());
return false; rgParam.append(coordinate.altitude());
} json[_jsonParamsKey] = rgParam;
for (int i=0; i<4; i++) { json.remove(_jsonCoordinateKey);
if (rgParams[i].type() != QJsonValue::Double && rgParams[i].type() != QJsonValue::Null) {
errorString = tr("Param %1 incorrect type %2, must be double or null").arg(i+1).arg(rgParams[i].type());
return false;
}
}
// Make sure to set these first since they can signal other changes return true;
setCommand((MAV_CMD)convertedJson[_jsonCommandKey].toInt()); }
setFrame((MAV_FRAME)convertedJson[_jsonFrameKey].toInt());
_doJumpId = -1; bool MissionItem::load(const QJsonObject &json, int sequenceNumber,
if (convertedJson.contains(_jsonDoJumpIdKey)) { QString &errorString) {
_doJumpId = convertedJson[_jsonDoJumpIdKey].toInt(); QJsonObject convertedJson;
} if (!_convertJsonV1ToV2(json, convertedJson, errorString)) {
setIsCurrentItem(false); return false;
setSequenceNumber(sequenceNumber); }
setAutoContinue(convertedJson[_jsonAutoContinueKey].toBool()); if (!_convertJsonV2ToV3(convertedJson, errorString)) {
return false;
setParam1(JsonHelper::possibleNaNJsonValue(rgParams[0])); }
setParam2(JsonHelper::possibleNaNJsonValue(rgParams[1]));
setParam3(JsonHelper::possibleNaNJsonValue(rgParams[2])); QList<JsonHelper::KeyValidateInfo> keyInfoList = {
setParam4(JsonHelper::possibleNaNJsonValue(rgParams[3])); {VisualMissionItem::jsonTypeKey, QJsonValue::String, true},
setParam5(JsonHelper::possibleNaNJsonValue(rgParams[4])); {_jsonFrameKey, QJsonValue::Double, true},
setParam6(JsonHelper::possibleNaNJsonValue(rgParams[5])); {_jsonCommandKey, QJsonValue::Double, true},
setParam7(JsonHelper::possibleNaNJsonValue(rgParams[6])); {_jsonParamsKey, QJsonValue::Array, true},
{_jsonAutoContinueKey, QJsonValue::Bool, true},
{_jsonDoJumpIdKey, QJsonValue::Double, false},
};
if (!JsonHelper::validateKeys(convertedJson, keyInfoList, errorString)) {
return false;
}
if (convertedJson[VisualMissionItem::jsonTypeKey] !=
VisualMissionItem::jsonTypeSimpleItemValue) {
errorString =
tr("Type found: %1 must be: %2")
.arg(convertedJson[VisualMissionItem::jsonTypeKey].toString())
.arg(VisualMissionItem::jsonTypeSimpleItemValue);
return false;
}
return true; QJsonArray rgParams = convertedJson[_jsonParamsKey].toArray();
if (rgParams.count() != 7) {
errorString = tr("%1 key must contains 7 values").arg(_jsonParamsKey);
return false;
}
for (int i = 0; i < 4; i++) {
if (rgParams[i].type() != QJsonValue::Double &&
rgParams[i].type() != QJsonValue::Null) {
errorString = tr("Param %1 incorrect type %2, must be double or null")
.arg(i + 1)
.arg(rgParams[i].type());
return false;
}
}
// Make sure to set these first since they can signal other changes
setCommand((MAV_CMD)convertedJson[_jsonCommandKey].toInt());
setFrame((MAV_FRAME)convertedJson[_jsonFrameKey].toInt());
_doJumpId = -1;
if (convertedJson.contains(_jsonDoJumpIdKey)) {
_doJumpId = convertedJson[_jsonDoJumpIdKey].toInt();
}
setIsCurrentItem(false);
setSequenceNumber(sequenceNumber);
setAutoContinue(convertedJson[_jsonAutoContinueKey].toBool());
setParam1(JsonHelper::possibleNaNJsonValue(rgParams[0]));
setParam2(JsonHelper::possibleNaNJsonValue(rgParams[1]));
setParam3(JsonHelper::possibleNaNJsonValue(rgParams[2]));
setParam4(JsonHelper::possibleNaNJsonValue(rgParams[3]));
setParam5(JsonHelper::possibleNaNJsonValue(rgParams[4]));
setParam6(JsonHelper::possibleNaNJsonValue(rgParams[5]));
setParam7(JsonHelper::possibleNaNJsonValue(rgParams[6]));
return true;
} }
void MissionItem::setSequenceNumber(int sequenceNumber) {
void MissionItem::setSequenceNumber(int sequenceNumber) if (_sequenceNumber != sequenceNumber) {
{ _sequenceNumber = sequenceNumber;
if (_sequenceNumber != sequenceNumber) { emit sequenceNumberChanged(_sequenceNumber);
_sequenceNumber = sequenceNumber; }
emit sequenceNumberChanged(_sequenceNumber);
}
} }
void MissionItem::setCommand(MAV_CMD command) void MissionItem::setCommand(MAV_CMD command) {
{ if ((MAV_CMD)this->command() != command) {
if ((MAV_CMD)this->command() != command) { _commandFact.setRawValue(command);
_commandFact.setRawValue(command); }
}
} }
void MissionItem::setFrame(MAV_FRAME frame) void MissionItem::setFrame(MAV_FRAME frame) {
{ if (this->frame() != frame) {
if (this->frame() != frame) { _frameFact.setRawValue(frame);
_frameFact.setRawValue(frame); }
}
} }
void MissionItem::setAutoContinue(bool autoContinue) void MissionItem::setAutoContinue(bool autoContinue) {
{ if (this->autoContinue() != autoContinue) {
if (this->autoContinue() != autoContinue) { _autoContinueFact.setRawValue(autoContinue);
_autoContinueFact.setRawValue(autoContinue); }
}
} }
void MissionItem::setIsCurrentItem(bool isCurrentItem) void MissionItem::setIsCurrentItem(bool isCurrentItem) {
{ if (_isCurrentItem != isCurrentItem) {
if (_isCurrentItem != isCurrentItem) { _isCurrentItem = isCurrentItem;
_isCurrentItem = isCurrentItem; emit isCurrentItemChanged(isCurrentItem);
emit isCurrentItemChanged(isCurrentItem); }
}
} }
void MissionItem::setParam1(double param) void MissionItem::setParam1(double param) {
{ if (param1() != param) {
if (param1() != param) { _param1Fact.setRawValue(param);
_param1Fact.setRawValue(param); }
}
} }
void MissionItem::setParam2(double param) void MissionItem::setParam2(double param) {
{ if (param2() != param) {
if (param2() != param) { _param2Fact.setRawValue(param);
_param2Fact.setRawValue(param); }
}
} }
void MissionItem::setParam3(double param) void MissionItem::setParam3(double param) {
{ if (param3() != param) {
if (param3() != param) { _param3Fact.setRawValue(param);
_param3Fact.setRawValue(param); }
}
} }
void MissionItem::setParam4(double param) void MissionItem::setParam4(double param) {
{ if (param4() != param) {
if (param4() != param) { _param4Fact.setRawValue(param);
_param4Fact.setRawValue(param); }
}
} }
void MissionItem::setParam5(double param) void MissionItem::setParam5(double param) {
{ if (param5() != param) {
if (param5() != param) { _param5Fact.setRawValue(param);
_param5Fact.setRawValue(param); }
}
} }
void MissionItem::setParam6(double param) void MissionItem::setParam6(double param) {
{ if (param6() != param) {
if (param6() != param) { _param6Fact.setRawValue(param);
_param6Fact.setRawValue(param); }
}
} }
void MissionItem::setParam7(double param) void MissionItem::setParam7(double param) {
{ if (param7() != param) {
if (param7() != param) { _param7Fact.setRawValue(param);
_param7Fact.setRawValue(param); }
}
} }
QGeoCoordinate MissionItem::coordinate(void) const QGeoCoordinate MissionItem::coordinate(void) const {
{ if (!std::isfinite(param5()) || !std::isfinite(param6())) {
if(!std::isfinite(param5()) || !std::isfinite(param6())) { //-- If either of these are NAN, return an invalid
//-- If either of these are NAN, return an invalid (QGeoCoordinate::isValid() == false) coordinate //(QGeoCoordinate::isValid() == false) coordinate
return QGeoCoordinate(); return QGeoCoordinate();
} }
return QGeoCoordinate(param5(), param6(), param7()); return QGeoCoordinate(param5(), param6(), param7());
} }
double MissionItem::specifiedFlightSpeed(void) const double MissionItem::specifiedFlightSpeed(void) const {
{ double flightSpeed = std::numeric_limits<double>::quiet_NaN();
double flightSpeed = std::numeric_limits<double>::quiet_NaN();
if (_commandFact.rawValue().toInt() == MAV_CMD_DO_CHANGE_SPEED && _param2Fact.rawValue().toDouble() > 0) { if (_commandFact.rawValue().toInt() == MAV_CMD_DO_CHANGE_SPEED &&
flightSpeed = _param2Fact.rawValue().toDouble(); _param2Fact.rawValue().toDouble() > 0) {
} flightSpeed = _param2Fact.rawValue().toDouble();
}
return flightSpeed; return flightSpeed;
} }
double MissionItem::specifiedGimbalYaw(void) const double MissionItem::specifiedGimbalYaw(void) const {
{ double gimbalYaw = std::numeric_limits<double>::quiet_NaN();
double gimbalYaw = std::numeric_limits<double>::quiet_NaN();
if (_commandFact.rawValue().toInt() == MAV_CMD_DO_MOUNT_CONTROL && _param7Fact.rawValue().toInt() == MAV_MOUNT_MODE_MAVLINK_TARGETING) { if (_commandFact.rawValue().toInt() == MAV_CMD_DO_MOUNT_CONTROL &&
gimbalYaw = _param3Fact.rawValue().toDouble(); _param7Fact.rawValue().toInt() == MAV_MOUNT_MODE_MAVLINK_TARGETING) {
} gimbalYaw = _param3Fact.rawValue().toDouble();
}
return gimbalYaw; return gimbalYaw;
} }
double MissionItem::specifiedGimbalPitch(void) const double MissionItem::specifiedGimbalPitch(void) const {
{ double gimbalPitch = std::numeric_limits<double>::quiet_NaN();
double gimbalPitch = std::numeric_limits<double>::quiet_NaN();
if (_commandFact.rawValue().toInt() == MAV_CMD_DO_MOUNT_CONTROL && _param7Fact.rawValue().toInt() == MAV_MOUNT_MODE_MAVLINK_TARGETING) { if (_commandFact.rawValue().toInt() == MAV_CMD_DO_MOUNT_CONTROL &&
gimbalPitch = _param1Fact.rawValue().toDouble(); _param7Fact.rawValue().toInt() == MAV_MOUNT_MODE_MAVLINK_TARGETING) {
} gimbalPitch = _param1Fact.rawValue().toDouble();
}
return gimbalPitch; return gimbalPitch;
} }
void MissionItem::_param1Changed(QVariant value) void MissionItem::_param1Changed(QVariant value) {
{ Q_UNUSED(value);
Q_UNUSED(value);
double gimbalPitch = specifiedGimbalPitch(); double gimbalPitch = specifiedGimbalPitch();
if (!qIsNaN(gimbalPitch)) { if (!qIsNaN(gimbalPitch)) {
emit specifiedGimbalPitchChanged(gimbalPitch); emit specifiedGimbalPitchChanged(gimbalPitch);
} }
} }
void MissionItem::_param2Changed(QVariant value) void MissionItem::_param2Changed(QVariant value) {
{ Q_UNUSED(value);
Q_UNUSED(value);
double flightSpeed = specifiedFlightSpeed(); double flightSpeed = specifiedFlightSpeed();
if (!qIsNaN(flightSpeed)) { if (!qIsNaN(flightSpeed)) {
emit specifiedFlightSpeedChanged(flightSpeed); emit specifiedFlightSpeedChanged(flightSpeed);
} }
} }
void MissionItem::_param3Changed(QVariant value) void MissionItem::_param3Changed(QVariant value) {
{ Q_UNUSED(value);
Q_UNUSED(value);
double gimbalYaw = specifiedGimbalYaw(); double gimbalYaw = specifiedGimbalYaw();
if (!qIsNaN(gimbalYaw)) { if (!qIsNaN(gimbalYaw)) {
emit specifiedGimbalYawChanged(gimbalYaw); emit specifiedGimbalYawChanged(gimbalYaw);
} }
} }
...@@ -121,9 +121,9 @@ const QObject *QmlObjectListModel::operator[](int index) const { ...@@ -121,9 +121,9 @@ const QObject *QmlObjectListModel::operator[](int index) const {
return _objectList[index]; return _objectList[index];
} }
bool QmlObjectListModel::operator==(const QmlObjectListModel &other) { bool QmlObjectListModel::operator==(const QmlObjectListModel &other) const {
if (this->count() == other.count()) { if (this->count() == other.count()) {
for (std::size_t i = 0; i < this->count(); ++i) { for (int i = 0; i < this->count(); ++i) {
if (this->get(i) != other.get(i)) { if (this->get(i) != other.get(i)) {
return false; return false;
} }
...@@ -134,7 +134,7 @@ bool QmlObjectListModel::operator==(const QmlObjectListModel &other) { ...@@ -134,7 +134,7 @@ bool QmlObjectListModel::operator==(const QmlObjectListModel &other) {
} }
} }
bool QmlObjectListModel::operator==(const QmlObjectListModel &other) { bool QmlObjectListModel::operator!=(const QmlObjectListModel &other) const {
return !this->operator==(other); return !this->operator==(other);
} }
......
...@@ -51,8 +51,8 @@ public: ...@@ -51,8 +51,8 @@ public:
} }
QList<QObject *> *objectList() { return &_objectList; } QList<QObject *> *objectList() { return &_objectList; }
bool operator==(const QmlObjectListModel &other); bool operator==(const QmlObjectListModel &other) const;
bool operator!=(const QmlObjectListModel &other); bool operator!=(const QmlObjectListModel &other) const;
/// Calls deleteLater on all items and this itself. /// Calls deleteLater on all items and this itself.
void deleteListAndContents(); void deleteListAndContents();
......
...@@ -359,7 +359,12 @@ void CircularSurvey::_rebuildTransectsPhase1(void) { ...@@ -359,7 +359,12 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
// Store raw transects. // Store raw transects.
const auto &transectsENU = this->_workerOutput->transects; const auto &transectsENU = this->_workerOutput->transects;
const auto &ori = this->_referencePoint; const auto &ori = this->_referencePoint;
for (auto &t : transectsENU) { std::size_t startIdx = 0;
if (transectsENU.size() > 0 && transectsENU.front().size() == 1) {
startIdx = 1;
}
for (std::size_t i = startIdx; i < transectsENU.size(); ++i) {
const auto &t = transectsENU[i];
QList<QGeoCoordinate> trGeo; QList<QGeoCoordinate> trGeo;
for (auto &v : t) { for (auto &v : t) {
QGeoCoordinate c; QGeoCoordinate c;
......
...@@ -28,6 +28,15 @@ TileData &TileData::operator=(const TileData &other) { ...@@ -28,6 +28,15 @@ TileData &TileData::operator=(const TileData &other) {
return *this; return *this;
} }
bool TileData::operator==(const TileData &other) const {
return this->tiles == other.tiles &&
this->tileCenterPoints == other.tileCenterPoints;
}
bool TileData::operator!=(const TileData &other) const {
return !this->operator==(other);
}
void TileData::clear() { void TileData::clear() {
this->tiles.clearAndDeleteContents(); this->tiles.clearAndDeleteContents();
this->tileCenterPoints.clear(); this->tileCenterPoints.clear();
......
...@@ -17,6 +17,8 @@ public: ...@@ -17,6 +17,8 @@ public:
~TileData(); ~TileData();
TileData &operator=(const TileData &other); TileData &operator=(const TileData &other);
bool operator==(const TileData &other) const;
bool operator!=(const TileData &other) const;
void clear(); void clear();
std::size_t size() const; std::size_t size() const;
......
...@@ -61,10 +61,10 @@ QVariantList &WimaMeasurementAreaData::tileCenterPoints() { ...@@ -61,10 +61,10 @@ QVariantList &WimaMeasurementAreaData::tileCenterPoints() {
} }
const TileData &WimaMeasurementAreaData::tileData() const { const TileData &WimaMeasurementAreaData::tileData() const {
return this->tileData(); return this->_tileData;
} }
TileData &WimaMeasurementAreaData::tileData() { return this->tileData(); } TileData &WimaMeasurementAreaData::tileData() { return this->_tileData; }
const QVector<int> &WimaMeasurementAreaData::progress() const { const QVector<int> &WimaMeasurementAreaData::progress() const {
return this->_progress; return this->_progress;
......
...@@ -21,7 +21,7 @@ RoutingThread::~RoutingThread() { ...@@ -21,7 +21,7 @@ RoutingThread::~RoutingThread() {
this->wait(); this->wait();
} }
bool RoutingThread::calculating() { return this->_calculating; } bool RoutingThread::calculating() const { return this->_calculating; }
void RoutingThread::route(const snake::BoostPolygon &safeArea, void RoutingThread::route(const snake::BoostPolygon &safeArea,
const RoutingThread::Generator &generator) { const RoutingThread::Generator &generator) {
...@@ -107,7 +107,7 @@ void RoutingThread::run() { ...@@ -107,7 +107,7 @@ void RoutingThread::run() {
} // end calculation } // end calculation
#ifdef DEBUG_CIRCULAR_SURVEY #ifdef DEBUG_CIRCULAR_SURVEY
else { else {
qWarning() << "RoutingWorker::run(): preconditions failed."; qWarning() << "RoutingWorker::run(): generator() failed.";
} }
#endif #endif
#ifdef SHOW_CIRCULAR_SURVEY_TIME #ifdef SHOW_CIRCULAR_SURVEY_TIME
......
...@@ -27,11 +27,12 @@ class RoutingThread : public QThread { ...@@ -27,11 +27,12 @@ class RoutingThread : public QThread {
public: public:
using PtrRoutingData = QSharedPointer<RoutingData>; using PtrRoutingData = QSharedPointer<RoutingData>;
using Generator = std::function<bool(snake::Transects &)>; using Generator = std::function<bool(snake::Transects &)>;
using Consumer = std::function<void(const RoutingData &)>;
RoutingThread(QObject *parent = nullptr); RoutingThread(QObject *parent = nullptr);
~RoutingThread() override; ~RoutingThread() override;
bool calculating(); bool calculating() const;
public slots: public slots:
void route(const snake::BoostPolygon &safeArea, const Generator &generator); void route(const snake::BoostPolygon &safeArea, const Generator &generator);
......
#include "NemoInterface.h" #include "NemoInterface.h"
#include "SnakeTilesLocal.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#include "QGCToolbox.h" #include "QGCToolbox.h"
...@@ -135,12 +136,12 @@ void NemoInterface::Impl::setTileData(const TileData &tileData) { ...@@ -135,12 +136,12 @@ void NemoInterface::Impl::setTileData(const TileData &tileData) {
const auto &origin = this->ENUOrigin; const auto &origin = this->ENUOrigin;
this->tilesENU.polygons().clear(); this->tilesENU.polygons().clear();
bool error = false; bool error = false;
for (std::size_t i = 0; i < tileData.tiles.count(); ++i) { for (int i = 0; i < tileData.tiles.count(); ++i) {
*obj = tileData.tiles.get(i); obj = tileData.tiles.get(i);
*tile = qobject_cast<const SnakeTile *>(obj); tile = qobject_cast<const SnakeTile *>(obj);
if (tile != nullptr) { if (tile != nullptr) {
snake::BoostPolygon tileENU; SnakeTileLocal tileENU;
snake::areaToEnu(origin, tile->coordinateList(), tileENU); snake::areaToEnu(origin, tile->coordinateList(), tileENU.path());
this->tilesENU.polygons().push_back(std::move(tileENU)); this->tilesENU.polygons().push_back(std::move(tileENU));
} else { } else {
qWarning() << "NemoInterface::Impl::setTileData(): nullptr."; qWarning() << "NemoInterface::Impl::setTileData(): nullptr.";
...@@ -162,7 +163,7 @@ void NemoInterface::Impl::setTileData(const TileData &tileData) { ...@@ -162,7 +163,7 @@ void NemoInterface::Impl::setTileData(const TileData &tileData) {
} }
bool NemoInterface::Impl::hasTileData(const TileData &tileData) const { bool NemoInterface::Impl::hasTileData(const TileData &tileData) const {
return this->tileData = tileData; return this->tileData == tileData;
} }
NemoInterface::NemoStatus NemoInterface::Impl::status() { NemoInterface::NemoStatus NemoInterface::Impl::status() {
......
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
#include <QGeoCoordinate> #include <QGeoCoordinate>
#include <QObject> #include <QObject>
#include "SnakeTilesLocal.h"
#include <memory> #include <memory>
class TileData; class TileData;
......
#pragma once #pragma once
#include "Wima/Geometry/GenericPolygon.h" #include "Wima/Geometry/GenericPolygon.h"
using SnakeTileLocal = GenericPolygon<>; using SnakeTileLocal = GenericPolygon<QPointF, std::vector>;
#pragma once #pragma once
#include "Wima/Snake/SnakeTileLocal.h"
#include "Wima/Geometry/GenericPolygonArray.h" #include "Wima/Geometry/GenericPolygonArray.h"
#include "Wima/Snake/SnakeTileLocal.h"
typedef GenericPolygonArray<SnakeTileLocal, QVector> SnakeTilesLocal; #include <vector>
typedef GenericPolygonArray<SnakeTileLocal, std::vector> SnakeTilesLocal;
...@@ -92,10 +92,10 @@ struct BoundingBox { ...@@ -92,10 +92,10 @@ struct BoundingBox {
BoostPolygon corners; BoostPolygon corners;
}; };
template <class GeoPoint> template <class GeoPoint1, class GeoPoint2>
void toENU(const GeoPoint &origin, const GeoPoint &in, BoostPoint &out) { void toENU(const GeoPoint1 &origin, const GeoPoint2 &in, BoostPoint &out) {
GeographicLib::Geocentric earth(GeographicLib::Constants::WGS84_a(), static GeographicLib::Geocentric earth(GeographicLib::Constants::WGS84_a(),
GeographicLib::Constants::WGS84_f()); GeographicLib::Constants::WGS84_f());
GeographicLib::LocalCartesian proj(origin.latitude(), origin.longitude(), GeographicLib::LocalCartesian proj(origin.latitude(), origin.longitude(),
origin.altitude(), earth); origin.altitude(), earth);
...@@ -108,10 +108,26 @@ void toENU(const GeoPoint &origin, const GeoPoint &in, BoostPoint &out) { ...@@ -108,10 +108,26 @@ void toENU(const GeoPoint &origin, const GeoPoint &in, BoostPoint &out) {
(void)z; (void)z;
} }
template <class GeoPoint1, class GeoPoint2, class Point>
void toENU(const GeoPoint1 &origin, const GeoPoint2 &in, Point &out) {
static GeographicLib::Geocentric earth(GeographicLib::Constants::WGS84_a(),
GeographicLib::Constants::WGS84_f());
GeographicLib::LocalCartesian proj(origin.latitude(), origin.longitude(),
origin.altitude(), earth);
double x = 0, y = 0, z = 0;
auto alt = in.altitude();
alt = std::isnan(alt) ? 0 : alt;
proj.Forward(in.latitude(), in.longitude(), alt, x, y, z);
out.setX(x);
out.setY(y);
(void)z;
}
template <class GeoPoint> template <class GeoPoint>
void fromENU(const GeoPoint &origin, const BoostPoint &in, GeoPoint &out) { void fromENU(const GeoPoint &origin, const BoostPoint &in, GeoPoint &out) {
GeographicLib::Geocentric earth(GeographicLib::Constants::WGS84_a(), static GeographicLib::Geocentric earth(GeographicLib::Constants::WGS84_a(),
GeographicLib::Constants::WGS84_f()); GeographicLib::Constants::WGS84_f());
GeographicLib::LocalCartesian proj(origin.latitude(), origin.longitude(), GeographicLib::LocalCartesian proj(origin.latitude(), origin.longitude(),
origin.altitude(), earth); origin.altitude(), earth);
...@@ -122,10 +138,18 @@ void fromENU(const GeoPoint &origin, const BoostPoint &in, GeoPoint &out) { ...@@ -122,10 +138,18 @@ void fromENU(const GeoPoint &origin, const BoostPoint &in, GeoPoint &out) {
out.setAltitude(alt); out.setAltitude(alt);
} }
template <class GeoPoint, template <class, class...> class Container> template <class GeoPoint, class Container1, class Container2>
void areaToEnu(const GeoPoint &origin, const Container<GeoPoint> &in, void areaToEnu(const GeoPoint &origin, const Container1 &in, Container2 &out) {
BoostPolygon &out) { for (auto &vertex : in) {
for (auto vertex : in) { typename Container2::value_type p;
toENU(origin, vertex, p);
out.push_back(p);
}
}
template <class GeoPoint, class Container>
void areaToEnu(const GeoPoint &origin, const Container &in, BoostPolygon &out) {
for (auto &vertex : in) {
BoostPoint p; BoostPoint p;
toENU(origin, vertex, p); toENU(origin, vertex, p);
out.outer().push_back(p); out.outer().push_back(p);
...@@ -133,11 +157,21 @@ void areaToEnu(const GeoPoint &origin, const Container<GeoPoint> &in, ...@@ -133,11 +157,21 @@ void areaToEnu(const GeoPoint &origin, const Container<GeoPoint> &in,
bg::correct(out); bg::correct(out);
} }
template <class GeoPoint, template <class, class...> class Container> template <class GeoPoint, class Container1, class Container2>
void areaFromEnu(const GeoPoint &origin, Container1 &in,
const Container2 &out) {
for (auto &vertex : in) {
typename Container2::value_type p;
fromENU(origin, vertex, p);
out.push_back(p);
}
}
template <class GeoPoint, class Container>
void areaFromEnu(const GeoPoint &origin, BoostPolygon &in, void areaFromEnu(const GeoPoint &origin, BoostPolygon &in,
const Container<GeoPoint> &out) { const Container &out) {
for (auto vertex : in.outer()) { for (auto &vertex : in.outer()) {
GeoPoint p; typename Container::value_type p;
fromENU(origin, vertex, p); fromENU(origin, vertex, p);
out.push_back(p); out.push_back(p);
} }
......
...@@ -6,14 +6,20 @@ ...@@ -6,14 +6,20 @@
#include "MissionSettingsItem.h" #include "MissionSettingsItem.h"
#include "PlanMasterController.h" #include "PlanMasterController.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#include "SettingsManager.h"
#include "SimpleMissionItem.h" #include "SimpleMissionItem.h"
#include "WimaSettings.h"
#include "Snake/QNemoHeartbeat.h" #include "Snake/QNemoHeartbeat.h"
#include "Snake/QNemoProgress.h" #include "Snake/QNemoProgress.h"
#include "Snake/SnakeTile.h"
#include "QVector3D" #include "QVector3D"
#include <QScopedPointer> #include <QScopedPointer>
#include <QtConcurrentRun>
#define CLIPPER_SCALE 10000
#include "clipper/clipper.hpp"
#include <memory> #include <memory>
...@@ -48,7 +54,7 @@ WimaController::StatusMap WimaController::_nemoStatusMap{ ...@@ -48,7 +54,7 @@ WimaController::StatusMap WimaController::_nemoStatusMap{
WimaController::WimaController(QObject *parent) WimaController::WimaController(QObject *parent)
: QObject(parent), _joinedArea(), _measurementArea(), _serviceArea(), : QObject(parent), _joinedArea(), _measurementArea(), _serviceArea(),
_corridor(), _localPlanDataValid(false), _corridor(), _planDataValid(false),
_areaInterface(&_measurementArea, &_serviceArea, &_corridor, _areaInterface(&_measurementArea, &_serviceArea, &_corridor,
&_joinedArea), &_joinedArea),
_WMSettings(), _defaultWM(_WMSettings, _areaInterface), _WMSettings(), _defaultWM(_WMSettings, _areaInterface),
...@@ -141,6 +147,12 @@ WimaController::WimaController(QObject *parent) ...@@ -141,6 +147,12 @@ WimaController::WimaController(QObject *parent)
connect(&_enableSnake, &Fact::rawValueChanged, this, connect(&_enableSnake, &Fact::rawValueChanged, this,
&WimaController::_switchToSnakeWaypointManager); &WimaController::_switchToSnakeWaypointManager);
_switchToSnakeWaypointManager(_enableSnake.rawValue()); _switchToSnakeWaypointManager(_enableSnake.rawValue());
// Routing
connect(&_routingThread, &RoutingThread::result, this,
&WimaController::_storeRoute);
connect(&_routingThread, &RoutingThread::calculatingChanged, this,
&WimaController::snakeCalcInProgressChanged);
} }
PlanMasterController *WimaController::masterController() { PlanMasterController *WimaController::masterController() {
...@@ -192,7 +204,7 @@ Fact *WimaController::arrivalReturnSpeed() { return &_arrivalReturnSpeed; } ...@@ -192,7 +204,7 @@ Fact *WimaController::arrivalReturnSpeed() { return &_arrivalReturnSpeed; }
Fact *WimaController::altitude() { return &_altitude; } Fact *WimaController::altitude() { return &_altitude; }
QmlObjectListModel *WimaController::snakeTiles() { QmlObjectListModel *WimaController::snakeTiles() {
return &this->_measurementArea.tiles(); return this->_measurementArea.tiles();
} }
QVariantList WimaController::snakeTileCenterPoints() { QVariantList WimaController::snakeTileCenterPoints() {
...@@ -222,8 +234,7 @@ QString WimaController::nemoStatusString() const { ...@@ -222,8 +234,7 @@ QString WimaController::nemoStatusString() const {
} }
bool WimaController::snakeCalcInProgress() const { bool WimaController::snakeCalcInProgress() const {
qWarning() << "using snakeCalcInProgress dummy"; return _routingThread.calculating();
return true;
} }
void WimaController::setMasterController(PlanMasterController *masterC) { void WimaController::setMasterController(PlanMasterController *masterC) {
...@@ -393,7 +404,7 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) { ...@@ -393,7 +404,7 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
emit snakeTilesChanged(); emit snakeTilesChanged();
emit nemoProgressChanged(); emit nemoProgressChanged();
_localPlanDataValid = false; _planDataValid = false;
// extract list with WimaAreas // extract list with WimaAreas
QList<const WimaAreaData *> areaList = planData->areaList(); QList<const WimaAreaData *> areaList = planData->areaList();
...@@ -452,20 +463,6 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) { ...@@ -452,20 +463,6 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
emit visualItemsChanged(); emit visualItemsChanged();
emit snakeTilesChanged(); emit snakeTilesChanged();
// Publish tiles if necessary.
if (!this->_nemoInterface.hasTileData(this->_measurementArea.tileData())) {
this->_nemoInterface.publishTileData(this->_measurementArea.tileData());
this->_measurementArea.progress() =
QVector<int>(this->_measurementArea.tiles()->count, 0);
emit nemoProgressChanged();
} else if (this->_enableSnake.rawValue().toBool()) {
const auto progess = this->_nemoInterface.progress();
if (progess.size() == this->_measurementArea.tiles()->count()) {
this->_measurementArea.progress() = std::move(progress);
emit nemoProgressChanged();
}
}
// Copy raw transects. // Copy raw transects.
this->_rawTransects = planData->transects(); this->_rawTransects = planData->transects();
...@@ -477,9 +474,9 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) { ...@@ -477,9 +474,9 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
} }
for (auto *item : tempMissionItems) { for (auto *item : tempMissionItems) {
_snakeWM.push_back(item->coordinate());
_defaultWM.push_back(item->coordinate()); _defaultWM.push_back(item->coordinate());
} }
// // extract mission items
_WMSettings.setHomePosition(QGeoCoordinate( _WMSettings.setHomePosition(QGeoCoordinate(
_serviceArea.depot().latitude(), _serviceArea.depot().longitude(), 0)); _serviceArea.depot().latitude(), _serviceArea.depot().longitude(), 0));
// auto tempMissionItems = planData->missionItems(); // auto tempMissionItems = planData->missionItems();
...@@ -487,15 +484,37 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) { ...@@ -487,15 +484,37 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
Q_ASSERT(false); Q_ASSERT(false);
return false; return false;
} }
// if (tempMissionItems.size() < 1) { if (!_snakeWM.reset()) {
emit missionItemsChanged(); Q_ASSERT(false);
emit currentMissionItemsChanged(); return false;
emit waypointPathChanged(); }
emit currentWaypointPathChanged();
if (_currentWM == &_defaultWM || _currentWM == &_snakeWM) {
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit waypointPathChanged();
emit currentWaypointPathChanged();
}
// Publish tiles, set progress if necessary.
if (!this->_nemoInterface.hasTileData(this->_measurementArea.tileData())) {
if (_enableSnake.rawValue().toBool()) {
this->_nemoInterface.publishTileData(this->_measurementArea.tileData());
}
this->_measurementArea.progress() =
QVector<int>(this->_measurementArea.tiles()->count(), 0);
emit nemoProgressChanged();
qWarning("WimaController: add snake update here lkjdfl!"); } else if (this->_enableSnake.rawValue().toBool()) {
const auto progress = this->_nemoInterface.progress();
if (progress.size() == this->_measurementArea.tiles()->count()) {
this->_measurementArea.progress() = std::move(progress);
emit nemoProgressChanged();
this->_updateRoute();
}
}
_localPlanDataValid = true; _planDataValid = true;
return true; return true;
} }
...@@ -701,7 +720,7 @@ void WimaController::_setPhaseDuration(double duration) { ...@@ -701,7 +720,7 @@ void WimaController::_setPhaseDuration(double duration) {
} }
bool WimaController::_SRTLPrecondition(QString &errorString) { bool WimaController::_SRTLPrecondition(QString &errorString) {
if (!_localPlanDataValid) { if (!_planDataValid) {
errorString.append(tr("No WiMA data available. Please define at least a " errorString.append(tr("No WiMA data available. Please define at least a "
"measurement and a service area.")); "measurement and a service area."));
return false; return false;
...@@ -772,27 +791,61 @@ void WimaController::_initSmartRTL() { ...@@ -772,27 +791,61 @@ void WimaController::_initSmartRTL() {
} }
} }
void WimaController::_threadFinishedHandler() { void WimaController::_storeRoute(RoutingThread::PtrRoutingData data) {
qWarning() << "update here as well .jisddf"; #ifdef SNAKE_SHOW_TIME
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
#endif #endif
// Copy waypoints to waypoint manager. // Copy waypoints to waypoint manager.
_snakeWM.clear(); _snakeWM.clear();
auto waypoints = 1;
if (waypoints.size() < 1) {
return;
}
for (auto &vertex : waypoints) {
_snakeWM.push_back(vertex);
}
// Do update. if (data->route.size() > 0) {
this->_snakeWM.update(); // this can take a while (ca. 200ms) // Store route.
const auto &transectsENU = data->transects;
const auto &transectsInfo = data->transectsInfo;
const auto &route = data->route;
// Find index of first waypoint.
std::size_t idxFirst = 0;
const auto &infoFirst = transectsInfo.front();
const auto &firstTransect = transectsENU[infoFirst.index];
const auto &firstWaypoint =
infoFirst.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 = route.size() - 1;
const auto &infoLast = transectsInfo.back();
const auto &lastTransect = transectsENU[infoLast.index];
const auto &lastWaypoint =
infoLast.reversed ? lastTransect.front() : lastTransect.back();
for (long i = route.size() - 1; i >= 0; --i) {
auto dist = bg::distance(route[i], lastWaypoint);
if (dist < th) {
idxLast = i;
break;
}
}
// Convert to geo coordinates and append to waypoint manager.
const auto &ori = this->_origin;
for (std::size_t i = idxFirst; i <= idxLast; ++i) {
auto &vertex = route[i];
QGeoCoordinate c;
snake::fromENU(ori, vertex, c);
_snakeWM.push_back(c);
}
// Do update.
this->_snakeWM.update(); // this can take a while (ca. 200ms)
emit missionItemsChanged(); emit missionItemsChanged();
emit currentMissionItemsChanged(); emit currentMissionItemsChanged();
emit currentWaypointPathChanged(); emit currentWaypointPathChanged();
emit waypointPathChanged(); emit waypointPathChanged();
}
#ifdef SNAKE_SHOW_TIME #ifdef SNAKE_SHOW_TIME
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();
std::cout << "WimaController::_threadFinishedHandler(): waypoints: " std::cout << "WimaController::_threadFinishedHandler(): waypoints: "
...@@ -813,10 +866,11 @@ void WimaController::_switchToSnakeWaypointManager(QVariant variant) { ...@@ -813,10 +866,11 @@ void WimaController::_switchToSnakeWaypointManager(QVariant variant) {
void WimaController::_progressChangedHandler() { void WimaController::_progressChangedHandler() {
const auto progress = this->_nemoInterface.progress(); const auto progress = this->_nemoInterface.progress();
if (this->_measurementArea.tiles().count() == progress.size()) { if (this->_measurementArea.tiles()->count() == progress.size()) {
this->_measurementArea.progress() = std::move(progress); this->_measurementArea.progress() = std::move(progress);
emit nemoProgressChanged(); emit nemoProgressChanged();
} else if (_localPlanDataValid) { this->_updateRoute();
} else if (_planDataValid) {
this->_nemoInterface.publishTileData(this->_measurementArea.tileData()); this->_nemoInterface.publishTileData(this->_measurementArea.tileData());
} }
} }
...@@ -824,43 +878,134 @@ void WimaController::_progressChangedHandler() { ...@@ -824,43 +878,134 @@ void WimaController::_progressChangedHandler() {
void WimaController::_enableSnakeChangedHandler() { void WimaController::_enableSnakeChangedHandler() {
if (this->_enableSnake.rawValue().toBool()) { if (this->_enableSnake.rawValue().toBool()) {
qDebug() << "WimaController: enabling snake."; qDebug() << "WimaController: enabling snake.";
_switchWaypointManager(_snakeWM);
this->_nemoInterface.start(); this->_nemoInterface.start();
if (_planDataValid) {
if (!this->_nemoInterface.hasTileData(
this->_measurementArea.tileData())) {
this->_nemoInterface.publishTileData(this->_measurementArea.tileData());
}
}
} else { } else {
qDebug() << "WimaController: disabling snake."; qDebug() << "WimaController: disabling snake.";
_switchWaypointManager(_defaultWM);
this->_nemoInterface.stop(); this->_nemoInterface.stop();
} }
} }
void WimaController::_updateRoute() { void WimaController::_updateRoute() {
if (_localPlanDataValid && this->_joinedArea.coordinateList().size() > 0) { // precondtion
auto safeArea = this->_joinedArea.coordinateList(); if (_planDataValid && this->_joinedArea.coordinateList().size() > 0) {
for (auto &v : safeArea) { const auto progress = this->_nemoInterface.progress();
v.setAltitude(0); const auto *tiles = this->_measurementArea.tiles();
} // precondtion
const auto &origin = safeArea.front(); if (tiles->count() > 0 && progress.size() == tiles->count() &&
snake::BoostPolygon safeAreaENU; this->_rawTransects.size() > 0 &&
snake::areaToEnu(origin, safeArea, safeAreaENU); this->_joinedArea.coordinateList().size() > 0) {
const auto &depot = this->_serviceArea.depot(); // Fetch tiles and convert to ENU.
const auto &geoTransects = this->_rawTransects; this->_origin = this->_joinedArea.coordinateList().first();
const auto progess = this->_nemoInterface.progress(); this->_origin.setAltitude(0);
auto pTiles = std::make_shared<QList<QList<QGeoCoordinate>>>(); const auto &origin = this->_origin;
auto pTiles = std::make_shared<std::vector<snake::BoostPolygon>>();
auto generator = [origin, depot, std::size_t numTiles = 0;
geoTransects](snake::Transects &transects) -> bool { for (int i = 0; i < progress.size(); ++i) {
snake::BoostPolygon depotENU; if (progress[i] == 100) {
snake::toENU(origin, depot, depotENU); ++numTiles;
transects.push_back(snake::BoostLineString{depotENU}); const auto *obj = tiles->get(i);
for (auto &geoTransect : geoTransects) { const auto *tile = qobject_cast<const SnakeTile *>(obj);
snake::BoostLineString t; if (tile != nullptr) {
for (auto &geoVertex : geoTransect) { snake::BoostPolygon t;
snake::BoostPoint v; snake::areaToEnu(origin, tile->coordinateList(), t);
snake::toENU(origin, geoVertex, v); pTiles->push_back(std::move(t));
t.push_back(v); } else {
return;
}
} }
transects.push_back(t);
} }
return true; if (numTiles > 0) {
}; // Fetch safe area and convert to ENU.
this->_routingThread.route(safeAreaENU, generator); auto safeArea = this->_joinedArea.coordinateList();
for (auto &v : safeArea) {
v.setAltitude(0);
}
snake::BoostPolygon safeAreaENU;
snake::areaToEnu(origin, safeArea, safeAreaENU);
const auto &depot = this->_serviceArea.depot();
snake::BoostPoint depotENU;
snake::toENU(origin, depot, depotENU);
// Fetch geo transects and convert to ENU.
const auto &geoTransects = this->_rawTransects;
auto pUnclippedTransects = std::make_shared<snake::Transects>();
for (auto &geoTransect : geoTransects) {
snake::BoostLineString t;
for (auto &geoVertex : geoTransect) {
snake::BoostPoint v;
snake::toENU(origin, geoVertex, v);
t.push_back(v);
}
pUnclippedTransects->push_back(t);
}
std::size_t minLength = 1; // meter
qWarning() << "using minLength dummy lkjfdslooij";
auto generator = [depotENU, pUnclippedTransects, pTiles,
minLength](snake::Transects &transects) -> bool {
// Convert transects to clipper path.
vector<ClipperLib::Path> transectsClipper;
for (const auto &t : *pUnclippedTransects) {
ClipperLib::Path path;
for (const auto &v : t) {
ClipperLib::IntPoint c{
static_cast<ClipperLib::cInt>(v.get<0>() * CLIPPER_SCALE),
static_cast<ClipperLib::cInt>(v.get<1>() * CLIPPER_SCALE)};
path.push_back(c);
}
transectsClipper.push_back(std::move(path));
}
// Add transects to clipper.
ClipperLib::Clipper clipper;
clipper.AddPaths(transectsClipper, ClipperLib::ptSubject, false);
// Add tiles to clipper.
vector<ClipperLib::Path> tilesClipper;
for (const auto &t : *pTiles) {
ClipperLib::Path path;
for (const auto &v : t.outer()) {
path.push_back(ClipperLib::IntPoint{
static_cast<ClipperLib::cInt>(v.get<0>() * CLIPPER_SCALE),
static_cast<ClipperLib::cInt>(v.get<1>() * CLIPPER_SCALE)});
}
tilesClipper.push_back(std::move(path));
}
clipper.AddPaths(tilesClipper, ClipperLib::ptClip, true);
// Clip transects.
ClipperLib::PolyTree clippedTransecs;
clipper.Execute(ClipperLib::ctDifference, clippedTransecs,
ClipperLib::pftNonZero, ClipperLib::pftNonZero);
// Extract transects from PolyTree and convert them to
// BoostLineString
transects.push_back(snake::BoostLineString{depotENU});
for (const auto &child : clippedTransecs.Childs) {
snake::BoostLineString transect;
for (const auto &v : child->Contour) {
snake::BoostPoint c{static_cast<double>(v.X) / CLIPPER_SCALE,
static_cast<double>(v.Y) / CLIPPER_SCALE};
transect.push_back(c);
}
if (bg::length(transect) >= minLength) {
transects.push_back(std::move(transect));
}
}
if (transects.size() > 1) {
return true;
} else {
return false;
}
}; // generator
this->_routingThread.route(safeAreaENU, generator);
} else {
this->_storeRoute(RoutingThread::PtrRoutingData(new RoutingData()));
}
}
} }
} }
...@@ -6,12 +6,8 @@ ...@@ -6,12 +6,8 @@
#include "QGCMapPolygon.h" #include "QGCMapPolygon.h"
#include "QmlObjectListModel.h" #include "QmlObjectListModel.h"
//#include "Geometry/WimaArea.h"
//#include "Geometry/WimaCorridor.h"
#include "Geometry/WimaCorridorData.h" #include "Geometry/WimaCorridorData.h"
//#include "Geometry/WimaMeasurementArea.h"
#include "Geometry/WimaMeasurementAreaData.h" #include "Geometry/WimaMeasurementAreaData.h"
//#include "Geometry/WimaServiceArea.h"
#include "Geometry/WimaServiceAreaData.h" #include "Geometry/WimaServiceAreaData.h"
#include "WimaPlanData.h" #include "WimaPlanData.h"
...@@ -33,8 +29,6 @@ typedef std::unique_ptr<rapidjson::Document> JsonDocUPtr; ...@@ -33,8 +29,6 @@ typedef std::unique_ptr<rapidjson::Document> JsonDocUPtr;
class WimaController : public QObject { class WimaController : public QObject {
Q_OBJECT Q_OBJECT
enum FileType { WimaFile, PlanFile };
public: public:
WimaController(QObject *parent = nullptr); WimaController(QObject *parent = nullptr);
...@@ -213,7 +207,7 @@ private slots: ...@@ -213,7 +207,7 @@ private slots:
void _initSmartRTL(); void _initSmartRTL();
void _smartRTLCleanUp(bool flying); void _smartRTLCleanUp(bool flying);
// Snake. // Snake.
void _threadFinishedHandler(); void _storeRoute(RoutingThread::PtrRoutingData data);
void _switchWaypointManager(WaypointManager::ManagerBase &manager); void _switchWaypointManager(WaypointManager::ManagerBase &manager);
void _switchToSnakeWaypointManager(QVariant variant); void _switchToSnakeWaypointManager(QVariant variant);
void _progressChangedHandler(); void _progressChangedHandler();
...@@ -234,7 +228,7 @@ private: ...@@ -234,7 +228,7 @@ private:
WimaMeasurementAreaData _measurementArea; // measurement area WimaMeasurementAreaData _measurementArea; // measurement area
WimaServiceAreaData _serviceArea; // area for supplying WimaServiceAreaData _serviceArea; // area for supplying
WimaCorridorData _corridor; // corridor connecting opArea and serArea WimaCorridorData _corridor; // corridor connecting opArea and serArea
bool _localPlanDataValid; bool _planDataValid;
// Waypoint Managers. // Waypoint Managers.
WaypointManager::AreaInterface _areaInterface; WaypointManager::AreaInterface _areaInterface;
...@@ -283,6 +277,7 @@ private: ...@@ -283,6 +277,7 @@ private:
using StatusMap = std::map<int, QString>; using StatusMap = std::map<int, QString>;
static StatusMap _nemoStatusMap; static StatusMap _nemoStatusMap;
RoutingThread _routingThread; RoutingThread _routingThread;
QGeoCoordinate _origin;
// Periodic tasks. // Periodic tasks.
QTimer _eventTimer; QTimer _eventTimer;
......
...@@ -89,6 +89,10 @@ void WimaPlanData::append(const WimaMeasurementAreaData &areaData) { ...@@ -89,6 +89,10 @@ void WimaPlanData::append(const WimaMeasurementAreaData &areaData) {
} }
} }
void WimaPlanData::setTransects(const QList<QList<QGeoCoordinate>> &transects) {
_transects = transects;
}
void WimaPlanData::append(const QList<MissionItem *> &missionItems) { void WimaPlanData::append(const QList<MissionItem *> &missionItems) {
for (auto *item : missionItems) { for (auto *item : missionItems) {
item->setParent(this); item->setParent(this);
...@@ -110,6 +114,10 @@ const QList<const WimaAreaData *> &WimaPlanData::areaList() const { ...@@ -110,6 +114,10 @@ const QList<const WimaAreaData *> &WimaPlanData::areaList() const {
return _areaList; return _areaList;
} }
const QList<QList<QGeoCoordinate>> &WimaPlanData::transects() const {
return _transects;
}
const QList<MissionItem *> &WimaPlanData::missionItems() const { const QList<MissionItem *> &WimaPlanData::missionItems() const {
return _missionItems; return _missionItems;
} }
......
...@@ -668,9 +668,13 @@ void WimaPlaner::synchronize() { ...@@ -668,9 +668,13 @@ void WimaPlaner::synchronize() {
if (_wimaBridge != nullptr) { if (_wimaBridge != nullptr) {
if (readyForSynchronization()) { if (readyForSynchronization()) {
auto planData = toPlanData(); auto planData = toPlanData();
(void)_wimaBridge->setWimaPlanData(planData); if (planData) {
this->_synchronized = true; (void)_wimaBridge->setWimaPlanData(planData);
emit synchronizedChanged(); this->_synchronized = true;
emit synchronizedChanged();
} else {
qWarning("WimaPlaner::uploadToContainer(): error creating plan data.");
}
} }
} else { } else {
qWarning("WimaPlaner::uploadToContainer(): no container assigned."); qWarning("WimaPlaner::uploadToContainer(): no container assigned.");
...@@ -741,17 +745,18 @@ QSharedPointer<WimaPlanData> WimaPlaner::toPlanData() { ...@@ -741,17 +745,18 @@ QSharedPointer<WimaPlanData> WimaPlaner::toPlanData() {
planData->append(WimaJoinedAreaData(_joinedArea)); planData->append(WimaJoinedAreaData(_joinedArea));
// convert mission items to mavlink commands // convert mission items to mavlink commands
QList<MissionItem *> missionItems;
if (_missionController && _missionController->visualItems()) { if (_missionController && _missionController->visualItems()) {
int surveyIndex = int surveyIndex =
_missionController->visualItems()->indexOf(_TSComplexItem); _missionController->visualItems()->indexOf(_TSComplexItem);
if (surveyIndex > 0) { if (surveyIndex > 0) {
QList<MissionItem *> missionItems;
_TSComplexItem->appendMissionItems(missionItems, nullptr); _TSComplexItem->appendMissionItems(missionItems, nullptr);
planData->append(missionItems);
planData->setTransects(this->_TSComplexItem->rawTransects());
return planData;
} }
} }
// store mavlink commands return QSharedPointer<WimaPlanData>();
planData->append(missionItems);
return planData;
} }
#ifndef NDEBUG #ifndef NDEBUG
......
...@@ -5,8 +5,8 @@ import QtLocation 5.3 ...@@ -5,8 +5,8 @@ import QtLocation 5.3
MapQuickItem { MapQuickItem {
id: root id: root
width: 20 width: 15
height: 20 height: 15
anchorPoint.x: width/2 anchorPoint.x: width/2
anchorPoint.y: height/2 anchorPoint.y: height/2
...@@ -89,7 +89,7 @@ MapQuickItem { ...@@ -89,7 +89,7 @@ MapQuickItem {
// From 0 to angle // From 0 to angle
ctx.beginPath(); ctx.beginPath();
ctx.lineWidth = 3; ctx.lineWidth = 1;
ctx.strokeStyle = root.secondaryColor; ctx.strokeStyle = root.secondaryColor;
ctx.arc(root.centerWidth, ctx.arc(root.centerWidth,
root.centerHeight, root.centerHeight,
......
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