Commit 67cbe3f7 authored by Valentin Platzgummer's avatar Valentin Platzgummer

generators seem to work, still some bugs

parent 60b604d9
This diff is collapsed.
......@@ -24,6 +24,8 @@ import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import Wima 1.0
FlightMap {
id: flightMap
anchors.fill: parent
......
......@@ -89,6 +89,8 @@
#include "VideoSurface.h"
#include "ViewWidgetController.h"
#include "VisualMissionItem.h"
#include "Wima/Snake/CircularGenerator.h"
#include "Wima/Snake/LinearGenerator.h"
#include "Wima/Snake/NemoInterface.h"
#include "Wima/WimaController.h"
#include "Wima/WimaPlaner.h"
......@@ -520,6 +522,10 @@ void QGCApplication::_initCommon(void) {
qmlRegisterType<WimaController>("Wima", 1, 0, "WimaController");
qmlRegisterType<WimaPlaner>("Wima", 1, 0, "WimaPlaner");
qmlRegisterType<NemoInterface>("Wima", 1, 0, "NemoInterface");
qmlRegisterInterface<routing::GeneratorBase>("GeneratorBase");
qmlRegisterType<routing::CircularGenerator>("Wima", 1, 0,
"CircularGenerator");
qmlRegisterType<routing::LinearGenerator>("Wima", 1, 0, "LinearGenerator");
// Register Qml Singletons
qmlRegisterSingletonType<QGroundControlQmlGlobal>(
......
......@@ -65,7 +65,6 @@ QGCViewDialog 1.0 QGCViewDialog.qml
QGCViewDialogContainer 1.0 QGCViewDialogContainer.qml
QGCViewMessage 1.0 QGCViewMessage.qml
QGCViewPanel 1.0 QGCViewPanel.qml
WimaToolBar 1.0 WimaToolBar.qml
RallyPointEditorHeader 1.0 RallyPointEditorHeader.qml
RallyPointItemEditor 1.0 RallyPointItemEditor.qml
RallyPointMapVisuals 1.0 RallyPointMapVisuals.qml
......@@ -85,22 +84,6 @@ VehicleSummaryRow 1.0 VehicleSummaryRow.qml
ViewWidget 1.0 ViewWidget.qml
FlyAreaItemEditor 1.0 FlyAreaItemEditor.qml
WimaMapVisual 1.0 WimaMapVisual.qml
WimaMeasurementAreaMapVisual 1.0 WimaMeasurementAreaMapVisual.qml
WimaJoinedAreaMapVisual 1.0 WimaJoinedAreaMapVisual.qml
WimaMeasurementAreaEditor 1.0 WimaMeasurementAreaEditor.qml
WimaServiceAreaMapVisual 1.0 WimaServiceAreaMapVisual.qml
WimaAreaMapVisual 1.0 WimaAreaMapVisual.qml
WimaServiceAreaEditor 1.0 WimaServiceAreaEditor.qml
WimaCorridorMapVisual 1.0 WimaCorridorMapVisual.qml
WimaItemEditor 1.0 WimaItemEditor.qml
WimaMapPolygonVisuals 1.0 WimaMapPolygonVisuals.qml
WimaMapPolylineVisuals 1.0 WimaMapPolylineVisuals.qml
CircularSurveyMapVisual 1.0 CircularSurveyMapVisual.qml
DragCoordinate 1.0 DragCoordinate.qml
CoordinateIndicator 1.0 CoordinateIndicator.qml
CoordinateIndicatorDrag 1.0 CoordinateIndicatorDrag.qml
ProgressIndicator 1.0 ProgressIndicator.qml
QGCButtonColumn 1.0 QGCButtonColumn.qml
This diff is collapsed.
......@@ -13,13 +13,17 @@
class RoutingThread;
class RoutingData;
namespace routing {
class GeneratorBase;
}
class CircularSurvey : public TransectStyleComplexItem {
Q_OBJECT
using PtrGenerator = std::shared_ptr<GeneratorBase>;
using PtrGenerator = std::shared_ptr<routing::GeneratorBase>;
using PtrRoutingData = std::shared_ptr<RoutingData>;
using PtrWorker = std::shared_ptr<RoutingThread>;
public:
/// @param vehicle Vehicle which this is being contructed for
......@@ -31,14 +35,15 @@ public:
QObject *parent);
~CircularSurvey();
Q_PROPERTY(Fact *type READ type CONSTANT)
Q_PROPERTY(int typeCount READ typeCount CONSTANT)
Q_PROPERTY(Fact *variant READ variant CONSTANT)
Q_PROPERTY(
QList<QString> variantNames READ variantNames NOTIFY variantNamesChanged)
Q_PROPERTY(QList<QString> generatorNameList READ generatorNameList NOTIFY
QStringList variantNames READ variantNames NOTIFY variantNamesChanged)
Q_PROPERTY(QStringList generatorNameList READ generatorNameList NOTIFY
generatorNameListChanged)
Q_PROPERTY(bool calculating READ calculating NOTIFY calculatingChanged)
Q_PROPERTY(
routing::GeneratorBase *generator READ generator NOTIFY generatorChanged)
Q_PROPERTY(int generatorIndex READ generatorIndex NOTIFY generatorChanged)
Q_INVOKABLE void reverse(void);
......@@ -46,10 +51,9 @@ public:
void setPlanData(const WimaPlanData &d);
// Property getters
Fact *type();
int typeCount() const;
Fact *variant();
QList<QString> variantNames() const;
QStringList variantNames() const;
bool calculating() const;
// Overrides
bool load(const QJsonObject &complexObject, int sequenceNumber,
......@@ -68,15 +72,17 @@ public:
double additionalTimeDelay(void) const override final;
// Generator
bool registerGenerator(const QString &name, std::shared_ptr<GeneratorBase> g);
bool registerGenerator(const QString &name,
std::shared_ptr<routing::GeneratorBase> g);
bool unregisterGenerator(const QString &name);
bool unregisterGenerator(int index);
Q_INVOKABLE bool switchToGenerator(const QString &name);
Q_INVOKABLE bool switchToGenerator(int index);
QList<QString> generatorNameList();
QStringList generatorNameList();
routing::GeneratorBase *generator();
int generatorIndex();
static const char *settingsGroup;
static const char *typeName;
static const char *variantName;
static const char *CircularSurveyName;
......@@ -120,20 +126,18 @@ private:
// center of the circular lanes, e.g. base station
QMap<QString, FactMetaData *> _metaDataMap;
SettingsFact _type;
SettingsFact _variant;
QList<QString> _variantNames;
QStringList _variantNames;
// Area data
std::shared_ptr<WimaAreaData> _areaData;
std::shared_ptr<WimaPlanData> _pAreaData;
// Generators
QList<PtrGenerator> _generatorList;
QList<QString> _generatorNameList;
QStringList _generatorNameList;
PtrGenerator _pGenerator;
// Worker
using PtrWorker = std::shared_ptr<RoutingThread>;
PtrWorker _pWorker;
PtrRoutingData _pRoutingData; // remove this, not necessary.
......
......@@ -43,11 +43,11 @@ CircularGenerator::CircularGenerator(GeneratorBase::Data d, QObject *parent)
establishConnections();
}
QString CircularGenerator::editorQML() {
QString CircularGenerator::editorQml() {
return QStringLiteral("CircularGeneratorEditor.qml");
}
QString CircularGenerator::mapVisualQML() {
QString CircularGenerator::mapVisualQml() {
return QStringLiteral("CircularGeneratorMapVisual.qml");
}
......@@ -61,13 +61,15 @@ bool CircularGenerator::get(Generator &generator) {
if (this->_d) {
if (this->_d->isValid()) {
// Prepare data.
const auto &origin = this->_d->origin();
auto origin = this->_d->origin();
origin.setAltitude(0);
if (!origin.isValid()) {
qCWarning(CircularGeneratorLog) << "get(): origin invalid." << origin;
return false;
}
const auto &ref = this->_reference;
auto ref = this->_reference;
ref.setAltitude(0);
if (!ref.isValid()) {
qCWarning(CircularGeneratorLog) << "get(): reference invalid." << ref;
return false;
......
......@@ -16,8 +16,8 @@ public:
Q_PROPERTY(Fact *deltaAlpha READ deltaAlpha CONSTANT)
Q_PROPERTY(Fact *minLength READ minLength CONSTANT)
virtual QString editorQML() override;
virtual QString mapVisualQML() override;
virtual QString editorQml() override;
virtual QString mapVisualQml() override;
virtual QString name() override;
virtual QString abbreviation() override;
......@@ -30,7 +30,7 @@ public:
Fact *minLength();
void setReference(const QGeoCoordinate &reference);
void resetReference();
Q_INVOKABLE void resetReference();
static const char *settingsGroup;
static const char *distanceName;
......
......@@ -12,6 +12,14 @@ GeneratorBase::GeneratorBase(GeneratorBase::Data d, QObject *parent)
GeneratorBase::~GeneratorBase() {}
QString GeneratorBase::editorQml() {
return QStringLiteral("EmptyGeneratorEditor.qml");
}
QString GeneratorBase::mapVisualQml() {
return QStringLiteral("EmptyGeneratorMapVisual.qml");
}
GeneratorBase::Data GeneratorBase::data() const { return _d; }
void GeneratorBase::setData(const Data &d) {
......
#pragma once
#include <QObject>
#include <functional>
......@@ -19,8 +21,11 @@ public:
explicit GeneratorBase(Data d, QObject *parent = nullptr);
~GeneratorBase();
virtual QString editorQML() = 0;
virtual QString mapVisualQML() = 0;
Q_PROPERTY(QString editorQml READ editorQml CONSTANT)
Q_PROPERTY(QString mapVisualQml READ mapVisualQml CONSTANT)
virtual QString editorQml();
virtual QString mapVisualQml();
virtual QString name() = 0;
virtual QString abbreviation() = 0;
......
......@@ -34,25 +34,24 @@ LinearGenerator::LinearGenerator(GeneratorBase::Data d, QObject *parent)
establishConnections();
}
QString LinearGenerator::editorQML() {
QString LinearGenerator::editorQml() {
return QStringLiteral("LinearGeneratorEditor.qml");
}
QString LinearGenerator::mapVisualQML() {
return QStringLiteral("LinearGeneratorMapVisual.qml");
}
QString LinearGenerator::name() { return QStringLiteral("Linear Generator"); }
QString LinearGenerator::abbreviation() { return QStringLiteral("L. Gen."); }
bool LinearGenerator::get(Generator &generator) {
if (_d) {
if (this->_d->isValid()) {
// Prepare data.
const auto &origin = this->_d->origin();
auto origin = this->_d->origin();
origin.setAltitude(0);
if (!origin.isValid()) {
qCWarning(LinearGeneratorLog) << "get(): origin invalid.";
}
auto geoPolygon = this->_d->measurementArea().coordinateList();
for (auto &v : geoPolygon) {
if (v.isValid()) {
......
......@@ -14,8 +14,7 @@ public:
Q_PROPERTY(Fact *alpha READ alpha CONSTANT)
Q_PROPERTY(Fact *minLength READ minLength CONSTANT)
virtual QString editorQML() override;
virtual QString mapVisualQML() override;
virtual QString editorQml() override;
virtual QString name() override;
virtual QString abbreviation() override;
......
......@@ -760,7 +760,17 @@ bool route(const FPolygon &area, const Transects &transects,
if (std::isinf(dist)) {
std::vector<std::size_t> route;
if (!dijkstraAlgorithm(n, i, j, route, dist, distLambda)) {
par.errorString = "Distance matrix calculation failed.";
std::stringstream ss;
ss << "Distance matrix calculation failed. connection graph: "
<< connectionGraph << std::endl;
ss << "area: " << bg::wkt(area) << std::endl;
ss << "transects:" << std::endl;
for (const auto &t : transects) {
ss << bg::wkt(t) << std::endl;
}
par.errorString = ss.str();
return false;
}
(void)route;
......
......@@ -356,8 +356,6 @@ void WimaPlaner::_update() {
}
// establish connections
_survey->setRefPoint(_measurementArea.center());
_survey->setHidePolygon(true);
connect(_survey, &CircularSurvey::calculatingChanged, this,
&WimaPlaner::CSCalculatingChangedHandler);
connect(_survey, &CircularSurvey::missionItemReady, this,
......@@ -369,9 +367,14 @@ void WimaPlaner::_update() {
// update survey area
disconnect(_survey, &CircularSurvey::calculatingChanged, this,
&WimaPlaner::CSCalculatingChangedHandler);
_survey->setMeasurementArea(this->_measurementArea);
_survey->setJoinedArea(this->_joinedArea);
_survey->setDepot(this->_serviceArea.depot());
WimaPlanData planData;
if (!toPlanData(planData)) {
qCWarning(WimaPlanerLog) << "not able to create plan data.";
return;
}
_survey->setPlanData(planData);
connect(_survey, &CircularSurvey::calculatingChanged, this,
&WimaPlaner::CSCalculatingChangedHandler);
......@@ -772,7 +775,6 @@ bool WimaPlaner::loadFromFile(const QString &filename) {
for (int i = 0; i < missionItems->count(); i++) {
_survey = missionItems->value<CircularSurvey *>(i);
if (_survey != nullptr) {
_survey->setHidePolygon(true);
connect(_survey, &CircularSurvey::calculatingChanged, this,
&WimaPlaner::CSCalculatingChangedHandler);
connect(_survey, &CircularSurvey::missionItemReady, this,
......
import QtQuick 2.0
import QtQuick.Layouts 1.11
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0
GridLayout {
// Item must be loaded, expects the following properties:
// property var generator
property real _margin: ScreenTools.defaultFontPixelWidth / 2
columnSpacing: _margin
rowSpacing: _margin
columns: 2
QGCLabel { text: qsTr("Distance") }
FactTextField {
fact: generator.distance
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Delta Alpha") }
FactTextField {
fact: generator.deltaAlpha
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Min. Length") }
FactTextField {
fact: generator.minLength
Layout.fillWidth: true
}
QGCButton {
text: qsTr("Reset Ref.")
onClicked: generator.resetReference();
Layout.fillWidth: true
Layout.columnSpan: 2
}
}
import QtQuick 2.0
Item {
id: _root
property var map ///< Map control to place item in
property var qgcView ///< QGCView to use for popping dialogs
property var generator
property bool checked: false
property var _referenceComponent
signal clicked()
function _addRefPoint(){
if (!_referenceComponent){
_referenceComponent = refPointComponent.createObject(_root)
map.addMapItem(_referenceComponent)
}
}
function _destroyRefPoint(){
if (_referenceComponent){
map.removeMapItem(_referenceComponent)
_referenceComponent.destroy()
_referenceComponent = undefined
}
}
onVisibleChanged: {
if (visible){
_addRefPoint()
} else {
_destroyRefPoint()
}
}
Component.onCompleted: {
if (visible){
_addRefPoint()
}
}
Component.onDestroyed: {
_destroyRefPoint()
}
// Ref. point (Base Station)
Component {
id: refPointComponent
DragCoordinate {
map: _root.map
qgcView: _root.qgcView
z: QGroundControl.zOrderMapItems
checked: _root.checked
coordinate: _root.generator.reference
onClicked: {
_root.clicked()
}
onDragReleased: {
_root.generator.reference = coordinate
coordinate = Qt.binding(function (){return _root.generator.reference})
}
}
}
}
......@@ -30,6 +30,8 @@ Rectangle {
property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
property real _cameraMinTriggerInterval: missionItem.cameraCalc.minTriggerInterval.rawValue
property var _generator: missionItem.generator
function polygonCaptureStarted() {
missionItem.clearPolygon()
}
......@@ -95,31 +97,24 @@ Rectangle {
}
QGCLabel {
text: qsTr("Type")
text: qsTr("Generator Type")
Layout.columnSpan: 2
}
Repeater{
id: typeRepeater
property var typeFact: missionItem.type
property int type: typeFact.value
property var names: ["Circular", "Linear"]
QGCComboBox {
property var names: missionItem.generatorNameList
property int length: names.length
model: missionItem.typeCount
QGCRadioButton {
checked: index === typeRepeater.type
text: qsTr(typeRepeater.names[index])
anchors.margins: ScreenTools.defaultFontPixelWidth
currentIndex: missionItem.generatorIndex
Layout.columnSpan: 2
model: missionItem.generatorNameList
onCheckedChanged: {
if (checked){
missionItem.type.value = index
}
checked = Qt.binding(function(){ return index === typeRepeater.type})
}
onActivated: {
missionItem.switchToGenerator(index)
}
}
QGCLabel {
text: qsTr("Variant")
Layout.columnSpan: 2
......@@ -156,74 +151,18 @@ Rectangle {
}
}
// Generator Editor
SectionHeader {
id: transectsHeader
text: qsTr("Transects")
text: qsTr("Generator")
}
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: transectsHeader.checked
QGCLabel { text: qsTr("Distance") }
FactTextField {
fact: missionItem.transectDistance
Layout.fillWidth: true
}
/*QGCSlider {
id: rSlider
minimumValue: 0.3
maximumValue: 20
stepSize: 0.1
tickmarksEnabled: false
Layout.fillWidth: true
Layout.columnSpan: 2
Layout.preferredHeight: ScreenTools.defaultFontPixelHeight * 1.5
onValueChanged: missionItem.deltaR.value = value
Component.onCompleted: value = missionItem.deltaR.defaultValue
updateValueWhileDragging: true
}*/
QGCLabel { text: qsTr("Alpha") }
FactTextField {
fact: missionItem.alpha
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Min. Length") }
FactTextField {
fact: missionItem.minLength
Layout.fillWidth: true
}
Loader{
source: _generator.editorQml
property var generator: _generator
property real margin: _margin
visible: transectsHeader.checked
}
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: transectsHeader.checked
QGCButton {
text: qsTr("Reverse")
onClicked: missionItem.reverse();
Layout.fillWidth: true
}
QGCButton {
text: qsTr("Reset Ref.")
onClicked: missionItem.resetReference();
Layout.fillWidth: true
}
}
Column{
anchors.left: parent.left
......
......@@ -26,12 +26,9 @@ Item {
property var qgcView ///< QGCView to use for popping dialogs
property var _missionItem: object
property var _mapPolygon: object.surveyAreaPolygon
property var _transectsComponent
property var _entryCoordinate
property var _exitCoordinate
property var _refPoint
property bool showRefPoint: _missionItem.type.value === 0 // type == Circular
signal clicked(int sequenceNumber)
......@@ -56,13 +53,6 @@ Item {
}
}
function _addRefPoint(){
if (!_refPoint){
_refPoint = refPointComponent.createObject(_root)
map.addMapItem(_refPoint)
}
}
function _destroyEntryCoordinate(){
if (_entryCoordinate){
map.removeMapItem(_entryCoordinate)
......@@ -79,14 +69,6 @@ Item {
}
}
function _destroyRefPoint(){
if (_refPoint){
map.removeMapItem(_refPoint)
_refPoint.destroy()
_refPoint = undefined
}
}
function _destroyTransectsComponent(){
if (_transectsComponent){
map.removeMapItem(_transectsComponent)
......@@ -95,79 +77,18 @@ Item {
}
}
/// Add an initial 4 sided polygon if there is none
function _addInitialPolygon() {
if (_mapPolygon.count < 3) {
// Initial polygon is inset to take 2/3rds space
var rect = Qt.rect(map.centerViewport.x, map.centerViewport.y, map.centerViewport.width, map.centerViewport.height)
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2), rect.y + (rect.height / 2)), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */)
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */)
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
// Initial polygon has max width and height of 3000 meters
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), 3000) / 2
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), 3000) / 2
topLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0)
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180)
_mapPolygon.appendVertex(topLeftCoord)
_mapPolygon.appendVertex(topRightCoord)
_mapPolygon.appendVertex(bottomRightCoord)
_mapPolygon.appendVertex(bottomLeftCoord)
}
}
Component.onCompleted: {
if ( _mapPolygon.count === 0 ) {
_addInitialPolygon()
_missionItem.resetReference();
}
_addEntryCoordinate()
_addExitCoordinate()
if (showRefPoint){
_addRefPoint()
}
_addTransectsComponent()
}
Component.onDestruction: {
_destroyEntryCoordinate()
_destroyExitCoordinate()
_destroyRefPoint()
_destroyTransectsComponent()
}
onShowRefPointChanged: {
if (showRefPoint){
_addRefPoint()
} else {
_destroyRefPoint()
}
}
WimaMapPolygonVisuals {
id: mapPolygonVisuals
qgcView: _root.qgcView
mapControl: map
mapPolygon: _mapPolygon
interactive: _missionItem.isCurrentItem
borderWidth: 1
borderColor: "black"
interiorColor: "green"
interiorOpacity: 0.5
visible: !_missionItem.hidePolygon
}
// Transect lines
Component {
id: visualTransectsComponent
......@@ -219,26 +140,4 @@ Item {
}
}
}