Commit f4eb1bde authored by Valentin Platzgummer's avatar Valentin Platzgummer

temp

parent dd135422
......@@ -421,8 +421,8 @@ INCLUDEPATH += \
src/Vehicle \
src/Audio \
src/comm \
src/RouteMissionItem \
src/RouteMissionItem/geometry \
src/MeasurementComplexItem \
src/MeasurementComplexItem/geometry \
src/comm/ros_bridge \
src/input \
src/lib/qmapcontrol \
......@@ -447,52 +447,52 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
HEADERS += \
src/QmlControls/QmlUnitsConversion.h \
src/RouteMissionItem/geometry/GeoArea.h \
src/RouteMissionItem/geometry/MeasurementArea.h \
src/RouteMissionItem/geometry/SafeArea.h \
src/MeasurementComplexItem/geometry/GeoArea.h \
src/MeasurementComplexItem/geometry/MeasurementArea.h \
src/MeasurementComplexItem/geometry/SafeArea.h \
src/Vehicle/VehicleEscStatusFactGroup.h \
src/RouteMissionItem/AreaData.h \
src/RouteMissionItem/RouteComplexItem.h \
src/RouteMissionItem/GenericSingelton.h \
src/RouteMissionItem/geometry/GenericCircle.h \
src/RouteMissionItem/RoutingThread.h \
src/RouteMissionItem/CircularGenerator.h \
src/RouteMissionItem/GeneratorBase.h \
src/RouteMissionItem/LinearGenerator.h \
src/RouteMissionItem/geometry/clipper/clipper.hpp \
src/RouteMissionItem/geometry/mapbox/feature.hpp \
src/RouteMissionItem/geometry/mapbox/geometry.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/box.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/empty.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/envelope.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/for_each_point.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/geometry.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/line_string.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/multi_line_string.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/multi_point.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/multi_polygon.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/point.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/point_arithmetic.hpp \
src/RouteMissionItem/geometry/mapbox/geometry/polygon.hpp \
src/RouteMissionItem/geometry/mapbox/geometry_io.hpp \
src/RouteMissionItem/geometry/mapbox/optional.hpp \
src/RouteMissionItem/geometry/mapbox/polylabel.hpp \
src/RouteMissionItem/geometry/mapbox/recursive_wrapper.hpp \
src/RouteMissionItem/geometry/mapbox/variant.hpp \
src/RouteMissionItem/geometry/mapbox/variant_io.hpp \
src/RouteMissionItem/geometry/snake.h \
src/RouteMissionItem/geometry/GenericPolygon.h \
src/RouteMissionItem/geometry/GenericPolygonArray.h \
src/RouteMissionItem/geometry/GeoPoint3D.h \
src/RouteMissionItem/NemoInterface.h \
src/RouteMissionItem/nemo_interface/QNemoHeartbeat.h \
src/RouteMissionItem/nemo_interface/QNemoProgress.h \
src/RouteMissionItem/nemo_interface/QNemoProgress.h \
src/RouteMissionItem/nemo_interface/SnakeTile.h \
src/RouteMissionItem/nemo_interface/SnakeTileLocal.h \
src/RouteMissionItem/nemo_interface/SnakeTiles.h \
src/RouteMissionItem/nemo_interface/SnakeTilesLocal.h \
src/RouteMissionItem/call_once.h \
src/MeasurementComplexItem/AreaData.h \
src/MeasurementComplexItem/MeasurementComplexItem.h \
src/MeasurementComplexItem/GenericSingelton.h \
src/MeasurementComplexItem/geometry/GenericCircle.h \
src/MeasurementComplexItem/RoutingThread.h \
src/MeasurementComplexItem/CircularGenerator.h \
src/MeasurementComplexItem/GeneratorBase.h \
src/MeasurementComplexItem/LinearGenerator.h \
src/MeasurementComplexItem/geometry/clipper/clipper.hpp \
src/MeasurementComplexItem/geometry/mapbox/feature.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/box.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/empty.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/envelope.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/for_each_point.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/geometry.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/line_string.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/multi_line_string.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/multi_point.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/multi_polygon.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/point.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/point_arithmetic.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry/polygon.hpp \
src/MeasurementComplexItem/geometry/mapbox/geometry_io.hpp \
src/MeasurementComplexItem/geometry/mapbox/optional.hpp \
src/MeasurementComplexItem/geometry/mapbox/polylabel.hpp \
src/MeasurementComplexItem/geometry/mapbox/recursive_wrapper.hpp \
src/MeasurementComplexItem/geometry/mapbox/variant.hpp \
src/MeasurementComplexItem/geometry/mapbox/variant_io.hpp \
src/MeasurementComplexItem/geometry/snake.h \
src/MeasurementComplexItem/geometry/GenericPolygon.h \
src/MeasurementComplexItem/geometry/GenericPolygonArray.h \
src/MeasurementComplexItem/geometry/GeoPoint3D.h \
src/MeasurementComplexItem/NemoInterface.h \
src/MeasurementComplexItem/nemo_interface/QNemoHeartbeat.h \
src/MeasurementComplexItem/nemo_interface/QNemoProgress.h \
src/MeasurementComplexItem/nemo_interface/QNemoProgress.h \
src/MeasurementComplexItem/nemo_interface/SnakeTile.h \
src/MeasurementComplexItem/nemo_interface/SnakeTileLocal.h \
src/MeasurementComplexItem/nemo_interface/SnakeTiles.h \
src/MeasurementComplexItem/nemo_interface/SnakeTilesLocal.h \
src/MeasurementComplexItem/call_once.h \
src/api/QGCCorePlugin.h \
src/api/QGCOptions.h \
src/api/QGCSettings.h \
......@@ -522,27 +522,27 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
}
SOURCES += \
src/RouteMissionItem/geometry/GeoArea.cc \
src/RouteMissionItem/geometry/MeasurementArea.cc \
src/RouteMissionItem/geometry/SafeArea.cc \
src/MeasurementComplexItem/geometry/GeoArea.cc \
src/MeasurementComplexItem/geometry/MeasurementArea.cc \
src/MeasurementComplexItem/geometry/SafeArea.cc \
src/Vehicle/VehicleEscStatusFactGroup.cc \
src/RouteMissionItem/AreaData.cc \
src/MeasurementComplexItem/AreaData.cc \
src/api/QGCCorePlugin.cc \
src/api/QGCOptions.cc \
src/api/QGCSettings.cc \
src/api/QmlComponentInfo.cc \
src/RouteMissionItem/RouteComplexItem.cc \
src/RouteMissionItem/GenericSingelton.cpp \
src/RouteMissionItem/RoutingThread.cpp \
src/RouteMissionItem/CircularGenerator.cpp \
src/RouteMissionItem/GeneratorBase.cc \
src/RouteMissionItem/LinearGenerator.cpp \
src/RouteMissionItem/geometry/clipper/clipper.cpp \
src/RouteMissionItem/geometry/snake.cpp \
src/RouteMissionItem/geometry/GeoPoint3D.cpp \
src/RouteMissionItem/NemoInterface.cpp \
src/RouteMissionItem/nemo_interface/QNemoProgress.cc \
src/RouteMissionItem/nemo_interface/SnakeTile.cpp \
src/MeasurementComplexItem/MeasurementComplexItem.cc \
src/MeasurementComplexItem/GenericSingelton.cpp \
src/MeasurementComplexItem/RoutingThread.cpp \
src/MeasurementComplexItem/CircularGenerator.cpp \
src/MeasurementComplexItem/GeneratorBase.cc \
src/MeasurementComplexItem/LinearGenerator.cpp \
src/MeasurementComplexItem/geometry/clipper/clipper.cpp \
src/MeasurementComplexItem/geometry/snake.cpp \
src/MeasurementComplexItem/geometry/GeoPoint3D.cpp \
src/MeasurementComplexItem/NemoInterface.cpp \
src/MeasurementComplexItem/nemo_interface/QNemoProgress.cc \
src/MeasurementComplexItem/nemo_interface/SnakeTile.cpp \
src/comm/ros_bridge/include/RosBridgeClient.cpp \
src/comm/ros_bridge/include/com_private.cpp \
src/comm/ros_bridge/include/messages/geographic_msgs/geopoint.cpp \
......
......@@ -263,8 +263,8 @@
<file alias="SerialSettings.qml">src/ui/preferences/SerialSettings.qml</file>
<file alias="CircularGeneratorEditor.qml">src/WimaView/CircularGeneratorEditor.qml</file>
<file alias="QGroundControl/Controls/CircularGeneratorMapVisual.qml">src/WimaView/CircularGeneratorMapVisual.qml</file>
<file alias="CircularSurveyItemEditor.qml">src/WimaView/CircularSurveyItemEditor.qml</file>
<file alias="QGroundControl/Controls/CircularSurveyMapVisual.qml">src/WimaView/CircularSurveyMapVisual.qml</file>
<file alias="CircularSurveyItemEditor.qml">src/WimaView/MeasurementItemEditor.qml</file>
<file alias="QGroundControl/Controls/CircularSurveyMapVisual.qml">src/WimaView/MeasurementItemMapVisual.qml</file>
<file alias="Wima/CoordinateIndicator.qml">src/WimaView/CoordinateIndicator.qml</file>
<file alias="Wima/CoordinateIndicatorDrag.qml">src/WimaView/CoordinateIndicatorDrag.qml</file>
<file alias="Wima/DragCoordinate.qml">src/WimaView/DragCoordinate.qml</file>
......@@ -352,9 +352,9 @@
<file alias="Video.SettingsGroup.json">src/Settings/Video.SettingsGroup.json</file>
<file alias="VTOLLandingPattern.FactMetaData.json">src/MissionManager/VTOLLandingPattern.FactMetaData.json</file>
<file alias="Wima.SettingsGroup.json">src/Settings/Wima.SettingsGroup.json</file>
<file alias="RouteComplexItem.SettingsGroup.json">src/RouteMissionItem/json/RouteComplexItem.SettingsGroup.json</file>
<file alias="LinearGenerator.SettingsGroup.json">src/RouteMissionItem/json/LinearGenerator.SettingsGroup.json</file>
<file alias="CircularGenerator.SettingsGroup.json">src/RouteMissionItem/json/CircularGenerator.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/CircularGenerator.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/LinearGenerator.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/MeasurementComplexItem.SettingsGroup.json</file>
</qresource>
<qresource prefix="/MockLink">
<file alias="APMArduSubMockLink.params">src/comm/APMArduSubMockLink.params</file>
......
#include "RouteComplexItem.h"
#include "MeasurementComplexItem.h"
#include "CircularGenerator.h"
#include "LinearGenerator.h"
......@@ -12,6 +12,7 @@
// QGC
#include "JsonHelper.h"
#include "PlanMasterController.h"
#include "QGCApplication.h"
#include "QGCLoggingCategory.h"
......@@ -21,67 +22,76 @@
#define CLIPPER_SCALE 1000000
QGC_LOGGING_CATEGORY(RouteComplexItemLog, "RouteComplexItemLog")
QGC_LOGGING_CATEGORY(MeasurementComplexItemLog, "MeasurementComplexItemLog")
template <typename T>
constexpr typename std::underlying_type<T>::type integral(T value) {
return static_cast<typename std::underlying_type<T>::type>(value);
}
const char *RouteComplexItem::settingsGroup = "Route";
const char *RouteComplexItem::jsonComplexItemTypeValue = "Route";
const char *RouteComplexItem::variantName = "Variant";
const QString RouteComplexItem::name(tr("Route"));
RouteComplexItem::RouteComplexItem(PlanMasterController *masterController,
bool flyView, const QString &kmlOrShpFile,
QObject *parent)
: TransectStyleComplexItem(masterController, flyView, settingsGroup,
parent),
_state(STATE::IDLE),
const char *MeasurementComplexItem::settingsGroup = "MeasurementComplexItem";
const char *MeasurementComplexItem::jsonComplexItemTypeValue =
"MeasurementComplexItem";
const char *MeasurementComplexItem::variantName = "Variant";
const char *MeasurementComplexItem::altitudeName = "Altitude";
const QString MeasurementComplexItem::name(tr("Measurement"));
MeasurementComplexItem::MeasurementComplexItem(
PlanMasterController *masterController, bool flyView,
const QString &kmlOrShpFile, QObject *parent)
: ComplexMissionItem(masterController, flyView, settingsGroup, parent),
_masterController(masterController), _sequenceNumber(0),
_followTerrain(false), _state(STATE::IDLE),
_metaDataMap(FactMetaData::createMapFromJsonFile(
QStringLiteral(":/json/RouteComplexItem.SettingsGroup.json"), this)),
QStringLiteral(":/json/MeasurementComplexItem.SettingsGroup.json"),
this)),
_variant(settingsGroup, _metaDataMap[variantName]),
_variant(settingsGroup, _metaDataMap[altitudeName]),
_areaData(new AreaData(this)), _editorData(new AreaData(this)),
_currentData(_areaData), _pWorker(new RoutingThread(this)) {
Q_UNUSED(kmlOrShpFile)
_editorQml = "qrc:/qml/CircularSurveyItemEditor.qml";
_editorQml = "qrc:/qml/MeasurementItemEditor.qml";
// Connect facts.
connect(&this->_variant, &Fact::rawValueChanged, this,
&RouteComplexItem::_changeVariant);
&MeasurementComplexItem::_changeVariant);
// Connect worker.
connect(this->_pWorker, &RoutingThread::result, this,
&RouteComplexItem::_setTransects);
&MeasurementComplexItem::_setTransects);
connect(this->_pWorker, &RoutingThread::calculatingChanged, this,
&RouteComplexItem::calculatingChanged);
&MeasurementComplexItem::calculatingChanged);
// Register Generators.
auto lg = new routing::LinearGenerator(this->_areaData, this);
registerGenerator(lg->name(), lg);
auto cg = new routing::CircularGenerator(this->_areaData, this);
registerGenerator(cg->name(), cg);
qCritical() << "ToDo: _altitude connections missing.";
qCritical() << "ToDo: add generator saveing.";
}
RouteComplexItem::~RouteComplexItem() {}
MeasurementComplexItem::~MeasurementComplexItem() {}
void RouteComplexItem::revertPath() {
void MeasurementComplexItem::revertPath() {
this->_setState(STATE::REVERT_PATH);
this->_rebuildTransects();
this->_update();
}
const AreaData *RouteComplexItem::areaData() const {
const AreaData *MeasurementComplexItem::areaData() const {
return this->_currentData;
}
AreaData *RouteComplexItem::areaData() { return this->_currentData; }
AreaData *MeasurementComplexItem::areaData() { return this->_currentData; }
QStringList RouteComplexItem::variantNames() const { return _variantNames; }
QStringList MeasurementComplexItem::variantNames() const {
return _variantNames;
}
bool RouteComplexItem::load(const QJsonObject &complexObject,
int sequenceNumber, QString &errorString) {
bool MeasurementComplexItem::load(const QJsonObject &complexObject,
int sequenceNumber, QString &errorString) {
// We need to pull version first to determine what validation/conversion
// needs to be performed
QList<JsonHelper::KeyValidateInfo> versionKeyInfoList = {
......@@ -102,6 +112,7 @@ bool RouteComplexItem::load(const QJsonObject &complexObject,
{VisualMissionItem::jsonTypeKey, QJsonValue::String, true},
{ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true},
{variantName, QJsonValue::Double, false},
{altitudeName, QJsonValue::Double, true},
};
if (!JsonHelper::validateKeys(complexObject, keyInfoList, errorString)) {
......@@ -137,6 +148,7 @@ bool RouteComplexItem::load(const QJsonObject &complexObject,
}
_variant.setRawValue(complexObject[variantName].toInt());
_altitude.setRawValue(complexObject[altitudeName].toDouble());
_ignoreRecalc = false;
......@@ -148,11 +160,17 @@ bool RouteComplexItem::load(const QJsonObject &complexObject,
return true;
}
QString RouteComplexItem::mapVisualQML() const {
return QStringLiteral("CircularSurveyMapVisual.qml");
bool MeasurementComplexItem::dirty() const { return _dirty; }
bool MeasurementComplexItem::isSimpleItem() const { return false; }
bool MeasurementComplexItem::isStandaloneCoordinate() const { return false; }
QString MeasurementComplexItem::mapVisualQML() const {
return QStringLiteral("MeasurementItemMapVisual.qml");
}
void RouteComplexItem::save(QJsonArray &planItems) {
void MeasurementComplexItem::save(QJsonArray &planItems) {
QJsonObject saveObject;
_save(saveObject);
......@@ -164,6 +182,7 @@ void RouteComplexItem::save(QJsonArray &planItems) {
jsonComplexItemTypeValue;
saveObject[variantName] = double(_variant.rawValue().toUInt());
saveObject[altitudeName] = double(_altitude.rawValue().toUInt());
// Polygon shape
_surveyAreaPolygon.saveToJson(saveObject);
......@@ -171,24 +190,101 @@ void RouteComplexItem::save(QJsonArray &planItems) {
planItems.append(saveObject);
}
bool RouteComplexItem::specifiesCoordinate() const {
return _transects.count() > 0 ? _transects.first().count() > 0 : false;
double MeasurementComplexItem::amslEntryAlt() const {
return _altitude.rawValue().toDouble() +
this->_masterController->missionController()
->plannedHomePosition()
.altitude();
}
double MeasurementComplexItem::amslExitAlt() const { return amslEntryAlt(); }
double MeasurementComplexItem::minAMSLAltitude() const {
return amslEntryAlt();
}
double MeasurementComplexItem::maxAMSLAltitude() const {
return amslEntryAlt();
}
bool MeasurementComplexItem::specifiesCoordinate() const {
return _route.count() > 0;
}
bool MeasurementComplexItem::specifiesAltitudeOnly() const { return false; }
QGeoCoordinate MeasurementComplexItem::coordinate() const {
return this->_route.size() > 0 ? _route.first() : QGeoCoordinate();
}
QGeoCoordinate MeasurementComplexItem::exitCoordinate() const {
return this->_route.size() > 0 ? _route.last() : QGeoCoordinate();
}
int MeasurementComplexItem::sequenceNumber() const { return _sequenceNumber; }
double MeasurementComplexItem::specifiedFlightSpeed() {
return std::numeric_limits<double>::quiet_NaN();
}
double MeasurementComplexItem::specifiedGimbalYaw() {
return std::numeric_limits<double>::quiet_NaN();
}
double MeasurementComplexItem::specifiedGimbalPitch() {
return std::numeric_limits<double>::quiet_NaN();
}
void MeasurementComplexItem::appendMissionItems(QList<MissionItem *> &items,
QObject *missionItemParent) {
qCDebug(MeasurementComplexItemLog) << "appendMissionItems()";
int seqNum = this->_sequenceNumber;
MAV_FRAME mavFrame =
followTerrain() ? MAV_FRAME_GLOBAL : MAV_FRAME_GLOBAL_RELATIVE_ALT;
int transectIndex = 0;
for (const auto &vertex : this->_route) {
MissionItem *item = new MissionItem(
seqNum++, MAV_CMD_NAV_WAYPOINT, mavFrame,
0, // hold time
0.0, // No acceptance radius specified
0.0, // Pass through waypoint
std::numeric_limits<double>::quiet_NaN(), // Yaw unchanged
vertex.latitude(), vertex.longitude(), vertex.altitude(),
true, // autoContinue
false, // isCurrentItem
missionItemParent);
items.append(item);
}
}
void MeasurementComplexItem::setMissionFlightStatus(
const MissionController::MissionFlightStatus_t &missionFlightStatus) {
ComplexMissionItem::setMissionFlightStatus(missionFlightStatus);
}
bool RouteComplexItem::_setGenerator(PtrGenerator newG) {
void MeasurementComplexItem::applyNewAltitude(double newAltitude) {
this->_altitude->setRawValue(newAltitude);
}
double MeasurementComplexItem::additionalTimeDelay() const { return 0; }
bool MeasurementComplexItem::_setGenerator(PtrGenerator newG) {
if (this->_pGenerator != newG) {
if (this->_pGenerator != nullptr) {
disconnect(this->_pGenerator, &routing::GeneratorBase::generatorChanged,
this, &RouteComplexItem::_rebuildTransects);
this, &MeasurementComplexItem::_update);
}
this->_pGenerator = newG;
connect(this->_pGenerator, &routing::GeneratorBase::generatorChanged, this,
&RouteComplexItem::_rebuildTransects);
&MeasurementComplexItem::_update);
emit generatorChanged();
this->_setState(STATE::IDLE);
_rebuildTransects();
_update();
return true;
} else {
......@@ -196,40 +292,40 @@ bool RouteComplexItem::_setGenerator(PtrGenerator newG) {
}
}
void RouteComplexItem::_setState(RouteComplexItem::STATE state) {
void MeasurementComplexItem::_setState(MeasurementComplexItem::STATE state) {
if (this->_state != state) {
auto oldState = this->_state;
this->_state = state;
if (_calculating(oldState) != _calculating(state)) {
emit calculatingChanged();
}
if (_editing(oldState) != _editing(state)) {
emit editingChanged();
}
}
}
bool RouteComplexItem::_calculating(RouteComplexItem::STATE state) const {
bool MeasurementComplexItem::_calculating(
MeasurementComplexItem::STATE state) const {
return state == STATE::ROUTING;
}
void RouteComplexItem::_setEditing(bool editing) {
if (editing != _editing) {
_editing = editing;
emit editingChanged();
}
}
void RouteComplexItem::_setAreaData(RouteComplexItem::PtrAreaData data) {
void MeasurementComplexItem::_setAreaData(
MeasurementComplexItem::PtrAreaData data) {
if (_currentData != data) {
_currentData = data;
emit areaDataChanged();
}
}
void RouteComplexItem::_changeVariant() {
void MeasurementComplexItem::_changeVariant() {
this->_setState(STATE::CHANGE_VARIANT);
this->_rebuildTransects();
this->_update();
}
bool RouteComplexItem::_updateWorker() {
bool MeasurementComplexItem::_updateRouteWorker() {
// Reset data.
this->_transects.clear();
this->_variantVector.clear();
......@@ -242,7 +338,7 @@ bool RouteComplexItem::_updateWorker() {
auto origin = this->_areaData->origin();
origin.setAltitude(0);
if (!origin.isValid()) {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_updateWorker(): origin invalid." << origin;
return false;
}
......@@ -252,7 +348,7 @@ bool RouteComplexItem::_updateWorker() {
getGeoArea<const SafeArea *>(*this->_areaData->areaList());
auto geoSafeArea = serviceArea->coordinateList();
if (!(geoSafeArea.size() >= 3)) {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_updateWorker(): safe area invalid." << geoSafeArea;
return false;
}
......@@ -260,7 +356,7 @@ bool RouteComplexItem::_updateWorker() {
if (v.isValid()) {
v.setAltitude(0);
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_updateWorker(): safe area contains invalid coordinate."
<< geoSafeArea;
return false;
......@@ -281,24 +377,24 @@ bool RouteComplexItem::_updateWorker() {
this->_pWorker->route(par, g);
return true;
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_updateWorker(): generator creation failed.";
return false;
}
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_updateWorker(): pGenerator == nullptr, number of registered "
"generators: "
<< this->_generatorList.size();
return false;
}
} else {
qCDebug(RouteComplexItemLog) << "_updateWorker(): plan data invalid.";
qCDebug(MeasurementComplexItemLog) << "_updateWorker(): plan data invalid.";
return false;
}
}
void RouteComplexItem::_changeVariantWorker() {
void MeasurementComplexItem::_changeVariantWorker() {
auto variant = this->_variant.rawValue().toUInt();
// Find old variant and run. Old run corresponts with empty list.
......@@ -325,15 +421,15 @@ void RouteComplexItem::_changeVariantWorker() {
this->_transects.swap(newVariantCoordinates);
} else { // error
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "Variant out of bounds (variant =" << variant << ").";
qCDebug(RouteComplexItemLog) << "Resetting variant to zero.";
qCDebug(MeasurementComplexItemLog) << "Resetting variant to zero.";
disconnect(&this->_variant, &Fact::rawValueChanged, this,
&RouteComplexItem::_changeVariant);
&MeasurementComplexItem::_changeVariant);
this->_variant.setCookedValue(QVariant(0));
connect(&this->_variant, &Fact::rawValueChanged, this,
&RouteComplexItem::_changeVariant);
&MeasurementComplexItem::_changeVariant);
if (this->_variantVector.size() > 0) {
this->_changeVariantWorker();
......@@ -342,23 +438,25 @@ void RouteComplexItem::_changeVariantWorker() {
}
}
void RouteComplexItem::_reverseWorker() {
void MeasurementComplexItem::_reverseWorker() {
if (this->_transects.size() > 0) {
auto &t = this->_transects.front();
std::reverse(t.begin(), t.end());
}
}
double RouteComplexItem::timeBetweenShots() { return 0; }
double MeasurementComplexItem::timeBetweenShots() { return 0; }
QString RouteComplexItem::commandDescription() const { return tr("Route"); }
QString MeasurementComplexItem::commandDescription() const {
return tr("Route");
}
QString RouteComplexItem::commandName() const { return tr("Route"); }
QString MeasurementComplexItem::commandName() const { return tr("Route"); }
QString RouteComplexItem::abbreviation() const { return tr("R"); }
QString MeasurementComplexItem::abbreviation() const { return tr("R"); }
TransectStyleComplexItem::ReadyForSaveState
RouteComplexItem::readyForSaveState() const {
MeasurementComplexItem::readyForSaveState() const {
if (TransectStyleComplexItem::readyForSaveState() ==
TransectStyleComplexItem::ReadyForSaveState::ReadyForSave) {
if (this->_state == STATE::IDLE) {
......@@ -371,25 +469,48 @@ RouteComplexItem::readyForSaveState() const {
}
}
double RouteComplexItem::additionalTimeDelay() const { return 0; }
bool MeasurementComplexItem::exitCoordinateSameAsEntry() const {
return this->_route.size() > 0 ? this->_route.first() == this->_route.last()
: false;
}
QString RouteComplexItem::patternName() const { return name; }
void MeasurementComplexItem::setDirty(bool dirty) {
if (this->_dirty != dirty) {
this->_dirty = dirty;
emit dirtyChanged(this->_dirty);
}
}
bool RouteComplexItem::registerGenerator(const QString &name,
routing::GeneratorBase *g) {
void MeasurementComplexItem::setCoordinate(const QGeoCoordinate &coordinate) {
Q_UNUSED(coordinate);
}
void MeasurementComplexItem::setSequenceNumber(int sequenceNumber) {
if (this->_sequenceNumber != sequenceNumber) {
this->_sequenceNumber = sequenceNumber;
emit sequenceNumberChanged(this->_sequenceNumber);
}
}
QString MeasurementComplexItem::patternName() const { return name; }
bool MeasurementComplexItem::registerGenerator(const QString &name,
routing::GeneratorBase *g) {
if (name.isEmpty()) {
qCDebug(RouteComplexItemLog) << "registerGenerator(): empty name string.";
qCDebug(MeasurementComplexItemLog)
<< "registerGenerator(): empty name string.";
return false;
}
if (!g) {
qCDebug(RouteComplexItemLog) << "registerGenerator(): empty generator.";
qCDebug(MeasurementComplexItemLog)
<< "registerGenerator(): empty generator.";
return false;
}
if (this->_generatorNameList.contains(name)) {
qCDebug(RouteComplexItemLog) << "registerGenerator(): generator "
"already registered.";
qCDebug(MeasurementComplexItemLog) << "registerGenerator(): generator "
"already registered.";
return false;
} else {
this->_generatorNameList.push_back(name);
......@@ -403,7 +524,7 @@ bool RouteComplexItem::registerGenerator(const QString &name,
}
}
bool RouteComplexItem::unregisterGenerator(const QString &name) {
bool MeasurementComplexItem::unregisterGenerator(const QString &name) {
auto index = this->_generatorNameList.indexOf(name);
if (index >= 0) {
// Is this the current generator?
......@@ -413,7 +534,7 @@ bool RouteComplexItem::unregisterGenerator(const QString &name) {
_setGenerator(this->_generatorList.at(index - 1));
} else {
_setGenerator(nullptr);
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "unregisterGenerator(): last generator unregistered.";
}
}
......@@ -425,106 +546,111 @@ bool RouteComplexItem::unregisterGenerator(const QString &name) {
emit generatorNameListChanged();
return true;
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "unregisterGenerator(): generator " << name << " not registered.";
return false;
}
}
bool RouteComplexItem::unregisterGenerator(int index) {
bool MeasurementComplexItem::unregisterGenerator(int index) {
if (index > 0 && index < this->_generatorNameList.size()) {
return unregisterGenerator(this->_generatorNameList.at(index));
} else {
qCDebug(RouteComplexItemLog) << "unregisterGenerator(): index (" << index
<< ") out"
"of bounds ( "
<< this->_generatorList.size() << " ).";
qCDebug(MeasurementComplexItemLog)
<< "unregisterGenerator(): index (" << index
<< ") out"
"of bounds ( "
<< this->_generatorList.size() << " ).";
return false;
}
}
bool RouteComplexItem::switchToGenerator(const QString &name) {
bool MeasurementComplexItem::switchToGenerator(const QString &name) {
auto index = this->_generatorNameList.indexOf(name);
if (index >= 0) {
_setGenerator(this->_generatorList.at(index));
return true;
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "switchToGenerator(): generator " << name << " not registered.";
return false;
}
}
bool RouteComplexItem::switchToGenerator(int index) {
bool MeasurementComplexItem::switchToGenerator(int index) {
if (index >= 0) {
_setGenerator(this->_generatorList.at(index));
return true;
} else {
qCDebug(RouteComplexItemLog) << "unregisterGenerator(): index (" << index
<< ") out"
"of bounds ( "
<< this->_generatorNameList.size() << " ).";
qCDebug(MeasurementComplexItemLog)
<< "unregisterGenerator(): index (" << index
<< ") out"
"of bounds ( "
<< this->_generatorNameList.size() << " ).";
return false;
}
}
QStringList RouteComplexItem::generatorNameList() {
QStringList MeasurementComplexItem::generatorNameList() {
return this->_generatorNameList;
}
routing::GeneratorBase *RouteComplexItem::generator() { return _pGenerator; }
routing::GeneratorBase *MeasurementComplexItem::generator() {
return _pGenerator;
}
int RouteComplexItem::generatorIndex() {
int MeasurementComplexItem::generatorIndex() {
return this->_generatorList.indexOf(this->_pGenerator);
}
void RouteComplexItem::editingStart() {
if (!_editing) {
void MeasurementComplexItem::editingStart() {
if (!_editing(this->_state)) {
*_editorData = *_areaData;
_setAreaData(_editorData);
_setEditing(true);
_setState(STATE::EDITING);
}
}
void RouteComplexItem::editingStop() {
if (_editing) {
void MeasurementComplexItem::editingStop() {
if (_editing(this->_state)) {
if (_editorData->isValid()) {
*_areaData = *_editorData;
}
_setAreaData(_areaData);
_setEditing(false);
_setState(STATE::IDLE);
}
}
void RouteComplexItem::_rebuildTransectsPhase1(void) {
void MeasurementComplexItem::_update(void) {
auto start = std::chrono::high_resolution_clock::now();
switch (this->_state) {
case STATE::SKIPP:
qCDebug(RouteComplexItemLog) << "rebuildTransectsPhase1: skipp.";
qCDebug(MeasurementComplexItemLog) << "rebuildTransectsPhase1: skipp.";
this->_setState(STATE::IDLE);
break;
case STATE::CHANGE_VARIANT:
qCDebug(RouteComplexItemLog) << "rebuildTransectsPhase1: variant change.";
qCDebug(MeasurementComplexItemLog)
<< "rebuildTransectsPhase1: variant change.";
this->_changeVariantWorker();
this->_setState(STATE::IDLE);
break;
case STATE::REVERT_PATH:
qCDebug(RouteComplexItemLog) << "rebuildTransectsPhase1: reverse.";
qCDebug(MeasurementComplexItemLog) << "rebuildTransectsPhase1: reverse.";
this->_reverseWorker();
this->_setState(STATE::IDLE);
break;
case STATE::IDLE:
case STATE::ROUTING:
this->_setState(STATE::ROUTING);
qCDebug(RouteComplexItemLog) << "rebuildTransectsPhase1: update.";
if (!this->_updateWorker()) {
qCDebug(MeasurementComplexItemLog) << "rebuildTransectsPhase1: update.";
if (!this->_updateRouteWorker()) {
this->_setState(STATE::IDLE);
}
break;
}
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "rebuildTransectsPhase1(): "
<< std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start)
......@@ -532,9 +658,10 @@ void RouteComplexItem::_rebuildTransectsPhase1(void) {
<< " ms";
}
void RouteComplexItem::_recalcCameraShots() { _cameraShots = 0; }
void MeasurementComplexItem::_recalcCameraShots() { _cameraShots = 0; }
void RouteComplexItem::_setTransects(RouteComplexItem::PtrRoutingData pRoute) {
void MeasurementComplexItem::_setTransects(
MeasurementComplexItem::PtrRoutingData pRoute) {
// Store solutions.
auto ori = this->_areaData->origin();
ori.setAltitude(0);
......@@ -591,19 +718,20 @@ void RouteComplexItem::_setTransects(RouteComplexItem::PtrRoutingData pRoute) {
}
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_setTransects(): lastTransect.size() == 0";
}
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_setTransects(): firstTransect.size() == 0";
}
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_setTransects(): transectsInfo.size() <= 1";
}
} else {
qCDebug(RouteComplexItemLog) << "_setTransects(): solution.size() == 0";
qCDebug(MeasurementComplexItemLog)
<< "_setTransects(): solution.size() == 0";
}
if (var.size() > 0 && var.front().size() > 0) {
......@@ -633,25 +761,29 @@ void RouteComplexItem::_setTransects(RouteComplexItem::PtrRoutingData pRoute) {
emit variantNamesChanged();
disconnect(&this->_variant, &Fact::rawValueChanged, this,
&RouteComplexItem::_changeVariant);
&MeasurementComplexItem::_changeVariant);
this->_variant.setCookedValue(QVariant(0));
connect(&this->_variant, &Fact::rawValueChanged, this,
&RouteComplexItem::_changeVariant);
&MeasurementComplexItem::_changeVariant);
this->_changeVariantWorker();
this->_setState(STATE::SKIPP);
this->_rebuildTransects();
this->_update();
} else {
qCDebug(RouteComplexItemLog)
qCDebug(MeasurementComplexItemLog)
<< "_setTransects(): failed, variantVector empty.";
this->_setState(STATE::IDLE);
}
}
Fact *RouteComplexItem::variant() { return &_variant; }
Fact *MeasurementComplexItem::variant() { return &_variant; }
Fact *MeasurementComplexItem::altitude() { return &this->_altitude; }
bool RouteComplexItem::calculating() const {
bool MeasurementComplexItem::calculating() const {
return this->_calculating(this->_state);
}
bool RouteComplexItem::editing() const { return this->_editing; }
bool MeasurementComplexItem::editing() const { return _editing(this->_state); }
bool MeasurementComplexItem::followTerrain() const { return _followTerrain; }
......@@ -4,8 +4,9 @@
#include <QVector>
#include <memory>
#include "ComplexMissionItem.h"
#include "QGCQGeoCoordinate.h"
#include "SettingsFact.h"
#include "TransectStyleComplexItem.h"
#include "AreaData.h"
......@@ -16,24 +17,24 @@ namespace routing {
class GeneratorBase;
}
class RouteComplexItem : public TransectStyleComplexItem {
class MeasurementComplexItem : public ComplexMissionItem {
Q_OBJECT
using PtrGenerator = routing::GeneratorBase *;
using PtrAreaData = AreaData *;
using PtrRoutingData = std::shared_ptr<RoutingData>;
using PtrWorker = RoutingThread *;
using Transects = QList<QList<CoordInfo_t>>;
using Variant = Transects;
using Variant = QList<QGeoCoordinate>;
enum class STATE { IDLE, ROUTING, SKIPP, REVERT_PATH, CHANGE_VARIANT };
enum class STATE { IDLE, ROUTING, REVERT_PATH, CHANGE_VARIANT, EDITING };
public:
RouteComplexItem(PlanMasterController *masterController, bool flyView,
const QString &kmlOrShpFile, QObject *parent);
~RouteComplexItem();
MeasurementComplexItem(PlanMasterController *masterController, bool flyView,
const QString &kmlOrShpFile, QObject *parent);
~MeasurementComplexItem();
Q_PROPERTY(Fact *variant READ variant CONSTANT)
Q_PROPERTY(Fact *altitude READ variant CONSTANT)
Q_PROPERTY(
QStringList variantNames READ variantNames NOTIFY variantNamesChanged)
Q_PROPERTY(QStringList generatorNameList READ generatorNameList NOTIFY
......@@ -44,30 +45,50 @@ public:
Q_PROPERTY(int generatorIndex READ generatorIndex NOTIFY generatorChanged)
Q_PROPERTY(bool editing READ editing NOTIFY editingChanged)
Q_PROPERTY(AreaData *areaData READ areaData NOTIFY areaDataChanged)
Q_PROPERTY(QVariantList visualTransectPoints READ visualTransectPoints NOTIFY
visualTransectPointsChanged)
Q_INVOKABLE void revertPath(void);
// Property getters
const AreaData *areaData() const;
AreaData *areaData();
Fact *variant();
QStringList variantNames() const;
bool calculating() const;
bool editing() const;
// Overrides
// Overrides from ComplexMissionItem
virtual QString patternName(void) const override final;
virtual double complexDistance(void) const override final;
virtual int lastSequenceNumber(void) const final;
virtual bool load(const QJsonObject &complexObject, int sequenceNumber,
QString &errorString) override final;
virtual void save(QJsonArray &planItems) override final;
virtual double
greatestDistanceTo(const QGeoCoordinate &other) const override final;
virtual QString mapVisualQML(void) const override final;
// Overrides from VisualMissionItem
virtual bool dirty(void) const override final;
virtual bool isSimpleItem(void) const override final;
virtual bool isStandaloneCoordinate(void) const override final;
virtual bool specifiesCoordinate(void) const override final;
virtual double timeBetweenShots(void) override final;
virtual QString commandDescription(void) const override final;
virtual QString commandName(void) const override final;
virtual QString abbreviation(void) const override final;
virtual ReadyForSaveState readyForSaveState(void) const override final;
virtual bool specifiesAltitudeOnly(void) const override final;
virtual QGeoCoordinate coordinate(void) const override final;
virtual QGeoCoordinate exitCoordinate(void) const override final;
virtual int sequenceNumber(void) const override final;
virtual double specifiedFlightSpeed(void) final override;
virtual double specifiedGimbalYaw(void) final override;
virtual double specifiedGimbalPitch(void) final override;
virtual void appendMissionItems(QList<MissionItem *> &items,
QObject *missionItemParent) final override;
virtual void setMissionFlightStatus(
const MissionController::MissionFlightStatus_t &missionFlightStatus)
final override;
virtual void applyNewAltitude(double newAltitude) override final;
virtual double additionalTimeDelay(void) const override final;
virtual QString patternName(void) const override;
virtual ReadyForSaveState readyForSaveState(void) const override final;
virtual bool exitCoordinateSameAsEntry(void) const override final;
virtual void setDirty(bool dirty) override final;
virtual void setCoordinate(const QGeoCoordinate &coordinate) override final;
virtual void setSequenceNumber(int sequenceNumber) override final;
virtual void save(QJsonArray &missionItems) override final;
virtual double amslEntryAlt(void) const override final;
virtual double amslExitAlt(void) const override final;
virtual double minAMSLAltitude(void) const override final;
virtual double maxAMSLAltitude(void) const override final;
// Generator
bool registerGenerator(const QString &name, routing::GeneratorBase *g);
......@@ -95,8 +116,19 @@ public:
//!
void editingStop();
// Property getters
const AreaData *areaData() const;
AreaData *areaData();
Fact *variant();
Fact *altitude();
QStringList variantNames() const;
bool calculating() const;
bool editing() const;
bool followTerrain() const;
static const char *settingsGroup;
static const char *variantName;
static const char *altitudeName;
static const char *jsonComplexItemTypeValue;
static const QString name;
......@@ -110,22 +142,27 @@ signals:
private slots:
// Overrides from TransectStyleComplexItem
virtual void _rebuildTransectsPhase1(void) override final;
virtual void _recalcCameraShots(void) override final;
void _update(void);
// Worker functions.
void _setTransects(PtrRoutingData pRoute);
void _changeVariant();
bool _updateWorker();
bool _updateRouteWorker();
void _changeVariantWorker();
void _reverseWorker();
private:
bool _setGenerator(PtrGenerator newG);
void _setState(STATE state);
bool _calculating(STATE state) const;
void _setEditing(bool editing);
void _setAreaData(PtrAreaData data);
static bool _calculating(STATE state);
static bool _editing(STATE state);
// Hirarcical stuff.
PlanMasterController *_masterController;
int _sequenceNumber;
bool _followTerrain;
SettingsFact *_altitude;
// State.
STATE _state;
......@@ -139,7 +176,6 @@ private:
PtrAreaData _areaData;
PtrAreaData _editorData;
PtrAreaData _currentData;
bool _editing;
// Generators
QList<PtrGenerator> _generatorList;
......@@ -148,5 +184,6 @@ private:
// Routing.
QVector<Variant> _variantVector;
Variant _route;
PtrWorker _pWorker;
};
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "Variant",
"shortDescription": "Route variant.",
"type": "uint64",
"defaultValue": 0
},
{
"name": "Altitude",
"shortDescription": "Altitude",
"type": "double",
"units": "m",
"min": 1,
"decimalPlaces": 1,
"defaultValue": 10.0
}
]
}
......@@ -15,6 +15,7 @@
#include "FlightPathSegment.h"
#include "JsonHelper.h"
#include "KMLPlanDomDocument.h"
#include "MeasurementComplexItem.h"
#include "MissionCommandUIInfo.h"
#include "MissionManager.h"
#include "MissionSettingsItem.h"
......@@ -26,7 +27,6 @@
#include "QGCCorePlugin.h"
#include "QGCQGeoCoordinate.h"
#include "QGroundControlQmlGlobal.h"
#include "RouteComplexItem.h"
#include "SettingsManager.h"
#include "SimpleMissionItem.h"
#include "StructureScanComplexItem.h"
......@@ -528,10 +528,10 @@ VisualMissionItem *MissionController::insertComplexMissionItem(
newItem = new CorridorScanComplexItem(_masterController, _flyView,
QString() /* kmlFile */,
_visualItems /* parent */);
} else if (itemName == RouteComplexItem::name) {
newItem = new RouteComplexItem(_masterController, _flyView,
QString() /* kmlFile */,
_visualItems /* parent */);
} else if (itemName == MeasurementComplexItem::name) {
newItem = new MeasurementComplexItem(_masterController, _flyView,
QString() /* kmlFile */,
_visualItems /* parent */);
} else {
qWarning() << "Internal error: Unknown complex item:" << itemName;
return nullptr;
......@@ -575,7 +575,7 @@ void MissionController::_insertComplexMissionItemWorker(
qobject_cast<SurveyComplexItem *>(complexItem) ||
qobject_cast<CorridorScanComplexItem *>(complexItem) ||
qobject_cast<StructureScanComplexItem *>(complexItem) ||
qobject_cast<RouteComplexItem *>(complexItem);
qobject_cast<MeasurementComplexItem *>(complexItem);
if (surveyStyleItem) {
bool rollSupported = false;
......@@ -642,7 +642,7 @@ void MissionController::removeVisualItem(int viIndex) {
bool removeSurveyStyle =
_visualItems->value<SurveyComplexItem *>(viIndex) ||
_visualItems->value<CorridorScanComplexItem *>(viIndex) ||
_visualItems->value<RouteComplexItem *>(viIndex);
_visualItems->value<MeasurementComplexItem *>(viIndex);
VisualMissionItem *item =
qobject_cast<VisualMissionItem *>(_visualItems->removeAt(viIndex));
......@@ -659,7 +659,7 @@ void MissionController::removeVisualItem(int viIndex) {
for (int i = 1; i < _visualItems->count(); i++) {
if (_visualItems->value<SurveyComplexItem *>(i) ||
_visualItems->value<CorridorScanComplexItem *>(i) ||
_visualItems->value<RouteComplexItem *>(i)) {
_visualItems->value<MeasurementComplexItem *>(i)) {
foundSurvey = true;
break;
}
......@@ -1062,11 +1062,11 @@ bool MissionController::_loadJsonMissionFileV2(const QJsonObject &json,
<< nextSequenceNumber;
visualItems->append(corridorItem);
} else if (complexItemType ==
RouteComplexItem::jsonComplexItemTypeValue) {
MeasurementComplexItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog)
<< "Loading Circular Survey: nextSequenceNumber"
<< "Loading Measurement Complex Item: nextSequenceNumber"
<< nextSequenceNumber;
RouteComplexItem *survey = new RouteComplexItem(
MeasurementComplexItem *survey = new MeasurementComplexItem(
_masterController, _flyView, QString() /* kmlFile */, visualItems);
if (!survey->load(itemObject, nextSequenceNumber++, errorString)) {
return false;
......@@ -2611,7 +2611,7 @@ QStringList MissionController::complexMissionItemNames(void) const {
complexItems.append(SurveyComplexItem::name);
complexItems.append(CorridorScanComplexItem::name);
complexItems.append(RouteComplexItem::name);
complexItems.append(MeasurementComplexItem::name);
if (_controllerVehicle->multiRotor() || _controllerVehicle->vtol()) {
complexItems.append(StructureScanComplexItem::name);
}
......
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "TransectDistance",
"shortDescription": "The distance between transects.",
"type": "double",
"units": "m",
"min": 0.3,
"decimalPlaces": 1,
"defaultValue": 20.0
},
{
"name": "Alpha",
"shortDescription": "Angle discretisation or transect angle (depending on type).",
"type": "double",
"units": "Deg",
"min": 0,
"max": 180,
"decimalPlaces": 1,
"defaultValue": 5.0
},
{
"name": "MinLength",
"shortDescription": "The minimal transect length.",
"type": "double",
"units": "m",
"min": 0.3,
"decimalPlaces": 1,
"defaultValue": 5.0
},
{
"name": "Type",
"shortDescription": "Survey Type.",
"type": "uint64",
"defaultValue": 0
},
{
"name": "Variant",
"shortDescription": "Route variant.",
"type": "uint64",
"defaultValue": 0
},
{
"name": "NumRuns",
"shortDescription": "The number of runs.",
"type": "uint64",
"min": 1,
"defaultValue": 1
},
{
"name": "Run",
"shortDescription": "The current run.",
"type": "uint64",
"defaultValue": 0
}
]
}
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