Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
62285253
Commit
62285253
authored
Feb 25, 2016
by
Don Gagne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More work on complex mission items
- Load/Save working - Entry point working
parent
17fee7a5
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
500 additions
and
271 deletions
+500
-271
qgroundcontrol.qrc
qgroundcontrol.qrc
+7
-2
JsonHelper.cc
src/JsonHelper.cc
+13
-1
JsonHelper.h
src/JsonHelper.h
+3
-1
MissionEditor.qml
src/MissionEditor/MissionEditor.qml
+1
-0
MissionItemStatus.qml
src/MissionEditor/MissionItemStatus.qml
+0
-1
SimpleItemEditor.qml
src/MissionEditor/SimpleItemEditor.qml
+123
-0
SurveyItemEditor.qml
src/MissionEditor/SurveyItemEditor.qml
+62
-0
ComplexMissionItem.cc
src/MissionManager/ComplexMissionItem.cc
+165
-20
ComplexMissionItem.h
src/MissionManager/ComplexMissionItem.h
+32
-14
MissionController.cc
src/MissionManager/MissionController.cc
+62
-23
MissionController.h
src/MissionManager/MissionController.h
+3
-1
MissionItem.cc
src/MissionManager/MissionItem.cc
+1
-1
MissionItem.h
src/MissionManager/MissionItem.h
+1
-1
SimpleMissionItem.cc
src/MissionManager/SimpleMissionItem.cc
+8
-9
SimpleMissionItem.h
src/MissionManager/SimpleMissionItem.h
+3
-2
VisualMissionItem.h
src/MissionManager/VisualMissionItem.h
+7
-6
MissionItemEditor.qml
src/QmlControls/MissionItemEditor.qml
+9
-189
No files found.
qgroundcontrol.qrc
View file @
62285253
...
...
@@ -42,9 +42,12 @@
<file alias="PowerComponent.qml">src/AutoPilotPlugins/PX4/PowerComponent.qml</file>
<file alias="PowerComponentSummary.qml">src/AutoPilotPlugins/PX4/PowerComponentSummary.qml</file>
<file alias="PX4FlowSensor.qml">src/VehicleSetup/PX4FlowSensor.qml</file>
<file alias="QGroundControl/Controls/qmldir">src/QmlControls/QGroundControl.Controls.qmldir</file>
<file alias="QGroundControl/Controls/ClickableColor.qml">src/QmlControls/ClickableColor.qml</file>
<file alias="QGroundControl/Controls/DropButton.qml">src/QmlControls/DropButton.qml</file>
<file alias="QGroundControl/Controls/ExclusiveGroupItem.qml">src/QmlControls/ExclusiveGroupItem.qml</file>
<file alias="QGroundControl/Controls/FactSliderPanel.qml">src/QmlControls/FactSliderPanel.qml</file>
<file alias="QGroundControl/Controls/IndicatorButton.qml">src/QmlControls/IndicatorButton.qml</file>
<file alias="QGroundControl/Controls/JoystickThumbPad.qml">src/QmlControls/JoystickThumbPad.qml</file>
<file alias="QGroundControl/Controls/MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file>
...
...
@@ -73,14 +76,16 @@
<file alias="QGroundControl/Controls/QGCViewDialog.qml">src/QmlControls/QGCViewDialog.qml</file>
<file alias="QGroundControl/Controls/QGCViewMessage.qml">src/QmlControls/QGCViewMessage.qml</file>
<file alias="QGroundControl/Controls/QGCViewPanel.qml">src/QmlControls/QGCViewPanel.qml</file>
<file alias="QGroundControl/Controls/qmldir">src/QmlControls/QGroundControl.Controls.qmldir</file>
<file alias="QGroundControl/Controls/RoundButton.qml">src/QmlControls/RoundButton.qml</file>
<file alias="QGroundControl/Controls/SignalStrength.qml">src/ui/toolbar/SignalStrength.qml</file>
<file alias="QGroundControl/Controls/SubMenuButton.qml">src/QmlControls/SubMenuButton.qml</file>
<file alias="QGroundControl/Controls/VehicleRotationCal.qml">src/QmlControls/VehicleRotationCal.qml</file>
<file alias="QGroundControl/Controls/VehicleSummaryRow.qml">src/QmlControls/VehicleSummaryRow.qml</file>
<file alias="QGroundControl/Controls/ViewWidget.qml">src/ViewWidgets/ViewWidget.qml</file>
<file alias="QGroundControl/Controls/FactSliderPanel.qml">src/QmlControls/FactSliderPanel.qml</file>
<file alias="SimpleItemEditor.qml">src/MissionEditor/SimpleItemEditor.qml</file>
<file alias="SurveyItemEditor.qml">src/MissionEditor/SurveyItemEditor.qml</file>
<file alias="QGroundControl/FactControls/FactBitmask.qml">src/FactSystem/FactControls/FactBitmask.qml</file>
<file alias="QGroundControl/FactControls/FactCheckBox.qml">src/FactSystem/FactControls/FactCheckBox.qml</file>
<file alias="QGroundControl/FactControls/FactComboBox.qml">src/FactSystem/FactControls/FactComboBox.qml</file>
...
...
src/JsonHelper.cc
View file @
62285253
...
...
@@ -82,7 +82,19 @@ bool JsonHelper::toQGeoCoordinate(const QJsonValue& jsonValue, QGeoCoordinate& c
return
true
;
}
bool
JsonHelper
::
validateKeyTypes
(
QJsonObject
&
jsonObject
,
const
QStringList
&
keys
,
const
QList
<
QJsonValue
::
Type
>&
types
,
QString
&
errorString
)
void
JsonHelper
::
writeQGeoCoordinate
(
QJsonValue
&
jsonValue
,
const
QGeoCoordinate
&
coordinate
,
bool
writeAltitude
)
{
QJsonArray
coordinateArray
;
coordinateArray
<<
coordinate
.
latitude
()
<<
coordinate
.
longitude
();
if
(
writeAltitude
)
{
coordinateArray
<<
coordinate
.
altitude
();
}
jsonValue
=
QJsonValue
(
coordinateArray
);
}
bool
JsonHelper
::
validateKeyTypes
(
const
QJsonObject
&
jsonObject
,
const
QStringList
&
keys
,
const
QList
<
QJsonValue
::
Type
>&
types
,
QString
&
errorString
)
{
for
(
int
i
=
0
;
i
<
keys
.
count
();
i
++
)
{
if
(
jsonObject
.
contains
(
keys
[
i
]))
{
...
...
src/JsonHelper.h
View file @
62285253
...
...
@@ -31,10 +31,12 @@ class JsonHelper
{
public:
static
bool
validateRequiredKeys
(
const
QJsonObject
&
jsonObject
,
const
QStringList
&
keys
,
QString
&
errorString
);
static
bool
validateKeyTypes
(
QJsonObject
&
jsonObject
,
const
QStringList
&
keys
,
const
QList
<
QJsonValue
::
Type
>&
types
,
QString
&
errorString
);
static
bool
validateKeyTypes
(
const
QJsonObject
&
jsonObject
,
const
QStringList
&
keys
,
const
QList
<
QJsonValue
::
Type
>&
types
,
QString
&
errorString
);
static
bool
toQGeoCoordinate
(
const
QJsonValue
&
jsonValue
,
QGeoCoordinate
&
coordinate
,
bool
altitudeRequired
,
QString
&
errorString
);
static
bool
parseEnum
(
QJsonObject
&
jsonObject
,
QStringList
&
enumStrings
,
QStringList
&
enumValues
,
QString
&
errorString
);
static
void
writeQGeoCoordinate
(
QJsonValue
&
jsonValue
,
const
QGeoCoordinate
&
coordinate
,
bool
writeAltitude
);
static
const
char
*
_enumStringsJsonKey
;
static
const
char
*
_enumValuesJsonKey
;
};
...
...
src/MissionEditor/MissionEditor.qml
View file @
62285253
...
...
@@ -552,6 +552,7 @@ QGCView {
var
index
=
controller
.
insertComplexMissionItem
(
coordinate
,
controller
.
visualItems
.
count
)
setCurrentItem
(
index
)
checked
=
false
addMissionItemsButton
.
checked
=
false
}
}
...
...
src/MissionEditor/MissionItemStatus.qml
View file @
62285253
...
...
@@ -49,7 +49,6 @@ Rectangle {
property
real
_gradient
:
_statusValid
?
Math
.
atan
(
_currentMissionItem
.
altDifference
/
_currentMissionItem
.
distance
)
:
0
property
real
_gradientPercent
:
isNaN
(
_gradient
)
?
0
:
_gradient
*
100
property
real
_azimuth
:
_statusValid
?
_currentMissionItem
.
azimuth
:
-
1
property
real
_isHomePosition
:
_statusValid
?
_currentMissionItem
.
homePosition
:
false
property
bool
_statusValid
:
currentMissionItem
!=
undefined
property
string
_distanceText
:
_statusValid
?
_distance
.
toFixed
(
2
)
+
"
m
"
:
""
property
string
_altText
:
_statusValid
?
_altDifference
.
toFixed
(
2
)
+
"
m
"
:
""
...
...
src/MissionEditor/SimpleItemEditor.qml
0 → 100644
View file @
62285253
import
QtQuick
2.2
import
QtQuick
.
Controls
1.2
import
QtQuick
.
Controls
.
Styles
1.2
import
QtQuick
.
Dialogs
1.2
import
QGroundControl
.
ScreenTools
1.0
import
QGroundControl
.
Vehicle
1.0
import
QGroundControl
.
Controls
1.0
import
QGroundControl
.
FactControls
1.0
import
QGroundControl
.
Palette
1.0
// Editor for Simple mission items
Rectangle
{
id
:
valuesRect
width
:
availableWidth
height
:
valuesItem
.
height
color
:
qgcPal
.
windowShadeDark
visible
:
missionItem
.
isCurrentItem
radius
:
_radius
// The following properties must be available up the hierachy chain
//property real availableWidth ///< Width for control
//property var missionItem ///< Mission Item for editor
Item
{
id
:
valuesItem
anchors.margins
:
_margin
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
anchors.top
:
parent
.
top
height
:
valuesColumn
.
height
+
(
_margin
*
2
)
Column
{
id
:
valuesColumn
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
anchors.top
:
parent
.
top
spacing
:
_margin
QGCLabel
{
width
:
parent
.
width
wrapMode
:
Text
.
WordWrap
text
:
missionItem
.
sequenceNumber
==
0
?
"
Planned home position.
"
:
(
missionItem
.
rawEdit
?
"
Provides advanced access to all commands/parameters. Be very careful!
"
:
missionItem
.
commandDescription
)
}
Repeater
{
model
:
missionItem
.
comboboxFacts
Item
{
width
:
valuesColumn
.
width
height
:
comboBoxFact
.
height
QGCLabel
{
id
:
comboBoxLabel
anchors.baseline
:
comboBoxFact
.
baseline
text
:
object
.
name
visible
:
object
.
name
!=
""
}
FactComboBox
{
id
:
comboBoxFact
anchors.right
:
parent
.
right
width
:
comboBoxLabel
.
visible
?
_editFieldWidth
:
parent
.
width
indexModel
:
false
model
:
object
.
enumStrings
fact
:
object
}
}
}
Repeater
{
model
:
missionItem
.
textFieldFacts
Item
{
width
:
valuesColumn
.
width
height
:
textField
.
height
QGCLabel
{
id
:
textFieldLabel
anchors.baseline
:
textField
.
baseline
text
:
object
.
name
}
FactTextField
{
id
:
textField
anchors.right
:
parent
.
right
width
:
_editFieldWidth
showUnits
:
true
fact
:
object
visible
:
!
_root
.
readOnly
}
FactLabel
{
anchors.baseline
:
textFieldLabel
.
baseline
anchors.right
:
parent
.
right
fact
:
object
visible
:
_root
.
readOnly
}
}
}
Repeater
{
model
:
missionItem
.
checkboxFacts
FactCheckBox
{
text
:
object
.
name
fact
:
object
}
}
QGCButton
{
text
:
"
Move Home to map center
"
visible
:
missionItem
.
homePosition
onClicked
:
editorRoot
.
moveHomeToMapCenter
()
anchors.horizontalCenter
:
parent
.
horizontalCenter
}
}
// Column
}
// Item
}
// Rectangle
src/MissionEditor/SurveyItemEditor.qml
0 → 100644
View file @
62285253
import
QtQuick
2.2
import
QtQuick
.
Controls
1.2
import
QGroundControl
.
ScreenTools
1.0
import
QGroundControl
.
Vehicle
1.0
import
QGroundControl
.
Controls
1.0
import
QGroundControl
.
FactControls
1.0
import
QGroundControl
.
Palette
1.0
// Editor for Survery mission items
Rectangle
{
id
:
_root
height
:
editorColumn
.
height
+
(
_margin
*
2
)
width
:
availableWidth
color
:
qgcPal
.
windowShadeDark
radius
:
_radius
// The following properties must be available up the hierachy chain
//property real availableWidth ///< Width for control
//property var missionItem ///< Mission Item for editor
property
bool
_addPointsMode
:
false
property
real
_margin
:
ScreenTools
.
defaultFontPixelWidth
/
2
QGCPalette
{
id
:
qgcPal
;
colorGroupEnabled
:
true
}
Column
{
id
:
editorColumn
anchors.margins
:
_margin
anchors.top
:
parent
.
top
anchors.left
:
parent
.
left
width
:
availableWidth
spacing
:
_margin
Connections
{
target
:
editorMap
onMapClicked
:
{
if
(
_addPointsMode
)
{
missionItem
.
addPolygonCoordinate
(
coordinate
)
}
}
}
QGCLabel
{
text
:
"
Fly a grid pattern over a defined area.
"
wrapMode
:
Text
.
WordWrap
}
QGCButton
{
text
:
_addPointsMode
?
"
Finished
"
:
"
Draw Polygon
"
onClicked
:
{
if
(
_addPointsMode
)
{
_addPointsMode
=
false
}
else
{
missionItem
.
clearPolygon
()
_addPointsMode
=
true
}
}
}
}
}
src/MissionManager/ComplexMissionItem.cc
View file @
62285253
/*===================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 201
0
QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
(c) 2009, 201
6
QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
...
...
@@ -21,12 +21,25 @@ This file is part of the QGROUNDCONTROL project
======================================================================*/
#include "ComplexMissionItem.h"
#include "JsonHelper.h"
#include "MissionController.h"
const
char
*
ComplexMissionItem
::
_jsonVersionKey
=
"version"
;
const
char
*
ComplexMissionItem
::
_jsonTypeKey
=
"type"
;
const
char
*
ComplexMissionItem
::
_jsonPolygonKey
=
"polygon"
;
const
char
*
ComplexMissionItem
::
_jsonIdKey
=
"id"
;
const
char
*
ComplexMissionItem
::
_complexType
=
"survey"
;
ComplexMissionItem
::
ComplexMissionItem
(
Vehicle
*
vehicle
,
QObject
*
parent
)
:
VisualMissionItem
(
vehicle
,
parent
)
,
_dirty
(
false
)
{
MissionItem
missionItem
;
// FIXME: Bogus entries for testing
_missionItems
+=
new
MissionItem
(
this
);
_missionItems
+=
new
MissionItem
(
this
);
}
ComplexMissionItem
::
ComplexMissionItem
(
const
ComplexMissionItem
&
other
,
QObject
*
parent
)
...
...
@@ -36,20 +49,6 @@ ComplexMissionItem::ComplexMissionItem(const ComplexMissionItem& other, QObject*
}
QVariantList
ComplexMissionItem
::
polygonPath
(
void
)
{
return
_polygonPath
;
#if 0
QVariantList list;
list << QVariant::fromValue(QGeoCoordinate(-35.362686830000001, 149.16410282999999))
<< QVariant::fromValue(QGeoCoordinate(-35.362660579999996, 149.16606619999999))
<< QVariant::fromValue(QGeoCoordinate(-35.363832989999999, 149.16505769));
return list;
#endif
}
void
ComplexMissionItem
::
clearPolygon
(
void
)
{
_polygonPath
.
clear
();
...
...
@@ -60,6 +59,11 @@ void ComplexMissionItem::addPolygonCoordinate(const QGeoCoordinate coordinate)
{
_polygonPath
<<
QVariant
::
fromValue
(
coordinate
);
emit
polygonPathChanged
();
// FIXME: Hack, first polygon point sets entry coordinate
if
(
_polygonPath
.
count
()
==
1
)
{
setCoordinate
(
coordinate
);
}
}
int
ComplexMissionItem
::
nextSequenceNumber
(
void
)
const
...
...
@@ -72,6 +76,10 @@ void ComplexMissionItem::setCoordinate(const QGeoCoordinate& coordinate)
if
(
_coordinate
!=
coordinate
)
{
_coordinate
=
coordinate
;
emit
coordinateChanged
(
_coordinate
);
_missionItems
[
0
]
->
setCoordinate
(
coordinate
);
// FIXME: Hack
_setExitCoordinate
(
coordinate
);
}
}
...
...
@@ -83,11 +91,148 @@ void ComplexMissionItem::setDirty(bool dirty)
}
}
bool
ComplexMissionItem
::
save
(
QJsonObject
&
missionObject
,
QJsonArray
&
missionItems
,
QString
&
errorString
)
void
ComplexMissionItem
::
save
(
QJsonObject
&
saveObject
)
const
{
saveObject
[
_jsonVersionKey
]
=
1
;
saveObject
[
_jsonTypeKey
]
=
_complexType
;
saveObject
[
_jsonIdKey
]
=
sequenceNumber
();
// Polygon shape
QJsonArray
polygonArray
;
for
(
int
i
=
0
;
i
<
_polygonPath
.
count
();
i
++
)
{
const
QVariant
&
polyVar
=
_polygonPath
[
i
];
QJsonValue
jsonValue
;
JsonHelper
::
writeQGeoCoordinate
(
jsonValue
,
polyVar
.
value
<
QGeoCoordinate
>
(),
false
/* writeAltitude */
);
polygonArray
+=
jsonValue
;
}
saveObject
[
_jsonPolygonKey
]
=
polygonArray
;
// Base mission items
QJsonArray
simpleItems
;
for
(
int
i
=
0
;
i
<
_missionItems
.
count
();
i
++
)
{
MissionItem
*
missionItem
=
_missionItems
[
i
];
QJsonObject
jsonObject
;
missionItem
->
save
(
jsonObject
);
simpleItems
.
append
(
jsonObject
);
}
saveObject
[
MissionController
::
jsonSimpleItemsKey
]
=
simpleItems
;
}
void
ComplexMissionItem
::
setSequenceNumber
(
int
sequenceNumber
)
{
VisualMissionItem
::
setSequenceNumber
(
sequenceNumber
);
// Update internal mission items to new numbering
for
(
int
i
=
0
;
i
<
_missionItems
.
count
();
i
++
)
{
_missionItems
[
i
]
->
setSequenceNumber
(
sequenceNumber
++
);
}
}
void
ComplexMissionItem
::
_clear
(
void
)
{
Q_UNUSED
(
missionObject
);
Q_UNUSED
(
missionItems
);
// Clear old settings
for
(
int
i
=
0
;
i
<
_missionItems
.
count
();
i
++
)
{
_missionItems
[
i
]
->
deleteLater
();
}
_missionItems
.
clear
();
_polygonPath
.
clear
();
}
bool
ComplexMissionItem
::
load
(
const
QJsonObject
&
complexObject
,
QString
&
errorString
)
{
_clear
();
// Validate requires keys
QStringList
requiredKeys
;
requiredKeys
<<
_jsonVersionKey
<<
_jsonTypeKey
<<
_jsonIdKey
<<
_jsonPolygonKey
<<
MissionController
::
jsonSimpleItemsKey
;
if
(
!
JsonHelper
::
validateRequiredKeys
(
complexObject
,
requiredKeys
,
errorString
))
{
_clear
();
return
false
;
}
// Validate types
QStringList
keyList
;
QList
<
QJsonValue
::
Type
>
typeList
;
keyList
<<
_jsonVersionKey
<<
_jsonTypeKey
<<
_jsonIdKey
<<
_jsonPolygonKey
<<
MissionController
::
jsonSimpleItemsKey
;
typeList
<<
QJsonValue
::
Double
<<
QJsonValue
::
String
<<
QJsonValue
::
Double
<<
QJsonValue
::
Array
<<
QJsonValue
::
Array
;
if
(
!
JsonHelper
::
validateKeyTypes
(
complexObject
,
keyList
,
typeList
,
errorString
))
{
_clear
();
return
false
;
}
// Version check
if
(
complexObject
[
_jsonVersionKey
].
toInt
()
!=
1
)
{
errorString
=
tr
(
"QGroundControl does not support this version of survey items"
);
_clear
();
return
false
;
}
QString
complexType
=
complexObject
[
_jsonTypeKey
].
toString
();
if
(
complexType
!=
_complexType
)
{
errorString
=
tr
(
"QGroundControl does not support loading this complex mission item type: %1"
).
arg
(
complexType
);
_clear
();
return
false
;
}
setSequenceNumber
(
complexObject
[
_jsonIdKey
].
toInt
());
// Polygon shape
QJsonArray
polygonArray
(
complexObject
[
_jsonPolygonKey
].
toArray
());
for
(
int
i
=
0
;
i
<
polygonArray
.
count
();
i
++
)
{
const
QJsonValue
&
pointValue
=
polygonArray
[
i
];
QGeoCoordinate
pointCoord
;
if
(
!
JsonHelper
::
toQGeoCoordinate
(
pointValue
,
pointCoord
,
false
/* altitudeRequired */
,
errorString
))
{
_clear
();
return
false
;
}
_polygonPath
<<
QVariant
::
fromValue
(
pointCoord
);
}
// Internal mission items
QJsonArray
itemArray
(
complexObject
[
MissionController
::
jsonSimpleItemsKey
].
toArray
());
for
(
int
i
=
0
;
i
<
itemArray
.
count
();
i
++
)
{
const
QJsonValue
&
itemValue
=
itemArray
[
i
];
if
(
!
itemValue
.
isObject
())
{
errorString
=
QStringLiteral
(
"Mission item is not an object"
);
_clear
();
return
false
;
}
MissionItem
*
item
=
new
MissionItem
(
_vehicle
,
this
);
if
(
item
->
load
(
itemValue
.
toObject
(),
errorString
))
{
_missionItems
.
append
(
item
);
}
else
{
_clear
();
return
false
;
}
}
errorString
=
"Complex save NYI"
;
return
false
;
int
itemCount
=
_missionItems
.
count
();
if
(
itemCount
>
0
)
{
setCoordinate
(
_missionItems
[
0
]
->
coordinate
());
_setExitCoordinate
(
_missionItems
[
itemCount
-
1
]
->
coordinate
());
}
return
true
;
}
void
ComplexMissionItem
::
_setExitCoordinate
(
const
QGeoCoordinate
&
coordinate
)
{
if
(
_exitCoordinate
!=
coordinate
)
{
_exitCoordinate
=
coordinate
;
emit
exitCoordinateChanged
(
coordinate
);
int
itemCount
=
_missionItems
.
count
();
if
(
itemCount
>
0
)
{
_missionItems
[
itemCount
-
1
]
->
setCoordinate
(
coordinate
);
}
}
}
src/MissionManager/ComplexMissionItem.h
View file @
62285253
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 201
4
QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
(c) 2009 - 201
6
QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef ComplexMissionItem_H
...
...
@@ -30,7 +30,7 @@
class
ComplexMissionItem
:
public
VisualMissionItem
{
Q_OBJECT
public:
ComplexMissionItem
(
Vehicle
*
vehicle
,
QObject
*
parent
=
NULL
);
ComplexMissionItem
(
const
ComplexMissionItem
&
other
,
QObject
*
parent
=
NULL
);
...
...
@@ -40,13 +40,19 @@ public:
Q_INVOKABLE
void
clearPolygon
(
void
);
Q_INVOKABLE
void
addPolygonCoordinate
(
const
QGeoCoordinate
coordinate
);
QVariantList
polygonPath
(
void
)
;
QVariantList
polygonPath
(
void
)
{
return
_polygonPath
;
}
const
QList
<
MissionItem
*>&
missionItems
(
void
)
{
return
_missionItems
;
}
QList
<
MissionItem
*>&
missionItems
(
void
)
{
return
_missionItems
;
}
/// @return The next sequence number to use after this item. Takes into account child items of the complex item
int
nextSequenceNumber
(
void
)
const
;
/// Load the complex mission item from Json
/// @param complexObject Complex mission item json object
/// @param[out] errorString Error if load fails
/// @return true: load success, false: load failed, errorString set
bool
load
(
const
QJsonObject
&
complexObject
,
QString
&
errorString
);
// Overrides from VisualMissionItem
bool
dirty
(
void
)
const
final
{
return
_dirty
;
}
...
...
@@ -56,24 +62,36 @@ public:
QString
commandDescription
(
void
)
const
final
{
return
"Survey"
;
}
QString
commandName
(
void
)
const
final
{
return
"Survey"
;
}
QGeoCoordinate
coordinate
(
void
)
const
final
{
return
_coordinate
;
}
QGeoCoordinate
exitCoordinate
(
void
)
const
final
{
return
_
c
oordinate
;
}
QGeoCoordinate
exitCoordinate
(
void
)
const
final
{
return
_
exitC
oordinate
;
}
bool
coordinateHasRelativeAltitude
(
void
)
const
final
{
return
true
;
}
bool
exitCoordinateHasRelativeAltitude
(
void
)
const
final
{
return
true
;
}
bool
exitCoordinateSameAsEntry
(
void
)
const
final
{
return
false
;
}
void
setDirty
(
bool
dirty
)
final
;
void
setCoordinate
(
const
QGeoCoordinate
&
coordinate
);
bool
save
(
QJsonObject
&
missionObject
,
QJsonArray
&
missionItems
,
QString
&
errorString
)
final
;
void
setCoordinate
(
const
QGeoCoordinate
&
coordinate
)
final
;
void
setSequenceNumber
(
int
sequenceNumber
)
final
;
void
save
(
QJsonObject
&
saveObject
)
const
final
;
signals:
void
polygonPathChanged
(
void
);
private:
void
_clear
(
void
);
void
_setExitCoordinate
(
const
QGeoCoordinate
&
coordinate
);
bool
_dirty
;
QVariantList
_polygonPath
;
QList
<
MissionItem
*>
_missionItems
;
QGeoCoordinate
_coordinate
;
QGeoCoordinate
_exitCoordinate
;
static
const
char
*
_jsonVersionKey
;
static
const
char
*
_jsonTypeKey
;
static
const
char
*
_jsonPolygonKey
;
static
const
char
*
_jsonIdKey
;
static
const
char
*
_complexType
;
};
#endif
src/MissionManager/MissionController.cc
View file @
62285253
...
...
@@ -29,6 +29,7 @@ This file is part of the QGROUNDCONTROL project
#include "QGCApplication.h"
#include "SimpleMissionItem.h"
#include "ComplexMissionItem.h"
#include "JsonHelper.h"
#ifndef __mobile__
#include "QGCFileDialog.h"
...
...
@@ -36,11 +37,13 @@ This file is part of the QGROUNDCONTROL project
QGC_LOGGING_CATEGORY
(
MissionControllerLog
,
"MissionControllerLog"
)
const
char
*
MissionController
::
jsonSimpleItemsKey
=
"items"
;
const
char
*
MissionController
::
_settingsGroup
=
"MissionController"
;
const
char
*
MissionController
::
_jsonVersionKey
=
"version"
;
const
char
*
MissionController
::
_jsonGroundStationKey
=
"groundStation"
;
const
char
*
MissionController
::
_jsonMavAutopilotKey
=
"MAV_AUTOPILOT"
;
const
char
*
MissionController
::
_json
ItemsKey
=
"i
tems"
;
const
char
*
MissionController
::
_json
ComplexItemsKey
=
"complexI
tems"
;
const
char
*
MissionController
::
_jsonPlannedHomePositionKey
=
"plannedHomePosition"
;
MissionController
::
MissionController
(
QObject
*
parent
)
...
...
@@ -140,7 +143,9 @@ void MissionController::sendMissionItems(void)
missionItem
.
setSequenceNumber
(
sequenceNumber
++
);
missionItems
.
append
(
&
missionItem
);
}
else
{
foreach
(
MissionItem
*
missionItem
,
qobject_cast
<
ComplexMissionItem
*>
(
visualItem
)
->
missionItems
())
{
ComplexMissionItem
*
complexItem
=
qobject_cast
<
ComplexMissionItem
*>
(
visualItem
);
for
(
int
j
=
0
;
j
<
complexItem
->
missionItems
().
count
();
j
++
)
{
MissionItem
*
missionItem
=
complexItem
->
missionItems
()[
i
];
missionItem
->
setSequenceNumber
(
sequenceNumber
++
);
missionItems
.
append
(
missionItem
);
}
...
...
@@ -247,29 +252,56 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QmlObjectL
QJsonObject
json
=
jsonDoc
.
object
();
if
(
!
json
.
contains
(
_jsonVersionKey
))
{
errorString
=
QStringLiteral
(
"File is missing version key"
);
// Check for required keys
QStringList
requiredKeys
;
requiredKeys
<<
_jsonVersionKey
<<
_jsonPlannedHomePositionKey
;
if
(
!
JsonHelper
::
validateRequiredKeys
(
json
,
requiredKeys
,
errorString
))
{
return
false
;
}
// Validate base key types
QStringList
keyList
;
QList
<
QJsonValue
::
Type
>
typeList
;
keyList
<<
jsonSimpleItemsKey
<<
_jsonVersionKey
<<
_jsonGroundStationKey
<<
_jsonMavAutopilotKey
<<
_jsonComplexItemsKey
<<
_jsonPlannedHomePositionKey
;
typeList
<<
QJsonValue
::
Array
<<
QJsonValue
::
String
<<
QJsonValue
::
String
<<
QJsonValue
::
Double
<<
QJsonValue
::
Array
<<
QJsonValue
::
Object
;
if
(
!
JsonHelper
::
validateKeyTypes
(
json
,
keyList
,
typeList
,
errorString
))
{
return
false
;
}
// Version check
if
(
json
[
_jsonVersionKey
].
toString
()
!=
"1.0"
)
{
errorString
=
QStringLiteral
(
"QGroundControl does not support this file version"
);
return
false
;
}
if
(
json
.
contains
(
_jsonItemsKey
))
{
if
(
!
json
[
_jsonItemsKey
].
isArray
())
{
errorString
=
QStringLiteral
(
"items values must be array"
);
return
false
;
// Simple items
if
(
json
.
contains
(
jsonSimpleItemsKey
))
{
QJsonArray
itemArray
(
json
[
jsonSimpleItemsKey
].
toArray
());
foreach
(
const
QJsonValue
&
itemValue
,
itemArray
)
{
if
(
!
itemValue
.
isObject
())
{
errorString
=
QStringLiteral
(
"Mission item is not an object"
);
return
false
;
}
SimpleMissionItem
*
item
=
new
SimpleMissionItem
(
_activeVehicle
,
this
);
if
(
item
->
load
(
itemValue
.
toObject
(),
errorString
))
{
missionItems
->
append
(
item
);
}
else
{
return
false
;
}
}
}
QJsonArray
itemArray
(
json
[
_jsonItemsKey
].
toArray
());
// Complex items
if
(
json
.
contains
(
_jsonComplexItemsKey
))
{
QJsonArray
itemArray
(
json
[
_jsonComplexItemsKey
].
toArray
());
foreach
(
const
QJsonValue
&
itemValue
,
itemArray
)
{
if
(
!
itemValue
.
isObject
())
{
errorString
=
QStringLiteral
(
"Mission item is not an object"
);
return
false
;
}
SimpleMissionItem
*
item
=
new
Simple
MissionItem
(
_activeVehicle
,
this
);
ComplexMissionItem
*
item
=
new
Complex
MissionItem
(
_activeVehicle
,
this
);
if
(
item
->
load
(
itemValue
.
toObject
(),
errorString
))
{
missionItems
->
append
(
item
);
}
else
{
...
...
@@ -418,12 +450,12 @@ void MissionController::_saveMissionToFile(const QString& filename)
if
(
!
file
.
open
(
QIODevice
::
WriteOnly
|
QIODevice
::
Text
))
{
qgcApp
()
->
showMessage
(
file
.
errorString
());
}
else
{
QJsonObject
missionObject
;
// top level json object
QJsonArray
missionItemArray
;
// array of mission items
Q
String
errorString
;
QJsonObject
mission
File
Object
;
// top level json object
QJsonArray
simpleItemsObject
;
Q
JsonArray
complexItemsObject
;
mission
Object
[
_jsonVersionKey
]
=
"1.0"
;
mission
Object
[
_jsonGroundStationKey
]
=
"QGroundControl"
;
mission
FileObject
[
_jsonVersionKey
]
=
"1.0"
;
mission
FileObject
[
_jsonGroundStationKey
]
=
"QGroundControl"
;
MAV_AUTOPILOT
firmwareType
=
MAV_AUTOPILOT_GENERIC
;
if
(
_activeVehicle
)
{
...
...
@@ -435,7 +467,7 @@ void MissionController::_saveMissionToFile(const QString& filename)
QSettings
settings
;
firmwareType
=
(
MAV_AUTOPILOT
)
settings
.
value
(
"OfflineEditingFirmwareType"
,
MAV_AUTOPILOT_ARDUPILOTMEGA
).
toInt
();
}
missionObject
[
_jsonMavAutopilotKey
]
=
firmwareType
;
mission
File
Object
[
_jsonMavAutopilotKey
]
=
firmwareType
;
// Save planned home position
QJsonObject
homePositionObject
;
...
...
@@ -446,19 +478,26 @@ void MissionController::_saveMissionToFile(const QString& filename)
qgcApp
()
->
showMessage
(
QStringLiteral
(
"Internal error: VisualMissionItem at index 0 not SimpleMissionItem"
));
return
;
}
missionObject
[
_jsonPlannedHomePositionKey
]
=
homePositionObject
;
mission
File
Object
[
_jsonPlannedHomePositionKey
]
=
homePositionObject
;
// Save the
remainder of the
visual items
// Save the visual items
for
(
int
i
=
1
;
i
<
_visualItems
->
count
();
i
++
)
{
QJsonObject
itemObject
;
VisualMissionItem
*
visualItem
=
qobject_cast
<
VisualMissionItem
*>
(
_visualItems
->
get
(
i
));
if
(
!
visualItem
->
save
(
missionObject
,
missionItemArray
,
errorString
))
{
qgcApp
()
->
showMessage
(
errorString
);
return
;
visualItem
->
save
(
itemObject
);
if
(
visualItem
->
isSimpleItem
())
{
simpleItemsObject
.
append
(
itemObject
);
}
else
{
complexItemsObject
.
append
(
itemObject
);
}
}
missionObject
[
"items"
]
=
missionItemArray
;
QJsonDocument
saveDoc
(
missionObject
);
missionFileObject
[
jsonSimpleItemsKey
]
=
simpleItemsObject
;
missionFileObject
[
_jsonComplexItemsKey
]
=
complexItemsObject
;
QJsonDocument
saveDoc
(
missionFileObject
);
file
.
write
(
saveDoc
.
toJson
());
}
...
...
src/MissionManager/MissionController.h
View file @
62285253
...
...
@@ -75,6 +75,8 @@ public:
void
setAutoSync
(
bool
autoSync
);
bool
syncInProgress
(
void
);
static
const
char
*
jsonSimpleItemsKey
;
///< Key for simple items in a json file
signals:
void
visualItemsChanged
(
void
);
void
complexVisualItemsChanged
(
void
);
...
...
@@ -131,7 +133,7 @@ private:
static
const
char
*
_jsonVersionKey
;
static
const
char
*
_jsonGroundStationKey
;
static
const
char
*
_jsonMavAutopilotKey
;
static
const
char
*
_jsonItemsKey
;
static
const
char
*
_json
Complex
ItemsKey
;
static
const
char
*
_jsonPlannedHomePositionKey
;
};
...
...
src/MissionManager/MissionItem.cc
View file @
62285253
...
...
@@ -148,7 +148,7 @@ MissionItem::~MissionItem()
{
}
void
MissionItem
::
save
(
QJsonObject
&
json
)
void
MissionItem
::
save
(
QJsonObject
&
json
)
const
{
json
[
_jsonTypeKey
]
=
_itemType
;
json
[
_jsonIdKey
]
=
sequenceNumber
();
...
...
src/MissionManager/MissionItem.h
View file @
62285253
...
...
@@ -103,7 +103,7 @@ public:
void
setParam7
(
double
param7
);
void
setCoordinate
(
const
QGeoCoordinate
&
coordinate
);
void
save
(
QJsonObject
&
json
);
void
save
(
QJsonObject
&
json
)
const
;
bool
load
(
QTextStream
&
loadStream
);
bool
load
(
const
QJsonObject
&
json
,
QString
&
errorString
);
...
...
src/MissionManager/SimpleMissionItem.cc
View file @
62285253
...
...
@@ -244,16 +244,9 @@ SimpleMissionItem::~SimpleMissionItem()
{
}
bool
SimpleMissionItem
::
save
(
QJsonObject
&
missionObject
,
QJsonArray
&
missionItems
,
QString
&
errorString
)
void
SimpleMissionItem
::
save
(
QJsonObject
&
saveObject
)
const
{
Q_UNUSED
(
missionObject
);
Q_UNUSED
(
errorString
);
QJsonObject
itemObject
;
_missionItem
.
save
(
itemObject
);
missionItems
.
append
(
itemObject
);
return
true
;
_missionItem
.
save
(
saveObject
);
}
bool
SimpleMissionItem
::
load
(
QTextStream
&
loadStream
)
...
...
@@ -585,3 +578,9 @@ void SimpleMissionItem::setCoordinate(const QGeoCoordinate& coordinate)
_missionItem
.
setCoordinate
(
coordinate
);
}
}
void
SimpleMissionItem
::
setSequenceNumber
(
int
sequenceNumber
)
{
_missionItem
.
setSequenceNumber
(
sequenceNumber
);
VisualMissionItem
::
setSequenceNumber
(
sequenceNumber
);
}
src/MissionManager/SimpleMissionItem.h
View file @
62285253
...
...
@@ -107,8 +107,9 @@ public:
bool
exitCoordinateSameAsEntry
(
void
)
const
final
{
return
true
;
}
void
setDirty
(
bool
dirty
)
final
;
void
setCoordinate
(
const
QGeoCoordinate
&
coordinate
);
bool
save
(
QJsonObject
&
missionObject
,
QJsonArray
&
missionItems
,
QString
&
errorString
)
final
;
void
setCoordinate
(
const
QGeoCoordinate
&
coordinate
)
final
;
void
setSequenceNumber
(
int
sequenceNumber
)
final
;
void
save
(
QJsonObject
&
saveObject
)
const
final
;
public
slots
:
void
setDefaultsForCommand
(
void
);
...
...
src/MissionManager/VisualMissionItem.h
View file @
62285253
...
...
@@ -108,10 +108,13 @@ public:
void
setAltPercent
(
double
altPercent
);
void
setAzimuth
(
double
azimuth
);
void
setDistance
(
double
distance
);
void
setSequenceNumber
(
int
sequenceNumber
);
Vehicle
*
vehicle
(
void
)
{
return
_vehicle
;
}
// Virtuals which may be overriden by derived classes
virtual
void
setSequenceNumber
(
int
sequenceNumber
);
// Pure virtuals which must be provides by derived classes
virtual
bool
dirty
(
void
)
const
=
0
;
...
...
@@ -130,11 +133,9 @@ public:
virtual
void
setDirty
(
bool
dirty
)
=
0
;
virtual
void
setCoordinate
(
const
QGeoCoordinate
&
coordinate
)
=
0
;
/// Save the item in Json format
/// @param missionObject Top level object for entire mission file
/// @param missionItems Array of mission items
/// @return false: save failed, errorString set
virtual
bool
save
(
QJsonObject
&
missionObject
,
QJsonArray
&
missionItems
,
QString
&
errorString
)
=
0
;
/// Save the item(s) in Json format
/// @param saveObject Save the item to this json object
virtual
void
save
(
QJsonObject
&
saveObject
)
const
=
0
;
signals:
void
altDifferenceChanged
(
double
altDifference
);
...
...
src/QmlControls/MissionItemEditor.qml
View file @
62285253
...
...
@@ -15,7 +15,7 @@ Rectangle {
id
:
_root
height
:
editorLoader
.
y
+
editorLoader
.
height
+
(
_margin
*
2
)
color
:
missionItem
.
isC
urrentItem
?
qgcPal
.
buttonHighlight
:
qgcPal
.
windowShade
color
:
_c
urrentItem
?
qgcPal
.
buttonHighlight
:
qgcPal
.
windowShade
radius
:
_radius
property
var
missionItem
///< MissionItem associated with this editor
...
...
@@ -27,11 +27,12 @@ Rectangle {
signal
insert
(
int
i
)
signal
moveHomeToMapCenter
property
bool
_currentItem
:
missionItem
.
isCurrentItem
property
color
_outerTextColor
:
_currentItem
?
"
black
"
:
qgcPal
.
text
readonly
property
real
_editFieldWidth
:
ScreenTools
.
defaultFontPixelWidth
*
16
readonly
property
real
_margin
:
ScreenTools
.
defaultFontPixelWidth
/
2
readonly
property
real
_radius
:
ScreenTools
.
defaultFontPixelWidth
/
2
property
color
_outerTextColor
:
missionItem
.
isCurrentItem
?
"
black
"
:
qgcPal
.
text
QGCPalette
{
id
:
qgcPal
...
...
@@ -88,7 +89,7 @@ Rectangle {
MenuItem
{
text
:
"
Show all values
"
checkable
:
true
checked
:
missionItem
.
rawEdit
checked
:
missionItem
.
isSimpleItem
?
missionItem
.
rawEdit
:
false
visible
:
missionItem
.
isSimpleItem
onTriggered
:
{
...
...
@@ -142,191 +143,10 @@ Rectangle {
anchors.topMargin
:
_margin
anchors.left
:
parent
.
left
anchors.top
:
commandPicker
.
bottom
sourceComponent
:
missionItem
.
isSimpleItem
?
simpleMissionItemEditor
:
complexMissionItemEditor
/// How wide the loaded component should be
property
real
availableWidth
:
_root
.
width
-
(
_margin
*
2
)
}
Component
{
id
:
valuesComponent
Rectangle
{
id
:
valuesRect
height
:
valuesItem
.
height
color
:
qgcPal
.
windowShadeDark
visible
:
missionItem
.
isCurrentItem
radius
:
_radius
Item
{
id
:
valuesItem
anchors.margins
:
_margin
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
anchors.top
:
parent
.
top
height
:
valuesColumn
.
height
+
(
_margin
*
2
)
Column
{
id
:
valuesColumn
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
anchors.top
:
parent
.
top
spacing
:
_margin
QGCLabel
{
width
:
parent
.
width
wrapMode
:
Text
.
WordWrap
text
:
missionItem
.
sequenceNumber
==
0
?
"
Planned home position.
"
:
(
missionItem
.
rawEdit
?
"
Provides advanced access to all commands/parameters. Be very careful!
"
:
missionItem
.
commandDescription
)
}
Repeater
{
model
:
missionItem
.
comboboxFacts
Item
{
width
:
valuesColumn
.
width
height
:
comboBoxFact
.
height
QGCLabel
{
id
:
comboBoxLabel
anchors.baseline
:
comboBoxFact
.
baseline
text
:
object
.
name
visible
:
object
.
name
!=
""
}
FactComboBox
{
id
:
comboBoxFact
anchors.right
:
parent
.
right
width
:
comboBoxLabel
.
visible
?
_editFieldWidth
:
parent
.
width
indexModel
:
false
model
:
object
.
enumStrings
fact
:
object
}
}
}
Repeater
{
model
:
missionItem
.
textFieldFacts
Item
{
width
:
valuesColumn
.
width
height
:
textField
.
height
QGCLabel
{
id
:
textFieldLabel
anchors.baseline
:
textField
.
baseline
text
:
object
.
name
}
FactTextField
{
id
:
textField
anchors.right
:
parent
.
right
width
:
_editFieldWidth
showUnits
:
true
fact
:
object
visible
:
!
_root
.
readOnly
}
FactLabel
{
anchors.baseline
:
textFieldLabel
.
baseline
anchors.right
:
parent
.
right
fact
:
object
visible
:
_root
.
readOnly
}
}
}
Repeater
{
model
:
missionItem
.
checkboxFacts
FactCheckBox
{
text
:
object
.
name
fact
:
object
}
}
QGCButton
{
text
:
"
Move Home to map center
"
visible
:
missionItem
.
homePosition
onClicked
:
moveHomeToMapCenter
()
anchors.horizontalCenter
:
parent
.
horizontalCenter
}
}
// Column
}
// Item
}
// Rectangle
height
:
_currentItem
&&
item
?
item
.
height
:
0
source
:
_currentItem
?
(
missionItem
.
isSimpleItem
?
"
qrc:/qml/SimpleItemEditor.qml
"
:
"
qrc:/qml/SurveyItemEditor.qml
"
)
:
""
property
real
availableWidth
:
_root
.
width
-
(
_margin
*
2
)
///< How wide the editor should be
property
var
editorRoot
:
_root
}
Component
{
id
:
simpleMissionItemEditor
Item
{
id
:
innerItem
width
:
availableWidth
height
:
_showValues
?
valuesLoader
.
y
+
valuesLoader
.
height
:
valuesLoader
.
y
property
bool
_showValues
:
missionItem
.
isCurrentItem
Loader
{
id
:
valuesLoader
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
sourceComponent
:
_showValues
?
valuesComponent
:
undefined
}
}
// Item
}
// Component - simpleMissionItemEditor
Component
{
id
:
complexMissionItemEditor
Rectangle
{
id
:
outerRect
height
:
editorColumn
.
height
+
(
_margin
*
2
)
width
:
availableWidth
color
:
qgcPal
.
windowShadeDark
radius
:
_radius
property
bool
addPointsMode
:
false
Column
{
id
:
editorColumn
anchors.margins
:
_margin
anchors.top
:
parent
.
top
anchors.left
:
parent
.
left
width
:
availableWidth
spacing
:
_margin
Connections
{
target
:
editorMap
onMapClicked
:
{
if
(
addPointsMode
)
{
missionItem
.
addPolygonCoordinate
(
coordinate
)
}
}
}
QGCLabel
{
text
:
"
Fly a grid pattern over a defined area.
"
wrapMode
:
Text
.
WordWrap
}
QGCButton
{
text
:
addPointsMode
?
"
Finished
"
:
"
Draw Polygon
"
onClicked
:
{
if
(
addPointsMode
)
{
addPointsMode
=
false
}
else
{
missionItem
.
clearPolygon
()
addPointsMode
=
true
}
}
}
}
}
}
// Component - complexMissionItemEditor
}
// Rectangle
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment